summaryrefslogtreecommitdiff
path: root/sources
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2005-02-04 13:04:57 +0000
committerMartin Odersky <odersky@gmail.com>2005-02-04 13:04:57 +0000
commit4ab12055ef6a548afdf1b9d583c291b74d3630bc (patch)
treef678ed874115f2654a7ec0398ddf027c0803a707 /sources
parent204dbd6dacd0bd3c16c3266b98673e4a630932ce (diff)
downloadscala-4ab12055ef6a548afdf1b9d583c291b74d3630bc.tar.gz
scala-4ab12055ef6a548afdf1b9d583c291b74d3630bc.tar.bz2
scala-4ab12055ef6a548afdf1b9d583c291b74d3630bc.zip
*** empty log message ***
Diffstat (limited to 'sources')
-rw-r--r--sources/scala/tools/nsc/CompilationUnits.scala27
-rw-r--r--sources/scala/tools/nsc/CompilerCommand.scala56
-rwxr-xr-xsources/scala/tools/nsc/FatalError.scala3
-rwxr-xr-xsources/scala/tools/nsc/Global.scala202
-rwxr-xr-xsources/scala/tools/nsc/Main.scala48
-rw-r--r--sources/scala/tools/nsc/NoPhase.scala6
-rw-r--r--sources/scala/tools/nsc/Phase.scala26
-rw-r--r--sources/scala/tools/nsc/Settings.scala155
-rw-r--r--sources/scala/tools/nsc/StdPhase.scala10
-rw-r--r--sources/scala/tools/nsc/ast/TreeInfo.scala136
-rw-r--r--sources/scala/tools/nsc/ast/TreePrinters.scala293
-rw-r--r--sources/scala/tools/nsc/ast/Trees.scala865
-rw-r--r--sources/scala/tools/nsc/ast/parser/Lexical.scala857
-rw-r--r--sources/scala/tools/nsc/ast/parser/ParserPhase.scala11
-rwxr-xr-xsources/scala/tools/nsc/ast/parser/Syntactic.scala1793
-rw-r--r--sources/scala/tools/nsc/ast/parser/TokenData.scala2
-rw-r--r--sources/scala/tools/nsc/ast/parser/Tokens.scala85
-rwxr-xr-xsources/scala/tools/nsc/build1
-rwxr-xr-xsources/scala/tools/nsc/build.bat1
-rw-r--r--sources/scala/tools/nsc/grepnsc1
-rwxr-xr-xsources/scala/tools/nsc/scalac0
-rwxr-xr-xsources/scala/tools/nsc/symtab/Definitions.scala231
-rw-r--r--sources/scala/tools/nsc/symtab/Flags.scala82
-rw-r--r--sources/scala/tools/nsc/symtab/InfoTransformers.scala39
-rwxr-xr-xsources/scala/tools/nsc/symtab/Names.scala272
-rwxr-xr-xsources/scala/tools/nsc/symtab/Scopes.scala232
-rwxr-xr-xsources/scala/tools/nsc/symtab/StdNames.scala193
-rwxr-xr-xsources/scala/tools/nsc/symtab/SymbolLoaders.scala142
-rwxr-xr-xsources/scala/tools/nsc/symtab/SymbolTable.scala35
-rwxr-xr-xsources/scala/tools/nsc/symtab/Symbols.scala658
-rwxr-xr-xsources/scala/tools/nsc/symtab/Types.scala1499
-rw-r--r--sources/scala/tools/nsc/symtab/classfile/ClassfileConstants.scala45
-rwxr-xr-xsources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala388
-rwxr-xr-xsources/scala/tools/nsc/symtab/classfile/MetaParser.scala152
-rw-r--r--sources/scala/tools/nsc/symtab/classfile/Pickle.scala6
-rwxr-xr-xsources/scala/tools/nsc/symtab/classfile/UnPickle.scala477
-rw-r--r--sources/scala/tools/nsc/typechecker/Analyzer.scala3020
-rw-r--r--sources/scala/tools/nsc/util/CharArrayReader.scala82
-rw-r--r--sources/scala/tools/nsc/util/FreshNameCreator.scala28
-rwxr-xr-xsources/scala/tools/nsc/util/NameTransformer.scala91
-rw-r--r--sources/scala/tools/util/ConsoleReporter.java4
41 files changed, 12251 insertions, 3 deletions
diff --git a/sources/scala/tools/nsc/CompilationUnits.scala b/sources/scala/tools/nsc/CompilationUnits.scala
new file mode 100644
index 0000000000..303f4dcdfd
--- /dev/null
+++ b/sources/scala/tools/nsc/CompilationUnits.scala
@@ -0,0 +1,27 @@
+package scala.tools.nsc;
+
+import scala.tools.util.{SourceFile, Position};
+import scala.tools.nsc.util.FreshNameCreator;
+
+class CompilationUnits: Global {
+
+ class CompilationUnit(val source: SourceFile, val mixinOnly: boolean) {
+
+ /** short constructor */
+ def this(source: SourceFile) = this(source, false);
+
+ /** the fresh name creator */
+ val fresh = new FreshNameCreator;
+
+ /** the content of the compilation unit in tree form */
+ var body: List[Tree] = List();
+
+ def position(pos: int) = new Position(source, pos);
+
+ def error(pos: int, msg: String) = reporter.error(position(pos), msg);
+ def warning(pos: int, msg: String) = reporter.warning(position(pos), msg);
+ override def toString() = source.toString();
+ }
+}
+
+
diff --git a/sources/scala/tools/nsc/CompilerCommand.scala b/sources/scala/tools/nsc/CompilerCommand.scala
new file mode 100644
index 0000000000..3d7b048292
--- /dev/null
+++ b/sources/scala/tools/nsc/CompilerCommand.scala
@@ -0,0 +1,56 @@
+package scala.tools.nsc;
+
+import scala.tools.util.Reporter;
+
+/** A class representing command line info for scalac */
+class CompilerCommand(arguments: Array[String], error: String => unit) {
+ private var fs: List[String] = List();
+
+ /** All files to compile */
+ def files: List[String] = fs.reverse;
+
+ /** The applicable settings */
+ val settings: Settings = new Settings(error);
+
+ /** A message explaining usage and options */
+ def usageMsg: String = {
+ val helpSyntaxColumnWidth: int =
+ Iterable.max(settings.allSettings map (. helpSyntax.length()));
+ def format(s: String): String = {
+ val buf = new StringBuffer();
+ buf.append(s);
+ var i = s.length();
+ while (i < helpSyntaxColumnWidth) { buf.append(' '); i = i + 1 }
+ buf.toString()
+ }
+ settings.allSettings
+ .map(setting =>
+ format(setting.helpSyntax) + " " + setting.helpDescription)
+ .mkString(
+ "Usage: scalac <options | source files>\n" +
+ "where possible options include: \n",
+ "\n ",
+ "\n");
+ }
+
+ // initialization
+ var args = List.fromArray(arguments);
+ var ok = true;
+ while (!args.isEmpty && ok) {
+ val args0 = args;
+ if (args.head.startsWith("-")) {
+ for (val setting <- settings.allSettings)
+ args = setting.tryToSet(args);
+ if (args eq args0) {
+ error("unknown option: '" + args.head + "'");
+ ok = false
+ }
+ } else if (args.head.endsWith(".scala")) {
+ fs = args.head :: fs;
+ args = args.tail
+ } else {
+ error("don't know what to do with " + args.head);
+ ok = false
+ }
+ }
+}
diff --git a/sources/scala/tools/nsc/FatalError.scala b/sources/scala/tools/nsc/FatalError.scala
new file mode 100755
index 0000000000..6a139069d6
--- /dev/null
+++ b/sources/scala/tools/nsc/FatalError.scala
@@ -0,0 +1,3 @@
+package scala.tools.nsc;
+
+case class FatalError(msg: String) extends Exception;
diff --git a/sources/scala/tools/nsc/Global.scala b/sources/scala/tools/nsc/Global.scala
new file mode 100755
index 0000000000..6e786f5b29
--- /dev/null
+++ b/sources/scala/tools/nsc/Global.scala
@@ -0,0 +1,202 @@
+package scala.tools.nsc;
+
+import java.io._;
+import java.nio.charset._;
+import scala.tools.util._;
+import scala.collection.mutable.{HashSet,HashMap,ListBuffer}
+
+import symtab._;
+import symtab.classfile.Pickle;
+import util._;
+import ast._;
+import ast.parser._;
+
+class Global(val settings: Settings, val reporter: Reporter)
+ extends SymbolTable
+ with Trees
+ with CompilationUnits {
+
+// sub-components --------------------------------------------------
+
+ object treePrinters extends TreePrinters {
+ val global: Global.this.type = Global.this
+ }
+ val treePrinter = treePrinters.create();
+
+ object treeInfo extends TreeInfo {
+ val global: Global.this.type = Global.this
+ }
+
+// reporting -------------------------------------------------------
+
+ def informTime(msg: String, start: long) = {
+ val end = System.currentTimeMillis();
+ reporter.info(null, "[" + msg + " in " + (end - start) + "ms]", false);
+ }
+
+ def error(msg: String) = reporter.error(null, msg);
+ def warning(msg: String) = reporter.warning(null, msg);
+ def inform(msg: String) = reporter.info(null, msg, true);
+
+ def log(msg: String) =
+ if (settings.log contains phase.name) inform("[log " + phase + "] " + msg);
+
+// file interface -------------------------------------------------------
+
+ private val reader: SourceReader = {
+ def stdCharset: Charset = {
+ settings.encoding.value = "ISO-8859-1"; // A mandatory charset
+ Charset.forName(settings.encoding.value);
+ }
+ val charset =
+ try {
+ Charset.forName(settings.encoding.value);
+ } catch {
+ case _: IllegalCharsetNameException =>
+ error("illegal charset name '" + settings.encoding.value + "'");
+ stdCharset
+ case _: UnsupportedCharsetException =>
+ error("unsupported charset '" + settings.encoding.value + "'");
+ stdCharset
+ }
+ new SourceReader(charset.newDecoder());
+ }
+
+ val classPath = new ClassPath(
+ settings.classpath.value,
+ settings.sourcepath.value,
+ settings.bootclasspath.value,
+ settings.extdirs.value);
+
+ if (settings.verbose.value) {
+ System.out.println("classpath = " + classPath);
+ }
+
+ def getSourceFile(f: AbstractFile): SourceFile =
+ new SourceFile(f, reader.read(f));
+
+ def getSourceFile(name: String): SourceFile = {
+ val f = AbstractFile.getFile(name);
+ if (f == null) throw new FileNotFoundException(
+ "source file '" + name + "' could not be found");
+ getSourceFile(f)
+ }
+
+ def getSourceFile(clazz: Symbol): SourceFile = {
+ val f = classPath.getRoot().lookupPath(
+ clazz.fullNameString(File.separatorChar) + ".scala", false);
+ if (f == null) throw new FileNotFoundException(
+ "source file for " + clazz + " could not be found");
+ getSourceFile(f)
+ }
+
+ private object loaders extends SymbolLoaders {
+ val global: Global.this.type = Global.this
+ }
+
+ def rootLoader: LazyType = loaders.packageLoader(classPath.getRoot());
+
+// Phases ------------------------------------------------------------
+
+ object parserPhase extends ParserPhase(NoPhase) {
+ val global: Global.this.type = Global.this
+ }
+ val analyzerPhase = new StdPhase(parserPhase) {
+ def name = "analyzer";
+ val global: Global.this.type = Global.this;
+ def apply(unit: CompilationUnit): unit = {}
+ }
+
+ val terminalPhase = new StdPhase(analyzerPhase) {
+ def name = "terminal";
+ val global: Global.this.type = Global.this;
+ def apply(unit: CompilationUnit): unit = {}
+ }
+
+ definitions.init;
+
+// Units and how to compile them -------------------------------------
+
+ private var unitbuf = new ListBuffer[CompilationUnit];
+ private var fileset = new HashSet[AbstractFile];
+
+ private def addUnit(unit: CompilationUnit): unit = {
+ unitbuf += unit;
+ fileset += unit.source.getFile();
+ }
+
+ def units: Seq[CompilationUnit] = unitbuf;
+
+ /** A map from compiled top-level symbols to their source files */
+ val symSource = new HashMap[Symbol, AbstractFile];
+
+ /** A map from compiled top-level symbols to their picklers */
+ val symData = new HashMap[Symbol, Pickle];
+
+ def compileSources(sources: List[SourceFile]): unit = {
+ val startTime = System.currentTimeMillis();
+ unitbuf.clear;
+ fileset.clear;
+ symSource.clear;
+ symData.clear;
+ reporter.resetCounters();
+ for (val source <- sources)
+ addUnit(new CompilationUnit(source));
+ phase = NoPhase.next;
+ while (phase != terminalPhase && reporter.errors() == 0) {
+ val startTime = System.currentTimeMillis();
+ if (!(settings.skip contains phase.name)) phase.run;
+ if (settings.print contains phase.name) treePrinter.printAll();
+ informTime(phase.description, startTime);
+ phase = if (settings.stop contains phase.name) terminalPhase else phase.next;
+ }
+ if (settings.Xshowcls.value != "") showDef(newTermName(settings.Xshowcls.value), false);
+ if (settings.Xshowobj.value != "") showDef(newTermName(settings.Xshowobj.value), true);
+
+ if (reporter.errors() != 0)
+ for (val Pair(sym, file) <- symSource.elements)
+ sym.reset(loaders.sourcefileLoader(file));
+ informTime("total", startTime);
+ }
+
+ def compileLate(file: AbstractFile, mixinOnly: boolean): unit = {
+ if (!(fileset contains file)) {
+ val unit = new CompilationUnit(getSourceFile(file), mixinOnly);
+ addUnit(unit);
+ atPhase(parserPhase) { parserPhase.apply(unit) }
+ //atPhase(analyzerPhase) { analyzerPhase.lateEnter(unit) }
+ }
+ }
+
+ def compileFiles(files: List[AbstractFile]): unit =
+ try {
+ compileSources(files map getSourceFile)
+ } catch {
+ case ex: IOException => error(ex.getMessage());
+ }
+
+ def compile(filenames: List[String]): unit =
+ try {
+ compileSources(filenames map getSourceFile)
+ } catch {
+ case ex: IOException => error(ex.getMessage());
+ }
+
+ def showDef(name: Name, module: boolean): unit = {
+ def getSym(name: Name, module: boolean): Symbol = {
+ var i = name.length - 1;
+ while (i != 0 && name(i) != '#' && name(i) != '.') i = i - 1;
+ if (i == 0)
+ definitions.getModule(name)
+ else {
+ val root = getSym(name.subName(0, i), name(i) == '.');
+ var selector = name.subName(i+1, name.length);
+ if (module) selector = selector.toTypeName;
+ root.info.lookup(selector)
+ }
+ }
+ val sym = getSym(name, module);
+ System.err.println("" + sym.name + ":" +
+ (if (module) sym.moduleClass.info else sym.info))
+ }
+}
diff --git a/sources/scala/tools/nsc/Main.scala b/sources/scala/tools/nsc/Main.scala
new file mode 100755
index 0000000000..8265c58843
--- /dev/null
+++ b/sources/scala/tools/nsc/Main.scala
@@ -0,0 +1,48 @@
+package scala.tools.nsc;
+
+import scala.tools.util.{Position, Reporter, ConsoleReporter}
+
+/** The main class for NSC, a compiler for the programming
+ * language Scala.
+ */
+object Main {
+
+ val PRODUCT: String =
+ System.getProperty("scala.product", "scalac");
+ val VERSION: String =
+ System.getProperty("scala.version", "unknown version");
+ val versionMsg = PRODUCT + " " + VERSION + " -- (c) 2002-04 LAMP/EPFL";
+
+ private var reporter: Reporter = _;
+
+ def error(msg: String): unit =
+ reporter.error(new Position(PRODUCT),
+ msg + "\n " + PRODUCT + " -help gives more information");
+
+ def process(args: Array[String]): unit = {
+ reporter = new ConsoleReporter();
+ val command = new CompilerCommand(args, error);
+ reporter.prompt(command.settings.prompt.value);
+ if (command.settings.version.value)
+ reporter.info(null, versionMsg, true)
+ else if (command.settings.help.value || command.files.isEmpty)
+ reporter.info(null, command.usageMsg, true)
+ else {
+ try {
+ val compiler = new Global(command.settings, reporter);
+ compiler.compile(command.files);
+ } catch {
+ case ex @ FatalError(msg) =>
+ if (command.settings.debug.value)
+ ex.printStackTrace();
+ System.out.println("fatal error: " + msg);
+ }
+ reporter.printSummary
+ }
+ }
+
+ def main(args: Array[String]): unit = {
+ process(args);
+ System.exit(if (reporter.errors() > 0) 1 else 0);
+ }
+}
diff --git a/sources/scala/tools/nsc/NoPhase.scala b/sources/scala/tools/nsc/NoPhase.scala
new file mode 100644
index 0000000000..f9685f8010
--- /dev/null
+++ b/sources/scala/tools/nsc/NoPhase.scala
@@ -0,0 +1,6 @@
+package scala.tools.nsc;
+
+object NoPhase extends Phase(null) {
+ def name = "<no phase>";
+ def run: unit = throw new Error("NoPhase.run");
+}
diff --git a/sources/scala/tools/nsc/Phase.scala b/sources/scala/tools/nsc/Phase.scala
new file mode 100644
index 0000000000..cd6034d29e
--- /dev/null
+++ b/sources/scala/tools/nsc/Phase.scala
@@ -0,0 +1,26 @@
+package scala.tools.nsc;
+
+abstract class Phase(val prev: Phase) {
+ val id: int = if (prev == null) 0 else prev.id + 1;
+
+ private var nx: Phase = NoPhase;
+ if (prev != null) prev.nx = this;
+
+ def next: Phase = nx;
+
+ def name: String;
+ def description: String = name;
+
+ val flagMask: long = if (prev == null) 0L else prev.flagMask;
+ def exactMatch: boolean = false;
+
+ def run: unit;
+
+ override def toString() = name;
+
+ // def check(units: List[CompilationUnit]): unit =
+ // for (val unit <- units; val checker <- checkers) checker.traverse(unit); // def checkers: List[Checker] = List();
+
+}
+
+
diff --git a/sources/scala/tools/nsc/Settings.scala b/sources/scala/tools/nsc/Settings.scala
new file mode 100644
index 0000000000..7820f0adcb
--- /dev/null
+++ b/sources/scala/tools/nsc/Settings.scala
@@ -0,0 +1,155 @@
+package scala.tools.nsc;
+
+class Settings(error: String => unit) {
+
+ private var allsettings: List[Setting] = List();
+
+ val debuginfo = BooleanSetting("-g", "Generate debugging info");
+ val nowarnings = BooleanSetting("-nowarn", "Generate no warnings");
+ val verbose = BooleanSetting("-verbose", "Output messages about what the compiler is doing");
+ val classpath = StringSetting ("-classpath", "path", "Specify where to find user class files",
+ System.getProperty("scala.class.path",
+ System.getProperty("java.class.path", ".")));
+ val sourcepath = StringSetting ("-sourcepath", "path", "Specify where to find input source files",
+ System.getProperty("scala.source.path",
+ System.getProperty("java.source.path", ".")));
+ val bootclasspath = StringSetting ("-bootclasspath", "path", "Override location of bootstrap class files",
+ System.getProperty("sun.boot.class.path", ""));
+ val extdirs = StringSetting ("-extdirs", "dirs", "Override location of installed extensions",
+ System.getProperty("java.ext.dirs", ""));
+ val outdir = StringSetting ("-d", "directory", "Specify where to place generated class files", ".");
+ val encoding = StringSetting ("-encoding", "encoding", "Specify character encoding used by source files", "ISO-8859-1");
+ val separate = ChoiceSetting ("-separate", "Read symbol files for separate compilation", List("yes","no"), "default");
+ val target = ChoiceSetting ("-target", "Specify which backend to use", List("jvm", "msil"), "jvm");
+ val debug = BooleanSetting("-debug", "Output debugging messages");
+ val explaintypes = BooleanSetting("-explaintypes", "Explain type errors in more detail");
+ val uniqid = BooleanSetting("-uniqid", "Print identifiers with unique names (debugging option)");
+ val printtypes = BooleanSetting("-printtypes", "Print tree types (debugging option)");
+ val prompt = BooleanSetting("-prompt", "Display a prompt after each error (debugging option)");
+ val noimports = BooleanSetting("-noimports", "Compile without any implicit imports");
+ val nopredefs = BooleanSetting("-nopredefs", "Compile without any implicit predefined values");
+ val skip = PhasesSetting ("-skip", "Skip");
+ val check = PhasesSetting ("-check", "Check the tree after");
+ val print = PhasesSetting ("-print", "Print out program after");
+ val printer = ChoiceSetting ("-printer", "Printer to use", List("text", "html"), "text");
+ val printfile = StringSetting ("-printfile", "file", "Specify file in which to print trees", "-");
+ val graph = PhasesSetting ("-graph", "Graph the program after");
+ val stop = PhasesSetting ("-stop", "Stop after first phase in");
+ val log = PhasesSetting ("-log", "Log operations in");
+ val version = BooleanSetting("-version", "Print product version and exit");
+ val help = BooleanSetting("-help", "Print a synopsis of standard options");
+
+ val Xshowcls = StringSetting ("-Xshowcls", "class", "Show class info", "");
+ val Xshowobj = StringSetting ("-Xshowobj", "object", "Show object info", "");
+
+ /** A list of all settings */
+ def allSettings: List[Setting] = allsettings.reverse;
+
+ /** A base class for settings of all types.
+ * Subclasses each define a `value' field of the appropriate type.
+ */
+ abstract class Setting(name: String, descr: String) {
+
+ /** If first arg defines this setting, consume it as well as all following
+ * args needed to define the setting. If this can be done without
+ * error, set value field and return suffix of args else
+ * issue error message and return empty.
+ * If first arg does not define this setting return args unchanged.
+ */
+ def tryToSet(args: List[String]): List[String];
+
+ /** The syntax defining this setting in a help string */
+ def helpSyntax: String = name;
+
+ /** A description of the purpose of this setting in a help string */
+ def helpDescription = descr;
+
+ // initialization
+ allsettings = this :: allsettings;
+ }
+
+ /** A setting represented by a boolean flag (false, unless set */
+ case class BooleanSetting(name: String, descr: String)
+ extends Setting(name, descr) {
+ var value: boolean = false;
+
+ def tryToSet(args: List[String]): List[String] = args match {
+ case n :: rest if (n == name) => value = true; rest
+ case _ => args
+ }
+ }
+
+ /** A setting represented by a string, (`default' unless set) */
+ case class StringSetting(name: String, arg: String, descr: String, default: String)
+ extends Setting(name, descr) {
+ var value: String = default;
+
+ def tryToSet(args: List[String]): List[String] = args match {
+ case n :: rest if (n == name) =>
+ if (rest.isEmpty) {
+ error("missing argument");
+ List()
+ } else {
+ value = rest.head;
+ rest.tail
+ }
+ case _ => args
+ }
+
+ override def helpSyntax = name + " <" + arg + ">";
+ }
+
+ /** A setting represented by a string in a given set of `choices',
+ * (`default' unless set)
+ */
+ case class ChoiceSetting(name: String, descr: String, choices: List[String], default: String)
+ extends Setting(name, descr + choices.mkString(" (", ",", ")")) {
+ var value: String = default;
+
+ private def argument: String = name.substring(1);
+
+ def tryToSet(args: List[String]): List[String] = args match {
+ case n :: rest if (n startsWith (name + ":")) =>
+ val choice = n.substring(name.length() + 1);
+ if (!(choices contains choice)) {
+ error(
+ if (choice == "") "missing " + argument
+ else "unknown " + argument + " '" + choice + "'");
+ List()
+ } else {
+ value = choice;
+ rest
+ }
+ case _ => args
+ }
+
+ override def helpSyntax = name + ":<" + argument + ">";
+ }
+
+ /** A setting represented by a list of strings which should be prefixes of
+ * phase names. This is not checked here, however.
+ * (the empty list, unless set)
+ */
+ case class PhasesSetting(name: String, descr: String)
+ extends Setting(name, descr + " <phases> (see below)") {
+ var value: List[String] = List();
+
+ def tryToSet(args: List[String]): List[String] = args match {
+ case n :: rest if (n startsWith (name + ":")) =>
+ val phase = n.substring(name.length() + 1);
+ if (phase == "") {
+ error("missing phase");
+ List()
+ } else {
+ value = value ::: List(phase);
+ rest
+ }
+ case _ => args
+ }
+
+ override def helpSyntax = name + ":<phases>";
+
+ def contains(phasename: String): boolean =
+ value exists (str => phasename startsWith str)
+ }
+}
diff --git a/sources/scala/tools/nsc/StdPhase.scala b/sources/scala/tools/nsc/StdPhase.scala
new file mode 100644
index 0000000000..46f4d296f4
--- /dev/null
+++ b/sources/scala/tools/nsc/StdPhase.scala
@@ -0,0 +1,10 @@
+package scala.tools.nsc;
+
+abstract class StdPhase(prev: Phase) extends Phase(prev) {
+ val global: Global;
+ def run: unit =
+ for (val unit <- global.units) apply(unit);
+ def apply(unit: global.CompilationUnit): unit;
+}
+
+
diff --git a/sources/scala/tools/nsc/ast/TreeInfo.scala b/sources/scala/tools/nsc/ast/TreeInfo.scala
new file mode 100644
index 0000000000..9b79027abc
--- /dev/null
+++ b/sources/scala/tools/nsc/ast/TreeInfo.scala
@@ -0,0 +1,136 @@
+package scala.tools.nsc.ast;
+
+import symtab.Flags._;
+
+abstract class TreeInfo {
+
+ val global: Global;
+ import global._;
+
+ def isTerm(tree: Tree): boolean = tree.isTerm;
+ def isType(tree: Tree): boolean = tree.isType;
+
+ def isOwnerDefinition(tree: Tree): boolean = tree match {
+ case PackageDef(_, _)
+ | ClassDef(_, _, _, _, _, _)
+ | ModuleDef(_, _, _, _)
+ | DefDef(_, _, _, _, _, _)
+ | Import(_, _) => true
+ case _ => false
+ }
+
+ def isDefinition(tree: Tree): boolean = tree.isDef;
+
+ def isDeclaration(tree: Tree): boolean = tree match {
+ case DefDef(_, _, _, _, _, EmptyTree)
+ | ValDef(_, _, _, EmptyTree)
+ | AbsTypeDef(_, _, _, _, _)
+ | AliasTypeDef(_, _, _, _) => true
+ case _ => false
+ }
+
+ /** Is tree a pure definition?
+ */
+ def isPureDef(tree: Tree): boolean = tree match {
+ case EmptyTree
+ | ClassDef(_, _, _, _, _, _)
+ | ModuleDef(_, _, _, _)
+ | AbsTypeDef(_, _, _, _, _)
+ | AliasTypeDef(_, _, _, _)
+ | Import(_, _)
+ | DefDef(_, nme.CONSTRUCTOR, _, _, _, _) =>
+ true
+ case ValDef(mods, _, _, rhs) =>
+ (mods & MUTABLE) == 0 && isPureExpr(rhs)
+ case DocDef(_, definition) =>
+ isPureDef(definition)
+ case _ =>
+ false
+ }
+
+ /** Is tree a stable & pure expression?
+ */
+ def isPureExpr(tree: Tree): boolean = tree match {
+ case EmptyTree
+ | This(_)
+ | Super(_, _)
+ | Literal(_) =>
+ true
+ case Ident(_) =>
+ tree.symbol.isStable
+ case Select(qual, _) =>
+ tree.symbol.isStable && isPureExpr(qual)
+ case TypeApply(fn, _) =>
+ isPureExpr(fn)
+ case Apply(fn, List()) =>
+ isPureExpr(fn)
+ case Typed(expr, _) =>
+ isPureExpr(expr)
+ case _ =>
+ false
+ }
+
+ /** Is tree a pure constructor?
+ */
+ def isPureConstr(tree: Tree): boolean = tree match {
+ case Ident(_)
+ | Select(_, _) =>
+ tree.symbol != null && tree.symbol.isPrimaryConstructor;
+ case TypeApply(fn, _) =>
+ isPureConstr(fn)
+ case Apply(fn, List()) =>
+ isPureConstr(fn)
+ case _ =>
+ false
+ }
+
+ /** Is tree a self constructor call?
+ */
+ def isSelfConstrCall(tree: Tree): boolean = tree match {
+ case Ident(nme.CONSTRUCTOR) =>
+ true
+ case TypeApply(constr, _) =>
+ isSelfConstrCall(constr)
+ case Apply(constr, _) =>
+ isSelfConstrCall(constr)
+ case _ =>
+ false
+ }
+
+ /** Is tree a variable pattern */
+ def isVarPattern(pat: Tree): boolean = pat match {
+ case Ident(name) => isVariableName(name)
+ case _ => false
+ }
+
+ /** Is name a variable name */
+ def isVariableName(name: Name): boolean = {
+ val first = name(0);
+ (('a' <= first && first <= 'z') || first == '_')
+ && name != nme.false_
+ && name != nme.true_
+ && name != nme.null_
+ }
+
+ /** Is tree a this node which belongs to `enclClass'? */
+ def isSelf(tree: Tree, enclClass: Symbol): boolean = tree match {
+ case This(_) => tree.symbol == enclClass
+ case _ => false
+ }
+
+ /** The method symbol of an application node, or NoSymbol, if none exists.
+ */
+ def methSymbol(tree: Tree): Symbol = {
+ val meth = methPart(tree);
+ if (meth.hasSymbol) meth.symbol else NoSymbol
+ }
+
+ /** The method part of an application node
+ */
+ def methPart(tree: Tree): Tree = tree match {
+ case Apply(fn, _) => methPart(fn)
+ case TypeApply(fn, _) => methPart(fn)
+ case AppliedTypeTree(fn, _) => methPart(fn)
+ case _ => tree
+ }
+}
diff --git a/sources/scala/tools/nsc/ast/TreePrinters.scala b/sources/scala/tools/nsc/ast/TreePrinters.scala
new file mode 100644
index 0000000000..329bed60d7
--- /dev/null
+++ b/sources/scala/tools/nsc/ast/TreePrinters.scala
@@ -0,0 +1,293 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+\* */
+
+// $Id: TreePrinter.scala
+
+package scala.tools.nsc.ast;
+
+import java.io._;
+import symtab.Flags._;
+
+abstract class TreePrinters {
+
+ val global: Global;
+ import global._;
+
+ class TreePrinter(out: PrintWriter) {
+ protected var indentMargin = 0;
+ protected val indentStep = 2;
+ protected var indentString = " ";
+
+ def flush = out.flush();
+
+ def indent = indentMargin = indentMargin + indentStep;
+ def undent = indentMargin = indentMargin - indentStep;
+
+ def println = {
+ out.println();
+ while (indentMargin > indentString.length())
+ indentString = indentString + indentString;
+ if (indentMargin > 0)
+ out.write(indentString, 0, indentMargin);
+ }
+
+ def printSeq[a](ls: List[a])(printelem: a => unit)(printsep: => unit): unit = ls match {
+ case List() =>
+ case List(x) => printelem(x)
+ case x :: rest => printelem(x); printsep; printSeq(rest)(printelem)(printsep)
+ }
+
+ def printColumn(ts: List[Tree], start: String, sep: String, end: String): unit = {
+ print(start); indent; println;
+ printSeq(ts){print}{print(sep); println}; undent; println; print(end)
+ }
+
+ def printRow(ts: List[Tree], start: String, sep: String, end: String): unit = {
+ print(start); printSeq(ts){print}{print(sep)}; print(end)
+ }
+
+ def printRow(ts: List[Tree], sep: String): unit = printRow(ts, "", sep, "");
+
+ def printTypeParams(ts: List[AbsTypeDef]): unit =
+ if (!ts.isEmpty) {
+ print("["); printSeq(ts){printParam}{print(", ")}; print("]")
+ }
+
+ def printValueParams(ts: List[ValDef]): unit =
+ if (!ts.isEmpty) {
+ print("("); printSeq(ts){printParam}{print(", ")}; print(")")
+ }
+
+ def printParam(tree: Tree): unit = tree match {
+ case ValDef(mods, name, tp, rhs) =>
+ if ((mods & PARAMACCESSOR) != 0) {
+ print(tree)
+ } else {
+ print(symName(tree, name)); printOpt(": ", tp);
+ }
+ case AbsTypeDef(mods, name, lo, hi, vu) =>
+ print(symName(tree, name));
+ printOpt(">: ", lo); printOpt("<: ", hi); printOpt("<% ", vu)
+ }
+
+ def symName(tree: Tree, name: Name): String =
+ if (tree.symbol != null && tree.symbol != NoSymbol) tree.symbol.nameString
+ else name.toString();
+
+ def printOpt(prefix: String, tree: Tree): unit =
+ if (tree != EmptyTree) { print(prefix); print(tree) }
+
+ def printModifiers(flags: int): unit = {
+ val s = flagsToString(flags);
+ if (s.length() != 0) print(s + " ")
+ }
+
+ def print(str: String): unit = out.print(str);
+ def print(name: Name): unit = print(name.toString());
+
+ def print(tree: Tree): unit = {
+ tree match {
+ case EmptyTree =>
+ print("<empty>");
+
+ case ClassDef(mods, name, tparams, vparams, tp, impl) =>
+ printModifiers(mods); print("class " + symName(tree, name));
+ printTypeParams(tparams); vparams foreach printValueParams;
+ printOpt(": ", tp); print(" extends "); print(impl);
+
+ case PackageDef(packaged, stats) =>
+ print("package "); print(packaged); printColumn(stats, " {", ";", "}")
+
+ case ModuleDef(mods, name, tpe, impl) =>
+ printModifiers(mods); print("object " + symName(tree, name));
+ printOpt(": ", tpe); print(" extends "); print(impl);
+
+ case ValDef(mods, name, tp, rhs) =>
+ printModifiers(mods);
+ print(if ((mods & MUTABLE) != 0) "var " else "val ");
+ print(symName(tree, name));
+ printOpt(": ", tp);
+ if ((mods & DEFERRED) == 0) {
+ print(" = ");
+ if (rhs == EmptyTree) print("_") else print(rhs)
+ }
+
+ case DefDef(mods, name, tparams, vparams, tp, rhs) =>
+ printModifiers(mods);
+ print("def " + (if (name == nme.CONSTRUCTOR) "this" else symName(tree, name)));
+ printTypeParams(tparams); vparams foreach printValueParams;
+ printOpt(": ", tp); printOpt(" = ", rhs);
+
+ case AbsTypeDef(mods, name, lo, hi, vu) =>
+ printModifiers(mods); print("type "); printParam(tree);
+
+ case AliasTypeDef(mods, name, tparams, rhs) =>
+ printModifiers(mods); print("type " + symName(tree, name));
+ printTypeParams(tparams); printOpt(" = ", rhs);
+
+ case LabelDef(name, params, rhs) =>
+ print(symName(tree, name)); printRow(params, "(", ",", ")"); print(rhs);
+
+ case Import(expr, selectors) =>
+ def printSelectors(ss: List[Name]): unit = ss match {
+ case List() =>
+ case List(s) => print(s.toString());
+ case s1 :: s2 :: ss1 =>
+ print(s1);
+ if (s1 != s2) print("=>" + s2);
+ printSelectors(ss1);
+ }
+ print("import "); print(expr); print(".{"); printSelectors(selectors); print("}");
+
+ case PatDef(mods, pat, rhs) =>
+ print(flagsToString(mods) + " val "); print(pat); printOpt(" = ", rhs);
+
+ case Attributed(attr, definition) =>
+ print("["); print(attr); print("]"); println; print(definition);
+
+ case DocDef(comment, definition) =>
+ print(comment); println; print(definition);
+
+ case Template(parents, body) =>
+ printRow(parents, " with "); printColumn(body, " {", ";", "}");
+
+ case Block(stats, expr) =>
+ printColumn(stats ::: List(expr), "{", ";", "}")
+
+ case Visitor(cases) =>
+ printColumn(cases, "{", "", "}");
+
+ case CaseDef(pat, guard, body) =>
+ print("case "); print(pat); printOpt(" if ", guard);
+ print(" => "); print(body)
+
+ case Sequence(trees) =>
+ printRow(trees, "[", ", ", "]")
+
+ case Alternative(trees) =>
+ printRow(trees, "(", "| ", ")")
+
+ case Bind(name, t) =>
+ print(symName(tree, name)); print(" @ "); print(t)
+
+ case Function(vparams, body) =>
+ print("("); printValueParams(vparams); print(" => "); print(body); print(")")
+
+ case Assign(lhs, rhs) =>
+ print(lhs); print(" = "); print(rhs)
+
+ case For(enumerators, body, isForYield) =>
+ printRow(enumerators, "for(", "; ", ") ");
+ if (isForYield) print("yield ");
+ print(body)
+
+ case If(cond, thenp, elsep) =>
+ print("if ("); print(cond); print(")"); indent; println;
+ print(thenp); undent;
+ if (elsep != EmptyTree) {
+ println; print("else"); indent; println; print(elsep); undent
+ }
+
+ case Switch(expr, tags, bodies, defaultBody) =>
+ print("<switch> ("); print(expr); print(") {"); indent;
+ printSeq(tags zip bodies)
+ {case Pair(tag, body) => print("case " + tag + " => "); print(body)} {println}
+ print("<default> => "); print(defaultBody); print(" }"); undent
+
+ case Return(expr) =>
+ print("return "); print(expr)
+
+ case Try(block, catcher, finalizer) =>
+ print("try "); print(block); print(" catch "); print(catcher);
+ print(" finally "); print(finalizer)
+
+ case Throw(expr) =>
+ print("throw "); print(expr)
+
+ case New(init) =>
+ print("new "); print(init)
+
+ case Typed(expr, tp) =>
+ print("("); print(expr); print(") : "); print(tp);
+
+ case TypeApply(fun, targs) =>
+ print(fun); printRow(targs, "[", ", ", "]");
+
+ case Apply(fun, vargs) =>
+ print(fun); printRow(vargs, "(", ", ", ")");
+
+ case Super(qual, mixin) =>
+ if (qual != nme.EMPTY.toTypeName) print(symName(tree, qual) + ".");
+ print("super");
+ if (mixin != nme.EMPTY.toTypeName) print("[" + mixin + "]")
+
+ case This(qual) =>
+ if (qual != nme.EMPTY.toTypeName) print(symName(tree, qual) + ".");
+ print("this");
+
+ case Select(qualifier, name) =>
+ if (global.settings.debug.value || qualifier.symbol == null || !qualifier.symbol.isRoot) {
+ print(qualifier); print(".");
+ }
+ print(symName(tree, name))
+
+ case Ident(name) =>
+ print(symName(tree, name))
+
+ case Literal(obj) =>
+ print(obj match {
+ case null => "null"
+ case s: String => "\"" + s + "\""
+ case _ => obj.toString()
+ })
+
+ case GeneralTypeTree() =>
+ print(tree.tpe.toString());
+
+ case SingletonTypeTree(ref) =>
+ print(ref); print(".type")
+
+ case SelectFromTypeTree(qualifier, selector) =>
+ print(qualifier); print("#"); print(symName(tree, selector))
+
+ case FunctionTypeTree(argtpes, restpe) =>
+ printRow(argtpes, "(", ", ", ") => "); print(restpe)
+
+ case IntersectionTypeTree(parents) =>
+ printRow(parents, " with ")
+
+ case RefinementTypeTree(base, members) =>
+ print(base); printColumn(members, "{", ";", "}")
+
+ case AppliedTypeTree(tp, args) =>
+ print(tp); printRow(args, "[", ", ", "]")
+ }
+ if (global.settings.printtypes.value && tree.isTerm && tree != EmptyTree) {
+ print("{"); print(if (tree.tpe == null) "<null>" else tree.tpe.toString()); print("}")
+ }
+ }
+
+ def print(unit: CompilationUnit): unit = {
+ print("// Scala source: " + unit.source + "\n");
+ if (unit.body != null) {
+ unit.body foreach { tree => print(tree); print(";"); println }
+ } else {
+ print("<null>")
+ }
+ println; flush
+ }
+
+ def printAll(): unit = {
+ print("[[syntax trees at end of " + phase + "]]");
+ for (val unit <- global.units) print(unit)
+ }
+ }
+
+ def create(writer: PrintWriter): TreePrinter = new TreePrinter(writer);
+ def create(stream: OutputStream): TreePrinter = create(new PrintWriter(stream));
+ def create(): TreePrinter = create(System.out);
+}
diff --git a/sources/scala/tools/nsc/ast/Trees.scala b/sources/scala/tools/nsc/ast/Trees.scala
new file mode 100644
index 0000000000..4cfa348e77
--- /dev/null
+++ b/sources/scala/tools/nsc/ast/Trees.scala
@@ -0,0 +1,865 @@
+package scala.tools.nsc.ast;
+
+import java.io.StringWriter;
+import java.io.PrintWriter;
+import scala.tools.util.Position;
+
+class Trees: Global {
+
+ abstract class Tree {
+
+ var pos: int = Position.NOPOS;
+ var tpe: Type = _;
+
+ def setPos(p: int): Tree = { pos = p; this }
+ def setType(tp: Type): Tree = { tpe = tp; this }
+
+ def symbol: Symbol = null;
+ def symbol_=(sym: Symbol): unit =
+ throw new Error("symbol_= inapplicable for " + this);
+ def setSymbol(sym: Symbol): Tree = { symbol = sym; this }
+
+ def hasSymbol = false;
+ def isDef = false;
+ def isTerm = false;
+ def isType = false;
+
+ override def toString(): String = {
+ val buffer = new StringWriter();
+ val printer = treePrinters.create(new PrintWriter(buffer));
+ printer.print(this); printer.flush;
+ buffer.toString()
+ }
+
+ def duplicate: Tree =
+ new Transformer(new StrictTreeCopier) transform this;
+ }
+
+ abstract class SymTree extends Tree {
+ override def hasSymbol = true;
+ override var symbol: Symbol = NoSymbol;
+ }
+
+ abstract class DefTree extends SymTree {
+ override def isDef = true;
+ }
+
+ abstract class TermTree extends Tree {
+ override def isTerm = true;
+ }
+
+ abstract class TypeTree extends Tree {
+ override def isType = true;
+ }
+
+ /** The empty tree */
+ case object EmptyTree extends Tree {
+ tpe = NoType;
+ override def isType = true;
+ override def isTerm = true;
+ }
+
+ /** Class definition */
+ case class ClassDef(mods: int, name: Name, tparams: List[AbsTypeDef],
+ vparams: List[List[ValDef]], tp: Tree, impl: Template)
+ extends DefTree;
+
+ /** Package clause */
+ case class PackageDef(pkg: Tree, stats: List[Tree])
+ extends DefTree;
+
+ /** Singleton object definition */
+ case class ModuleDef(mods: int, name: Name, tp: Tree, impl: Template)
+ extends DefTree;
+
+ /** Value definition */
+ case class ValDef(mods: int, name: Name, tp: Tree, rhs: Tree)
+ extends DefTree;
+
+ /** Method definition */
+ case class DefDef(mods: int, name: Name, tparams: List[AbsTypeDef],
+ vparams: List[List[ValDef]], tp: Tree, rhs: Tree)
+ extends DefTree;
+
+ /** Abstract type or type parameter */
+ case class AbsTypeDef(mods: int, name: Name, lo: Tree, hi: Tree, vu: Tree)
+ extends DefTree;
+
+ /** Type alias */
+ case class AliasTypeDef(mods: int, name: Name, tparams: List[AbsTypeDef],
+ rhs: Tree)
+ extends DefTree;
+
+ /** Labelled expression - the symbols in the array (must be Idents!)
+ * are those the label takes as argument */
+ case class LabelDef(name: Name, params: List[Ident], rhs: Tree)
+ extends DefTree with TermTree;
+
+ /** Import clause */
+ case class Import(expr: Tree, selectors: List[Name])
+ extends SymTree;
+
+ /** Pattern definition, eliminated by Analyzer */
+ case class PatDef(mods: int, pat: Tree, rhs: Tree)
+ extends Tree;
+
+ /** Attribuetd definition */
+ case class Attributed(attribute: Tree, definition: Tree)
+ extends Tree;
+
+ /** Documented definition, eliminated by analyzer */
+ case class DocDef(comment: String, definition: Tree)
+ extends Tree;
+
+ /** Instantiation template */
+ case class Template(parents: List[Tree], body: List[Tree])
+ extends SymTree;
+
+ /** Block of expressions (semicolon separated expressions) */
+ case class Block(stats: List[Tree], expr: Tree)
+ extends TermTree;
+
+ /** Visitor (a sequence of cases), eliminated by TransMatch */
+ case class Visitor(cases: List[CaseDef])
+ extends TermTree;
+
+ /** Case clause in a pattern match, eliminated by TransMatch */
+ case class CaseDef(pat: Tree, guard: Tree, body: Tree)
+ extends Tree;
+
+ /** Sequence of expression/patterns (comma separated expressions),
+ * eliminated by TransMatch */
+ case class Sequence(trees: List[Tree])
+ extends TermTree;
+
+ /** Alternatives of patterns, eliminated by TransMatch */
+ case class Alternative(trees: List[Tree])
+ extends TermTree;
+
+ /** Bind of a variable to a rhs pattern, eliminated by TransMatch */
+ case class Bind(name: Name, rhs: Tree)
+ extends TermTree;
+
+ /** Anonymous function, eliminated by analyzer */
+ case class Function(vparams: List[ValDef], body: Tree)
+ extends TermTree;
+
+ /** Assignment */
+ case class Assign(lhs: Tree, rhs: Tree)
+ extends TermTree;
+
+ /** Conditional expression */
+ case class If(cond: Tree, thenp: Tree, elsep: Tree)
+ extends TermTree;
+
+ /** For comprehension */
+ case class For(enumerators: List[Tree], body: Tree, isForYield: boolean)
+ extends TermTree;
+
+ /** Switch, introduced by refcheck */
+ case class Switch(test: Tree, tags: List[int], bodies: List[Tree],
+ default: Tree)
+ extends TermTree;
+
+ /** Return expression */
+ case class Return(expr: Tree)
+ extends TermTree;
+
+ case class Try(block: Tree, catcher: Tree, finalizer: Tree)
+ extends TermTree;
+
+ /** Throw expression */
+ case class Throw(expr: Tree)
+ extends TermTree;
+
+ /** Object instantiation
+ * @param init either a constructor or a template
+ */
+ case class New(init: Tree)
+ extends TermTree;
+
+ /** Type annotation, eliminated by explicit outer */
+ case class Typed(expr: Tree, tp: Tree)
+ extends TermTree;
+
+ /** Type application */
+ case class TypeApply(fun: Tree, args: List[Tree])
+ extends TermTree;
+
+ /** Value application */
+ case class Apply(fun: Tree, args: List[Tree])
+ extends TermTree;
+
+ /** Super reference */
+ case class Super(qual: Name, mixin: Name)
+ extends TermTree with SymTree;
+
+ /** Self reference */
+ case class This(qual: Name)
+ extends TermTree with SymTree;
+
+ /** Designator */
+ case class Select(qualifier: Tree, selector: Name)
+ extends SymTree {
+ override def isTerm = selector.isTermName;
+ override def isType = selector.isTypeName;
+ }
+
+ /** Identifier */
+ case class Ident(name: Name)
+ extends SymTree {
+ override def isTerm = name.isTermName;
+ override def isType = name.isTypeName;
+ }
+
+ /** Literal */
+ case class Literal(value: Any)
+ extends TermTree;
+
+ /** General type term, introduced by RefCheck. */
+ case class GeneralTypeTree()
+ extends TypeTree;
+
+ /** Singleton type, eliminated by RefCheck */
+ case class SingletonTypeTree(ref: Tree)
+ extends TypeTree;
+
+ /** Type selection, eliminated by RefCheck */
+ case class SelectFromTypeTree(qualifier: Tree, selector: Name)
+ extends TypeTree with SymTree;
+
+ /** Function type, eliminated by RefCheck */
+ case class FunctionTypeTree(argtpes: List[Tree], restpe: Tree)
+ extends TypeTree;
+
+ /** Intersection type, eliminated by RefCheck */
+ case class IntersectionTypeTree(parents: List[Tree])
+ extends TypeTree;
+
+ /** Refinement type, eliminated by RefCheck */
+ case class RefinementTypeTree(base: Tree, members: List[Tree])
+ extends TypeTree;
+
+ /** Applied type, eliminated by RefCheck */
+ case class AppliedTypeTree(tp: Tree, args: List[Tree])
+ extends TypeTree;
+
+/* A standard pattern match
+ case EmptyTree =>
+ case ClassDef(mods, name, tparams, vparams, tp, impl) =>
+ case PackageDef(pkg, stats) =>
+ case ModuleDef(mods, name, tp, impl) =>
+ case ValDef(mods, name, tp, rhs) =>
+ case DefDef(mods, name, tparams, vparams, tp, rhs) =>
+ case AbsTypeDef(mods, name, lo, hi, vu) =>
+ case AliasTypeDef(mods, name, tparams, rhs) =>
+ case LabelDef(name, params, rhs) =>
+ case Import(expr, selectors) =>
+ case PatDef(mods, pat, rhs) =>
+ case Attributed(attribute, definition) =>
+ case DocDef(comment, definition) =>
+ case Template(parents, body) =>
+ case Block(stats, expr) =>
+ case Visitor(cases) =>
+ case CaseDef(pat, guard, body) =>
+ case Sequence(trees) =>
+ case Alternative(trees) =>
+ case Bind(name, rhs) =>
+ case Function(vparams, body) =>
+ case Assign(lhs, rhs) =>
+ case For(enumerators, body, isForYield) =>
+ case If(cond, thenp, elsep) =>
+ case Switch(test, tags, bodies, default) =>
+ case Return(expr) =>
+ case Try(block, catcher, finalizer) =>
+ case Throw(expr) =>
+ case New(init) =>
+ case Typed(expr, tp) =>
+ case TypeApply(fun, args) =>
+ case Apply(fun, args) =>
+ case Super(qual, mixin) =>
+ case This(qual) =>
+ case Select(qualifier, selector) =>
+ case Ident(name) =>
+ case Literal(value) =>
+ case GeneralTypeTree() =>
+ case SingletonTypeTree(ref) =>
+ case SelectFromTypeTree(qualifier, selector) =>
+ case FunctionTypeTree(argtpes, restpe) =>
+ case IntersectionTypeTree(parents) =>
+ case RefinementTypeTree(base, members) =>
+ case AppliedTypeTree(tp, args) =>
+*/
+
+ trait TreeCopier {
+ def ClassDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], vparams: List[List[ValDef]], tp: Tree, impl: Template): ClassDef;
+ def PackageDef(tree: Tree, pkg: Tree, stats: List[Tree]): PackageDef;
+ def ModuleDef(tree: Tree, mods: int, name: Name, tp: Tree, impl: Template): ModuleDef;
+ def ValDef(tree: Tree, mods: int, name: Name, tp: Tree, rhs: Tree): ValDef;
+ def DefDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], vparams: List[List[ValDef]], tp: Tree, rhs: Tree): DefDef;
+ def AbsTypeDef(tree: Tree, mods: int, name: Name, lo: Tree, hi: Tree, vu: Tree): AbsTypeDef;
+ def AliasTypeDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], rhs: Tree): AliasTypeDef;
+ def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree): LabelDef;
+ def Import(tree: Tree, expr: Tree, selectors: List[Name]): Import;
+ def PatDef(tree: Tree, mods: int, pat: Tree, rhs: Tree): PatDef;
+ def Attributed(tree: Tree, attribute: Tree, definition: Tree): Attributed;
+ def DocDef(tree: Tree, comment: String, definition: Tree): DocDef;
+ def Template(tree: Tree, parents: List[Tree], body: List[Tree]): Template;
+ def Block(tree: Tree, stats: List[Tree], expr: Tree): Block;
+ def Visitor(tree: Tree, cases: List[CaseDef]): Visitor;
+ def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree): CaseDef;
+ def Sequence(tree: Tree, trees: List[Tree]): Sequence;
+ def Alternative(tree: Tree, trees: List[Tree]): Alternative;
+ def Bind(tree: Tree, name: Name, rhs: Tree): Bind;
+ def Function(tree: Tree, vparams: List[ValDef], body: Tree): Function;
+ def Assign(tree: Tree, lhs: Tree, rhs: Tree): Assign;
+ def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree): If;
+ def For(tree: Tree, enumerators: List[Tree], body: Tree, isForYield: boolean): For;
+ def Switch(tree: Tree, test: Tree, tags: List[int], bodies: List[Tree], default: Tree): Switch;
+ def Return(tree: Tree, expr: Tree): Return;
+ def Try(tree: Tree, block: Tree, catcher: Tree, finalizer: Tree): Try;
+ def Throw(tree: Tree, expr: Tree): Throw;
+ def New(tree: Tree, init: Tree): New;
+ def Typed(tree: Tree, expr: Tree, tp: Tree): Typed;
+ def TypeApply(tree: Tree, fun: Tree, args: List[Tree]): TypeApply;
+ def Apply(tree: Tree, fun: Tree, args: List[Tree]): Apply;
+ def Super(tree: Tree, qual: Name, mixin: Name): Super;
+ def This(tree: Tree, qual: Name): This;
+ def Select(tree: Tree, qualifier: Tree, selector: Name): Select;
+ def Ident(tree: Tree, name: Name): Ident;
+ def Literal(tree: Tree, value: Any): Literal;
+ def GeneralTypeTree(tree: Tree): GeneralTypeTree;
+ def SingletonTypeTree(tree: Tree, ref: Tree): SingletonTypeTree;
+ def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name): SelectFromTypeTree;
+ def FunctionTypeTree(tree: Tree, argtpes: List[Tree], restpe: Tree): FunctionTypeTree;
+ def IntersectionTypeTree(tree: Tree, parents: List[Tree]): IntersectionTypeTree;
+ def RefinementTypeTree(tree: Tree, base: Tree, members: List[Tree]): RefinementTypeTree;
+ def AppliedTypeTree(tree: Tree, tp: Tree, args: List[Tree]): AppliedTypeTree;
+ }
+
+ class StrictTreeCopier extends TreeCopier {
+ def ClassDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], vparams: List[List[ValDef]], tp: Tree, impl: Template) =
+ { val t = new ClassDef(mods, name, tparams, vparams, tp, impl); t.setPos(tree.pos); t }
+ def PackageDef(tree: Tree, pkg: Tree, stats: List[Tree]) =
+ { val t = new PackageDef(pkg, stats); t.setPos(tree.pos); t }
+ def ModuleDef(tree: Tree, mods: int, name: Name, tp: Tree, impl: Template) =
+ { val t = new ModuleDef(mods, name, tp, impl); t.setPos(tree.pos); t }
+ def ValDef(tree: Tree, mods: int, name: Name, tp: Tree, rhs: Tree) =
+ { val t = new ValDef(mods, name, tp, rhs); t.setPos(tree.pos); t }
+ def DefDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], vparams: List[List[ValDef]], tp: Tree, rhs: Tree) =
+ { val t = new DefDef(mods, name, tparams, vparams, tp, rhs); t.setPos(tree.pos); t }
+ def AbsTypeDef(tree: Tree, mods: int, name: Name, lo: Tree, hi: Tree, vu: Tree) =
+ { val t = new AbsTypeDef(mods, name, lo, hi, vu); t.setPos(tree.pos); t }
+ def AliasTypeDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], rhs: Tree) =
+ { val t = new AliasTypeDef(mods, name, tparams, rhs); t.setPos(tree.pos); t }
+ def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree) =
+ { val t = new LabelDef(name, params, rhs); t.setPos(tree.pos); t }
+ def Import(tree: Tree, expr: Tree, selectors: List[Name]) =
+ { val t = new Import(expr, selectors); t.setPos(tree.pos); t }
+ def PatDef(tree: Tree, mods: int, pat: Tree, rhs: Tree) =
+ { val t = new PatDef(mods, pat, rhs); t.setPos(tree.pos); t }
+ def Attributed(tree: Tree, attribute: Tree, definition: Tree) =
+ { val t = new Attributed(attribute, definition); t.setPos(tree.pos); t }
+ def DocDef(tree: Tree, comment: String, definition: Tree) =
+ { val t = new DocDef(comment, definition); t.setPos(tree.pos); t }
+ def Template(tree: Tree, parents: List[Tree], body: List[Tree]) =
+ { val t = new Template(parents, body); t.setPos(tree.pos); t }
+ def Block(tree: Tree, stats: List[Tree], expr: Tree) =
+ { val t = new Block(stats, expr); t.setPos(tree.pos); t }
+ def Visitor(tree: Tree, cases: List[CaseDef]) =
+ { val t = new Visitor(cases); t.setPos(tree.pos); t }
+ def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree) =
+ { val t = new CaseDef(pat, guard, body); t.setPos(tree.pos); t }
+ def Sequence(tree: Tree, trees: List[Tree]) =
+ { val t = new Sequence(trees); t.setPos(tree.pos); t }
+ def Alternative(tree: Tree, trees: List[Tree]) =
+ { val t = new Alternative(trees); t.setPos(tree.pos); t }
+ def Bind(tree: Tree, name: Name, rhs: Tree) =
+ { val t = new Bind(name, rhs); t.setPos(tree.pos); t }
+ def Function(tree: Tree, vparams: List[ValDef], body: Tree) =
+ { val t = new Function(vparams, body); t.setPos(tree.pos); t }
+ def Assign(tree: Tree, lhs: Tree, rhs: Tree) =
+ { val t = new Assign(lhs, rhs); t.setPos(tree.pos); t }
+ def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree) =
+ { val t = new If(cond, thenp, elsep); t.setPos(tree.pos); t }
+ def For(tree: Tree, enumerators: List[Tree], body: Tree, isForYield: boolean) =
+ { val t = new For(enumerators, body, isForYield); t.setPos(tree.pos); t }
+ def Switch(tree: Tree, test: Tree, tags: List[int], bodies: List[Tree], default: Tree) =
+ { val t = new Switch(test, tags, bodies, default); t.setPos(tree.pos); t }
+ def Return(tree: Tree, expr: Tree) =
+ { val t = new Return(expr); t.setPos(tree.pos); t }
+ def Try(tree: Tree, block: Tree, catcher: Tree, finalizer: Tree) =
+ { val t = new Try(block, catcher, finalizer); t.setPos(tree.pos); t }
+ def Throw(tree: Tree, expr: Tree) =
+ { val t = new Throw(expr); t.setPos(tree.pos); t }
+ def New(tree: Tree, init: Tree) =
+ { val t = new New(init); t.setPos(tree.pos); t }
+ def Typed(tree: Tree, expr: Tree, tp: Tree) =
+ { val t = new Typed(expr, tp); t.setPos(tree.pos); t }
+ def TypeApply(tree: Tree, fun: Tree, args: List[Tree]) =
+ { val t = new TypeApply(fun, args); t.setPos(tree.pos); t }
+ def Apply(tree: Tree, fun: Tree, args: List[Tree]) =
+ { val t = new Apply(fun, args); t.setPos(tree.pos); t }
+ def Super(tree: Tree, qual: Name, mixin: Name) =
+ { val t = new Super(qual, mixin); t.setPos(tree.pos); t }
+ def This(tree: Tree, qual: Name) =
+ { val t = new This(qual); t.setPos(tree.pos); t }
+ def Select(tree: Tree, qualifier: Tree, selector: Name) =
+ { val t = new Select(qualifier, selector); t.setPos(tree.pos); t }
+ def Ident(tree: Tree, name: Name) =
+ { val t = new Ident(name); t.setPos(tree.pos); t }
+ def Literal(tree: Tree, value: Any) =
+ { val t = new Literal(value); t.setPos(tree.pos); t }
+ def GeneralTypeTree(tree: Tree) =
+ { val t = new GeneralTypeTree(); t.setPos(tree.pos); t }
+ def SingletonTypeTree(tree: Tree, ref: Tree) =
+ { val t = new SingletonTypeTree(ref); t.setPos(tree.pos); t }
+ def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name) =
+ { val t = new SelectFromTypeTree(qualifier, selector); t.setPos(tree.pos); t }
+ def FunctionTypeTree(tree: Tree, argtpes: List[Tree], restpe: Tree) =
+ { val t = new FunctionTypeTree(argtpes, restpe); t.setPos(tree.pos); t }
+ def IntersectionTypeTree(tree: Tree, parents: List[Tree]) =
+ { val t = new IntersectionTypeTree(parents); t.setPos(tree.pos); t }
+ def RefinementTypeTree(tree: Tree, base: Tree, members: List[Tree]) =
+ { val t = new RefinementTypeTree(base, members); t.setPos(tree.pos); t }
+ def AppliedTypeTree(tree: Tree, tp: Tree, args: List[Tree]) =
+ { val t = new AppliedTypeTree(tp, args); t.setPos(tree.pos); t }
+ }
+
+ class LazyTreeCopier(copy: TreeCopier) extends TreeCopier {
+ def this() = this(new StrictTreeCopier);
+ def ClassDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], vparams: List[List[ValDef]], tp: Tree, impl: Template) = tree match {
+ case t @ ClassDef(mods0, name0, tparams0, vparams0, tp0, impl0)
+ if (mods0 == mods && name0 == name && tparams0 == tparams && vparams0 == vparams && tp0 == tp && impl0 == impl) => t
+ case _ => copy.ClassDef(tree, mods, name, tparams, vparams, tp, impl)
+ }
+ def PackageDef(tree: Tree, pkg: Tree, stats: List[Tree]) = tree match {
+ case t @ PackageDef(pkg0, stats0)
+ if (pkg0 == pkg && stats0 == stats) => t
+ case _ => copy.PackageDef(tree, pkg, stats)
+ }
+ def ModuleDef(tree: Tree, mods: int, name: Name, tp: Tree, impl: Template) = tree match {
+ case t @ ModuleDef(mods0, name0, tp0, impl0)
+ if (mods0 == mods && name0 == name && tp0 == tp && impl0 == impl) => t
+ case _ => copy.ModuleDef(tree, mods, name, tp, impl)
+ }
+ def ValDef(tree: Tree, mods: int, name: Name, tp: Tree, rhs: Tree) = tree match {
+ case t @ ValDef(mods0, name0, tp0, rhs0)
+ if (mods0 == mods && name0 == name && tp0 == tp && rhs0 == rhs) => t
+ case _ => copy.ValDef(tree, mods, name, tp, rhs)
+ }
+ def DefDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], vparams: List[List[ValDef]], tp: Tree, rhs: Tree) = tree match {
+ case t @ DefDef(mods0, name0, tparams0, vparams0, tp0, rhs0)
+ if (mods0 == mods && name0 == name && tparams0 == tparams && vparams0 == vparams && tp0 == tp && rhs == rhs0) => t
+ case _ => copy.DefDef(tree, mods, name, tparams, vparams, tp, rhs)
+ }
+ def AbsTypeDef(tree: Tree, mods: int, name: Name, lo: Tree, hi: Tree, vu: Tree) = tree match {
+ case t @ AbsTypeDef(mods0, name0, lo0, hi0, vu0)
+ if (mods0 == mods && name0 == name && lo0 == lo && hi0 == hi && vu0 == vu) => t
+ case _ => copy.AbsTypeDef(tree, mods, name, lo, hi, vu)
+ }
+ def AliasTypeDef(tree: Tree, mods: int, name: Name, tparams: List[AbsTypeDef], rhs: Tree) = tree match {
+ case t @ AliasTypeDef(mods0, name0, tparams0, rhs0)
+ if (mods0 == mods && name0 == name && tparams0 == tparams && rhs0 == rhs) => t
+ case _ => copy.AliasTypeDef(tree, mods, name, tparams, rhs)
+ }
+ def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree) = tree match {
+ case t @ LabelDef(name0, params0, rhs0)
+ if (name0 == name && params0 == params && rhs0 == rhs) => t
+ case _ => copy.LabelDef(tree, name, params, rhs)
+ }
+ def Import(tree: Tree, expr: Tree, selectors: List[Name]) = tree match {
+ case t @ Import(expr0, selectors0)
+ if (expr0 == expr && selectors0 == selectors) => t
+ case _ => copy.Import(tree, expr, selectors)
+ }
+ def PatDef(tree: Tree, mods: int, pat: Tree, rhs: Tree) = tree match {
+ case t @ PatDef(mods0, pat0, rhs0)
+ if (mods0 == mods && pat0 == pat && rhs0 == rhs) => t
+ case _ => copy.PatDef(tree, mods, pat, rhs)
+ }
+ def Attributed(tree: Tree, attribute: Tree, definition: Tree) = tree match {
+ case t @ Attributed(attribute0, definition0)
+ if (attribute0 == attribute && definition0 == definition) => t
+ case _ => copy.Attributed(tree, attribute, definition)
+ }
+ def DocDef(tree: Tree, comment: String, definition: Tree) = tree match {
+ case t @ DocDef(comment0, definition0)
+ if (comment0 == comment && definition0 == definition) => t
+ case _ => copy.DocDef(tree, comment, definition)
+ }
+ def Template(tree: Tree, parents: List[Tree], body: List[Tree]) = tree match {
+ case t @ Template(parents0, body0)
+ if (parents0 == parents && body0 == body) => t
+ case _ => copy.Template(tree, parents, body)
+ }
+ def Block(tree: Tree, stats: List[Tree], expr: Tree) = tree match {
+ case t @ Block(stats0, expr0)
+ if (stats0 == stats && expr0 == expr) => t
+ case _ => copy.Block(tree, stats, expr)
+ }
+ def Visitor(tree: Tree, cases: List[CaseDef]) = tree match {
+ case t @ Visitor(cases0)
+ if (cases == cases0) => t
+ case _ => copy.Visitor(tree, cases)
+ }
+ def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree) = tree match {
+ case t @ CaseDef(pat0, guard0, body0)
+ if (pat0 == pat && guard0 == guard && body0 == body) => t
+ case _ => copy.CaseDef(tree, pat, guard, body)
+ }
+ def Sequence(tree: Tree, trees: List[Tree]) = tree match {
+ case t @ Sequence(trees0)
+ if (trees0 == trees) => t
+ case _ => copy.Sequence(tree, trees)
+ }
+ def Alternative(tree: Tree, trees: List[Tree]) = tree match {
+ case t @ Alternative(trees0)
+ if (trees0 == trees) => t
+ case _ => copy.Alternative(tree, trees)
+ }
+ def Bind(tree: Tree, name: Name, rhs: Tree) = tree match {
+ case t @ Bind(name0, rhs0)
+ if (name0 == name && rhs0 == rhs) => t
+ case _ => copy.Bind(tree, name, rhs)
+ }
+ def Function(tree: Tree, vparams: List[ValDef], body: Tree) = tree match {
+ case t @ Function(vparams0, body0)
+ if (vparams0 == vparams && body0 == body) => t
+ case _ => copy.Function(tree, vparams, body)
+ }
+ def Assign(tree: Tree, lhs: Tree, rhs: Tree) = tree match {
+ case t @ Assign(lhs0, rhs0)
+ if (lhs0 == lhs && rhs0 == rhs) => t
+ case _ => copy.Assign(tree, lhs, rhs)
+ }
+ def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree) = tree match {
+ case t @ If(cond0, thenp0, elsep0)
+ if (cond0 == cond && thenp0 == thenp && elsep0 == elsep) => t
+ case _ => copy.If(tree, cond, thenp, elsep)
+ }
+ def For(tree: Tree, enumerators: List[Tree], body: Tree, isForYield: boolean) = tree match {
+ case t @ For(enumerators0, body0, isForYield0)
+ if (enumerators0 == enumerators && body0 == body && isForYield0 == isForYield) => t
+ case _ => copy.For(tree, enumerators, body, isForYield)
+ }
+ def Switch(tree: Tree, test: Tree, tags: List[int], bodies: List[Tree], default: Tree) = tree match {
+ case t @ Switch(test0, tags0, bodies0, default0)
+ if (test0 == test && tags0 == tags && bodies0 == bodies && default0 == default) => t
+ case _ => copy.Switch(tree, test, tags, bodies, default)
+ }
+ def Return(tree: Tree, expr: Tree) = tree match {
+ case t @ Return(expr0)
+ if (expr0 == expr) => t
+ case _ => copy.Return(tree, expr)
+ }
+ def Try(tree: Tree, block: Tree, catcher: Tree, finalizer: Tree) = tree match {
+ case t @ Try(block0, catcher0, finalizer0)
+ if (block0 == block && catcher0 == catcher && finalizer0 == finalizer) => t
+ case _ => copy.Try(tree, block, catcher, finalizer)
+ }
+ def Throw(tree: Tree, expr: Tree) = tree match {
+ case t @ Throw(expr0)
+ if (expr0 == expr) => t
+ case _ => copy.Throw(tree, expr)
+ }
+ def New(tree: Tree, init: Tree) = tree match {
+ case t @ New(init0)
+ if (init0 == init) => t
+ case _ => copy.New(tree, init)
+ }
+ def Typed(tree: Tree, expr: Tree, tp: Tree) = tree match {
+ case t @ Typed(expr0, tp0)
+ if (expr0 == expr && tp0 == tp) => t
+ case _ => copy.Typed(tree, expr, tp)
+ }
+ def TypeApply(tree: Tree, fun: Tree, args: List[Tree]) = tree match {
+ case t @ TypeApply(fun0, args0)
+ if (fun0 == fun && args0 == args) => t
+ case _ => copy.TypeApply(tree, fun, args)
+ }
+ def Apply(tree: Tree, fun: Tree, args: List[Tree]) = tree match {
+ case t @ Apply(fun0, args0)
+ if (fun0 == fun && args0 == args) => t
+ case _ => copy.Apply(tree, fun, args)
+ }
+ def Super(tree: Tree, qual: Name, mixin: Name) = tree match {
+ case t @ Super(qual0, mixin0)
+ if (qual0 == qual && mixin0 == mixin) => t
+ case _ => copy.Super(tree, qual, mixin)
+ }
+ def This(tree: Tree, qual: Name) = tree match {
+ case t @ This(qual0)
+ if (qual0 == qual) => t
+ case _ => copy.This(tree, qual)
+ }
+ def Select(tree: Tree, qualifier: Tree, selector: Name) = tree match {
+ case t @ Select(qualifier0, selector0)
+ if (qualifier0 == qualifier && selector0 == selector) => t
+ case _ => copy.Select(tree, qualifier, selector)
+ }
+ def Ident(tree: Tree, name: Name) = tree match {
+ case t @ Ident(name0)
+ if (name0 == name) => t
+ case _ => copy.Ident(tree, name)
+ }
+ def Literal(tree: Tree, value: Any) = tree match {
+ case t @ Literal(value0)
+ if (value0 == value) => t
+ case _ => copy.Literal(tree, value)
+ }
+ def GeneralTypeTree(tree: Tree) = tree match {
+ case t @ GeneralTypeTree() => t
+ case _ => copy.GeneralTypeTree(tree)
+ }
+ def SingletonTypeTree(tree: Tree, ref: Tree) = tree match {
+ case t @ SingletonTypeTree(ref0)
+ if (ref0 == ref) => t
+ case _ => copy.SingletonTypeTree(tree, ref)
+ }
+ def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name) = tree match {
+ case t @ SelectFromTypeTree(qualifier0, selector0)
+ if (qualifier0 == qualifier && selector0 == selector) => t
+ case _ => copy.SelectFromTypeTree(tree, qualifier, selector)
+ }
+ def FunctionTypeTree(tree: Tree, argtpes: List[Tree], restpe: Tree) = tree match {
+ case t @ FunctionTypeTree(argtpes0, restpe0)
+ if (argtpes0 == argtpes && restpe0 == restpe) => t
+ case _ => copy.FunctionTypeTree(tree, argtpes, restpe)
+ }
+ def IntersectionTypeTree(tree: Tree, parents: List[Tree]) = tree match {
+ case t @ IntersectionTypeTree(parents0)
+ if (parents0 == parents) => t
+ case _ => copy.IntersectionTypeTree(tree, parents)
+ }
+ def RefinementTypeTree(tree: Tree, base: Tree, members: List[Tree]) = tree match {
+ case t @ RefinementTypeTree(base0, members0)
+ if (base0 == base && members0 == members) => t
+ case _ => copy.RefinementTypeTree(tree, base, members)
+ }
+ def AppliedTypeTree(tree: Tree, tp: Tree, args: List[Tree]) = tree match {
+ case t @ AppliedTypeTree(tp0, args0)
+ if (tp0 == tp && args0 == args) => t
+ case _ => copy.AppliedTypeTree(tree, tp, args)
+ }
+ }
+
+ class Transformer(copy: TreeCopier) {
+ def this() = this(new LazyTreeCopier);
+ def transform(tree: Tree): Tree = tree match {
+ case EmptyTree =>
+ tree
+ case ClassDef(mods, name, tparams, vparams, tp, impl) =>
+ copy.ClassDef(tree, mods, name, transformAbsTypeDefs(tparams), transformValDefss(vparams), transform(tp), transformTemplate(impl))
+ case PackageDef(pkg, stats) =>
+ copy.PackageDef(tree, transform(pkg), transform(stats))
+ case ModuleDef(mods, name, tp, impl) =>
+ copy.ModuleDef(tree, mods, name, transform(tp), transformTemplate(impl))
+ case ValDef(mods, name, tp, rhs) =>
+ copy.ValDef(tree, mods, name, transform(tp), transform(rhs))
+ case DefDef(mods, name, tparams, vparams, tp, rhs) =>
+ copy.DefDef(tree, mods, name, transformAbsTypeDefs(tparams), transformValDefss(vparams), transform(tp), transform(rhs))
+ case AbsTypeDef(mods, name, lo, hi, vu) =>
+ copy.AbsTypeDef(tree, mods, name, transform(lo), transform(hi), transform(vu))
+ case AliasTypeDef(mods, name, tparams, rhs) =>
+ copy.AliasTypeDef(tree, mods, name, transformAbsTypeDefs(tparams), transform(rhs))
+ case LabelDef(name, params, rhs) =>
+ copy.LabelDef(tree, name, transformIdents(params), transform(rhs))
+ case Import(expr, selectors) =>
+ copy.Import(tree, transform(expr), selectors)
+ case PatDef(mods, pat, rhs) =>
+ copy.PatDef(tree, mods, transform(pat), transform(rhs))
+ case Attributed(attribute, definition) =>
+ copy.Attributed(tree, transform(attribute), transform(definition))
+ case DocDef(comment, definition) =>
+ copy.DocDef(tree, comment, transform(definition))
+ case Template(parents, body) =>
+ copy.Template(tree, transform(parents), transform(body))
+ case Block(stats, expr) =>
+ copy.Block(tree, transform(stats), transform(expr))
+ case Visitor(cases) =>
+ copy.Visitor(tree, transformCaseDefs(cases))
+ case CaseDef(pat, guard, body) =>
+ copy.CaseDef(tree, transform(pat), transform(guard), transform(body))
+ case Sequence(trees) =>
+ copy.Sequence(tree, transform(trees))
+ case Alternative(trees) =>
+ copy.Alternative(tree, transform(trees))
+ case Bind(name, rhs) =>
+ copy.Bind(tree, name, transform(rhs))
+ case Function(vparams, body) =>
+ copy.Function(tree, transformValDefs(vparams), transform(body))
+ case Assign(lhs, rhs) =>
+ copy.Assign(tree, transform(lhs), transform(rhs))
+ case For(enumerators, body: Tree, isForYield) =>
+ copy.For(tree, transform(enumerators), transform(body), isForYield)
+ case If(cond, thenp, elsep) =>
+ copy.If(tree, transform(cond), transform(thenp), transform(elsep))
+ case Switch(test, tags, bodies, default) =>
+ copy.Switch(tree, transform(test), tags, transform(bodies), transform(default))
+ case Return(expr) =>
+ copy.Return(tree, transform(expr))
+ case Try(block, catcher, finalizer) =>
+ copy.Try(tree, transform(block), transform(catcher), transform(finalizer))
+ case Throw(expr) =>
+ copy.Throw(tree, transform(expr))
+ case New(init) =>
+ copy.New(tree, transform(init))
+ case Typed(expr, tp) =>
+ copy.Typed(tree, transform(expr), transform(tp))
+ case TypeApply(fun, args) =>
+ copy.TypeApply(tree, transform(fun), transform(args))
+ case Apply(fun, args) =>
+ copy.Apply(tree, transform(fun), transform(args))
+ case Super(qual, mixin) =>
+ copy.Super(tree, qual, mixin)
+ case This(qual) =>
+ copy.This(tree, qual)
+ case Select(qualifier, selector) =>
+ copy.Select(tree, transform(qualifier), selector)
+ case Ident(name) =>
+ copy.Ident(tree, name)
+ case Literal(value) =>
+ copy.Literal(tree, value)
+ case GeneralTypeTree() =>
+ copy.GeneralTypeTree(tree)
+ case SingletonTypeTree(ref) =>
+ copy.SingletonTypeTree(tree, transform(ref))
+ case SelectFromTypeTree(qualifier, selector) =>
+ copy.SelectFromTypeTree(tree, transform(qualifier), selector)
+ case FunctionTypeTree(argtpes, restpe) =>
+ copy.FunctionTypeTree(tree, transform(argtpes), transform(restpe))
+ case IntersectionTypeTree(parents) =>
+ copy.IntersectionTypeTree(tree, transform(parents))
+ case RefinementTypeTree(base, members) =>
+ copy.RefinementTypeTree(tree, transform(base), transform(members))
+ case AppliedTypeTree(tp, args) =>
+ copy.AppliedTypeTree(tree, transform(tp), transform(args))
+ }
+
+ def transform(trees: List[Tree]): List[Tree] =
+ trees map transform;
+ def transformTemplate(tree: Template): Template =
+ transform(tree: Tree).asInstanceOf[Template];
+ def transformAbsTypeDefs(trees: List[AbsTypeDef]): List[AbsTypeDef] =
+ trees map (tree => transform(tree).asInstanceOf[AbsTypeDef]);
+ def transformValDefs(trees: List[ValDef]): List[ValDef] =
+ trees map (tree => transform(tree).asInstanceOf[ValDef]);
+ def transformValDefss(treess: List[List[ValDef]]): List[List[ValDef]] =
+ treess map transformValDefs;
+ def transformCaseDefs(trees: List[CaseDef]): List[CaseDef] =
+ trees map (tree => transform(tree).asInstanceOf[CaseDef]);
+ def transformIdents(trees: List[Ident]): List[Ident] =
+ trees map (tree => transform(tree).asInstanceOf[Ident]);
+ }
+
+ class Traverser {
+ def traverse(tree: Tree): unit = tree match {
+ case ClassDef(mods, name, tparams, vparams, tp, impl) =>
+ traverse(tparams); traverseTreess(vparams); traverse(tp); traverse(impl)
+ case PackageDef(pkg, stats) =>
+ traverse(pkg); traverse(stats)
+ case ModuleDef(mods, name, tp, impl) =>
+ traverse(tp); traverse(impl)
+ case ValDef(mods, name, tp, rhs) =>
+ traverse(tp); traverse(rhs)
+ case DefDef(mods, name, tparams, vparams, tp, rhs) =>
+ traverse(tparams); traverseTreess(vparams); traverse(tp); traverse(rhs)
+ case AbsTypeDef(mods, name, lo, hi, vu) =>
+ traverse(lo); traverse(hi); traverse(vu)
+ case AliasTypeDef(mods, name, tparams, rhs) =>
+ traverse(tparams); traverse(rhs)
+ case LabelDef(name, params, rhs) =>
+ traverse(params); traverse(rhs)
+ case Import(expr, selectors) =>
+ traverse(expr)
+ case PatDef(mods, pat, rhs) =>
+ traverse(pat); traverse(rhs)
+ case Attributed(attribute, definition) =>
+ traverse(attribute); traverse(definition)
+ case DocDef(comment, definition) =>
+ traverse(definition)
+ case Template(parents, body) =>
+ traverse(parents); traverse(body)
+ case Block(stats, expr) =>
+ traverse(stats); traverse(expr)
+ case Visitor(cases) =>
+ traverse(cases)
+ case CaseDef(pat, guard, body) =>
+ traverse(pat); traverse(guard); traverse(body)
+ case Sequence(trees) =>
+ traverse(trees)
+ case Alternative(trees) =>
+ traverse(trees)
+ case Bind(name, rhs) =>
+ traverse(rhs)
+ case Function(vparams, body) =>
+ traverse(vparams); traverse(body)
+ case Assign(lhs, rhs) =>
+ traverse(lhs); traverse(rhs)
+ case For(enumerators, body: Tree, isForYield) =>
+ traverse(enumerators); traverse(body)
+ case If(cond, thenp, elsep) =>
+ traverse(cond); traverse(thenp); traverse(elsep)
+ case Switch(test, tags, bodies, default) =>
+ traverse(test); traverse(bodies); traverse(default)
+ case Return(expr) =>
+ traverse(expr)
+ case Try(block, catcher, finalizer) =>
+ traverse(block); traverse(catcher); traverse(finalizer)
+ case Throw(expr) =>
+ traverse(expr)
+ case New(init) =>
+ traverse(init)
+ case Typed(expr, tp) =>
+ traverse(expr); traverse(tp)
+ case TypeApply(fun, args) =>
+ traverse(fun); traverse(args)
+ case Apply(fun, args) =>
+ traverse(fun); traverse(args)
+ case Select(qualifier, selector) =>
+ traverse(qualifier)
+ case SingletonTypeTree(ref) =>
+ traverse(ref)
+ case SelectFromTypeTree(qualifier, selector) =>
+ traverse(qualifier)
+ case FunctionTypeTree(argtpes, restpe) =>
+ traverse(argtpes); traverse(restpe)
+ case IntersectionTypeTree(parents) =>
+ traverse(parents)
+ case RefinementTypeTree(base, members) =>
+ traverse(base); traverse(members)
+ case AppliedTypeTree(tp, args) =>
+ traverse(tp); traverse(args)
+ case EmptyTree | Super(_, _) | This(_) | Ident(_) | Literal(_) | GeneralTypeTree() =>
+ {}
+ }
+
+ def traverse(trees: List[Tree]): unit =
+ trees foreach traverse;
+ def traverseTreess(treess: List[List[Tree]]): unit =
+ treess foreach traverse;
+ }
+
+ final class TreeList {
+ private var trees = List[Tree]();
+ def append(t: Tree): TreeList = { trees = t :: trees; this }
+ def append(ts: List[Tree]): TreeList = { trees = ts reverse_::: trees; this }
+ def toList: List[Tree] = trees.reverse;
+ }
+
+ object posAssigner extends Traverser {
+ private var pos: int = _;
+ override def traverse(t: Tree): unit =
+ if (t != EmptyTree && t.pos == Position.NOPOS) {
+ t.pos = pos;
+ super.traverse(t);
+ }
+ def atPos[T <: Tree](pos: int)(tree: T): T = {
+ this.pos = pos;
+ traverse(tree);
+ tree
+ }
+ }
+}
+
diff --git a/sources/scala/tools/nsc/ast/parser/Lexical.scala b/sources/scala/tools/nsc/ast/parser/Lexical.scala
new file mode 100644
index 0000000000..b3d12948c5
--- /dev/null
+++ b/sources/scala/tools/nsc/ast/parser/Lexical.scala
@@ -0,0 +1,857 @@
+package scala.tools.nsc.ast.parser;
+
+import Tokens._;
+import scala.tools.util.{Position, SourceFile}
+import SourceFile.{LF, FF, CR, SU}
+import scala.tools.nsc.util.CharArrayReader;
+
+abstract class Lexical: ParserPhase {
+
+ import global._;
+
+ /** A class for representing a token's data. */
+ class TokenData {
+
+ /** the next token */
+ var token: int = EMPTY;
+
+ /** the token's position */
+ var pos: int = 0;
+
+ /** the name of an identifier or token */
+ var name: Name = null;
+
+ /** the base of a number */
+ var base: int = 0;
+
+ def copyFrom(td: TokenData) = {
+ this.token = td.token;
+ this.pos = td.pos;
+ this.name = td.name;
+ this.base = td.base;
+ }
+ }
+
+ /** A scanner for the programming language Scala.
+ *
+ * @author Matthias Zenger, Martin Odersky, Burak Emir
+ * @version 1.1
+ */
+ class Scanner(unit: CompilationUnit) extends TokenData {
+
+ import Tokens._;
+ import java.lang.{Integer, Long, Float, Double, Character}
+
+ /** Character input reader
+ */
+ val in = new CharArrayReader(unit.source.getContent(), true, syntaxError);
+
+ /** character buffer for literals
+ */
+ val cbuf = new StringBuffer();
+
+ /** append Unicode character to "lit" buffer
+ */
+ protected def putChar(c: char) = cbuf.append(c);
+
+ /** Clear buffer and set name */
+ private def setName = {
+ name = newTermName(cbuf.toString());
+ cbuf.setLength(0)
+ }
+
+ /** buffer for the documentation comment
+ */
+ var docBuffer: StringBuffer = null;
+
+ /** add the given character to the documentation buffer
+ */
+ protected def putDocChar(c: char): unit =
+ if (docBuffer != null) docBuffer.append(c);
+
+ /** we need one token lookahead
+ */
+ val next = new TokenData();
+ val prev = new TokenData();
+
+ /** the first character position after the previous token
+ */
+ var lastpos = 0;
+
+ /** the last error position
+ */
+ var errpos = -1;
+
+// Get next token ------------------------------------------------------------
+
+ /** read next token and return last position
+ */
+ def skipToken(): int = {
+ val p = pos; nextToken(); p
+ }
+
+ def nextToken(): unit = {
+ if (token == RBRACE) {
+ val prevpos = pos;
+ fetchToken();
+ token match {
+ case ELSE | EXTENDS | WITH | YIELD | CATCH | FINALLY |
+ COMMA | SEMI | DOT | COLON | EQUALS | ARROW |
+ LARROW | SUBTYPE | SUPERTYPE | HASH | AT |
+ RPAREN | RBRACKET | RBRACE =>
+ case _ =>
+ if (token == EOF || Position.line(pos) > Position.line(prevpos)) {
+ next.copyFrom(this);
+ this.token = SEMI;
+ this.pos = prevpos;
+ }
+ }
+ } else {
+ if (next.token == EMPTY) {
+ fetchToken();
+ } else {
+ copyFrom(next);
+ next.token = EMPTY
+ }
+ if (token == CASE) {
+ prev.copyFrom(this);
+ fetchToken();
+ if (token == CLASS) {
+ token = CASECLASS;
+ } else if (token == OBJECT) {
+ token = CASEOBJECT;
+ } else {
+ next.copyFrom(this);
+ this.copyFrom(prev);
+ }
+ } else if (token == SEMI) {
+ prev.copyFrom(this);
+ fetchToken();
+ if (token != ELSE) {
+ next.copyFrom(this);
+ this.copyFrom(prev);
+ }
+ }
+ //Console.println("<" + this + ">");//DEBUG
+ }
+ }
+
+ /** read next token
+ */
+ private def fetchToken(): unit = {
+ if (token == EOF) return;
+ lastpos = Position.encode(in.cline, in.ccol);
+ //var index = bp;
+ while (true) {
+ in.ch match {
+ case ' ' | '\t' | CR | LF | FF =>
+ in.next;
+ case _ =>
+ pos = Position.encode(in.cline, in.ccol);
+ in.ch match {
+ case '\u21D2' =>
+ in.next; token = ARROW;
+ return;
+ case 'A' | 'B' | 'C' | 'D' | 'E' |
+ 'F' | 'G' | 'H' | 'I' | 'J' |
+ 'K' | 'L' | 'M' | 'N' | 'O' |
+ 'P' | 'Q' | 'R' | 'S' | 'T' |
+ 'U' | 'V' | 'W' | 'X' | 'Y' |
+ 'Z' | '$' | '_' |
+ 'a' | 'b' | 'c' | 'd' | 'e' |
+ 'f' | 'g' | 'h' | 'i' | 'j' |
+ 'k' | 'l' | 'm' | 'n' | 'o' |
+ 'p' | 'q' | 'r' | 's' | 't' |
+ 'u' | 'v' | 'w' | 'x' | 'y' | // scala-mode: need to understand multi-line case patterns
+ 'z' =>
+ putChar(in.ch);
+ in.next;
+ getIdentRest; // scala-mode: wrong indent for multi-line case blocks
+ return;
+ case '~' | '!' | '@' | '#' | '%' |
+ '^' | '*' | '+' | '-' | '<' |
+ '>' | '?' | ':' | '=' | '&' |
+ '|' | '\\' =>
+ putChar(in.ch);
+ in.next;
+ getOperatorRest; // XXX
+ return;
+ case '/' =>
+ in.next;
+ if (!skipComment()) {
+ putChar('/');
+ getOperatorRest;
+ return;
+ }
+
+ case '0' =>
+ putChar(in.ch);
+ in.next;
+ if (in.ch == 'x' || in.ch == 'X') {
+ in.next;
+ base = 16
+ } else {
+ base = 8;
+ }
+ getNumber;
+ return; // scala-mode: return is a keyword
+ case '1' | '2' | '3' | '4' |
+ '5' | '6' | '7' | '8' | '9' =>
+ base = 10;
+ getNumber;
+ return;
+ case '`' => //" scala-mode: need to understand literals
+ getStringLit('`');
+ token = IDENTIFIER;
+ return;
+ case '\"' => //" scala-mode: need to understand literals
+ getStringLit('\"');
+ return;
+ case '\'' =>
+ in.next;
+ in.ch match {
+ case 'A' | 'B' | 'C' | 'D' | 'E' |
+ 'F' | 'G' | 'H' | 'I' | 'J' |
+ 'K' | 'L' | 'M' | 'N' | 'O' |
+ 'P' | 'Q' | 'R' | 'S' | 'T' |
+ 'U' | 'V' | 'W' | 'X' | 'Y' |
+ 'Z' | '$' | '_' |
+ 'a' | 'b' | 'c' | 'd' | 'e' |
+ 'f' | 'g' | 'h' | 'i' | 'j' |
+ 'k' | 'l' | 'm' | 'n' | 'o' |
+ 'p' | 'q' | 'r' | 's' | 't' |
+ 'u' | 'v' | 'w' | 'x' | 'y' |
+ 'z' =>
+ putChar(in.ch);
+ in.next;
+ if (in.ch != '\'') {
+ getIdentRest;
+ token = SYMBOLLIT;
+ return;
+ }
+ case _ =>
+ if (Character.isUnicodeIdentifierStart(in.ch)) {
+ putChar(in.ch);
+ in.next;
+ if (in.ch != '\'') {
+ getIdentRest;
+ token = SYMBOLLIT;
+ return;
+ }
+ } else {
+ getlitch()
+ }
+ }
+ if (in.ch == '\'') {
+ in.next;
+ token = CHARLIT;
+ setName
+ } else {
+ syntaxError("unclosed character literal");
+ }
+ return;
+ case '.' =>
+ in.next;
+ if ('0' <= in.ch && in.ch <= '9') {
+ putChar('.'); getFraction;
+ } else {
+ token = DOT
+ }
+ return;
+ case ';' =>
+ in.next; token = SEMI;
+ return;
+ case ',' =>
+ in.next; token = COMMA;
+ return;
+ case '(' => //scala-mode: need to understand character quotes
+ in.next; token = LPAREN;
+ return;
+ case '{' =>
+ in.next; token = LBRACE;
+ return;
+ case ')' =>
+ in.next; token = RPAREN;
+ return;
+ case '}' =>
+ in.next; token = RBRACE;
+ return;
+ case '[' =>
+ in.next; token = LBRACKET;
+ return;
+ case ']' =>
+ in.next; token = RBRACKET;
+ return;
+ case SU =>
+ if (!in.hasNext) token = EOF;
+ else syntaxError("illegal character");
+ return;
+ case _ =>
+ if (Character.isUnicodeIdentifierStart(in.ch)) {
+ putChar(in.ch);
+ in.next;
+ getIdentRest;
+ } else if (isSpecial(in.ch)) {
+ putChar(in.ch);
+ getOperatorRest;
+ } else {
+ syntaxError("illegal character");
+ in.next;
+ }
+ return;
+ }
+ }
+ }
+ }
+
+ private def skipComment(): boolean =
+ if (in.ch == '/') {
+ do {
+ in.next;
+ } while ((in.ch != CR) && (in.ch != LF) && (in.ch != SU));
+ true
+ } else if (in.ch == '*') {
+ docBuffer = null;
+ var openComments = 1;
+ in.next;
+ if (in.ch == '*') docBuffer = new StringBuffer("/**");
+ while (openComments > 0) {
+ do {
+ do {
+ if (in.ch == '/') {
+ in.next; putDocChar(in.ch);
+ if (in.ch == '*') {
+ in.next; putDocChar(in.ch);
+ openComments = openComments + 1;
+ }
+ }
+ in.next; putDocChar(in.ch);
+ } while (in.ch != '*' && in.ch != SU);
+ while (in.ch == '*') {
+ in.next; putDocChar(in.ch);
+ }
+ } while (in.ch != '/' && in.ch != SU);
+ if (in.ch == '/') in.next;
+ else syntaxError("unclosed comment");
+ openComments = openComments - 1;
+ }
+ true
+ } else {
+ false
+ }
+
+// Identifiers ---------------------------------------------------------------
+
+ def isIdentStart(c: char): boolean =
+ ('A' <= c && c <= 'Z') ||
+ ('a' <= c && c <= 'a') ||
+ (c == '_') || (c == '$') ||
+ Character.isUnicodeIdentifierStart(c);
+
+ def isIdentPart(c: char) =
+ isIdentStart(c) ||
+ ('0' <= c && c <= '9') ||
+ Character.isUnicodeIdentifierPart(c);
+
+ def isSpecial(c: char) = {
+ val chtp = Character.getType(c);
+ chtp == Character.MATH_SYMBOL || chtp == Character.OTHER_SYMBOL;
+ }
+
+ private def getIdentRest: unit =
+ while (true) {
+ in.ch match {
+ case 'A' | 'B' | 'C' | 'D' | 'E' |
+ 'F' | 'G' | 'H' | 'I' | 'J' |
+ 'K' | 'L' | 'M' | 'N' | 'O' |
+ 'P' | 'Q' | 'R' | 'S' | 'T' |
+ 'U' | 'V' | 'W' | 'X' | 'Y' |
+ 'Z' | '$' |
+ 'a' | 'b' | 'c' | 'd' | 'e' |
+ 'f' | 'g' | 'h' | 'i' | 'j' |
+ 'k' | 'l' | 'm' | 'n' | 'o' |
+ 'p' | 'q' | 'r' | 's' | 't' |
+ 'u' | 'v' | 'w' | 'x' | 'y' |
+ 'z' |
+ '0' | '1' | '2' | '3' | '4' |
+ '5' | '6' | '7' | '8' | '9' =>
+ putChar(in.ch);
+ in.next;
+ case '_' =>
+ putChar(in.ch);
+ in.next;
+ getIdentOrOperatorRest;
+ return;
+ case _ =>
+ if(java.lang.Character.isUnicodeIdentifierPart(in.ch)) {
+ putChar(in.ch);
+ in.next
+ } else {
+ setName;
+ token = name2token(name);
+ return
+ }
+ }
+ }
+
+ private def getOperatorRest: unit =
+ while (true) {
+ in.ch match {
+ case '~' | '!' | '@' | '#' | '%' |
+ '^' | '*' | '+' | '-' | '<' |
+ '>' | '?' | ':' | '=' | '&' |
+ '|' | '\\' =>
+ putChar(in.ch);
+ in.next
+ case '/' =>
+ in.next;
+ if (skipComment()) {
+ setName;
+ token = name2token(name);
+ return;
+ } else {
+ putChar('/');
+ }
+ case _ =>
+ if (isSpecial(in.ch)) {
+ putChar(in.ch);
+ in.next;
+ } else {
+ setName;
+ token = name2token(name);
+ return;
+ }
+ }
+ }
+
+ private def getIdentOrOperatorRest: unit =
+ if (isIdentPart(in.ch))
+ getIdentRest
+ else in.ch match {
+ case '~' | '!' | '@' | '#' | '%' |
+ '^' | '*' | '+' | '-' | '<' |
+ '>' | '?' | ':' | '=' | '&' |
+ '|' | '\\' | '/' =>
+ getOperatorRest;
+ case _ =>
+ if (isSpecial(in.ch)) getOperatorRest
+ else {
+ setName;
+ token = name2token(name)
+ }
+ }
+
+ private def getStringLit(delimiter: char): unit = {
+ in.next;
+ while (in.ch != delimiter && in.ch != CR && in.ch != LF && in.ch != SU) {
+ getlitch();
+ }
+ if (in.ch == delimiter) {
+ token = STRINGLIT;
+ setName;
+ in.next
+ } else {
+ syntaxError("unclosed string literal");
+ }
+ }
+
+// Literals -----------------------------------------------------------------
+
+ /** read next character in character or string literal:
+ */
+ protected def getlitch() =
+ if (in.ch == '\\') {
+ in.next;
+ if ('0' <= in.ch && in.ch <= '7') {
+ val leadch: char = in.ch;
+ var oct: int = in.digit2int(in.ch, 8);
+ in.next;
+ if ('0' <= in.ch && in.ch <= '7') {
+ oct = oct * 8 + in.digit2int(in.ch, 8);
+ in.next;
+ if (leadch <= '3' && '0' <= in.ch && in.ch <= '7') {
+ oct = oct * 8 + in.digit2int(in.ch, 8);
+ in.next;
+ }
+ }
+ putChar(oct.asInstanceOf[char]);
+ } else
+ in.ch match {
+ case 'b' => putChar('\b')
+ case 't' => putChar('\t')
+ case 'n' => putChar('\n')
+ case 'f' => putChar('\f')
+ case 'r' => putChar('\r')
+ case '\"' => putChar('\"')
+ case '\'' => putChar('\'')
+ case '\\' => putChar('\\')
+ case _ =>
+ syntaxError(Position.encode(in.cline, in.ccol - 1),
+ "invalid escape character");
+ putChar(in.ch);
+ }
+ in.next;
+ } else {
+ putChar(in.ch);
+ in.next;
+ }
+
+ /** read fractional part and exponent of floating point number
+ * if one is present.
+ */
+ protected def getFraction = {
+ while ('0' <= in.ch && in.ch <= '9') {
+ putChar(in.ch);
+ in.next;
+ token = DOUBLELIT;
+ }
+ if (in.ch == 'e' || in.ch == 'E') {
+ val lookahead = in.copy;
+ lookahead.next;
+ if (lookahead.ch == '+' || lookahead.ch == '-') {
+ lookahead.next;
+ }
+ if ('0' <= lookahead.ch && lookahead.ch <= '9') {
+ putChar(in.ch);
+ in.next;
+ if (in.ch == '+' || in.ch == '-') {
+ putChar(in.ch);
+ in.next;
+ }
+ while ('0' <= in.ch && in.ch <= '9') {
+ putChar(in.ch);
+ in.next;
+ }
+ }
+ token = DOUBLELIT;
+ }
+ if ((in.ch == 'd') || (in.ch == 'D')) {
+ putChar(in.ch);
+ in.next;
+ token = DOUBLELIT;
+ } else if ((in.ch == 'f') || (in.ch == 'F')) {
+ putChar(in.ch);
+ in.next;
+ token = FLOATLIT;
+ }
+ setName
+ }
+
+ /** convert name to long value
+ */
+ def intVal(negated: boolean): long = {
+ if (token == CHARLIT && !negated) {
+ if (name.length > 0) name(0) else 0
+ } else {
+ var value: long = 0;
+ val divider = if (base == 10) 1 else 2;
+ val limit: long =
+ if (token == LONGLIT) Long.MAX_VALUE else Integer.MAX_VALUE;
+ var i = 0;
+ val len = name.length;
+ while (i < len) {
+ val d = in.digit2int(name(i), base);
+ if (d < 0) {
+ syntaxError("malformed integer number");
+ return 0;
+ }
+ if (value < 0 ||
+ limit / (base / divider) < value ||
+ limit - (d / divider) < value * (base / divider) &&
+ !(negated && limit == value * base - 1 + d)) {
+ syntaxError("integer number too large");
+ return 0;
+ }
+ value = value * base + d;
+ i = i + 1;
+ }
+ if (negated) -value else value
+ }
+ }
+
+ def intVal: long = intVal(false);
+
+ /** convert name, base to double value
+ */
+ def floatVal(negated: boolean): double = {
+ val limit: double =
+ if (token == DOUBLELIT) Double.MAX_VALUE else Float.MAX_VALUE;
+ try {
+ val value = Double.valueOf(name.toString()).doubleValue();
+ if (value > limit)
+ syntaxError("floating point number too large");
+ if (negated) -value else value
+ } catch {
+ case _: NumberFormatException =>
+ syntaxError("malformed floating point number");
+ 0.0
+ }
+ }
+
+ def floatVal: double = floatVal(false);
+
+ /** read a number into name and set base
+ */
+ protected def getNumber:unit = {
+ while (in.digit2int(in.ch, if (base < 10) 10 else base) >= 0) {
+ putChar(in.ch);
+ in.next;
+ }
+ token = INTLIT;
+ if (base <= 10 && in.ch == '.') {
+ putChar(in.ch);
+ in.next;
+ getFraction
+ } else if (base <= 10 &&
+ (in.ch == 'e' || in.ch == 'E' ||
+ in.ch == 'f' || in.ch == 'F' ||
+ in.ch == 'd' || in.ch == 'D')) {
+ getFraction
+ } else {
+ setName;
+ if (in.ch == 'l' || in.ch == 'L') {
+ in.next;
+ token = LONGLIT;
+ }
+ }
+ }
+
+// XML lexing----------------------------------------------------------------
+
+/*
+ // start XML tokenizing methods
+ // prod. [i] refers to productions in http://www.w3.org/TR/REC-xml
+
+ /** calls nextToken, starting the scanning of Scala tokens,
+ * after XML tokens.
+ */
+ def xSync = {
+ token = SEMI; // avoid getting SEMI from nextToken if last was RBRACE
+ //in.next;
+ nextToken();
+ }
+
+ def xSync2 = fetchToken();
+
+ def xLookahead = srcIterator.lookahead1;
+
+ /** read the next character. do not skip whitespace.
+ * treat CR LF as single LF. update ccol and cline
+ *
+ * @todo: may XML contain SU, in CDATA sections ?
+ */
+ def xNext = {
+ lastpos = pos;
+ ch = srcIterator.raw; ccol = ccol + 1; // = in.next without unicode
+ ch match {
+ case SU =>
+ syntaxError(lastpos, "unclosed XML literal");
+ token = EOF;
+ case LF =>
+ ccol = 0; cline = cline + 1;
+ case CR =>
+ if (LF == srcIterator.lookahead1) {
+ srcIterator.raw; ccol = 0; cline = cline + 1;
+ }
+ case _ =>
+ //Console.print(ch.asInstanceOf[char]); // DEBUG
+ }
+ pos = Position.encode(cline, ccol);
+ //Console.print(ch);
+ }
+
+ final val LT = Name.fromString("<");
+
+ def xStartsXML = {
+ /* unit.global.xmlMarkup && */ (token == IDENTIFIER) &&(name == LT);
+ /* || // support for proc instr, cdata, comment... ?
+ {val s = name.toString();
+ s.charAt(0) == '<' && (s.charAt(1)=='?' || s.charAt(1)=='!')}) */
+ }
+
+ // end XML tokenizing
+
+*/
+// Errors -----------------------------------------------------------------
+
+ /** generate an error at the given position
+ */
+ def syntaxError(pos: int, msg: String) = {
+ unit.error(pos, msg);
+ token = ERROR;
+ errpos = pos;
+ }
+
+ /** generate an error at the current token position
+ */
+ def syntaxError(msg: String): unit = syntaxError(pos, msg);
+
+// Keywords -----------------------------------------------------------------
+
+ /** Keyword array; maps from name indices to tokens */
+ private var key: Array[byte] = _;
+ private var maxKey = 0;
+ private var tokenName = new Array[Name](128);
+
+ {
+ var tokenCount = 0;
+
+ // Enter keywords
+
+ def enterKeyword(s: String, tokenId: int) = {
+ while (tokenId >= tokenName.length) {
+ val newTokName = new Array[Name](tokenName.length * 2);
+ System.arraycopy(tokenName, 0, newTokName, 0, newTokName.length);
+ tokenName = newTokName;
+ }
+ val n = newTermName(s);
+ tokenName(tokenId) = n;
+ if (n.start > maxKey) maxKey = n.start;
+ if (tokenId >= tokenCount) tokenCount = tokenId + 1;
+ }
+
+ enterKeyword("abstract", ABSTRACT);
+ enterKeyword("case", CASE);
+ enterKeyword("class", CLASS);
+ enterKeyword("catch", CATCH);
+ enterKeyword("def", DEF);
+ enterKeyword("do", DO);
+ enterKeyword("else", ELSE);
+ enterKeyword("extends", EXTENDS);
+ enterKeyword("false", FALSE);
+ enterKeyword("final", FINAL);
+ enterKeyword("finally", FINALLY);
+ enterKeyword("for", FOR);
+ enterKeyword("if", IF);
+ enterKeyword("import", IMPORT);
+ enterKeyword("new", NEW);
+ enterKeyword("null", NULL);
+ enterKeyword("object", OBJECT);
+ enterKeyword("override", OVERRIDE);
+ enterKeyword("package", PACKAGE);
+ enterKeyword("private", PRIVATE);
+ enterKeyword("protected", PROTECTED);
+ enterKeyword("return", RETURN);
+ enterKeyword("sealed", SEALED);
+ enterKeyword("super", SUPER);
+ enterKeyword("this", THIS);
+ enterKeyword("throw", THROW);
+ enterKeyword("trait", TRAIT);
+ enterKeyword("true", TRUE);
+ enterKeyword("try", TRY);
+ enterKeyword("type", TYPE);
+ enterKeyword("val", VAL);
+ enterKeyword("var", VAR);
+ enterKeyword("with", WITH);
+ enterKeyword("while", WHILE);
+ enterKeyword("yield", YIELD);
+ enterKeyword(".", DOT);
+ enterKeyword("_", USCORE);
+ enterKeyword(":", COLON);
+ enterKeyword("=", EQUALS);
+ enterKeyword("=>", ARROW);
+ enterKeyword("<-", LARROW);
+ enterKeyword("<:", SUBTYPE);
+ enterKeyword(">:", SUPERTYPE);
+ enterKeyword("<%", VIEWBOUND);
+ enterKeyword("#", HASH);
+ enterKeyword("@", AT);
+
+ // Build keyword array
+ key = new Array[byte](maxKey+1);
+ for (val i <- Iterator.range(0, maxKey + 1))
+ key(i) = IDENTIFIER;
+ for (val j <- Iterator.range(0, tokenCount))
+ if (tokenName(j) != null)
+ key(tokenName(j).start) = j.asInstanceOf[byte];
+
+ }
+
+// Token representation -----------------------------------------------------
+
+ /** Convert name to token */
+ def name2token(name: Name): int =
+ if (name.start <= maxKey) key(name.start) else IDENTIFIER;
+
+ /** Returns the string representation of given token. */
+ def token2string(token: int): String = token match {
+ case IDENTIFIER =>
+ "identifier"/* + \""+name+"\""*/
+ case CHARLIT =>
+ "character literal"
+ case INTLIT =>
+ "integer literal"
+ case LONGLIT =>
+ "long literal"
+ case FLOATLIT =>
+ "float literal"
+ case DOUBLELIT =>
+ "double literal"
+ case STRINGLIT =>
+ "string literal"
+ case SYMBOLLIT =>
+ "symbol literal"
+ case LPAREN =>
+ "'('"
+ case RPAREN =>
+ "')'"
+ case LBRACE =>
+ "'{'"
+ case RBRACE =>
+ "'}'"
+ case LBRACKET =>
+ "'['"
+ case RBRACKET =>
+ "']'"
+ case EOF =>
+ "eof"
+ case ERROR =>
+ "something"
+ case SEMI =>
+ "';'"
+ case COMMA =>
+ "','"
+ case CASECLASS =>
+ "case class"
+ case CASEOBJECT =>
+ "case object"
+ case _ =>
+ try {
+ "'" + tokenName(token) + "'"
+ } catch {
+ case _: ArrayIndexOutOfBoundsException =>
+ "'<" + token + ">'"
+ case _: NullPointerException =>
+ "'<(" + token + ")>'"
+ }
+ }
+
+ override def toString() = token match {
+ case IDENTIFIER =>
+ "id(" + name + ")"
+ case CHARLIT =>
+ "char(" + intVal + ")"
+ case INTLIT =>
+ "int(" + intVal + ")"
+ case LONGLIT =>
+ "long(" + intVal + ")"
+ case FLOATLIT =>
+ "float(" + floatVal + ")"
+ case DOUBLELIT =>
+ "double(" + floatVal + ")"
+ case STRINGLIT =>
+ "string(" + name + ")"
+ case SEMI =>
+ ";"
+ case COMMA =>
+ ","
+ case _ =>
+ token2string(token)
+ }
+
+ /** INIT: read lookahead character and token.
+ */
+ in.next;
+ nextToken();
+ }
+}
diff --git a/sources/scala/tools/nsc/ast/parser/ParserPhase.scala b/sources/scala/tools/nsc/ast/parser/ParserPhase.scala
new file mode 100644
index 0000000000..dab3581355
--- /dev/null
+++ b/sources/scala/tools/nsc/ast/parser/ParserPhase.scala
@@ -0,0 +1,11 @@
+package scala.tools.nsc.ast.parser;
+
+abstract class ParserPhase(prev: Phase)
+ extends StdPhase(prev)
+ with Lexical
+ with Syntactic {
+ def name = "parser";
+ def apply(unit: global.CompilationUnit): unit = {
+ unit.body = new Parser(unit).parse();
+ }
+}
diff --git a/sources/scala/tools/nsc/ast/parser/Syntactic.scala b/sources/scala/tools/nsc/ast/parser/Syntactic.scala
new file mode 100755
index 0000000000..6922adc862
--- /dev/null
+++ b/sources/scala/tools/nsc/ast/parser/Syntactic.scala
@@ -0,0 +1,1793 @@
+package scala.tools.nsc.ast.parser;
+
+import scala.tools.util.Position;
+import scala.collection.mutable.ListBuffer;
+import symtab.Flags;
+import Tokens._;
+
+abstract class Syntactic: ParserPhase {
+
+ import global._;
+ import posAssigner.atPos;
+
+ class Parser(unit: CompilationUnit) {
+
+ val in = new Scanner(unit);
+
+ /** the markup parser
+ val xmlp = new MarkupParser(unit, s, this, false);
+ */
+
+ /** The current nesting depths of while and do loops.
+ */
+ var loopNestingDepth = 0;
+
+ /** this is the general parse method
+ */
+ def parse(): List[Tree] = {
+ val ts = compilationUnit();
+ accept(EOF);
+ ts
+ }
+
+/////// ERROR HANDLING //////////////////////////////////////////////////////
+
+ private def skip(): unit = {
+ //System.out.println("<skipping> " + in.token2string(in.token));//DEBUG
+ var nparens = 0;
+ var nbraces = 0;
+ while (true) {
+ in.token match {
+ case EOF =>
+ return;
+ case SEMI =>
+ if (nparens == 0 && nbraces == 0) return;
+ case RPAREN =>
+ nparens = nparens - 1;
+ case RBRACE =>
+ if (nbraces == 0) return;
+ nbraces = nbraces - 1;
+ case LPAREN =>
+ nparens = nparens + 1;
+ case LBRACE =>
+ nbraces = nbraces + 1;
+ case _ =>
+ }
+ in.nextToken();
+ }
+ }
+
+ def syntaxError(msg: String, skipIt: boolean): unit =
+ syntaxError(in.pos, msg, skipIt);
+
+ def syntaxError(pos: int, msg: String, skipIt: boolean): unit = {
+ if (pos != in.errpos) {
+ unit.error(pos, msg);
+ in.errpos = pos;
+ }
+ if (skipIt) skip();
+ }
+
+ def accept(token: int): int = {
+ val pos = in.pos;
+ if (in.token != token)
+ syntaxError(
+ if (Position.line(in.pos) > Position.line(in.lastpos)) in.lastpos
+ else in.pos,
+ in.token2string(token) + " expected but " +
+ in.token2string(in.token) + " found.", true);
+ if (in.token == token) in.nextToken();
+ pos
+ }
+
+ def errorTypeTree = GeneralTypeTree().setType(ErrorType).setPos(in.pos);
+ def errorTermTree = Literal(null).setPos(in.pos);
+ def errorPatternTree = Ident(nme.WILDCARD).setPos(in.pos);
+
+/////// TOKEN CLASSES //////////////////////////////////////////////////////
+
+ def isModifier: boolean = in.token match {
+ case ABSTRACT | FINAL | SEALED | PRIVATE | PROTECTED | OVERRIDE => true
+ case _ => false
+ }
+
+ def isLocalModifier: boolean = in.token match {
+ case ABSTRACT | FINAL | SEALED => true
+ case _ => false
+ }
+
+ def isDefIntro: boolean = in.token match {
+ case VAL | VAR | DEF | TYPE | OBJECT |
+ CASEOBJECT | CLASS | CASECLASS | TRAIT => true
+ case _ => false
+ }
+
+ def isDclIntro: boolean = in.token match {
+ case VAL | VAR | DEF | TYPE => true
+ case _ => false
+ }
+
+ def isExprIntro: boolean = in.token match {
+ case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT |
+ STRINGLIT | SYMBOLLIT | TRUE | FALSE | NULL | IDENTIFIER |
+ THIS | SUPER | IF | FOR | NEW | USCORE | TRY | WHILE |
+ DO | RETURN | THROW | LPAREN | LBRACE => true
+ case _ => false
+ }
+
+/////// COMMENT AND ATTRIBUTE COLLECTION //////////////////////////////////////
+
+ /** Join the comment associated with a definition
+ */
+ def joinComment(def trees: List[Tree]): List[Tree] = {
+ val buf = in.docBuffer;
+ if (buf != null) {
+ in.docBuffer = null;
+ trees map (t => DocDef(buf.toString(), t) setPos t.pos)
+ } else trees
+ }
+
+/////// TREE CONSTRUCTION ////////////////////////////////////////////////////
+
+ def fresh(): Name = unit.fresh.newName("x");
+
+ /** Create a tree representing a packaging
+ */
+ def makePackaging(pkg: Tree, stats: List[Tree]): Tree =
+ atPos(in.pos) {
+ pkg match {
+ case Ident(name) =>
+ PackageDef(pkg, stats)
+ case Select(qual, name) =>
+ makePackaging(qual, List(PackageDef(Ident(name), stats)))
+ }
+ }
+
+ /** Create tree representing binary operation expression or pattern.
+ */
+ def makeBinop(isExpr: boolean, left: Tree, op: Name, right: Tree): Tree = {
+ if (isExpr) {
+ if (isLeftAssoc(op)) {
+ Apply(Select(left, op.encode), List(right))
+ } else {
+ val x: Name = fresh();
+ Block(
+ List(ValDef(0, x, EmptyTree, left)),
+ Apply(Select(right, op.encode), List(Ident(x))))
+ }
+ } else {
+ Apply(Ident(op.encode.toTypeName), List(left, right))
+ }
+ }
+ def makeAlternative(ts: List[Tree]): Tree = {
+ def alternatives(t: Tree): List[Tree] = t match {
+ case Alternative(ts) => ts
+ case _ => List(t)
+ }
+ Alternative(for (val t <- ts; val a <- alternatives(t)) yield a)
+ }
+
+ def makeSequence(ts: List[Tree]): Tree = {
+ def elements(t: Tree): List[Tree] = t match {
+ case Sequence(ts) => ts
+ case _ => List(t)
+ }
+ Sequence(for (val t <- ts; val e <- elements(t)) yield e)
+ }
+
+ def scalaDot(name: Name): Tree =
+ Select(Ident(nme.scala), name);
+ def scalaRuntimeDot(name: Name): Tree =
+ Select(scalaDot(nme.runtime), name);
+ def ScalaRunTimeDot(name: Name): Tree =
+ Select(scalaRuntimeDot(nme.ScalaRunTime), name);
+ def scalaBooleanDot(name: Name): Tree =
+ Select(scalaDot(nme.Boolean), name);
+ def scalaAnyRefConstr(): Tree =
+ Apply(scalaDot(nme.AnyRef.toTypeName), List());
+ def scalaObjectConstr(): Tree =
+ Apply(scalaDot(nme.ScalaObject.toTypeName), List());
+ def caseClassConstr(): Tree =
+ Apply(scalaDot(nme.CaseClass.toTypeName), List());
+
+ def makeWhile(lname: Name, cond: Tree, body: Tree): Tree = {
+ val continu = Apply(Ident(lname), List());
+ val rhs = If(cond, Block(List(body), continu), Literal(()));
+ LabelDef(lname, Nil, rhs)
+ }
+
+ def makeDoWhile(lname: Name, body: Tree, cond: Tree): Tree = {
+ val continu = Apply(Ident(lname), List());
+ val rhs = Block(List(body), If(cond, continu, Literal(())));
+ LabelDef(lname, Nil, rhs)
+ }
+
+ def makeBlock(stats: List[Tree]): Tree = {
+ if (stats.isEmpty) Literal(())
+ else if (!stats.last.isTerm) Block(stats, Literal(()));
+ else if (stats.length == 1) stats(0)
+ else Block(stats.init, stats.last)
+ }
+
+ /** Convert tree to formal parameter list
+ */
+ def convertToParams(t: Tree): List[ValDef] = t match {
+ case Function(params, EmptyTree) =>
+ params
+ case Ident(_) | Typed(Ident(_), _) =>
+ List(convertToParam(t));
+ case Literal(x) if x == () => //todo: check with Literal(())
+ Nil
+ case _ =>
+ syntaxError(t.pos, "malformed formal parameter list", false);
+ Nil
+ }
+
+ /** Convert tree to formal parameter
+ */
+ def convertToParam(tree: Tree): ValDef =
+ atPos(tree.pos) {
+ tree match {
+ case Ident(name) =>
+ ValDef(Flags.PARAM, name, EmptyTree, EmptyTree)
+ case Typed(Ident(name), tpe) =>
+ ValDef(Flags.PARAM, name, tpe, EmptyTree)
+ case _ =>
+ syntaxError(tree.pos, "not a legal formal parameter", false);
+ ValDef(Flags.PARAM, nme.ERROR, errorTypeTree, EmptyTree)
+ }
+ }
+
+ /** Convert (qual)ident to type identifier
+ */
+ def convertToTypeId(tree: Tree): Tree = tree match {
+ case Ident(name) =>
+ Ident(name.toTypeName).setPos(tree.pos)
+ case Select(qual, name) =>
+ Select(qual, name.toTypeName).setPos(tree.pos)
+ case _ =>
+ System.out.println(tree);//debug
+ syntaxError(tree.pos, "identifier expected", false);
+ errorTypeTree
+ }
+
+ /** Complete unapplied constructor with `()' arguments
+ */
+ def applyConstr(t: Tree): Tree = t match {
+ case Apply(_, _) => t
+ case _ => Apply(t, List()) setPos t.pos
+ }
+
+ /** make closure from tree */
+ def makeClosure(tree: Tree): Tree = {
+ val pname = fresh();
+ def insertParam(tree: Tree): Tree = tree match {
+ case Ident(name) =>
+ Select(Ident(pname), name)
+ case Select(qual, name) =>
+ Select(insertParam(qual), name)
+ case Apply(fn, args) =>
+ Apply(insertParam(fn), args)
+ case TypeApply(fn, args) =>
+ TypeApply(insertParam(fn), args)
+ case _ =>
+ syntaxError(tree.pos, "cannot convert to closure", false);
+ errorTermTree
+ }
+ Function(
+ List(ValDef(Flags.PARAM, pname, EmptyTree, EmptyTree)),
+ insertParam(tree))
+ }
+
+/////// OPERAND/OPERATOR STACK /////////////////////////////////////////////////
+
+ case class OpInfo(operand: Tree, operator: Name, pos: int);
+ var opstack: List[OpInfo] = Nil;
+
+ def precedence(operator: Name): int =
+ if (operator eq nme.ERROR) -1
+ else {
+ val firstCh = operator(0);
+ if (((firstCh >= 'A') && (firstCh <= 'Z')) ||
+ ((firstCh >= 'a') && (firstCh <= 'z')))
+ 1
+ else
+ firstCh match {
+ case '|' => 2
+ case '^' => 3
+ case '&' => 4
+ case '<' | '>' => 5
+ case '=' | '!' => 6
+ case ':' => 7
+ case '+' | '-' => 8;
+ case '*' | '/' | '%' => 9;
+ case _ => 10;
+ }
+ }
+
+ def isLeftAssoc(operator: Name): boolean =
+ operator.length > 0 && operator(operator.length - 1) != ':';
+
+ def reduceStack(isExpr: boolean, base: List[OpInfo], top0: Tree, prec: int, leftAssoc: boolean): Tree = {
+ var top = top0;
+ if (opstack != base &&
+ precedence(opstack.head.operator) == prec &&
+ isLeftAssoc(opstack.head.operator) != leftAssoc) {
+ syntaxError(
+ opstack.head.pos,
+ "left- and right-associative operators with same precedence may not be mixed",
+ false);
+ }
+ while (opstack != base &&
+ (prec < precedence(opstack.head.operator) ||
+ (leftAssoc && prec == precedence(opstack.head.operator)))) {
+ top = atPos(opstack.head.pos) {
+ makeBinop(isExpr, opstack.head.operand, opstack.head.operator, top)
+ }
+ opstack = opstack.tail;
+ }
+ top
+ }
+
+/////// IDENTIFIERS AND LITERALS ////////////////////////////////////////////////////////////
+
+ final val MINUS: Name = "-";
+ final val PLUS : Name = "+";
+ final val BANG : Name = "!";
+ final val TILDE: Name = "~";
+ final val STAR : Name = "*";
+ final val BAR : Name = "|";
+ final val OPT : Name = "?";
+ final val LT : Name = "<";
+
+ def ident(): Name =
+ if (in.token == IDENTIFIER) {
+ val name = in.name.encode;
+ in.nextToken();
+ name
+ } else {
+ accept(IDENTIFIER);
+ nme.ERROR
+ }
+
+ /** StableRef ::= StableId
+ * | [Ident `.'] this
+ * SimpleType ::= StableRef [`.' type]
+ */
+ def stableRef(thisOK: boolean, typeOK: boolean): Tree = {
+ var t: Tree = null;
+ if (in.token == THIS) {
+ t = atPos(in.skipToken()) { This(nme.EMPTY.toTypeName) }
+ if (!thisOK || in.token == DOT)
+ t = atPos(accept(DOT)) { selectors(t, typeOK) }
+ } else if (in.token == SUPER) {
+ t = atPos(in.skipToken()) {
+ Super(nme.EMPTY.toTypeName, mixinQualifierOpt())
+ }
+ t = atPos(accept(DOT)) { Select(t, ident()) }
+ if (in.token == DOT)
+ t = atPos(in.skipToken()) { selectors(t, typeOK) }
+ } else {
+ val i = atPos(in.pos) { Ident(ident()) }
+ t = i;
+ if (in.token == DOT) {
+ val pos = in.skipToken();
+ if (in.token == THIS) {
+ in.nextToken();
+ t = atPos(i.pos) { This(i.name.toTypeName) }
+ if (!thisOK || in.token == DOT)
+ t = atPos(accept(DOT)) { selectors(t, typeOK) }
+ } else if (in.token == SUPER) {
+ in.nextToken();
+ t = atPos(i.pos) { Super(i.name.toTypeName, mixinQualifierOpt()) }
+ t = atPos(accept(DOT)) { Select(t, ident())}
+ if (in.token == DOT)
+ t = atPos(in.skipToken()) { selectors(t, typeOK) }
+ } else {
+ t = atPos(pos) { selectors(t, typeOK) }
+ }
+ }
+ }
+ t
+ }
+
+ def selectors(t: Tree, typeOK: boolean): Tree =
+ if (typeOK && in.token == TYPE) {
+ in.nextToken();
+ SingletonTypeTree(t)
+ } else {
+ val t1 = Select(t, ident());
+ if (in.token == DOT) atPos(in.skipToken()) { selectors(t1, typeOK) }
+ else t1
+ }
+
+ /** MixinQualifier ::= `[' Id `]'
+ */
+ def mixinQualifierOpt(): Name =
+ if (in.token == LBRACKET) {
+ in.nextToken();
+ val name = ident().toTypeName;
+ accept(RBRACKET);
+ name
+ } else {
+ nme.EMPTY.toTypeName
+ }
+
+ /** StableId ::= Id
+ * | StableRef `.' Id
+ * | [Id '.'] super [MixinQualifier] ` `.' Id
+ */
+ def stableId(): Tree =
+ stableRef(false, false);
+
+ /** QualId ::= Id {`.' Id}
+ */
+ def qualId(): Tree = {
+ val id = atPos(in.pos) { Ident(ident()) }
+ if (in.token == DOT) atPos(in.skipToken()) { selectors(id, false) }
+ else id
+ }
+
+ /** SimpleExpr ::= literal
+ * | symbol [ArgumentExprs]
+ * | null
+ */
+ def literal(isPattern: boolean, isNegated: boolean): Tree = {
+ def litToTree() = atPos(in.pos) {
+ Literal(
+ in.token match {
+ case CHARLIT =>
+ in.intVal.asInstanceOf[char]
+ case INTLIT =>
+ in.intVal(isNegated).asInstanceOf[int]
+ case LONGLIT =>
+ in.intVal(isNegated)
+ case FLOATLIT =>
+ in.floatVal(isNegated).asInstanceOf[float]
+ case DOUBLELIT =>
+ in.floatVal(isNegated)
+ case STRINGLIT | SYMBOLLIT =>
+ in.name.toString()
+ case TRUE =>
+ true
+ case FALSE =>
+ false
+ case NULL =>
+ null
+ case _ =>
+ syntaxError("illegal literal", true);
+ null
+ })
+ }
+
+ val isSymLit = in.token == SYMBOLLIT;
+ val t = litToTree();
+ val pos = in.skipToken();
+ if (isSymLit) {
+ atPos(pos) {
+ var symid = scalaDot(nme.Symbol);
+ if (isPattern) { symid = convertToTypeId(symid) }
+ Apply(symid, List(t))
+ }
+ } else {
+ t
+ }
+ }
+
+//////// TYPES ///////////////////////////////////////////////////////////////
+
+ /** TypedOpt ::= [`:' Type]
+ */
+ def typedOpt(): Tree =
+ if (in.token == COLON) { in.nextToken(); typ() }
+ else EmptyTree;
+
+ /** SimpleTypedOpt ::= [`:' SimpleType]
+ */
+ def simpleTypedOpt(): Tree =
+ if (in.token == COLON) { in.nextToken(); simpleType() }
+ else EmptyTree;
+
+ /** Types ::= Type {`,' Type}
+ */
+ def types(): List[Tree] = {
+ val ts = new ListBuffer[Tree] + typ();
+ while (in.token == COMMA) {
+ in.nextToken();
+ ts + typ();
+ }
+ ts.toList
+ }
+
+ /** Type ::= Type1 `=>' Type
+ * | `(' [Types] `)' `=>' Type
+ * | Type1
+ */
+ def typ(): Tree = {
+ val t =
+ if (in.token == LPAREN) {
+ in.nextToken();
+ if (in.token == RPAREN) {
+ in.nextToken();
+ atPos(accept(ARROW)) { FunctionTypeTree(List(), typ()) }
+ } else {
+ val t0 = typ();
+ if (in.token == COMMA) {
+ in.nextToken();
+ val ts = new ListBuffer[Tree] + t0 ++ types();
+ accept(RPAREN);
+ atPos (accept(ARROW)) { FunctionTypeTree(ts.toList, typ()) }
+ } else {
+ accept(RPAREN); t0
+ }
+ }
+ } else {
+ type1()
+ }
+ if (in.token == ARROW) atPos(in.skipToken()) {
+ FunctionTypeTree(List(t), typ()) }
+ else t
+ }
+
+ /** Type1 ::= SimpleType {with SimpleType} [Refinement]
+ */
+ def type1(): Tree = {
+ val pos = in.pos;
+ var t = simpleType();
+ if (in.token == WITH) {
+ val ts = new ListBuffer[Tree] + t;
+ while (in.token == WITH) {
+ in.nextToken(); ts + simpleType()
+ }
+ t = atPos(pos) { IntersectionTypeTree(ts.toList) }
+ }
+ if (in.token == LBRACE)
+ t = atPos(pos) { RefinementTypeTree(t, refinement()) }
+ t
+ }
+
+ /** SimpleType ::= SimpleType TypeArgs
+ * | SimpleType `#' Id
+ * | StableId
+ * | StableRef `.' type
+ * | `(' Type `)'
+ */
+ def simpleType(): Tree = {
+ val pos = in.pos;
+ var t: Tree =
+ if (in.token == LPAREN) {
+ in.nextToken();
+ val t = typ();
+ accept(RPAREN);
+ t
+ } else {
+ val r = stableRef(false, true);
+ r match {
+ case SingletonTypeTree(_) => r
+ case _ => convertToTypeId(r);
+ }
+ }
+ while (true) {
+ if (in.token == HASH)
+ t = atPos(in.skipToken()) {
+ SelectFromTypeTree(t, ident().toTypeName)
+ }
+ else if (in.token == LBRACKET)
+ t = atPos(pos) { AppliedTypeTree(t, typeArgs()) }
+ else
+ return t
+ }
+ null; //dummy
+ }
+
+ /** TypeArgs ::= `[' Types `]'
+ */
+ def typeArgs(): List[Tree] = {
+ accept(LBRACKET);
+ val ts = types();
+ accept(RBRACKET);
+ ts
+ }
+
+//////// EXPRESSIONS ////////////////////////////////////////////////////////
+
+ /** EqualsExpr ::= `=' Expr
+ */
+ def equalsExpr(): Tree = {
+ accept(EQUALS);
+ expr()
+ }
+
+ /** Exprs ::= Expr {`,' Expr} [ `:' `_' `*' ]
+ */
+ def exprs(): List[Tree] = {
+ val ts = new ListBuffer[Tree] + expr(true, false);
+ while (in.token == COMMA) {
+ in.nextToken(); ts + expr(true, false)
+ }
+ ts.toList
+ }
+
+ /** Expr ::= Bindings `=>' Expr
+ * | Expr1
+ * ResultExpr ::= Bindings `=>' Block
+ * | Expr1
+ * Expr1 ::= (' Expr `)' Expr [[`;'] else Expr]
+ * | try `{' block `}' [catch Expr] [finally Expr]
+ * | while `(' Expr `)' Expr
+ * | do Expr [`;'] while `(' Expr `)'
+ * | for `(' Enumerators `)' (do | yield) Expr
+ * | throw Expr
+ * | return [Expr]
+ * | [SimpleExpr `.'] Id `=' Expr
+ * | SimpleExpr ArgumentExprs `=' Expr
+ * | `.' SimpleExpr
+ * | PostfixExpr [`:' Type1]
+ * Bindings ::= Id [`:' Type1]
+ * | `(' [Binding {`,' Binding}] `)'
+ * Binding ::= Id [`:' Type]
+ */
+
+ def expr(): Tree =
+ expr(false, false);
+
+ def expr(isArgument: boolean, isInBlock: boolean): Tree = {
+ if (in.token == IF) {
+ val pos = in.skipToken();
+ accept(LPAREN);
+ val cond = expr();
+ accept(RPAREN);
+ val thenp = expr();
+ val elsep =
+ if (in.token == ELSE) { in.nextToken(); expr() }
+ else EmptyTree;
+ atPos(pos) { If(cond, thenp, elsep) }
+ } else if (in.token == TRY) {
+ atPos(in.skipToken()) {
+ accept(LBRACE);
+ val body = block();
+ accept(RBRACE);
+ val catcher =
+ if (in.token == CATCH) { in.nextToken(); expr() }
+ else EmptyTree;
+ val finalizer =
+ if (in.token == FINALLY) { in.nextToken(); expr() }
+ else EmptyTree;
+ Try(body, catcher, finalizer)
+ }
+ } else if (in.token == WHILE) {
+ val lname: Name = "label$" + loopNestingDepth;
+ loopNestingDepth = loopNestingDepth + 1;
+ val pos = in.skipToken();
+ accept(LPAREN);
+ val cond = expr();
+ accept(RPAREN);
+ val body = expr();
+ loopNestingDepth = loopNestingDepth - 1;
+ atPos(pos) { makeWhile(lname, cond, body) }
+ } else if (in.token == DO) {
+ val lname: Name = "label$" + loopNestingDepth;
+ loopNestingDepth = loopNestingDepth + 1;
+ val pos = in.skipToken();
+ val body = expr();
+ if (in.token == SEMI) in.nextToken();
+ accept(WHILE);
+ accept(LPAREN);
+ val cond = expr();
+ accept(RPAREN);
+ loopNestingDepth = loopNestingDepth - 1;
+ atPos(pos) { makeDoWhile(lname, body, cond) }
+ } else if (in.token == FOR) {
+ atPos(in.skipToken()) {
+ accept(LPAREN);
+ val enums = enumerators();
+ accept(RPAREN);
+ if (in.token == YIELD) {
+ in.nextToken(); For(enums, expr(), true)
+ } else For(enums, expr(), false)
+ }
+ } else if (in.token == RETURN) {
+ atPos(in.skipToken()) {
+ Return(if (isExprIntro) expr() else Literal(()))
+ }
+ } else if (in.token == THROW) {
+ atPos(in.skipToken()) {
+ Throw(expr())
+ }
+ } else if (in.token == DOT) {
+ atPos(in.skipToken()) {
+ if (in.token == IDENTIFIER) makeClosure(simpleExpr())
+ else { syntaxError("identifier expected", true); errorTermTree }
+ }
+ } else {
+ var t = postfixExpr();
+ if (in.token == EQUALS) {
+ t match {
+ case Ident(_) | Select(_, _) | Apply(_, _) =>
+ t = atPos(in.skipToken()) { Assign(t, expr()) }
+ case _ =>
+ }
+ } else if (in.token == COLON) {
+ val pos = in.skipToken();
+ if (isArgument && in.token == USCORE) {
+ val pos1 = in.skipToken();
+ if (in.token == IDENTIFIER && in.name == nme.STAR) {
+ in.nextToken();
+ t = atPos(pos) {
+ Typed(t, atPos(pos1) { Ident(nme.WILDCARD_STAR.toTypeName) })
+ }
+ } else {
+ syntaxError(in.pos, "`*' expected", true);
+ }
+ } else {
+ t = atPos(pos) { Typed(t, type1()) }
+ }
+ }
+ if (in.token == ARROW) {
+ t = atPos(in.skipToken()) {
+ Function(convertToParams(t), if (isInBlock) block() else expr())
+ }
+ }
+ t
+ }
+ }
+
+ /** PostfixExpr ::= [`.'] InfixExpr [Id]
+ * InfixExpr ::= PrefixExpr
+ * | InfixExpr Id InfixExpr
+ */
+ def postfixExpr(): Tree = {
+ val base = opstack;
+ var top = prefixExpr();
+ while (in.token == IDENTIFIER) {
+ top = reduceStack(
+ true, base, top, precedence(in.name), isLeftAssoc(in.name));
+ opstack = OpInfo(top, in.name, in.pos) :: opstack;
+ ident();
+ if (isExprIntro) {
+ top = prefixExpr();
+ } else {
+ val topinfo = opstack.head;
+ opstack = opstack.tail;
+ return Select(
+ reduceStack(true, base, topinfo.operand, 0, true),
+ topinfo.operator.encode).setPos(topinfo.pos);
+ }
+ }
+ reduceStack(true, base, top, 0, true)
+ }
+
+ /** PrefixExpr ::= [`-' | `+' | `~' | `!'] SimpleExpr
+ */
+ def prefixExpr(): Tree =
+ if (in.token == IDENTIFIER && in.name == MINUS) {
+ val name = ident();
+ in.token match {
+ case INTLIT | LONGLIT | FLOATLIT | DOUBLELIT => literal(false, true)
+ case _ => atPos(in.pos) { Select(simpleExpr(), name) }
+ }
+ } else if (in.token == IDENTIFIER && (in.name == PLUS || in.name == TILDE || in.name == BANG)) {
+ val pos = in.pos;
+ val name = ident();
+ atPos(pos) { Select(simpleExpr(), name) }
+ } else {
+ simpleExpr()
+ }
+
+ /* SimpleExpr ::= literal
+ * | xLiteral
+ * | StableRef
+ * | `(' [Expr] `)'
+ * | BlockExpr
+ * | new Template
+ * | SimpleExpr `.' Id
+ * | SimpleExpr TypeArgs
+ * | SimpleExpr ArgumentExprs
+ */
+ def simpleExpr(): Tree = {
+ var t: Tree = _;
+ in.token match {
+ case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT | STRINGLIT |
+ SYMBOLLIT | TRUE | FALSE | NULL =>
+ t = literal(false, false);
+ case IDENTIFIER | THIS | SUPER =>
+ t = /*if (s.xStartsXML) xmlp.xLiteral else*/ stableRef(true, false);
+ case LPAREN =>
+ val pos = in.skipToken();
+ if (in.token == RPAREN) {
+ in.nextToken();
+ t = Literal(()).setPos(pos);
+ } else {
+ t = expr();
+ if (in.token == COMMA) {
+ val commapos = in.skipToken();
+ val ts = new ListBuffer[Tree] + t ++ exprs();
+ accept(RPAREN);
+ if (in.token == ARROW) {
+ t = atPos(pos) {
+ Function(ts.toList map convertToParam, EmptyTree)
+ }
+ } else {
+ syntaxError(commapos, "`)' expected", false);
+ }
+ } else {
+ accept(RPAREN);
+ }
+ }
+ case LBRACE =>
+ t = blockExpr()
+ case NEW =>
+ t = atPos(in.skipToken()) {
+ val templ = template();
+ New(if (templ.parents.length == 1 && templ.body.isEmpty) templ.parents.head
+ else templ)
+ }
+ case _ =>
+ syntaxError("illegal start of simple expression", true);
+ t = errorTermTree
+ }
+ while (true) {
+ in.token match {
+ case DOT =>
+ t = atPos(in.skipToken()) { Select(t, ident()) }
+ case LBRACKET =>
+ t match {
+ case Ident(_) | Select(_, _) =>
+ t = atPos(in.pos) { TypeApply(t, typeArgs()) }
+ case _ =>
+ return t;
+ }
+ case LPAREN | LBRACE =>
+ t = atPos(in.pos) { Apply(t, argumentExprs()) }
+ case _ =>
+ return t
+ }
+ }
+ null;//dummy
+ }
+
+ /** ArgumentExprs ::= `(' [Exprs] `)'
+ * | BlockExpr
+ */
+ def argumentExprs(): List[Tree] = {
+ if (in.token == LBRACE) {
+ List(blockExpr())
+ } else {
+ accept(LPAREN);
+ val ts = if (in.token == RPAREN) List() else exprs();
+ accept(RPAREN);
+ ts
+ }
+ }
+
+ /** BlockExpr ::= `{' CaseClause {CaseClause} `}'
+ * | `{' Block `}'
+ */
+ def blockExpr(): Tree = {
+ val res =
+ atPos(accept(LBRACE)) {
+ if (in.token == CASE) {
+ var stats: List[CaseDef] = List();
+ do {
+ stats = caseClause() :: stats;
+ } while (in.token == CASE);
+ Visitor(stats.reverse)
+ } else {
+ block()
+ }
+ }
+ accept(RBRACE);
+ res
+ }
+
+ /** Block ::= BlockStatSeq
+ */
+ def block(): Tree = makeBlock(blockStatSeq(new ListBuffer[Tree]));
+
+ /** caseClause : =>= case Pattern [if PostfixExpr] `=>' Block
+ */
+ def caseClause(): CaseDef =
+ atPos(accept(CASE)) {
+ val pat = pattern();
+ val guard =
+ if (in.token == IF) { in.nextToken(); postfixExpr() }
+ else EmptyTree;
+ CaseDef(pat, guard, atPos(accept(ARROW))(block()))
+ }
+
+ /** Enumerators ::= Generator {`;' Enumerator}
+ * Enumerator ::= Generator
+ * | Expr
+ */
+ def enumerators(): List[Tree] = {
+ val enums = new ListBuffer[Tree] + generator();
+ while (in.token == SEMI) {
+ in.nextToken();
+ enums + (if (in.token == VAL) generator() else expr())
+ }
+ enums.toList
+ }
+
+ /** Generator ::= val Pattern1 `<-' Expr
+ */
+ def generator(): Tree =
+ atPos(accept(VAL)) {
+ PatDef(0, pattern1(false), { accept(LARROW); expr() })
+ }
+
+//////// PATTERNS ////////////////////////////////////////////////////////////
+
+ /** Patterns ::= SeqPattern { `,' SeqPattern }
+ */
+ def patterns(): List[Tree] = {
+ val ts = new ListBuffer[Tree];
+ ts + pattern(true);
+ while (in.token == COMMA) {
+ in.nextToken(); ts + pattern(true);
+ }
+ ts.toList
+ }
+
+ /** Pattern ::= Pattern1 { `|' Pattern1 }
+ * SeqPattern ::= SeqPattern1 { `|' SeqPattern1 }
+ */
+ def pattern(seqOK: boolean): Tree = {
+ val pos = in.pos;
+ val t = pattern1(seqOK);
+ if (in.token == IDENTIFIER && in.name == BAR) {
+ val ts = new ListBuffer[Tree] + t;
+ while (in.token == IDENTIFIER && in.name == BAR) {
+ in.nextToken(); ts + pattern1(seqOK);
+ }
+ atPos(pos) { makeAlternative(ts.toList) }
+ } else t
+ }
+
+ def pattern(): Tree = pattern(false);
+
+ /** Pattern1 ::= varid `:' Type1
+ * | `_' `:' Type1
+ * | Pattern2
+ * SeqPattern1 ::= varid `:' Type1
+ * | `_' `:' Type1
+ * | [SeqPattern2]
+ */
+ def pattern1(seqOK: boolean): Tree =
+ if (seqOK && !isExprIntro) {
+ atPos(in.pos) { Sequence(List()) }
+ } else {
+ val p = pattern2(seqOK);
+ if (in.token == COLON && treeInfo.isVarPattern(p))
+ atPos(in.skipToken()) { Typed(p, type1()) }
+ else p
+ }
+
+ /* Pattern2 ::= varid [ @ Pattern3 ]
+ * | Pattern3
+ * SeqPattern2 ::= varid [ @ SeqPattern3 ]
+ * | SeqPattern3
+ */
+ def pattern2(seqOK: boolean): Tree = {
+ val p = pattern3(seqOK);
+ if (in.token == AT) {
+ p match {
+ case Ident(name) =>
+ if (name == nme.WILDCARD) {
+ in.nextToken(); pattern3(seqOK)
+ } else if (treeInfo.isVariableName(name)) {
+ atPos(in.skipToken()) { Bind(name, pattern3(seqOK)) }
+ } else {
+ p
+ }
+ case _ =>
+ p
+ }
+ } else p
+ }
+
+ /* Pattern3 ::= SimplePattern
+ * | SimplePattern {Id SimplePattern}
+ * SeqPattern3 ::= SeqSimplePattern [ '*' | '?' | '+' ]
+ * | SeqSimplePattern {Id SeqSimplePattern}
+ */
+ def pattern3(seqOK: boolean): Tree = {
+ val base = opstack;
+ var top = simplePattern(seqOK);
+ if (seqOK && in.token == IDENTIFIER) {
+ if (in.name == STAR) { /* p* becomes z@( |(p,z)) */
+ return atPos(in.skipToken()) {
+ val zname = fresh();
+ Bind(
+ zname,
+ makeAlternative(List(
+ Sequence(List()), makeSequence(List(top, Ident(zname))))))
+ }
+ } else if (in.name == PLUS) { /* p+ becomes z@(p,(z| )) */
+ return atPos(in.skipToken()) {
+ val zname = fresh();
+ Bind(
+ zname,
+ makeSequence(List(
+ top, makeAlternative(List(Ident(zname), Sequence(List()))))))
+ }
+ } else if (in.name == OPT) { /* p? becomes (p| ) */
+ return atPos(in.skipToken()) {
+ makeAlternative(List(top, Sequence(List())))
+ }
+ }
+ }
+ while (in.token == IDENTIFIER && in.name != BAR) {
+ top = reduceStack(
+ false, base, top, precedence(in.name), isLeftAssoc(in.name));
+ opstack = OpInfo(top, in.name, in.pos) :: opstack;
+ ident();
+ top = simplePattern(seqOK)
+ }
+ reduceStack(false, base, top, 0, true)
+ }
+
+ /** SimplePattern ::= varid
+ * | `_'
+ * | literal
+ * | `<' xLiteralPattern
+ * | StableId [ `(' Patterns `)' ]
+ * | `(' [Pattern] `)'
+ * SimpleSeqPattern ::= varid
+ * | `_'
+ * | literal
+ * | `<' xLiteralPattern
+ * | StableId [ `(' Patterns `)' ]
+ * | `(' Patterns `)'
+ */
+ def simplePattern(seqOK: boolean): Tree = in.token match {
+ case IDENTIFIER | THIS =>
+ var t = stableId();
+ in.token match {
+ case INTLIT | LONGLIT | FLOATLIT | DOUBLELIT =>
+ t match {
+ case Ident(name) if name == nme.MINUS =>
+ return literal(true, true);
+ case _ =>
+ }
+ case _ =>
+ }
+ if (in.token == LPAREN) {
+ atPos(in.skipToken()) {
+ val ps = if (in.token == RPAREN) List() else patterns();
+ accept(RPAREN);
+ Apply(convertToTypeId(t), ps)
+ }
+ } else t
+ case USCORE =>
+ atPos(in.skipToken()) { Ident(nme.WILDCARD) }
+ case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT | STRINGLIT | SYMBOLLIT | TRUE | FALSE | NULL =>
+ literal(true, false)
+ case LPAREN =>
+ val pos = in.skipToken();
+ val p =
+ if (seqOK) atPos(pos) { makeSequence(patterns()) }
+ else if (in.token != RPAREN) pattern(false);
+ else Literal(()).setPos(pos);
+ accept(RPAREN);
+ p
+ case _ =>
+ syntaxError("illegal start of simple pattern", true);
+ errorPatternTree
+ }
+
+////////// MODIFIERS ////////////////////////////////////////////////////////////
+
+ /** Modifiers ::= {Modifier}
+ * Modifier ::= final
+ * | private
+ * | protected
+ * | override
+ * | abstract
+ */
+ def modifiers(): int = {
+ def loop(mods: int): int = in.token match {
+ case ABSTRACT =>
+ loop(addMod(mods, Flags.ABSTRACT))
+ case FINAL =>
+ loop(addMod(mods, Flags.FINAL))
+ case SEALED =>
+ loop(addMod(mods, Flags.SEALED))
+ case PRIVATE =>
+ loop(addMod(mods, Flags.PRIVATE))
+ case PROTECTED =>
+ loop(addMod(mods, Flags.PROTECTED))
+ case OVERRIDE =>
+ loop(addMod(mods, Flags.OVERRIDE))
+ case _ =>
+ mods
+ }
+ loop(0);
+ }
+
+ /** LocalClassModifiers ::= {LocalClassModifier}
+ * LocalClassModifier ::= final
+ * | private
+ */
+ def localClassModifiers(): int = {
+ def loop(mods: int): int = in.token match {
+ case ABSTRACT =>
+ loop(addMod(mods, Flags.ABSTRACT))
+ case FINAL =>
+ loop(addMod(mods, Flags.FINAL))
+ case SEALED =>
+ loop(addMod(mods, Flags.SEALED))
+ case _ =>
+ mods
+ }
+ loop(0)
+ }
+
+ private def addMod(mods: int, mod: int): int = {
+ if ((mods & mod) != 0)
+ syntaxError(in.pos, "repeated modifier", false);
+ in.nextToken();
+ mods | mod;
+ }
+
+//////// PARAMETERS //////////////////////////////////////////////////////////
+
+ /** ParamClauses ::= {ParamClause}
+ */
+ def paramClauses(): List[List[ValDef]] = {
+ val vds = new ListBuffer[List[ValDef]];
+ while (in.token == LPAREN) vds + paramClause(false);
+ vds.toList
+ }
+
+ /** ParamClauseOpt ::= [ParamClause]
+ */
+ def paramClauseOpt(ofClass: boolean): List[List[ValDef]] =
+ if (in.token == LPAREN) List(paramClause(ofClass))
+ else List();
+
+ /** ParamClause ::= `(' [Param {`,' Param}] `)'
+ * ClassParamClause ::= `(' [ClassParam {`,' ClassParam}] `)'
+ */
+ def paramClause(ofClass: boolean): List[ValDef] = {
+ accept(LPAREN);
+ val params = new ListBuffer[ValDef];
+ if (in.token != RPAREN) {
+ params + param(ofClass);
+ while (in.token == COMMA) {
+ in.nextToken(); params + param(ofClass)
+ }
+ }
+ accept(RPAREN);
+ params.toList
+ }
+
+ /** Param ::= Id `:' ParamType
+ * ClassParam ::= [[modifiers] val] Param
+ */
+ def param(ofClass: boolean): ValDef = {
+ atPos(in.pos) {
+ var mods = if (ofClass) modifiers() | Flags.PARAM else Flags.PARAM;
+ if (in.token == VAL) {
+ in.nextToken(); mods = mods | Flags.PARAMACCESSOR;
+ } else if (mods != Flags.PARAM) {
+ accept(VAL);
+ }
+ val name = ident();
+ accept(COLON);
+ ValDef(mods, name, paramType(), EmptyTree)
+ }
+ }
+
+ /** ParamType ::= Type | `=>' Type | Type `*'
+ */
+ def paramType(): Tree =
+ if (in.token == ARROW)
+ atPos(in.skipToken()) { FunctionTypeTree(List(), typ()) }
+ else {
+ val t = typ();
+ if (in.token == IDENTIFIER && in.name == STAR) {
+ in.nextToken();
+ atPos(t.pos) {
+ AppliedTypeTree(
+ scalaDot(nme.REPEATED_PARAM_CLASS_NAME.toTypeName), List(t))
+ }
+ } else t
+ }
+
+ /** TypeParamClauseOpt ::= [`[' TypeParam {`,' TypeParam} `]']
+ * FunTypeParamClauseOpt ::= [`[' FunTypeParam {`,' FunTypeParam} `]']
+ */
+ def typeParamClauseOpt(ofClass: boolean): List[AbsTypeDef] = {
+ val params = new ListBuffer[AbsTypeDef];
+ if (in.token == LBRACKET) {
+ in.nextToken();
+ params + typeParam(ofClass);
+ while (in.token == COMMA) {
+ in.nextToken();
+ params + typeParam(ofClass);
+ }
+ accept(RBRACKET);
+ }
+ params.toList
+ }
+
+ /** TypeParam ::= [`+' | `-'] FunTypeParam
+ * FunTypeParam ::= Id TypeBounds
+ */
+ def typeParam(ofClass: boolean): AbsTypeDef = {
+ var mods = Flags.PARAM;
+ if (ofClass && in.token == IDENTIFIER) {
+ if (in.name == PLUS) {
+ in.nextToken();
+ mods = mods | Flags.COVARIANT;
+ } else if (in.name == MINUS) {
+ in.nextToken();
+ mods = mods | Flags.CONTRAVARIANT;
+ }
+ }
+ atPos(in.pos) { typeBounds(mods, ident()) }
+ }
+
+ /** TypeBounds ::= [`>:' Type] [`<:' Type] [`<%' Type]
+ */
+ def typeBounds(mods: int, name: Name): AbsTypeDef = {
+ def bound(tok: int, default: Name): Tree =
+ if (in.token == tok) { in.nextToken(); typ() }
+ else scalaDot(default.toTypeName);
+ AbsTypeDef(mods, name.toTypeName,
+ bound(SUPERTYPE, nme.All),
+ bound(SUBTYPE, nme.Any),
+ bound(VIEWBOUND, nme.Any))
+ }
+
+//////// DEFS ////////////////////////////////////////////////////////////////
+
+ /** Import ::= import ImportExpr {`,' ImportExpr}
+ */
+ def importClause(): List[Tree] = {
+ accept(IMPORT);
+ val ts = new ListBuffer[Tree] + importExpr();
+ while (in.token == COMMA) {
+ in.nextToken(); ts + importExpr();
+ }
+ ts.toList
+ }
+
+ /** ImportRef ::= StableId `.' (Id | `_' | ImportSelectors)
+ */
+ def importExpr(): Tree =
+ atPos(in.pos) {
+ var t: Tree = null;
+ var pos = 0;
+ if (in.token == THIS) {
+ t = atPos(in.pos) { This(nme.EMPTY.toTypeName) }
+ t = atPos(accept(DOT)) { Select(t, ident()) }
+ pos = accept(DOT);
+ } else {
+ val i = atPos(in.pos) { Ident(ident()) }
+ pos = accept(DOT);
+ if (in.token == THIS) {
+ in.nextToken();
+ t = atPos(i.pos) { This(i.name.toTypeName) }
+ t = atPos(accept(DOT)) { Select(t, ident()) }
+ pos = accept(DOT);
+ } else {
+ t = i;
+ }
+ }
+ def loop: Tree =
+ if (in.token == USCORE) {
+ in.nextToken();
+ Import(t, List(nme.WILDCARD))
+ } else if (in.token == LBRACE) {
+ Import(t, importSelectors())
+ } else {
+ val name = ident();
+ if (in.token == DOT) {
+ t = atPos(pos) { Select(t, name) }
+ pos = accept(DOT);
+ loop
+ } else {
+ Import(t, List(name, name));
+ }
+ }
+ loop
+ }
+
+ /** ImportSelectors ::= `{' {ImportSelector `,'} (ImportSelector | `_') `}'
+ */
+ def importSelectors(): List[Name] = {
+ val names = new ListBuffer[Name];
+ accept(LBRACE);
+ var isLast = importSelector(names);
+ while (!isLast && in.token == COMMA) {
+ in.nextToken();
+ isLast = importSelector(names);
+ }
+ accept(RBRACE);
+ names.toList
+ }
+
+ /** ImportSelector ::= Id [`=>' Id | `=>' `_']
+ */
+ def importSelector(names: ListBuffer[Name]): boolean =
+ if (in.token == USCORE) {
+ in.nextToken(); names + nme.WILDCARD; true
+ } else {
+ val name = ident();
+ names + name;
+ if (in.token == ARROW) {
+ in.nextToken();
+ if (in.token == USCORE) {
+ in.nextToken(); names + nme.WILDCARD;
+ } else {
+ names + ident()
+ }
+ } else {
+ names + name
+ }
+ false
+ }
+
+ /** Def ::= val PatDef
+ * | var VarDef
+ * | def FunDef
+ * | type TypeDef
+ * | TmplDef
+ * Dcl ::= val ValDcl
+ * | var ValDcl
+ * | def FunDcl
+ * | type TypeDcl
+ */
+ def defOrDcl(mods: int): List[Tree] = {
+ in.token match {
+ case VAL =>
+ patDefOrDcl(mods);
+ case VAR =>
+ varDefOrDcl(mods);
+ case DEF =>
+ funDefOrDcl(mods);
+ case TYPE =>
+ in.nextToken();
+ List(typeDefOrDcl(mods))
+ case _ =>
+ tmplDef(mods)
+ }
+ }
+
+ /** PatDef ::= Pattern2 {`,' Pattern2} [`:' Type] `=' Expr
+ * ValDcl ::= Id {`,' Id} `:' Type
+ */
+ def patDefOrDcl(mods: int): List[Tree] = {
+ var newmods = mods;
+ var lhs = new ListBuffer[Tree];
+ do {
+ in.nextToken();
+ lhs + pattern2(false)
+ } while (in.token == COMMA);
+ val tp = typedOpt();
+ val rhs =
+ if (tp == EmptyTree || in.token == EQUALS) equalsExpr()
+ else {
+ newmods = newmods | Flags.DEFERRED;
+ EmptyTree
+ }
+ for (val p <- lhs.toList) yield {
+ atPos(p.pos) {
+ p match {
+ case Ident(name) =>
+ ValDef(mods, name, tp.duplicate, rhs.duplicate)
+ case _ =>
+ if (rhs == EmptyTree) {
+ syntaxError(p.pos, "cannot defer pattern definition", false);
+ errorPatternTree
+ } else {
+ PatDef(
+ mods,
+ if (tp == EmptyTree) p else Typed(p, tp),
+ rhs.duplicate)
+ }
+ }
+ }
+ }
+ }
+
+ /** VarDef ::= Id {`,' Id} [`:' Type] `=' Expr
+ * | Id {`,' Id} `:' Type `=' `_'
+ * VarDcl ::= Id {`,' Id} `:' Type
+ */
+ def varDefOrDcl(mods: int): List[Tree] = {
+ var newmods = mods | Flags.MUTABLE;
+ val lhs = new ListBuffer[Pair[Int, Name]];
+ do {
+ lhs + Pair(in.skipToken(), ident())
+ } while (in.token == COMMA);
+ val tp = typedOpt();
+ val rhs = if (tp == EmptyTree || in.token == EQUALS) {
+ accept(EQUALS);
+ if (tp != EmptyTree && in.token == USCORE) {
+ in.nextToken();
+ EmptyTree
+ } else
+ expr();
+ } else {
+ newmods = newmods | Flags.DEFERRED;
+ EmptyTree
+ }
+ lhs.toList map { case Pair(pos, name) =>
+ ValDef(newmods, name, tp.duplicate, rhs.duplicate) setPos pos }
+ }
+
+ /** FunDef ::= FunSig {`,' FunSig} `:' Type `=' Expr
+ * | this ParamClause `=' ConstrExpr
+ * FunDcl ::= FunSig {`,' FunSig} `:' Type
+ * FunSig ::= id [FunTypeParamClause] ParamClauses
+ */
+ def funDefOrDcl(mods: int): List[Tree] = {
+ in.nextToken();
+ if (in.token == THIS)
+ List(
+ atPos(in.skipToken()) {
+ val vparams = List(paramClause(false));
+ accept(EQUALS);
+ DefDef(
+ mods, nme.CONSTRUCTOR, List(), vparams, EmptyTree, constrExpr())
+ })
+ else {
+ var newmods = mods;
+ val lhs = new ListBuffer[Tuple4[Int, Name, List[AbsTypeDef], List[List[ValDef]]]]
+ + Tuple4(
+ in.pos, ident(), typeParamClauseOpt(false), paramClauses());
+ while (in.token == COMMA)
+ lhs + Tuple4(
+ in.skipToken(), ident(), typeParamClauseOpt(false), paramClauses());
+ val restype = typedOpt();
+ val rhs =
+ if (restype == EmptyTree || in.token == EQUALS) equalsExpr();
+ else {
+ newmods = newmods | Flags.DEFERRED;
+ EmptyTree
+ }
+ for (val Tuple4(pos, name, tparams, vparams) <- lhs.toList) yield
+ DefDef(newmods, name, tparams, vparams,
+ restype.duplicate, rhs.duplicate) setPos pos
+ }
+ }
+
+ /** ConstrExpr ::= SelfInvocation
+ * | `{' SelfInvocation {`;' BlockStat} `}'
+ * SelfInvocation ::= this ArgumentExpr
+ */
+ def constrExpr(): Tree =
+ if (in.token == LBRACE) {
+ atPos(in.skipToken()) {
+ val statlist = new ListBuffer[Tree];
+ statlist + selfInvocation();
+ val stats =
+ if (in.token == SEMI) { in.nextToken(); blockStatSeq(statlist) }
+ else statlist.toList;
+ accept(RBRACE);
+ makeBlock(stats)
+ }
+ } else selfInvocation();
+
+ /** SelfInvocation ::= this ArgumentExprs
+ */
+ def selfInvocation(): Tree =
+ atPos(accept(THIS)) { Apply(Ident(nme.CONSTRUCTOR), argumentExprs()) }
+
+ /** TypeDef ::= Id `=' Type
+ * TypeDcl ::= Id TypeBounds
+ */
+ def typeDefOrDcl(mods: int): Tree =
+ atPos(in.pos) {
+ val name = ident().toTypeName;
+ in.token match {
+ case LBRACKET =>
+ val tparams = typeParamClauseOpt(true);
+ accept(EQUALS);
+ AliasTypeDef(mods, name, tparams, typ())
+ case EQUALS =>
+ in.nextToken();
+ AliasTypeDef(mods, name, List(), typ())
+ case SUPERTYPE | SUBTYPE | VIEWBOUND | SEMI | COMMA | RBRACE =>
+ typeBounds(mods | Flags.DEFERRED, name)
+ case _ =>
+ syntaxError("`=', `>:', or `<:' expected", true);
+ EmptyTree
+ }
+ }
+
+ /** TmplDef ::= ([case] class | trait) ClassDef
+ * | [case] object ObjectDef
+ */
+ def tmplDef(mods: int): List[Tree] = in.token match {
+ case TRAIT =>
+ classDef(mods | Flags.TRAIT | Flags.ABSTRACT);
+ case CLASS =>
+ classDef(mods);
+ case CASECLASS =>
+ classDef(mods | Flags.CASE);
+ case OBJECT =>
+ objectDef(mods);
+ case CASEOBJECT =>
+ objectDef(mods | Flags.CASE);
+ case _ =>
+ syntaxError("illegal start of definition", true);
+ List()
+ }
+
+ /** ClassDef ::= ClassSig {`,' ClassSig} [`:' SimpleType] ClassTemplate
+ * ClassSig ::= Id [TypeParamClause] [ClassParamClause]
+ */
+ def classDef(mods: int): List[Tree] = {
+ val lhs = new ListBuffer[Tuple4[Int, Name, List[AbsTypeDef], List[List[ValDef]]]];
+ do {
+ lhs + Tuple4(in.skipToken(),
+ ident().toTypeName,
+ typeParamClauseOpt(true),
+ paramClauseOpt(true))
+ } while (in.token == COMMA);
+ val thistpe = simpleTypedOpt();
+ val template = classTemplate((mods & Flags.CASE) != 0);
+
+ for (val Tuple4(pos, name, tparams, vparams) <- lhs.toList) yield
+ ClassDef(mods, name, tparams, vparams, thistpe.duplicate,
+ template.duplicate.asInstanceOf[Template]) setPos pos
+ }
+
+ /** ObjectDef ::= Id { , Id } [`:' SimpleType] ClassTemplate
+ */
+ def objectDef(mods: int): List[Tree] = {
+ val lhs = new ListBuffer[Pair[Int, Name]];
+ do {
+ lhs + Pair(in.skipToken(), ident());
+ } while (in.token == COMMA);
+ val thistpe = simpleTypedOpt();
+ val template = classTemplate((mods & Flags.CASE)!= 0);
+ for (val Pair(pos, name) <- lhs.toList) yield
+ ModuleDef(mods, name, thistpe.duplicate,
+ template.duplicate.asInstanceOf[Template]) setPos pos
+ }
+
+ /** ClassTemplate ::= [`extends' Constr] {`with' Constr} [TemplateBody]
+ */
+ def classTemplate(isCaseClass:boolean): Template = {
+ atPos(in.pos) {
+ val parents = new ListBuffer[Tree];
+ if (in.token == EXTENDS) {
+ in.nextToken();
+ parents + constr()
+ } else {
+ parents + scalaAnyRefConstr()
+ }
+ parents + scalaObjectConstr();
+ if (isCaseClass) parents + caseClassConstr();
+ if (in.token == WITH) {
+ in.nextToken();
+ template(parents)
+ } else if (in.token == LBRACE) {
+ Template(parents.toList, templateBody())
+ } else {
+ if (!(in.token == SEMI || in.token == COMMA || in.token == RBRACE))
+ syntaxError("`extends' or `{' expected", true);
+ Template(parents.toList, List())
+ }
+ }
+ }
+
+////////// TEMPLATES ////////////////////////////////////////////////////////////
+ /** Template ::= Constr {`with' Constr} [TemplateBody]
+ */
+ def template(): Template = template(new ListBuffer[Tree]);
+
+ def template(parents: ListBuffer[Tree]): Template = {
+ parents + constr();
+ while (in.token == WITH) {
+ in.nextToken();
+ parents + constr()
+ }
+ val stats = if (in.token == LBRACE) templateBody() else List();
+ Template(parents.toList, stats)
+ }
+
+ /** Constr ::= StableId [TypeArgs] [`(' [Exprs] `)']
+ */
+ def constr(): Tree = {
+ var t: Tree = convertToTypeId(stableId());
+ if (in.token == LBRACKET)
+ t = AppliedTypeTree(t, typeArgs()) setPos in.pos;
+ if (in.token == LPAREN)
+ t = Apply(t, argumentExprs()) setPos in.pos;
+ applyConstr(t)
+ }
+
+ /** TemplateBody ::= `{' [TemplateStat {`;' TemplateStat}] `}'
+ */
+ def templateBody(): List[Tree] = {
+ accept(LBRACE);
+ var body = templateStatSeq();
+ if (body.length == 0) body = List(EmptyTree);
+ accept(RBRACE);
+ body
+ }
+
+ /** Refinement ::= `{' [RefineStat {`;' RefineStat}] `}'
+ */
+ def refinement(): List[Tree] = {
+ accept(LBRACE);
+ val body = refineStatSeq();
+ accept(RBRACE);
+ body
+ }
+
+/////// STATSEQS //////////////////////////////////////////////////////////////
+
+ /** Packaging ::= package QualId `{' TopStatSeq `}'
+ */
+ def packaging(): Tree = {
+ atPos(accept(PACKAGE)) {
+ val pkg = qualId();
+ accept(LBRACE);
+ val stats = topStatSeq();
+ accept(RBRACE);
+ makePackaging(pkg, stats)
+ }
+ }
+
+ /** TopStatSeq ::= [TopStat {`;' TopStat}]
+ * TopStat ::= AttributeClauses Modifiers ClsDef
+ * | Packaging
+ * | Import
+ * |
+ */
+ def topStatSeq(): List[Tree] = {
+ val stats = new ListBuffer[Tree];
+ while (in.token != RBRACE && in.token != EOF) {
+ if (in.token == PACKAGE) {
+ stats + packaging()
+ } else if (in.token == IMPORT) {
+ stats ++ importClause()
+ } else if (in.token == CLASS ||
+ in.token == CASECLASS ||
+ in.token == TRAIT ||
+ in.token == OBJECT ||
+ in.token == CASEOBJECT ||
+ in.token == LBRACKET ||
+ isModifier) {
+ stats ++
+ joinAttributes(attributeClauses(), joinComment(tmplDef(modifiers())))
+ } else if (in.token != SEMI) {
+ syntaxError("illegal start of class or object definition", true);
+ }
+ if (in.token != RBRACE && in.token != EOF) accept(SEMI);
+ }
+ stats.toList
+ }
+
+ /** TemplateStatSeq ::= TemplateStat {`;' TemplateStat}
+ * TemplateStat ::= Import
+ * | AttributeClauses Modifiers Def
+ * | AttributeClauses Modifiers Dcl
+ * | Expr
+ * |
+ */
+ def templateStatSeq(): List[Tree] = {
+ val stats = new ListBuffer[Tree];
+ while (in.token != RBRACE && in.token != EOF) {
+ if (in.token == IMPORT) {
+ stats ++ importClause()
+ } else if (isExprIntro) {
+ stats + expr()
+ } else if (isDefIntro || isModifier || in.token == LBRACKET) {
+ stats ++
+ joinAttributes(attributeClauses(), joinComment(defOrDcl(modifiers())))
+ } else if (in.token != SEMI) {
+ syntaxError("illegal start of definition", true);
+ }
+ if (in.token != RBRACE) accept(SEMI);
+ }
+ stats.toList
+ }
+
+ /** AttributeClauses ::= {AttributeClause}
+ * AttributeClause ::= `[' Attribute {`,' Attribute} `]'
+ * Attribute ::= Constr
+ */
+ def attributeClauses(): List[Tree] = {
+ var attrs = new ListBuffer[Tree];
+ while (in.token == LBRACKET) {
+ in.nextToken();
+ attrs + constr();
+ while (in.token == COMMA) {
+ in.nextToken();
+ attrs + constr()
+ }
+ accept(RBRACKET);
+ }
+ attrs.toList
+ }
+
+ def joinAttributes(attrs: List[Tree], defs: List[Tree]): List[Tree] =
+ defs map (defn =>
+ (attrs :\ defn) ((attr, tree) => Attributed(attr, tree) setPos attr.pos));
+
+ /** RefineStatSeq ::= RefineStat {`;' RefineStat}
+ * RefineStat ::= Dcl
+ * | type TypeDef
+ * |
+ */
+ def refineStatSeq(): List[Tree] = {
+ val stats = new ListBuffer[Tree];
+ while (in.token != RBRACE && in.token != EOF) {
+ if (isDclIntro) {
+ stats ++ joinComment(defOrDcl(0))
+ } else if (in.token != SEMI) {
+ syntaxError("illegal start of declaration", true);
+ }
+ if (in.token != RBRACE) accept(SEMI);
+ }
+ stats.toList
+ }
+
+ /** BlockStatSeq ::= { BlockStat `;' } [Expr]
+ * BlockStat ::= Import
+ * | Def
+ * | LocalModifiers TmplDef
+ * | Expr
+ * |
+ */
+ def blockStatSeq(stats: ListBuffer[Tree]): List[Tree] = {
+ while ((in.token != RBRACE) && (in.token != EOF) && (in.token != CASE)) {
+ if (in.token == IMPORT) {
+ stats ++ importClause();
+ accept(SEMI);
+ } else if (isExprIntro) {
+ stats + expr(false, true);
+ if (in.token != RBRACE && in.token != CASE) accept(SEMI);
+ } else if (isDefIntro) {
+ stats ++ defOrDcl(0);
+ accept(SEMI);
+ if (in.token == RBRACE || in.token == CASE) {
+ stats + Literal(()).setPos(in.pos)
+ }
+ } else if (isLocalModifier) {
+ stats ++ tmplDef(localClassModifiers());
+ accept(SEMI);
+ if (in.token == RBRACE || in.token == CASE) {
+ stats + Literal(()).setPos(in.pos)
+ }
+ } else if (in.token == SEMI) {
+ in.nextToken();
+ } else {
+ syntaxError("illegal start of statement", true);
+ }
+ }
+ stats.toList
+ }
+
+ /** CompilationUnit ::= [ package QualId ( `;' | `{' TopStatSeq `}' ) ] TopStatSeq .
+ */
+ def compilationUnit(): List[Tree] = {
+ if (in.token == PACKAGE) {
+ val pos = in.skipToken();
+ val pkg = qualId();
+ if (in.token == SEMI) {
+ in.nextToken();
+ List(makePackaging(pkg, topStatSeq()) setPos pos);
+ } else {
+ val stats = new ListBuffer[Tree];
+ accept(LBRACE);
+ stats + atPos(pos) { makePackaging(pkg, topStatSeq()) }
+ accept(RBRACE);
+ stats ++ topStatSeq();
+ stats.toList
+ }
+ } else {
+ topStatSeq()
+ }
+ }
+ }
+}
+
+// LocalWords: SOcos
diff --git a/sources/scala/tools/nsc/ast/parser/TokenData.scala b/sources/scala/tools/nsc/ast/parser/TokenData.scala
new file mode 100644
index 0000000000..7a74dfb092
--- /dev/null
+++ b/sources/scala/tools/nsc/ast/parser/TokenData.scala
@@ -0,0 +1,2 @@
+package scala.tools.nsc.ast.parser;
+
diff --git a/sources/scala/tools/nsc/ast/parser/Tokens.scala b/sources/scala/tools/nsc/ast/parser/Tokens.scala
new file mode 100644
index 0000000000..8f3247acd3
--- /dev/null
+++ b/sources/scala/tools/nsc/ast/parser/Tokens.scala
@@ -0,0 +1,85 @@
+package scala.tools.nsc.ast.parser;
+
+object Tokens {
+
+ /** special tokens */
+ val EMPTY = -3;
+ val UNDEF = -2;
+ val ERROR = -1;
+ val EOF = 0;
+
+ /** literals */
+ val CHARLIT = 1;
+ val INTLIT = 2;
+ val LONGLIT = 3;
+ val FLOATLIT = 4;
+ val DOUBLELIT = 5;
+ val STRINGLIT = 6;
+ val SYMBOLLIT = 7;
+
+ /** identifier */
+ val IDENTIFIER = 10;
+
+ /** keywords */
+ val IF = 20;
+ val FOR = 21;
+ val ELSE = 22;
+ val THIS = 23;
+ val NULL = 24;
+ val NEW = 25;
+ val WITH = 26;
+ val SUPER = 27;
+ val CASE = 28;
+ val CASECLASS = 29;
+ val CASEOBJECT = 30;
+ val VAL = 31;
+ val ABSTRACT = 32;
+ val FINAL = 33;
+ val PRIVATE = 34;
+ val PROTECTED = 35;
+ val OVERRIDE = 36;
+ val VAR = 37;
+ val DEF = 38;
+ val TYPE = 39;
+ val EXTENDS = 40;
+ val TRUE = 41;
+ val FALSE = 42;
+ val OBJECT = 43;
+ val CLASS = 44;
+
+ val IMPORT = 46;
+ val PACKAGE = 47;
+ val YIELD = 48;
+ val DO = 49;
+ val TRAIT = 50;
+ val SEALED = 51;
+ val THROW = 52;
+ val TRY = 53;
+ val CATCH = 54;
+ val FINALLY = 55;
+ val WHILE = 56;
+ val RETURN = 57;
+
+ /** special symbols */
+ val COMMA = 61;
+ val SEMI = 62;
+ val DOT = 63;
+ val USCORE = 64;
+ val COLON = 65;
+ val EQUALS = 66;
+ val LARROW = 67;
+ val ARROW = 68;
+ val SUBTYPE = 69;
+ val SUPERTYPE = 70;
+ val HASH = 71;
+ val AT = 72;
+ val VIEWBOUND = 73;
+
+ /** parenthesis */
+ val LPAREN = 90;
+ val RPAREN = 91;
+ val LBRACKET = 92;
+ val RBRACKET = 93;
+ val LBRACE = 94;
+ val RBRACE = 95;
+}
diff --git a/sources/scala/tools/nsc/build b/sources/scala/tools/nsc/build
new file mode 100755
index 0000000000..76113a10f6
--- /dev/null
+++ b/sources/scala/tools/nsc/build
@@ -0,0 +1 @@
+/home/linuxsoft/apps/scala/bin/scalac -d /tmp/classes *.scala ast/*.scala ast/parser/*.scala symtab/*.scala symtab/classfile/*.scala util/*.scala $* \ No newline at end of file
diff --git a/sources/scala/tools/nsc/build.bat b/sources/scala/tools/nsc/build.bat
new file mode 100755
index 0000000000..810d74d61e
--- /dev/null
+++ b/sources/scala/tools/nsc/build.bat
@@ -0,0 +1 @@
+scalac -d c:\classes *.scala ast/*.scala ast/parser/*.scala symtab/*.scala symtab/classfile/*.scala util/*.scala %1 %2 %3 %4 %5 \ No newline at end of file
diff --git a/sources/scala/tools/nsc/grepnsc b/sources/scala/tools/nsc/grepnsc
new file mode 100644
index 0000000000..df9006b7dd
--- /dev/null
+++ b/sources/scala/tools/nsc/grepnsc
@@ -0,0 +1 @@
+grep $1 *.scala ast/*.scala ast/parser/*.scala symtab/*.scala symtab/classfile/*.scala util/*.scala \ No newline at end of file
diff --git a/sources/scala/tools/nsc/scalac b/sources/scala/tools/nsc/scalac
new file mode 100755
index 0000000000..e69de29bb2
--- /dev/null
+++ b/sources/scala/tools/nsc/scalac
diff --git a/sources/scala/tools/nsc/symtab/Definitions.scala b/sources/scala/tools/nsc/symtab/Definitions.scala
new file mode 100755
index 0000000000..205ada1bf4
--- /dev/null
+++ b/sources/scala/tools/nsc/symtab/Definitions.scala
@@ -0,0 +1,231 @@
+package scala.tools.nsc.symtab;
+
+import scala.tools.util.Position;
+import Flags._;
+
+abstract class Definitions: SymbolTable {
+ object definitions {
+
+ // root packages and classes
+ var RootClass: Symbol = _;
+
+ var JavaPackage: Symbol = _;
+ var JavaLangPackage: Symbol = _;
+ var ScalaPackage: Symbol = _;
+ var ScalaPackageClass: Symbol = _;
+
+ var AnyClass: Symbol = _;
+ var AnyValClass: Symbol = _;
+ var ObjectClass: Symbol = _;
+
+ var AnyRefClass: Symbol = _;
+
+ var AllRefClass: Symbol = _;
+ var AllClass: Symbol = _;
+
+ var StringClass: Symbol = _;
+ var ThrowableClass: Symbol = _;
+
+ // the scala value classes
+ var UnitClass: Symbol = _;
+ var BooleanClass: Symbol = _;
+ var ByteClass: Symbol = _;
+ var ShortClass: Symbol = _;
+ var CharClass: Symbol = _;
+ var IntClass: Symbol = _;
+ var LongClass: Symbol = _;
+ var FloatClass: Symbol = _;
+ var DoubleClass: Symbol = _;
+
+ // the scala reference classes
+ var ScalaObjectClass: Symbol = _;
+ var AttributeClass: Symbol = _;
+ var RefClass: Symbol = _;
+ var PartialFunctionClass: Symbol = _;
+ var IterableClass: Symbol = _;
+ var IteratorClass: Symbol = _;
+ var SeqClass: Symbol = _;
+ var ListClass: Symbol = _;
+ var ArrayClass: Symbol = _;
+ var TypeClass: Symbol = _;
+ var PredefModule: Symbol = _;
+ var ConsoleModule: Symbol = _;
+ var MatchErrorModule: Symbol = _;
+ var NilModule: Symbol = _;
+ var ConsClass: Symbol = _;
+ var RepeatedParamClass: Symbol = _;
+
+ def TupleClass(i: int): Symbol = getClass("scala.Tuple" + i);
+ def FunctionClass(i: int): Symbol = getClass("scala.Function" + i);
+
+ // members of class scala.Any
+ var Any_== : Symbol = _;
+ var Any_!= : Symbol = _;
+ var Any_equals : Symbol = _;
+ var Any_hashCode : Symbol = _;
+ var Any_toString : Symbol = _;
+ var Any_isInstanceOf: Symbol = _;
+ var Any_asInstanceOf: Symbol = _;
+ var Any_match : Symbol = _;
+
+ // members of class java.lang.{Object, String}
+ var Object_eq : Symbol = _;
+ var Object_synchronized: Symbol = _;
+ var String_+ : Symbol = _;
+
+ // pattern wildcard
+ var PatternWildcard: Symbol = _;
+
+ def getModule(fullname: Name): Symbol =
+ getModuleOrClass(fullname, true);
+ def getClass(fullname: Name): Symbol =
+ getModuleOrClass(fullname, false);
+
+ private def getModuleOrClass(fullname: Name, module: boolean): Symbol = {
+ var sym = RootClass;
+ var i = 0;
+ var j = fullname.pos('.', i);
+ while (j < fullname.length) {
+ sym = sym.info.lookup(fullname.subName(i, j));
+ i = j + 1;
+ j = fullname.pos('.', i)
+ }
+ val result =
+ if (module)
+ sym.info.lookup(fullname.subName(i, j)).withFlag(MODULE | PACKAGE)
+ else
+ sym.info.lookup(fullname.subName(i, j).toTypeName);
+ if (result == NoSymbol)
+ throw new FatalError((if (module) "object " else "class ") + fullname + " not found.");
+ result
+ }
+
+ private def newClass(owner: Symbol, name: Name, parents: List[Type]): Symbol = {
+ val clazz = owner.newClass(Position.NOPOS, name.toTypeName);
+ clazz.setInfo(ClassInfoType(parents, new Scope(), clazz));
+ owner.info.members.enter(clazz);
+ clazz
+ }
+
+ private def newAlias(owner: Symbol, name: Name, alias: Type): Symbol = {
+ val tpsym = owner.newAliasType(Position.NOPOS, name.toTypeName);
+ tpsym.setInfo(alias);
+ owner.info.members.enter(tpsym);
+ tpsym
+ }
+
+ private def newMethod(owner: Symbol, name: Name): Symbol = {
+ val msym = owner.newMethod(Position.NOPOS, name);
+ owner.info.members.enter(msym);
+ msym
+ }
+
+ private def newTypeParam(owner: Symbol, index: int): Symbol =
+ owner.newTypeParameter(Position.NOPOS, "T" + index)
+ .setInfo(TypeBounds(AllClass.tpe, AnyClass.tpe, AnyClass.tpe));
+
+ def init = {
+ RootClass =
+ NoSymbol.newClass(Position.NOPOS, nme.ROOT.toTypeName)
+ .setFlag(FINAL | PACKAGE | JAVA).setInfo(rootLoader);
+
+ JavaPackage = getModule("java");
+ JavaLangPackage = getModule("java.lang");
+ ScalaPackage = getModule("scala");
+ ScalaPackageClass = ScalaPackage.moduleClass;
+
+ AnyClass = newClass(ScalaPackageClass, "Any", List());
+ AnyValClass = getClass("scala.AnyVal");
+ ObjectClass = getClass("java.lang.Object");
+
+ AnyRefClass = newAlias(ScalaPackageClass, "AnyRef", ObjectClass.tpe);
+
+ AllRefClass = newClass(ScalaPackageClass, "AllRef", List(AnyRefClass.tpe));
+ AllClass = newClass(ScalaPackageClass, "All", List(AnyClass.tpe));
+
+ StringClass = getClass("java.lang.String");
+ ThrowableClass = getClass("java.lang.Throwable");
+
+ // the scala value classes
+ UnitClass = getClass("scala.Unit");
+ BooleanClass = getClass("scala.Boolean");
+ ByteClass = getClass("scala.Byte");
+ ShortClass = getClass("scala.Short");
+ CharClass = getClass("scala.Char");
+ IntClass = getClass("scala.Int");
+ LongClass = getClass("scala.Long");
+ FloatClass = getClass("scala.Float");
+ DoubleClass = getClass("scala.Double");
+
+ // the scala reference classes
+ ScalaObjectClass = getClass("scala.ScalaObject");
+ AttributeClass = getClass("scala.Attribute");
+ RefClass = getClass("scala.Ref");
+ PartialFunctionClass = getClass("scala.PartialFunction");
+ IterableClass = getClass("scala.Iterable");
+ IteratorClass = getClass("scala.Iterator");
+ SeqClass = getClass("scala.Seq");
+ ListClass = getClass("scala.List");
+ ArrayClass = getClass("scala.Array");
+ TypeClass = getClass("scala.Type");
+ PredefModule = getModule("scala.Predef");
+ ConsoleModule = getModule("scala.Console");
+ MatchErrorModule = getModule("scala.MatchError");
+ NilModule = getModule("scala.Nil");
+ ConsClass = getClass("scala.$colon$colon");
+ RepeatedParamClass = newClass(ScalaPackageClass, nme.REPEATED_PARAM_CLASS_NAME, List(SeqClass.tpe));
+
+ // members of class scala.Any
+ Any_== = newMethod(AnyClass, "==")
+ .setInfo(MethodType(List(AnyClass.tpe), BooleanClass.tpe))
+ .setFlag(FINAL);
+ Any_!= = newMethod(AnyClass, "!=")
+ .setInfo(MethodType(List(AnyClass.tpe), BooleanClass.tpe))
+ .setFlag(FINAL);
+ Any_equals = newMethod(AnyClass, "equals")
+ .setInfo(MethodType(List(AnyClass.tpe), BooleanClass.tpe));
+ Any_hashCode = newMethod(AnyClass, "hashCode")
+ .setInfo(MethodType(List(), IntClass.tpe));
+ Any_toString = newMethod(AnyClass, "toString")
+ .setInfo(MethodType(List(), StringClass.tpe));
+ Any_isInstanceOf = newMethod(AnyClass, "isInstanceOf")
+ .setFlag(FINAL);
+ { val tparam = newTypeParam(Any_isInstanceOf, 0);
+ Any_isInstanceOf.setInfo(PolyType(List(tparam), BooleanClass.tpe));
+ }
+ Any_asInstanceOf = newMethod(AnyClass, "asInstanceOf")
+ .setFlag(FINAL);
+ { val tparam = newTypeParam(Any_asInstanceOf, 0);
+ Any_asInstanceOf.setInfo(PolyType(List(tparam), tparam.typeConstructor));
+ }
+ Any_match = newMethod(AnyClass, "match")
+ .setFlag(FINAL);
+ { val tparam0 = newTypeParam(Any_match, 0);
+ val tparam1 = newTypeParam(Any_match, 1);
+ Any_match.setInfo(
+ PolyType(
+ List(tparam0, tparam1),
+ MethodType(List(tparam0.typeConstructor), tparam1.typeConstructor)));
+ }
+
+ // members of class java.lang.{Object, String}
+ Object_eq = newMethod(ObjectClass, "eq")
+ .setInfo(MethodType(List(AnyRefClass.tpe), BooleanClass.tpe))
+ .setFlag(FINAL);
+ Object_synchronized = newMethod(ObjectClass, "synchronized")
+ .setFlag(FINAL);
+ { val tparam = newTypeParam(Object_synchronized, 0);
+ Object_synchronized.setInfo(
+ PolyType(
+ List(tparam),
+ MethodType(List(tparam.typeConstructor), tparam.typeConstructor)));
+ }
+ String_+ = newMethod(StringClass, "+")
+ .setInfo(MethodType(List(AnyClass.tpe), StringClass.tpe))
+ .setFlag(FINAL);
+
+ // pattern wildcard
+ PatternWildcard = NoSymbol.newValue(Position.NOPOS, "_").setInfo(AllClass.tpe)
+ }
+ }
+}
diff --git a/sources/scala/tools/nsc/symtab/Flags.scala b/sources/scala/tools/nsc/symtab/Flags.scala
new file mode 100644
index 0000000000..754ecaa26a
--- /dev/null
+++ b/sources/scala/tools/nsc/symtab/Flags.scala
@@ -0,0 +1,82 @@
+package scala.tools.nsc.symtab;
+
+object Flags {
+
+ // modifiers
+ val DEFERRED = 0x00000001; // was `abstract' for members
+ val FINAL = 0x00000002;
+ val PRIVATE = 0x00000004;
+ val PROTECTED = 0x00000008;
+
+ val SEALED = 0x00000010;
+ val OVERRIDE = 0x00000020;
+ val CASE = 0x00000040;
+ val ABSTRACT = 0x00000080; // abstract class, or used in conjunction
+ // with abstract override.
+ // Note difference to DEFERRED!
+
+ val METHOD = 0x00000100; // a def parameter
+ val TRAIT = 0x00000200; // a trait
+ val JAVA = 0x00000400; // symbol was defined by a Java class
+ val MODULE = 0x00000800; // symbol is module or class implementing a module
+
+ val MUTABLE = 0x00001000; // symbol is a mutable variable.
+ val PARAM = 0x00002000; // symbol is a (value or type) parameter to a method
+ val PACKAGE = 0x00004000; // symbol is a java package
+ val DEPRECATED = 0x00008000; // symbol is deprecated.
+
+ val COVARIANT = 0x00010000; // symbol is a covariant type variable
+ val CONTRAVARIANT = 0x00020000; // symbol is a contravariant type variable
+ val SYNTHETIC = 0x00040000; // symbol is compiler-generated
+ val STABLE = 0x00080000; // functions that are assumed to be stable
+ // (typically, access methods for valdefs)
+ val INITIALIZED = 0x00100000; // symbol's definition is complete
+ val LOCKED = 0x00200000; // temporary flag to catch cyclic dependencies
+ val ACCESSED = 0x00400000; // symbol was accessed at least once
+ val SELECTOR = 0x00800000; // symbol was used as selector in Select
+
+ val CAPTURED = 0x01000000; // variables is accessed from nested function. Set by LambdaLift
+ val ACCESSOR = 0x02000000; // function is an access function for a value or variable
+ val ACCESS_METHOD = 0x04000000; // function is an access function for a method in some
+ // outer class; set by ExplicitOuter
+ val PARAMACCESSOR = 0x08000000; // for methods: is an access method for a val parameter
+ // for parameters: is a val parameter
+
+ val LABEL = 0x10000000; // symbol is a label. Set by TailCall
+ val BRIDGE = 0x20000000; // function is a bridge method. Set by Erasure
+ val IS_ERROR = 0x40000000; // symbol is an error symbol
+
+ val TRANS_FLAG = 0x80000000; // transient flag guaranteed to be reset after each phase.
+ val LIFTED = TRANS_FLAG; // transient flag for lambdalift
+ val INCONSTRUCTOR = TRANS_FLAG; // transient flag for analyzer
+
+ // masks
+ val SOURCEFLAGS = 0x00037777; // these modifiers can be set in source programs.
+ val ACCESSFLAGS = PRIVATE | PROTECTED;
+ val VARIANCES = COVARIANT | CONTRAVARIANT;
+ val CONSTRFLAGS = CASE | JAVA;
+
+ /** Flags already set by object creation and never set afterwards */
+ val CREATIONFLAGS = ACCESSFLAGS | METHOD | MODULE | MUTABLE | PARAM | PACKAGE |
+ COVARIANT | CONTRAVARIANT | SYNTHETIC | STABLE | ACCESSOR | PARAMACCESSOR | IS_ERROR;
+
+ /** Module flags inherited by their module-class */
+ val MODULE2CLASSFLAGS = ACCESSFLAGS | PACKAGE;
+
+ def flagsToString(flags: long): String =
+ List.range(0, 63)
+ .map(i => flagToString(flags & (1L << i)))
+ .filter("" !=).mkString("", " ", "");
+
+ private def flagToString(flag: long): String = flag.asInstanceOf[int] match {
+ case PRIVATE => "private"
+ case PROTECTED => "protected"
+ case ABSTRACT => "abstract"
+ case FINAL => "final"
+ case SEALED => "sealed"
+ case TRAIT => "trait"
+ case OVERRIDE => "override"
+ case CASE => "case"
+ case _ => ""
+ }
+}
diff --git a/sources/scala/tools/nsc/symtab/InfoTransformers.scala b/sources/scala/tools/nsc/symtab/InfoTransformers.scala
new file mode 100644
index 0000000000..fb32abc7b7
--- /dev/null
+++ b/sources/scala/tools/nsc/symtab/InfoTransformers.scala
@@ -0,0 +1,39 @@
+package scala.tools.nsc.symtab;
+
+abstract class InfoTransformers: SymbolTable {
+
+ abstract class InfoTransformer {
+ private var prev: InfoTransformer = this;
+ private var next: InfoTransformer = this;
+
+ val phase: Phase;
+ def transform(sym: Symbol, tpe: Type): Type;
+
+ def insert(that: InfoTransformer): unit = {
+ assert(this.phase.id != that.phase.id);
+ if (that.phase.id < this.phase.id) {
+ prev insert that
+ } else if (next.phase.id <= that.phase.id && next.phase != NoPhase) {
+ next insert that
+ } else {
+ that.next = next;
+ that.prev = this;
+ next.prev = that;
+ this.next = that
+ }
+ }
+
+ def nextFrom(from: Phase): InfoTransformer =
+ if (from.id == this.phase.id) this
+ else if (from.id < this.phase.id)
+ if (prev.phase.id < from.id) this
+ else prev.nextFrom(from);
+ else if (next.phase == NoPhase) next
+ else next.nextFrom(from);
+ }
+}
+
+
+
+
+
diff --git a/sources/scala/tools/nsc/symtab/Names.scala b/sources/scala/tools/nsc/symtab/Names.scala
new file mode 100755
index 0000000000..0c5226c1c3
--- /dev/null
+++ b/sources/scala/tools/nsc/symtab/Names.scala
@@ -0,0 +1,272 @@
+package scala.tools.nsc.symtab;
+
+import scala.tools.nsc.util.NameTransformer;
+
+class Names {
+
+// Operations -------------------------------------------------------------
+
+ private val HASH_SIZE = 0x8000;
+ private val HASH_MASK = 0x7FFF;
+ private val NAME_SIZE = 0x20000;
+
+ /** memory to store all names sequentially
+ */
+ var chrs: Array[char] = new Array[char](NAME_SIZE);
+ private var nc = 0;
+
+ /** hashtable for finding term names quickly
+ */
+ private val termHashtable = new Array[Name](HASH_SIZE);
+
+ /** hashtable for finding type names quickly
+ */
+ private val typeHashtable = new Array[Name](HASH_SIZE);
+
+ /** the hashcode of a name
+ */
+ private def hashValue(cs: Array[char], offset: int, len: int): int =
+ if (len > 0)
+ len * (41 * 41 * 41) +
+ cs(offset) * (41 * 41) +
+ cs(offset + len - 1) * 41 +
+ cs(offset + (len >> 1));
+ else 0;
+
+ /** is (the ascii representation of) name at given index equal to
+ * cs[offset..offset+len-1]?
+ */
+ private def equals(index: int, cs: Array[char], offset: int, len: int): boolean = {
+ var i = 0;
+ while ((i < len) && (chrs(index + i) == cs(offset + i)))
+ i = i + 1;
+ i == len
+ }
+
+ /** enter characters into chrs array
+ */
+ private def enterChars(cs: Array[char], offset: int, len: int): unit = {
+ var i = 0;
+ while (i < len) {
+ if (nc == chrs.length) {
+ val newchrs = new Array[char](chrs.length * 2);
+ System.arraycopy(chrs, 0, newchrs, 0, chrs.length);
+ chrs = newchrs;
+ }
+ chrs(nc + i) = cs(offset + i);
+ i = i + 1
+ }
+ if (len == 0) nc = nc + 1
+ else nc = nc + len
+ }
+
+ /** create a term name from the characters in cs[offset..offset+len-1].
+ */
+ def newTermName(cs: Array[char], offset: int, len: int): Name = {
+ val h = hashValue(cs, offset, len) & HASH_MASK;
+ var n = termHashtable(h);
+ while ((n != null) && (n.length != len || !equals(n.start, cs, offset, len)))
+ n = n.next;
+ if (n == null) {
+ n = new TermName(nc, len, h);
+ enterChars(cs, offset, len);
+ }
+ n
+ }
+
+ /** create a term name from string
+ */
+ def newTermName(s: String): Name =
+ newTermName(s.toCharArray(), 0, s.length());
+
+ /** create a type name from the characters in cs[offset..offset+len-1].
+ */
+ def newTypeName(cs: Array[char], offset: int, len: int): Name = {
+ val h = hashValue(cs, offset, len) & HASH_MASK;
+ var n = typeHashtable(h);
+ while ((n != null) && (n.length != len || !equals(n.start, cs, offset, len)))
+ n = n.next;
+ if (n == null) {
+ n = new TypeName(nc, len, h);
+ enterChars(cs, offset, len);
+ }
+ n
+ }
+
+ /** create a type name from string
+ */
+ def newTypeName(s: String): Name =
+ newTypeName(s.toCharArray(), 0, s.length());
+
+ def nameChars: Array[char] = chrs;
+
+ def view(s: String): Name = newTermName(s);
+
+// Classes ----------------------------------------------------------------------
+
+ /** The name class */
+ abstract class Name(index: int, len: int) extends Function1[int, char] {
+
+ /** Index into name table */
+ def start: int = index;
+
+ /** next name in the same hash bucket
+ */
+ var next: Name = null;
+
+ /** return the length of this name
+ */
+ final def length: int = len;
+
+ def isTermName: boolean;
+ def isTypeName: boolean;
+ def toTermName: Name;
+ def toTypeName: Name;
+
+
+ /** copy bytes of this name to buffer cs, starting at offset
+ */
+ final def copyChars(cs: Array[char], offset: int) =
+ System.arraycopy(chrs, index, cs, offset, len);
+
+ /** return the ascii representation of this name
+ */
+ final def toChars = {
+ val cs = new Array[char](len);
+ copyChars(cs, 0);
+ cs
+ }
+
+ /** return the string representation of this name
+ */
+ final override def toString(): String = new String(chrs, index, len);
+
+ /** return the hash value of this name
+ */
+ final override def hashCode(): int = index;
+
+ /** return the i'th char of this name
+ */
+ final def apply(i: int): char = chrs(index + i);
+
+ /** return the index of first occurrence of char c in this name, length if not found
+ */
+ final def pos(c: char): int = pos(c, 0);
+
+ /** return the index of first occurrence of char c in this name from `start',
+ * length if not found
+ */
+ final def pos(c: char, start: int): int = {
+ var i = start;
+ while (i < len && chrs(index + i) != c) i = i + 1;
+ i
+ }
+
+ /** return the index of last occurrence of char c in this name, -1 if not found.
+ */
+ final def lastPos(c: char): int = lastPos(c, len - 1);
+
+ /** return the index of last occurrence of char c in this name from `start',
+ * -1 if not found
+ */
+ final def lastPos(c: char, start: int): int = {
+ var i = start;
+ while (i >= 0 && chrs(index + i) != c) i = i - 1;
+ i
+ }
+
+ /** does this name start with prefix?
+ */
+ final def startsWith(prefix: Name): boolean = startsWith(prefix, 0);
+
+ /** does this name start with prefix at given start index?
+ */
+ final def startsWith(prefix: Name, start: int): boolean = {
+ var i = 0;
+ while (i < prefix.length && start + i < len && chrs(index + start + i) == chrs(prefix.start + i))
+ i = i + 1;
+ i == prefix.length
+ }
+
+ /** does this name end with suffix?
+ */
+ final def endsWith(suffix: Name): boolean = endsWith(suffix, len);
+
+ /** does this name end with suffix just before given end index?
+ */
+ final def endsWith(suffix: Name, end: int): boolean = {
+ var i = 1;
+ while (i <= suffix.length && i <= end && chrs(index + end - i) == chrs(suffix.start + suffix.length - i))
+ i = i - 1;
+ i == suffix.length
+ }
+
+ /** the subname with characters from start to end-1
+ */
+ def subName(from: int, to: int): Name;
+
+ /** replace all occurrences of `from' by `to' in name.
+ * result is always a term name.
+ */
+ def replace(from: char, to: char): Name = {
+ val cs = new Array[char](len);
+ var i = 0;
+ while (i < len) {
+ val ch = this(i);
+ cs(i) = if (ch == from) to else ch;
+ i = i + 1
+ }
+ newTermName(cs, 0, len)
+ }
+
+ /** Replace operator symbols by corresponding "$op_name" */
+ def encode: Name = {
+ val str = toString();
+ val res = NameTransformer.encode(str);
+ if (res == str) this
+ else if (isTypeName) newTypeName(str)
+ else newTermName(str)
+ }
+
+ /** Replace $op_name by corresponding operator symbol */
+ def decode: String = NameTransformer.decode(toString())
+ }
+
+ private class TermName(index: int, len: int, hash: int) extends Name(index, len) {
+ next = termHashtable(hash);
+ termHashtable(hash) = this;
+ def isTermName: boolean = true;
+ def isTypeName: boolean = false;
+ def toTermName: Name = this;
+ def toTypeName = {
+ val h = hashValue(chrs, index, len) & HASH_MASK;
+ var n = typeHashtable(h);
+ while (n != null && n.start != index)
+ n = n.next;
+ if (n == null)
+ n = new TypeName(index, len, h);
+ n
+ }
+ def subName(from: int, to: int): Name =
+ newTermName(chrs, start + from, to - from);
+ }
+
+ private class TypeName(index: int, len: int, hash: int) extends Name(index, len) {
+ next = typeHashtable(hash);
+ typeHashtable(hash) = this;
+ def isTermName: boolean = false;
+ def isTypeName: boolean = true;
+ def toTermName: Name = {
+ val h = hashValue(chrs, index, len) & HASH_MASK;
+ var n = termHashtable(h);
+ while (n != null && n.start != index)
+ n = n.next;
+ if (n == null)
+ n = new TermName(index, len, h);
+ n
+ }
+ def toTypeName: Name = this;
+ def subName(from: int, to: int): Name =
+ newTypeName(chrs, start + from, to - from);
+ }
+}
diff --git a/sources/scala/tools/nsc/symtab/Scopes.scala b/sources/scala/tools/nsc/symtab/Scopes.scala
new file mode 100755
index 0000000000..d22d82769f
--- /dev/null
+++ b/sources/scala/tools/nsc/symtab/Scopes.scala
@@ -0,0 +1,232 @@
+package scala.tools.nsc.symtab;
+
+abstract class Scopes: SymbolTable {
+
+ abstract class ScopeEntry(val sym: Symbol, val owner: Scope) {
+
+ /** the next entry in the hash bucket
+ */
+ var tail: ScopeEntry = _;
+
+ /** the next entry in this scope
+ */
+ var next: ScopeEntry = null;
+
+ override def hashCode(): int = sym.name.start;
+ override def toString(): String = sym.toString();
+ }
+
+ def newScopeEntry(sym: Symbol, owner: Scope) = new ScopeEntry(sym, owner) {
+ next = owner.elems;
+ owner.elems = this;
+ }
+
+ object NoScopeEntry extends ScopeEntry(NoSymbol, null);
+
+ class Scope(initElems: ScopeEntry) {
+
+ var elems: ScopeEntry = initElems;
+
+ /** the hash table
+ */
+ private var hashtable: Array[ScopeEntry] = null;
+
+ /** a cache for all elements, to be used by symbol iterator.
+ */
+ private var elemsCache: List[Symbol] = null;
+
+ /** size and mask of hash tables
+ * todo: make hashtables grow?
+ */
+ private val HASHSIZE = 0x80;
+ private val HASHMASK = 0x7f;
+
+ /** the threshold number of entries from which a hashtable is constructed.
+ */
+ private val MIN_HASH = 8;
+
+ if (size >= MIN_HASH) createHash;
+
+ def this() = this(null: ScopeEntry);
+
+ def this(base: Scope) = {
+ this(base.elems);
+ if (base.hashtable != null) {
+ this.hashtable = new Array[ScopeEntry](HASHSIZE);
+ System.arraycopy(base.hashtable, 0, this.hashtable, 0, HASHSIZE);
+ }
+ }
+
+ def this(members: List[Symbol]) = {
+ this();
+ members foreach enter
+ }
+
+ /** Returns a new scope with the same content as this one. */
+ def cloneScope: Scope = {
+ val clone = new Scope();
+ this.toList foreach clone.enter;
+ clone
+ }
+
+ /** is the scope empty? */
+ def isEmpty: boolean = elems == null;
+
+ /** the number of entries in this scope */
+ def size: int = {
+ var s = 0;
+ var e = elems;
+ while (e != null) {
+ s = s + 1;
+ e = e.next
+ }
+ s
+ }
+
+ /** enter a scope entry
+ */
+ def enter(e: ScopeEntry): unit = {
+ elems = e;
+ elemsCache = null;
+ if (hashtable != null) {
+ val i = e.sym.name.start & HASHMASK;
+ elems.tail = hashtable(i);
+ hashtable(i) = elems;
+ } else if (size >= MIN_HASH) {
+ createHash;
+ }
+ }
+
+ /** enter a symbol
+ */
+ def enter(sym: Symbol): unit = enter(newScopeEntry(sym, this));
+
+ private def createHash: unit = {
+ hashtable = new Array[ScopeEntry](HASHSIZE);
+ enterInHash(elems);
+ }
+
+ private def enterInHash(e: ScopeEntry): unit = {
+ if (e != null) {
+ enterInHash(e.next);
+ val i = e.sym.name.start & HASHMASK;
+ e.tail = hashtable(i);
+ hashtable(i) = e;
+ }
+ }
+
+ /** remove entry
+ */
+ def unlink(e: ScopeEntry): unit = {
+ if (elems == e) {
+ elems = e.next;
+ } else {
+ var e1 = elems;
+ while (e1.next != e) e1 = e1.next;
+ e1.next = e.next;
+ }
+ if (hashtable != null) {
+ var e1 = hashtable(e.sym.name.start & HASHMASK);
+ if (e1 == e) {
+ hashtable(e.sym.name.start & HASHMASK) = e.tail;
+ } else {
+ while (e1.tail != e) e1 = e1.tail;
+ e1.tail = e.tail;
+ }
+ }
+ elemsCache = null
+ }
+
+ /** remove symbol */
+ def unlink(sym: Symbol): unit =
+ for (val e <- lookupAllEntries(sym.name))
+ if (e.sym == sym) unlink(e);
+
+ /** lookup a symbol
+ */
+ def lookup(name: Name): Symbol = {
+ val e = lookupEntry(name);
+ if (e == null) NoSymbol else e.sym;
+ }
+
+ /** lookup a symbol entry matching given name
+ */
+ def lookupEntry(name: Name): ScopeEntry = {
+ var e: ScopeEntry = null;
+ if (hashtable != null) {
+ e = hashtable(name.start & HASHMASK);
+ while (e != null && e.sym.name != name) e = e.tail;
+ } else {
+ e = elems;
+ while (e != null && e.sym.name != name) e = e.next;
+ }
+ e
+ }
+
+ /** Iterates through all symbol entries matching given name.
+ * Iteration is from last declared to first declared.
+ */
+ def lookupAllEntries(name: Name) = new Iterator[ScopeEntry] {
+ var e: ScopeEntry =
+ if (hashtable != null) hashtable(name.start & HASHMASK)
+ else elems;
+ def hasNext: boolean = {
+ while (e != null && e.sym.name != name)
+ if (hashtable != null) e = e.tail else e = e.next;
+ e != null
+ }
+ def next: ScopeEntry = if (hasNext) {
+ val result = e;
+ if (hashtable != null) e = e.tail else e = e.next;
+ result
+ } else {
+ null
+ }
+ }
+
+ /** Iterates through all symbols matching given name.
+ * Iteration is from last declared to first declared.
+ */
+ def lookupAll(name: Name): Iterator[Symbol] =
+ lookupAllEntries(name) map (.sym);
+
+ /** Return all symbols as a list in the order they were entered in this scope.
+ */
+ def toList: List[Symbol] = {
+ if (elemsCache == null) {
+ elemsCache = Nil;
+ var e = elems;
+ while (e != null) {
+ elemsCache = e.sym :: elemsCache;
+ e = e.next
+ }
+ }
+ elemsCache
+ }
+
+ override def toString(): String =
+ toList.map(.defString).mkString("{\n ", ";\n ", "\n}");
+ }
+
+ /** The empty scope (immutable).
+ */
+ object EmptyScope extends Scope {
+ override def enter(e: ScopeEntry): unit =
+ throw new Error("EmptyScope.enter");
+ }
+
+ /** The error scope.
+ */
+ class ErrorScope(owner: Symbol) extends Scope(null: ScopeEntry) {
+ override def lookupEntry(name: Name): ScopeEntry = {
+ val e = super.lookupEntry(name);
+ if (e != NoSymbol) e
+ else {
+ enter(if (name.isTermName) owner.newErrorValue(name)
+ else owner.newErrorClass(name));
+ super.lookupEntry(name);
+ }
+ }
+ }
+}
+
diff --git a/sources/scala/tools/nsc/symtab/StdNames.scala b/sources/scala/tools/nsc/symtab/StdNames.scala
new file mode 100755
index 0000000000..267bec4142
--- /dev/null
+++ b/sources/scala/tools/nsc/symtab/StdNames.scala
@@ -0,0 +1,193 @@
+package scala.tools.nsc.symtab;
+
+import scala.tools.nsc.util.NameTransformer;
+
+abstract class StdNames: SymbolTable {
+
+ object nme {
+
+ private val LOCAL_PREFIX_STRING = "local$";
+ private val MIXIN_PREFIX_STRING = "mixin$";
+ private val OUTER_PREFIX_STRING = "outer$";
+ private val SUPER_PREFIX_STRING = "super$";
+ private val ACCESS_PREFIX_STRING = "access$";
+ private val TUPLE_FIELD_PREFIX_STRING = "_";
+ private val TYPE_PREFIX_STRING = "type$";
+
+ val LOCAL_PREFIX = newTermName(LOCAL_PREFIX_STRING);
+
+ def LOCAL(clazz: Symbol) = newTermName(LOCAL_PREFIX_STRING + clazz.name);
+
+ def TUPLE_FIELD(index: int) = newTermName(TUPLE_FIELD_PREFIX_STRING + index);
+
+ val ERROR = newTermName("<error>");
+ val ERRORtype = newTypeName("<error>");
+
+ val NOSYMBOL = newTermName("<none>");
+ val EMPTY = newTermName("");
+ val WILDCARD = newTermName("_");
+ val WILDCARD_STAR = newTermName("_*");
+ val COMPOUND_NAME = newTermName("<ct>");
+ val ANON_CLASS_NAME = newTermName("$anon");
+ val REFINE_CLASS_NAME = newTermName("<refinement>");
+ val ZERO = newTermName("<zero>");
+ val STAR = newTermName("*");
+ val ROOT = newTermName("<root>");
+ val REPEATED_PARAM_CLASS_NAME = newTermName("<repeated>");
+
+ val CONSTRUCTOR = newTermName("<init>");
+ val INITIALIZER = newTermName("<init>");
+ val INLINED_INITIALIZER = newTermName("$init$");
+
+ val _EQ = encode("_=");
+ val MINUS = encode("-");
+ val PLUS = encode("+");
+ val TILDE = encode("~");
+ val EQEQ = encode("==");
+ val BANG = encode("!");
+ val BANGEQ = encode("!=");
+ val BARBAR = encode("||");
+ val AMPAMP = encode("&&");
+ val COLONCOLON = encode("::");
+ val PERCENT = encode("%");
+
+ val All = newTermName("All");
+ val AllRef = newTermName("AllRef");
+ val Any = newTermName("Any");
+ val AnyVal = newTermName("AnyVal");
+ val AnyRef = newTermName("AnyRef");
+ val Array = newTermName("Array");
+ val Byte = newTermName("Byte");
+ val CaseClass = newTermName("CaseClass");
+ val Catch = newTermName("Catch");
+ val Char = newTermName("Char");
+ val Boolean = newTermName("Boolean");
+ val Do = newTermName("Do");
+ val Double = newTermName("Double");
+ val Element = newTermName("Element");
+ val Finally = newTermName("Finally");
+ val Float = newTermName("Float");
+ val Function = newTermName("Function");
+ val Int = newTermName("Int");
+ val Labelled = newTermName("Labelled");
+ val List = newTermName("List");
+ val Long = newTermName("Long");
+ val Nil = newTermName("Nil");
+ val Object = newTermName("Object");
+ val PartialFunction = newTermName("PartialFunction");
+ val Predef = newTermName("Predef");
+ val ScalaObject = newTermName("ScalaObject");
+ val ScalaRunTime = newTermName("ScalaRunTime");
+ val Seq = newTermName("Seq");
+ val Short = newTermName("Short");
+ val SourceFile = newTermName("SourceFile");
+ val String = newTermName("String");
+ val Symbol = newTermName("Symbol");
+ val Synthetic = newTermName("Synthetic");
+
+ val Text = newTermName("Text");
+ val Throwable = newTermName("Throwable");
+ val Try = newTermName("Try");
+ val Tuple = newTermName("Tuple");
+ val Type = newTermName("Type");
+ val Tuple2 = newTermName("Tuple2");
+ val Unit = newTermName("Unit");
+ val While = newTermName("While");
+ val apply = newTermName("apply");
+ val array = newTermName("array");
+ val asInstanceOf = newTermName("asInstanceOf");
+ val box = newTermName("box");
+ val checkCastability = newTermName("checkCastability");
+ val coerce = newTermName("coerce");
+ val defaultValue = newTermName("defaultValue");
+ val elem = newTermName("elem");
+ val elements = newTermName("elements");
+ val fail = newTermName("fail");
+ val report = newTermName("report");
+ val false_ = newTermName("false");
+ val filter = newTermName("filter");
+ val flatmap = newTermName("flatMap");
+ val foreach = newTermName("foreach");
+ val getClass_ = newTermName("getClass");
+ val hasAsInstance = newTermName("hasAsInstance");
+ val hashCode_ = newTermName("hashCode");
+ val hasNext = newTermName("hasNext");
+ val head = newTermName("head");
+ val isInstanceOf = newTermName("isInstanceOf");
+ val isDefinedAt = newTermName("isDefinedAt");
+ val isEmpty = newTermName("isEmpty");
+ val java = newTermName("java");
+ val lang = newTermName("lang");
+ val length = newTermName("length");
+ val _match = newTermName("match");
+ val map = newTermName("map");
+ val n = newTermName("n");
+ val nobinding = newTermName("nobinding");
+ val next = newTermName("next");
+ val newArray = newTermName("newArray");
+ val null_ = newTermName("null");
+ val predef = newTermName("predef");
+ val print = newTermName("print");
+ val runtime = newTermName("runtime");
+ val scala = newTermName("scala");
+ val xml = newTermName("xml");
+ val synchronized_ = newTermName("synchronized");
+ val caseArity = newTermName("caseArity");
+ val caseElement = newTermName("caseElement");
+ val eq = newTermName("eq");
+ val equals = newTermName("equals");
+ val tail = newTermName("tail");
+ val toString_ = newTermName("toString");
+ val that = newTermName("that");
+ val that1 = newTermName("that1");
+ val this_ = newTermName("this");
+ val throw_ = newTermName("throw");
+ val true_ = newTermName("true");
+ val update = newTermName("update");
+ val view_ = newTermName("view");
+ val tag = newTermName("$tag");
+ val finalize_ = newTermName("finalize");
+ val wait = newTermName("wait");
+ val notify_ = newTermName("notify");
+ val notifyAll_ = newTermName("notifyAll");
+ val GetType = newTermName("GetType");
+
+ val ZNOT = encode("!");
+ val ZAND = encode("&&");
+ val ZOR = encode("||");
+ val NOT = encode("~");
+ val ADD = encode("+");
+ val SUB = encode("-");
+ val MUL = encode("*");
+ val DIV = encode("/");
+ val MOD = encode("%");
+ val EQ = encode("==");
+ val NE = encode("!=");
+ val LT = encode("<");
+ val LE = encode("<=");
+ val GT = encode(">");
+ val GE = encode(">=");
+ val OR = encode("|");
+ val XOR = encode("^");
+ val AND = encode("&");
+ val LSL = encode("<<");
+ val LSR = encode(">>>");
+ val ASR = encode(">>");
+
+ val SourceFileATTR = newTermName("SourceFile");
+ val SyntheticATTR = newTermName("Synthetic");
+ val BridgeATTR = newTermName("Bridge");
+ val DeprecatedATTR = newTermName("Deprecated");
+ val CodeATTR = newTermName("Code");
+ val ExceptionsATTR = newTermName("Exceptions");
+ val ConstantValueATTR = newTermName("ConstantValue");
+ val LineNumberTableATTR = newTermName("LineNumberTable");
+ val LocalVariableTableATTR = newTermName("LocalVariableTable");
+ val InnerClassesATTR = newTermName("InnerClasses");
+ val JacoMetaATTR = newTermName("JacoMeta");
+ val ScalaSignatureATTR = newTermName("ScalaSignature");
+ val JavaInterfaceATTR = newTermName("JacoInterface");
+ }
+
+ def encode(str: String): Name = newTermName(NameTransformer.encode(str));
+}
diff --git a/sources/scala/tools/nsc/symtab/SymbolLoaders.scala b/sources/scala/tools/nsc/symtab/SymbolLoaders.scala
new file mode 100755
index 0000000000..79cf3b6948
--- /dev/null
+++ b/sources/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -0,0 +1,142 @@
+package scala.tools.nsc.symtab;
+
+import java.io.IOException;
+import scala.tools.util.{AbstractFile, Position}
+import scala.tools.nsc.util.NameTransformer;
+import scala.collection.mutable.HashMap;
+import classfile.ClassfileParser;
+import Flags._;
+
+
+abstract class SymbolLoaders {
+ val global: Global;
+ import global._;
+
+ /** A lazy type that completes itself by calling parameter doComplete.
+ * Any linked modules/classes or module classes are also initialized.
+ * @param doComplete The type completion procedure to be run.
+ * It takes symbol to compkete as parameter and returns
+ * name of file loaded for completion as a result.
+ * Can throw an IOException on error.
+ */
+ class SymbolLoader(doComplete: Symbol => String) extends LazyType {
+ private var ok = false;
+ override def complete(root: Symbol): unit = {
+ try {
+ val start = System.currentTimeMillis();
+ val currentphase = phase;
+ phase = analyzerPhase;
+ val source = doComplete(root);
+ phase = currentphase;
+ informTime("loaded " + source, start);
+ if (root.rawInfo != this) ok = true
+ else error(source + " does not define " + root)
+ } catch {
+ case ex: IOException =>
+ if (settings.debug.value) ex.printStackTrace();
+ val msg = ex.getMessage();
+ error(
+ if (msg == null) "i/o error while loading " + root.name
+ else "error while loading " + root.name + ", " + msg);
+ }
+ initRoot(root);
+ if (!root.isPackageClass)
+ initRoot(if (root.isModule) root.linkedClass else root.linkedModule);
+ }
+
+ private def initRoot(root: Symbol): unit = {
+ if (root.rawInfo == this)
+ root.setInfo(if (ok) NoType else ErrorType);
+ if (root.isModule) initRoot(root.moduleClass)
+ }
+ }
+
+ /** Load contents of a package
+ */
+ def packageLoader(directory: AbstractFile): SymbolLoader =
+ new SymbolLoader(root => {
+ System.out.println("loading " + root);//debug
+ assert(root.isPackageClass, root);
+ val members = new Scope();
+ root.setInfo(new PackageClassInfoType(members, root));
+
+ def enterPackage(str: String, completer: SymbolLoader): unit = {
+ val pkg = root.newPackage(Position.NOPOS, newTermName(str));
+ pkg.moduleClass.setInfo(completer);
+ pkg.setInfo(pkg.moduleClass.tpe);
+ members.enter(pkg)
+ }
+
+ def enterClassAndModule(str: String, completer: SymbolLoader): unit = {
+ val name = newTermName(str);
+ val clazz = root.newClass(Position.NOPOS, name.toTypeName);
+ val module = root.newModule(Position.NOPOS, name);
+ clazz.setInfo(completer);
+ module.setInfo(completer);
+ module.moduleClass.setInfo(errorLoader);
+ members.enter(clazz);
+ members.enter(module);
+ assert(clazz.linkedModule == module);
+ assert(module.linkedClass == clazz);
+ }
+
+ val sources = new HashMap[String, AbstractFile];
+ val classes = new HashMap[String, AbstractFile];
+ val packages = new HashMap[String, AbstractFile];
+ val it = directory.list();
+ while (it.hasNext()) {
+ val file = it.next().asInstanceOf[AbstractFile];
+ val filename = file.getName();
+ if (file.isDirectory()) {
+ if (filename != "META_INF") {
+ if (!packages.isDefinedAt(filename)) packages(filename) = file;
+ }
+ } else if (!root.isRoot && filename.endsWith(".class")) {
+ val name = filename.substring(0, filename.length() - 6);
+ if (!classes.isDefinedAt(name)) classes(name) = file;
+ } else if (!root.isRoot && filename.endsWith(".scala")) {
+ val name = filename.substring(0, filename.length() - 6);
+ if (!sources.isDefinedAt(name)) sources(name) = file;
+ }
+ }
+ for (val Pair(name, sfile) <- sources.elements) {
+ classes.get(name) match {
+ case Some(cfile) if (cfile.lastModified() > sfile.lastModified()) => {}
+ case _ => enterClassAndModule(name, sourcefileLoader(sfile));
+ }
+ }
+ for (val Pair(name, cfile) <- classes.elements) {
+ sources.get(name) match {
+ case Some(sfile) if (sfile.lastModified() > cfile.lastModified()) => {}
+ case _ => enterClassAndModule(name, classfileLoader(cfile));
+ }
+ }
+ for (val Pair(name, file) <- packages.elements) {
+ if (!sources.contains(name) && !classes.contains(name))
+ enterPackage(name, packageLoader(file));
+ }
+
+ "directory path '" + directory + "'"
+ });
+
+ private object classfileParser extends ClassfileParser {
+ val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global;
+ }
+
+ def classfileLoader(file: AbstractFile) =
+ new SymbolLoader(root => {
+ classfileParser.parse(file, root);
+ "class file '" + file + "'";
+ });
+
+ def sourcefileLoader(file: AbstractFile) =
+ new SymbolLoader(root => {
+ global.compileLate(file, false);
+ "source file '" + file + "'";
+ });
+
+ val errorLoader =
+ new SymbolLoader(root => {
+ throw new Error(" loading " + root + " without loading module first");
+ });
+}
diff --git a/sources/scala/tools/nsc/symtab/SymbolTable.scala b/sources/scala/tools/nsc/symtab/SymbolTable.scala
new file mode 100755
index 0000000000..1a0ce88b67
--- /dev/null
+++ b/sources/scala/tools/nsc/symtab/SymbolTable.scala
@@ -0,0 +1,35 @@
+package scala.tools.nsc.symtab;
+
+import util._;
+
+abstract class SymbolTable extends Names
+ with Symbols
+ with Types
+ with Scopes
+ with Definitions
+ with InfoTransformers
+ with StdNames {
+ def settings: Settings;
+ def rootLoader: LazyType;
+
+ private var ph: Phase = NoPhase;
+ def phase: Phase = ph;
+ def phase_=(p: Phase): unit = {
+ //System.out.println("setting phase to " + p);
+ assert(p != null);
+ ph = p
+ }
+
+ def atPhase[T](ph: Phase)(def op: T): T = {
+ val current = phase;
+ phase = ph;
+ val result = op;
+ phase = current;
+ result
+ }
+
+ var infoTransformers = new InfoTransformer {
+ val phase = NoPhase;
+ def transform(sym: Symbol, tpe: Type): Type = tpe;
+ }
+}
diff --git a/sources/scala/tools/nsc/symtab/Symbols.scala b/sources/scala/tools/nsc/symtab/Symbols.scala
new file mode 100755
index 0000000000..0f2017fe21
--- /dev/null
+++ b/sources/scala/tools/nsc/symtab/Symbols.scala
@@ -0,0 +1,658 @@
+package scala.tools.nsc.symtab;
+
+import scala.tools.util.Position;
+import Flags._;
+
+abstract class Symbols: SymbolTable {
+ import definitions._;
+
+ private var ids = 0;
+
+ val emptySymbolArray = new Array[Symbol](0);
+
+ /** The class for all symbols */
+ abstract class Symbol(initOwner: Symbol, initPos: int, initName: Name) {
+
+ var owner = initOwner;
+ var name = initName;
+ var pos = initPos;
+ val id = { ids = ids + 1; ids }
+ private var rawflags: long = 0;
+
+// Creators -------------------------------------------------------------------
+
+ final def newValue(pos: int, name: Name) =
+ new TermSymbol(this, pos, name);
+ final def newVariable(pos: int, name: Name) =
+ newValue(pos, name).setFlag(MUTABLE);
+ final def newValueParameter(pos: int, name: Name) =
+ newValue(pos, name).setFlag(PARAM);
+ final def newLocalDummy(pos: int) =
+ newValue(pos, nme.LOCAL(owner)).setInfo(NoType);
+ final def newMethod(pos: int, name: Name) =
+ newValue(pos, name).setFlag(METHOD);
+ final def newLabel(pos: int, name: Name) =
+ newMethod(pos, name).setFlag(LABEL);
+ final def newConstructor(pos: int) =
+ newMethod(pos, nme.CONSTRUCTOR);
+ final def newModule(pos: int, name: Name, clazz: ClassSymbol) =
+ new ModuleSymbol(this, pos, name, clazz);
+ final def newModule(pos: int, name: Name) =
+ new ModuleSymbol(this, pos, name, null);
+ final def newPackage(pos: int, name: Name) = {
+ assert(isPackageClass);
+ val m = newModule(pos, name);
+ m.setFlag(JAVA | PACKAGE);
+ m.moduleClass.setFlag(JAVA | PACKAGE);
+ m
+ }
+ final def newThisSym(pos: int) =
+ newValue(pos, nme.this_).setFlag(SYNTHETIC);
+ final def newErrorValue(name: Name) =
+ newValue(pos, name).setFlag(SYNTHETIC | IS_ERROR).setInfo(ErrorType);
+ final def newAliasType(pos: int, name: Name) =
+ new TypeSymbol(this, pos, name);
+ final def newAbstractType(pos: int, name: Name) =
+ new TypeSymbol(this, pos, name).setFlag(DEFERRED);
+ final def newTypeParameter(pos: int, name: Name) =
+ newAbstractType(pos, name).setFlag(PARAM);
+ final def newClass(pos: int, name: Name) =
+ new ClassSymbol(this, pos, name);
+ final def newAnonymousClass(pos: int) =
+ newClass(pos, nme.ANON_CLASS_NAME.toTypeName);
+ final def newRefinementClass(pos: int) =
+ newClass(pos, nme.REFINE_CLASS_NAME.toTypeName);
+ final def newErrorClass(name: Name) = {
+ val clazz = newClass(pos, name).setFlag(SYNTHETIC | IS_ERROR);
+ clazz.setInfo(ClassInfoType(List(), new ErrorScope(this), clazz));
+ clazz
+ }
+
+
+// Tests ----------------------------------------------------------------------
+
+ def isTerm = false; //to be overridden
+ def isType = false; //to be overridden
+ def isClass = false; //to be overridden
+
+ final def isValue = isTerm && !(isModule && ((rawflags & (PACKAGE | JAVA)) != 0));
+ final def isVariable = isTerm && (rawflags & MUTABLE) != 0;
+ final def isValueParameter = isTerm && (rawflags & PARAM) != 0;
+ final def isLocalDummy = isTerm && (name startsWith nme.LOCAL_PREFIX);
+ final def isMethod = isTerm && (rawflags & METHOD) != 0;
+ final def isLabel = isTerm && (rawflags & LABEL) != 0;
+ final def isConstructor = isTerm && name == nme.CONSTRUCTOR;
+ final def isModule = isTerm && (rawflags & MODULE) != 0;
+ final def isPackage = isModule && (rawflags & PACKAGE) != 0;
+ final def isThisSym = isTerm && name == nme.this_;
+ final def isError = (rawflags & IS_ERROR) != 0;
+ final def isAliasType = isType && !isClass && (rawflags & DEFERRED) == 0;
+ final def isAbstractType = isType && !isClass && (rawflags & DEFERRED) != 0;
+ final def isTypeParameter = isType && (rawflags & PARAM) != 0;
+ final def isAnonymousClass = isClass && (name startsWith nme.ANON_CLASS_NAME); // startsWith necessary because name may grow when lifted
+ final def isRefinementClass = isClass && name == nme.REFINE_CLASS_NAME; // no lifting for refinement classes
+ final def isModuleClass = isClass && (rawflags & MODULE) != 0;
+ final def isPackageClass = isClass && (rawflags & PACKAGE) != 0;
+ final def isRoot = isPackageClass && name == nme.ROOT.toTypeName;
+
+ /** Does this symbol denote a stable value? */
+ final def isStable =
+ isTerm && (rawflags & MUTABLE) == 0 &&
+ ((rawflags & METHOD) == 0 || (rawflags & STABLE) != 0);
+
+ /** Does this symbol denote the primary constructor
+ * of its enclosing class? */
+ final def isPrimaryConstructor =
+ isConstructor && owner.primaryConstructor == this;
+
+ /** Is this symbol static (i.e. with no outer instance)? */
+ final def isStatic: boolean = isRoot || owner.isStaticOwner;
+
+ /** Does this symbol denote a class that defines static symbols? */
+ final def isStaticOwner: boolean = isPackageClass || isStatic && isModuleClass;
+
+ /** Is this symbol final?*/
+ final def isFinal: boolean = hasFlag(FINAL | PRIVATE) || isLocal || owner.isModuleClass;
+
+ /** Is this symbol locally defined? I.e. not a member of a class or module */
+ final def isLocal: boolean = owner.isTerm;
+
+ /** Is this class locally defined?
+ * A class is local, if
+ * - it is anonymous, or
+ * - its owner is a value
+ * - it is defined within a local class
+ */
+ final def isLocalClass: boolean =
+ isClass && (isAnonymousClass || isRefinementClass || isLocal ||
+ !owner.isPackageClass && owner.isLocalClass);
+
+ /** Symbol was preloaded from package */
+ final def isExternal: boolean = pos == Position.NOPOS;
+
+ /** The variance of this symbol as an integer */
+ final def variance: int =
+ if ((rawflags & COVARIANT) != 0) 1
+ else if ((rawflags & CONTRAVARIANT) != 0) -1
+ else 0;
+
+// Flags ----------------------------------------------------------------------------
+
+ final def flags = {
+ initialize; rawflags & phase.flagMask
+ }
+ final def setFlag(mask: long): Symbol = {
+ rawflags = rawflags | mask; this
+ }
+ final def resetFlag(mask: long): Symbol = {
+ rawflags = rawflags & ~mask; this
+ }
+ final def getFlag(mask: long): long =
+ (if ((mask & ~CREATIONFLAGS) == 0) rawflags else flags) & mask;
+ final def hasFlag(mask: long): boolean =
+ ((if ((mask & ~CREATIONFLAGS) == 0) rawflags else flags) & mask) != 0;
+ final def resetFlags =
+ rawflags = rawflags & SOURCEFLAGS;
+
+// Info and Type -------------------------------------------------------------------
+
+ private var infos: TypeHistory = null;
+ private var limit: Phase = NoPhase;
+
+ /** Get type. The type of a symbol is:
+ * for a type symbol, the type corresponding to the symbol itself
+ * for a term symbol, its usual type
+ */
+ def tpe: Type = info;
+
+ /** Get type info associated with symbol at current phase, after
+ * ensuring that symbol is initialized (i.e. type is completed).
+ */
+ final def info: Type = {
+ var cnt = 0;
+ while ((rawflags & INITIALIZED) == 0) {
+ assert(infos != null, "infos null for " + this.name);//debug
+ val tp = infos.info;
+ if ((rawflags & LOCKED) != 0) {
+ setInfo(ErrorType);
+ throw new CyclicReference(this, tp);
+ }
+ rawflags = rawflags | LOCKED;
+ val current = phase;
+ phase = infos.start;
+ //System.out.println("completing " + this);//DEBUG
+ tp.complete(this);
+ phase = current;
+ rawflags = rawflags & ~LOCKED;
+ cnt = cnt + 1;
+ // allow for two completions:
+ // one: sourceCompleter to LazyType, two: LazyType to completed type
+ if (cnt == 2) throw new Error("no progress in completing " + this + ":" + tp);
+ }
+ rawInfo
+ }
+
+ /** Set initial info. */
+ def setInfo(info: Type): Symbol = {
+ infos = new TypeHistory(phase, info, null);
+ limit = phase;
+ assert(info != null, "setInfo(null) for " + name + " at phase " + phase);//debug
+ rawflags = if (info.isComplete) rawflags | INITIALIZED
+ else rawflags & ~INITIALIZED;
+ if (info.isInstanceOf[MethodType] || info.isInstanceOf[PolyType])
+ assert(isClass || (rawflags & METHOD) != 0);
+ this
+ }
+
+ /** Set new info valid from start of next phase. */
+ final def updateInfo(info: Type): Symbol = {
+ val current = phase;
+ phase = phase.next;
+ assert(infos.start.id <= phase.id);
+ if (infos.start == phase) infos = infos.prev;
+ infos = new TypeHistory(phase, info, infos);
+ phase = current;
+ this
+ }
+
+ /** Return info without checking for initialization or completing */
+ final def rawInfo: Type = {
+ if (limit.id < phase.id) {
+ if ((rawflags & INITIALIZED) != 0) {
+ val current = phase;
+ var itr = infoTransformers.nextFrom(limit);
+ infoTransformers = itr; // caching optimization
+ while (itr.phase != NoPhase && itr.phase.id < current.id) {
+ phase = itr.phase;
+ val info1 = itr.transform(this, infos.info);
+ if (!(info1 eq infos.info))
+ infos = new TypeHistory(phase.next, info1, infos);
+ itr = itr.nextFrom(phase.next)
+ }
+ phase = current;
+ limit = current;
+ }
+ assert(infos != null, "info = null at " + this.name + " " + limit + " " + phase);//debug
+ infos.info
+ } else {
+ var infos = this.infos;
+ while (phase.id < infos.start.id && infos.prev != null) infos = infos.prev;
+ infos.info
+ }
+ }
+
+ /** Initialize the symbol */
+ final def initialize: Symbol = {
+ if ((rawflags & INITIALIZED) == 0) info;
+ this
+ }
+
+ /** Was symbol's type updated during given phase? */
+ final def isUpdatedAt(phase: Phase): boolean = {
+ var infos = this.infos;
+ while (infos != null && infos.start != phase.next) infos = infos.prev;
+ infos != null
+ }
+
+ /** The type constructor of a symbol is:
+ * For a type symbol, the type corresponding to the symbol itself,
+ * excluding parameters.
+ * Not applicable for term symbols.
+ */
+ def typeConstructor: Type = throw new Error("typeConstructor inapplicable for " + this);
+
+ /** The type parameters of this symbol */
+ def typeParams: List[Symbol] = rawInfo.typeParams;
+
+// Comparisons ----------------------------------------------------------------
+
+ /** A total ordering between symbols that refines the class
+ * inheritance graph (i.e. subclass.isLess(superclass) always holds).
+ * the ordering is given by: (isType, -|closure| for type symbols, id)
+ */
+ final def isLess(that: Symbol): boolean =
+ if (this.isType)
+ that.isType &&
+ {val diff = this.info.closure.length - that.info.closure.length;
+ diff > 0 || diff == 0 && this.id < that.id}
+ else
+ that.isType || this.id < that.id;
+
+ /** A partial ordering between symbols.
+ * (this isNestedIn that) holds iff this symbol is defined within
+ * a class or method defining that symbol
+ */
+ final def isNestedIn(that: Symbol): boolean =
+ owner == that || owner != NoSymbol && (owner isNestedIn that);
+
+ /** Is this class symbol a subclass of that symbol? */
+ final def isSubClass(that: Symbol): boolean =
+ this == that || this.isError || that.isError ||
+ info.closurePos(that) >= 0 ||
+ this == AllClass ||
+ this == AllRefClass &&
+ (that == AnyClass ||
+ that != AllClass && (that isSubClass AnyRefClass));
+
+// Overloaded Alternatives ---------------------------------------------------------
+
+ /** All overloaded alternatives of this symbol */
+ def alternatives: Iterator[Symbol] =
+ Iterator.fromValues(this);
+
+ private def findUnique(alts: Iterator[Symbol], p: Symbol => boolean): Symbol = {
+ if (alts.hasNext) {
+ val alt = alts.next;
+ if (p(alt)) {
+ while (alts.hasNext) assert(!p(alts.next));
+ alt
+ } else findUnique(alts, p)
+ } else NoSymbol
+ }
+
+ /** The unique alternative whose type at given prefix `pre' matches `tp'
+ * or NoSymbol, if no such alternatives exist.
+ */
+ final def matching(pre: Type, tp: Type): Symbol =
+ findUnique(alternatives, alt => pre.memberType(alt).matches(tp));
+
+ final def withFlag(mask: long): Symbol =
+ findUnique(alternatives, .hasFlag(mask));
+
+ /** Reset symbol to initial state
+ */
+ def reset(completer: Type): unit = {
+ resetFlags;
+ pos = Position.NOPOS;
+ infos = null;
+ setInfo(completer)
+ }
+
+// Cloneing -------------------------------------------------------------------
+
+ /** A clone of this symbol */
+ final def cloneSymbol: Symbol =
+ cloneSymbol(owner);
+
+ /** A clone of this symbol, but with given owner */
+ final def cloneSymbol(owner: Symbol): Symbol =
+ cloneSymbolImpl(owner).setInfo(info.cloneInfo(owner)).setFlag(rawflags);
+
+ /** Internal method to clone a symbol's implementation without flags or type
+ */
+ def cloneSymbolImpl(owner: Symbol): Symbol;
+
+// Access to related symbols --------------------------------------------------
+
+ /** The next enclosing class */
+ def enclClass: Symbol = if (isClass) this else owner.enclClass;
+
+ /** The next enclosing method */
+ def enclMethod: Symbol = if (isMethod) this else owner.enclMethod;
+
+ /** The primary constructor of a class */
+ def primaryConstructor: Symbol = {
+ var constr: Symbol = NoSymbol;
+ val syms = info.members.lookupAll(nme.CONSTRUCTOR);
+ while (syms.hasNext) constr = syms.next;
+ constr
+ }
+
+ /** The self symbol of a class with explicit self type, or else the symbol itself.
+ */
+ def thisSym: Symbol = this;
+
+ /** The type of `this' in a class, or else the type of the symbol itself. */
+ final def typeOfThis = thisSym.tpe;
+
+ /** Sets the type of `this' in a class */
+ def typeOfThis_=(tp: Type): unit = throw new Error("typeOfThis cannot be set for " + this);
+
+ /** If symbol is a class, the type this.type in this class, otherwise NoPrefix */
+ def thisType: Type = NoPrefix;
+
+ /** Return every accessor of a primary constructor parameter in this case class */
+ final def caseFieldAccessors: List[Symbol] = {
+ assert(isClass && hasFlag(CASE));
+ info.members.toList.filter(sym => sym.isMethod && sym.hasFlag(PARAMACCESSOR))
+ }
+
+ /** The symbol accessed by this accessor function.
+ */
+ final def accessed: Symbol = {
+ assert((rawflags & ACCESSOR) != 0);
+ val name1 = if (name.endsWith(nme._EQ)) name.subName(0, name.length - nme._EQ.length)
+ else name;
+ owner.info.lookup(name1.toString() + "$")
+ }
+
+ /** The class with the same name in the same package as this module or
+ * case class factory
+ */
+ final def linkedClass: Symbol = {
+ if (!owner.isPackageClass) NoSymbol
+ else {
+ val clazz = owner.info.lookup(name.toTypeName);
+ if (clazz.rawInfo == NoType) NoSymbol else clazz
+ }
+ }
+
+ /** The module or case class factory with the same name in the same
+ * package as this class.
+ */
+ final def linkedModule: Symbol = {
+ if (!owner.isPackageClass) NoSymbol
+ else {
+ val module = owner.info.lookup(name.toTermName).withFlag(MODULE);
+ if (module.rawInfo == NoType) NoSymbol else module
+ }
+ }
+
+ /** The module corresponding to this module class (note that this
+ * is not updated when a module is cloned).
+ */
+ def sourceModule: Symbol = NoSymbol;
+
+ /** The module class corresponding to this module.
+ */
+ def moduleClass: Symbol = NoSymbol;
+
+ /** The symbol overridden by this symbol in given base class */
+ final def overriddenSymbol(base: Symbol): Symbol =
+ base.info.lookupNonPrivate(name).matching(owner.thisType, info);
+
+ /** The symbol overriding this symbol in given subclass */
+ final def overridingSymbol(base: Symbol): Symbol =
+ base.info.lookupNonPrivate(name).matching(base.thisType, base.tpe.memberType(this));
+
+// ToString -------------------------------------------------------------------
+
+ /** A tag which (in the ideal case) uniquely identifies class symbols */
+ final def tag: int = name.toString().hashCode();
+
+ /** The simple name of this Symbol (this is always a term name) */
+ final def simpleName: Name =
+ if (isConstructor && !settings.debug.value) owner.name.toTermName else name;
+
+ /** String representation of symbol's definition key word */
+ final def keyString: String =
+ if (isClass)
+ if (hasFlag(TRAIT))
+ if (hasFlag(JAVA)) "interface" else "trait"
+ else "class"
+ else if (isType && !hasFlag(PARAM)) "type"
+ else if (isVariable) "var"
+ else if (isPackage) "package"
+ else if (isModule) "object"
+ else if (isMethod) "def"
+ else if (isTerm && (!hasFlag(PARAM) || hasFlag(PARAMACCESSOR))) "val"
+ else "";
+
+ /** String representation of symbol's kind */
+ final def kindString: String =
+ if (isPackageClass)
+ if (settings.debug.value) "package class" else "package"
+ else if (isAnonymousClass) "<template>"
+ else if (isRefinementClass) ""
+ else if (isModuleClass) "singleton class"
+ else if (isClass)
+ if ((rawflags & TRAIT) != 0) "trait" else "class"
+ else if (isType) "type"
+ else if (isVariable) "variable"
+ else if (isPackage) "package"
+ else if (isModule) "object"
+ else if (isConstructor) "constructor"
+ else if (isMethod) "method"
+ else if (isTerm) "value"
+ else "";
+
+ /** String representation of symbol's simple name.
+ * If !settings.debug translates expansions of operators back to operator symbol.
+ * E.g. $eq => =.
+ * If settings.uniquId adds id.
+ */
+ final def nameString: String =
+ simpleName.decode + idString;
+
+ /** String representation of symbol's full name with `separator'
+ * between class names.
+ * Never translates expansions of operators back to operator symbol.
+ * Never adds id.
+ */
+ final def fullNameString(separator: char): String =
+ if (owner.isRoot) simpleName.toString()
+ else owner.fullNameString(separator) + separator + simpleName;
+
+ final def fullNameString: String = fullNameString('.');
+
+ /** If settings.uniqid is set, the symbol's id, else "" */
+ final def idString: String =
+ if (settings.uniqid.value) "#" + id else "";
+
+ /** String representation, including symbol's kind
+ * e.g., "class Foo", "method Bar".
+ */
+ override def toString(): String =
+ compose(List(kindString, nameString));
+
+ /** String representation of location. */
+ final def locationString: String =
+ if (owner.isClass &&
+ (!owner.isAnonymousClass && !owner.isRefinementClass || settings.debug.value))
+ " in " + (if (owner.isModuleClass) owner.sourceModule else owner)
+ else "";
+
+ /** String representation of symbol's definition following its name */
+ final def infoString(tp: Type): String = {
+ def typeParamsString: String = tp match {
+ case PolyType(tparams, _) if (tparams.length != 0) =>
+ (tparams map (.defString)).mkString("[", ",", "]")
+ case _ =>
+ ""
+ }
+ if (isClass)
+ typeParamsString + " extends " + tp.resultType
+ else if (isAliasType)
+ typeParamsString + " = " + tp.resultType
+ else if (isAbstractType)
+ tp.match {
+ case TypeBounds(lo, hi, vu) =>
+ (if (lo.symbol == AllClass) "" else " >: " + lo) +
+ (if (hi.symbol == AnyClass) "" else " <: " + hi) +
+ (if (vu.symbol == AnyClass) "" else " <% " + vu)
+ case _ =>
+ "<: " + tp;
+ }
+ else if (isModule)
+ moduleClass.infoString(tp)
+ else
+ tp match {
+ case PolyType(tparams, res) =>
+ typeParamsString + infoString(res)
+ case MethodType(pts, res) =>
+ pts.mkString("(", ",", ")") + infoString(res)
+ case _ =>
+ ": " + tp
+ }
+ }
+
+ /** String representation of symbol's variance */
+ private def varianceString: String =
+ if (variance > 0) "+"
+ else if (variance < 0) "-"
+ else "";
+
+ /** String representation of symbol's definition */
+ final def defString: String =
+ compose(List(flagsToString(flags & SOURCEFLAGS),
+ keyString,
+ varianceString + nameString,
+ infoString(rawInfo)));
+
+ /** Concatenate strings separated by spaces */
+ private def compose(ss: List[String]): String =
+ ss.filter("" !=).mkString("", " ", "");
+ }
+
+ /** A class for term symbols */
+ class TermSymbol(initOwner: Symbol, initPos: int, initName: Name) extends Symbol(initOwner, initPos, initName) {
+ override def isTerm = true;
+ override def alternatives: Iterator[Symbol] =
+ if (owner.isClass) owner.info.members.lookupAll(name)
+ else super.alternatives;
+ def cloneSymbolImpl(owner: Symbol): Symbol =
+ new TermSymbol(owner, pos, name);
+ }
+
+ /** A class for module symbols */
+ class ModuleSymbol(initOwner: Symbol, initPos: int, initName: Name, mclazz: ClassSymbol) extends TermSymbol(initOwner, initPos, initName) {
+ setFlag(MODULE | FINAL);
+ private val clazz: ClassSymbol =
+ if (mclazz != null) mclazz else new ModuleClassSymbol(this);
+ override def moduleClass: ClassSymbol = clazz;
+ override def cloneSymbolImpl(owner: Symbol): Symbol =
+ new ModuleSymbol(owner, pos, name, clazz);
+ }
+
+ /** A class of type symbols. Alias and abstract types are direct instances
+ * of this class. Classes are instances of a subclass.
+ */
+ class TypeSymbol(initOwner: Symbol, initPos: int, initName: Name) extends Symbol(initOwner, initPos, initName) {
+ override def isType = true;
+ private var tyconCache: Type = null;
+ private var tpeCache: Type = _;
+ private var valid: Phase = null;
+ override def tpe: Type = {
+ if (valid != phase) {
+ valid = phase;
+ tpeCache = typeRef(owner.thisType, this, typeParams map (.tpe))
+ }
+ tpeCache
+ }
+ override def typeConstructor: Type = {
+ if (tyconCache == null)
+ tyconCache = typeRef(owner.thisType, this, List());
+ tyconCache;
+ }
+ override def reset(completer: Type): unit = {
+ super.reset(completer);
+ valid = null;
+ tyconCache = null;
+ }
+ def cloneSymbolImpl(owner: Symbol): Symbol =
+ new TypeSymbol(owner, pos, name);
+ }
+
+ /** A class for class symbols */
+ class ClassSymbol(initOwner: Symbol, initPos: int, initName: Name)
+ extends TypeSymbol(initOwner, initPos, initName) {
+ private var thissym: Symbol = this;
+ override def isClass: boolean = true;
+ override def reset(completer: Type): unit = {
+ super.reset(completer);
+ thissym = this;
+ }
+
+ /** the type this.type in this class */
+ override val thisType: Type = ThisType(this);
+
+ /** A symbol carrying the self type of the class as its type */
+ override def thisSym: Symbol = thissym;
+
+ /** Sets the self type of the class */
+ override def typeOfThis_=(tp: Type): unit =
+ thissym = newThisSym(pos).setInfo(tp);
+
+ override def cloneSymbolImpl(owner: Symbol): Symbol = {
+ assert(!isModuleClass);
+ val clone = new ClassSymbol(owner, pos, name);
+ if (thisSym != this) clone.typeOfThis = typeOfThis;
+ clone
+ }
+ }
+
+ /** A class for module class symbols */
+ class ModuleClassSymbol(module: ModuleSymbol)
+ extends ClassSymbol(module.owner, module.pos, module.name.toTypeName) {
+ setFlag(module.getFlag(MODULE2CLASSFLAGS) | MODULE | FINAL);
+ override def sourceModule = module;
+ }
+
+ /** An object repreesenting a missing symbol */
+ object NoSymbol extends Symbol(null, Position.NOPOS, nme.NOSYMBOL) {
+ super.setInfo(NoType);
+ override def setInfo(info: Type): Symbol = { assert(info == NoType); this }
+ override def enclClass: Symbol = this;
+ override def enclMethod: Symbol = this;
+ override def owner: Symbol = throw new Error();
+ override def reset(completer: Type): unit = {}
+ override def alternatives: Iterator[Symbol] = Iterator.empty[Symbol];
+ def cloneSymbolImpl(owner: Symbol): Symbol = throw new Error();
+ }
+
+ /** An exception for cyclic references of symbol definitions */
+ case class CyclicReference(sym: Symbol, info: Type) extends TypeError("illegal cyclic reference involving " + sym);
+
+ /** A class for type histories */
+ private class TypeHistory(val start: Phase, val info: Type, val prev: TypeHistory);
+}
diff --git a/sources/scala/tools/nsc/symtab/Types.scala b/sources/scala/tools/nsc/symtab/Types.scala
new file mode 100755
index 0000000000..e3faa45813
--- /dev/null
+++ b/sources/scala/tools/nsc/symtab/Types.scala
@@ -0,0 +1,1499 @@
+package scala.tools.nsc.symtab;
+
+import scala.tools.util.Position;
+import Flags._;
+
+abstract class Types: SymbolTable {
+ import definitions._;
+
+ private var explainSwitch = false;
+
+ val emptyTypeArray = new Array[Type](0);
+
+ /** The base class for all types */
+ trait Type {
+
+ /** The symbol associated with the type */
+ def symbol: Symbol = NoSymbol;
+
+ /** The base type underlying a singleton type,
+ * identity on all other types */
+ def singleDeref: Type = this;
+
+ /** Widen from singleton type to its underlying non-singleton base type
+ * by applying one or more singleDeref steps,
+ * identity for all other types */
+ def widen: Type = this;
+
+ /** Map to a this type which is a subtype of this type.
+ */
+ def narrow: Type = {
+ val reftpe = refinedType(this, commonOwner(this), EmptyScope);
+ ThisType(reftpe.symbol);
+ }
+
+ /** Map a constant type to its underlying base type,
+ * identity for all other types */
+ def deconst: Type = this;
+
+ /** Map a parameterless method type to its result type
+ * identity for all other types */
+ def derefDef: Type = match {
+ case PolyType(List(), restp) => restp
+ case _ => this
+ }
+
+ /** For a TypeBounds type, itself;
+ * for a reference denoting an abstract type, its bounds,
+ * for all other types, a TypeBounds type all of whose bounds are this type.
+ * error for all other types */
+ def bounds: TypeBounds = TypeBounds(this, this, this);
+
+ /** For a class or intersection type, its parents.
+ * For a TypeBounds type, the parents of its hi bound.
+ * inherited by typerefs, singleton types, and refinement types,
+ * The empty list for all other types */
+ def parents: List[Type] = List();
+
+ /** For a typeref or single-type, its prefix. NoType for all other types. */
+ def prefix: Type = NoType;
+
+ /** For a typeref, its arguments. The empty list for all other types */
+ def typeArgs: List[Type] = List();
+
+ /** For a method or poly type, its result type,
+ * the type itself for all other types */
+ def resultType: Type = this;
+
+ /** For a method or poly type, the number of its value parameter sections,
+ * 0 for all other types */
+ def paramSectionCount: int = 0;
+
+ /** For a method or poly type, the types of its first value parameter section,
+ * the empty list for all other types */
+ def paramTypes: List[Type] = List();
+
+ /** For a poly type, its type parameters,
+ * the empty list for all other types */
+ def typeParams: List[Symbol] = List();
+
+ /** Is this type produced as a repair for an error? */
+ def isError: boolean = this == ErrorType || symbol.isError;
+
+ /** Does this type denote a stable reference (i.e. singleton type)? */
+ def isStable: boolean = false;
+
+ /** For a classtype or refined type, its members;
+ * inherited by subtypes and typerefs.
+ * The empty scope for all other types */
+ def members: Scope = EmptyScope;
+
+ /** An iterator that enumerates all members of this type and its base types
+ * Members of any type precede members of its base types in the ordering
+ * Members of parents of a type are enumerated right to left. */
+ def rawMembersIterator: Iterator[Symbol] = Iterator.empty;
+
+ /** An iterator that enumerates all members of this type
+ * (defined or inherited).
+ * Defined members of a type precede members inherited from its base types
+ * in the ordering.
+ * Members of parents of a type are enumerated right to left. */
+ def allPublicMembersIterator: Iterator[Symbol] =
+ for (val sym <- rawMembersIterator;
+ !sym.hasFlag(PRIVATE) && (lookup(sym.name).alternatives contains sym))
+ yield sym;
+
+ /** The member with given name of this type, NoSymbol if none exists */
+ def lookup(name: Name): Symbol = lookupNonPrivate(name);
+
+ /** The non-private member with given name of this type,
+ * NoSymbol if none exists. */
+ def lookupNonPrivate(name: Name): Symbol = NoSymbol;
+
+ /** The least type instance of given class which is a supertype
+ * of this type */
+ def baseType(clazz: Symbol): Type = NoType;
+
+ /** This type as seen from prefix `pre' and class `clazz'. This means:
+ * Replace all thistypes of `clazz' or one of its subclasses by `pre'
+ * and instantiate all parameters by arguments of `pre'.
+ * Proceed analogously for thistypes referring to outer classes. */
+ def asSeenFrom(pre: Type, clazz: Symbol): Type =
+ new AsSeenFromMap(pre, clazz) apply this;
+
+ /** The info of `sym', seen as a member of this type. */
+ def memberInfo(sym: Symbol): Type =
+ sym.info.asSeenFrom(this, sym.owner);
+
+ /** The type of `sym', seen as a member of this type. */
+ def memberType(sym: Symbol): Type =
+ sym.tpe.asSeenFrom(this, sym.owner);
+
+ /** Substitute types `to' for occurrences of references to symbols `from'
+ * in this type. */
+ def subst(from: List[Symbol], to: List[Type]): Type =
+ new SubstTypeMap(from, to) apply this;
+
+ /** Substitute symbols `to' for occurrences of symbols `from' in this type. */
+ def substSym(from: List[Symbol], to: List[Symbol]): Type =
+ new SubstSymMap(from, to) apply this;
+
+ /** Substitute all occurrences of ThisType(from) in this type by `to' */
+ def substThis(from: Symbol, to: Type): Type =
+ new SubstThisMap(from, to) apply this;
+
+ /** Does this type contain a reference to this symbol? */
+ def contains(sym: Symbol): boolean = {
+ val m = new ContainsMap(sym);
+ m(this);
+ m.result
+ }
+
+ /** Is this type a subtype of that type? */
+ def <:<(that: Type): boolean =
+ if (explainSwitch) explain("<", isSubType, this, that)
+ else this == that || isSubType(this, that);
+
+ /** Is this type equivalent to that type? */
+ def =:=(that: Type): boolean =
+ if (explainSwitch) explain("<", isSameType, this, that)
+ else this == that || isSameType(this, that);
+
+ /** Does this type implement symbol `sym' with same or stronger type? */
+ def specializes(sym: Symbol): boolean =
+ if (explainSwitch) explain("specializes", specializesSym, this, sym)
+ else specializesSym(this, sym);
+
+ /** Is this type close enough to that type so that
+ * members with the two type would override each other?
+ * This means:
+ * - Either both types are polytypes with the same number of
+ * type parameters and their result types match after renaming
+ * corresponding type parameters
+ * - Or both types are method types with equivalent type parameter types
+ * and matching result types
+ * - Or both types are equivalent
+ * - Or phase.exactMatch is false and both types are neither method nor
+ * poly types.
+ */
+ def matches(that: Type): boolean =
+ matchesType(this, that);
+
+ /** The shortest sorted upwards closed array of types that contains
+ * this type as first element.
+ *
+ * A list or array of types ts is upwards closed if
+ *
+ * for all t in ts:
+ * for all typerefs p.s[args] such that t <: p.s[args]
+ * there exists a typeref p'.s[args'] in ts such that
+ * t <: p'.s['args] <: p.s[args],
+ * and
+ * for all singleton types p.s such that t <: p.s
+ * there exists a singleton type p'.s in ts such that
+ * t <: p'.s <: p.s
+ *
+ * Sorting is with respect to Symbol.isLess() on type symbols.
+ */
+ def closure: Array[Type] = Predef.Array(this);
+
+ /** The index of given class symbol in the closure of this type, -1
+ * of no base type with gien class symbol exists */
+ def closurePos(sym: Symbol): int = {
+ val cl = closure;
+ var lo = 0;
+ var hi = cl.length - 1;
+ while (lo <= hi) {
+ val mid = (lo + hi) / 2;
+ val clsym = cl(mid).symbol;
+ if (sym == clsym) return mid
+ else if (sym isLess clsym) hi = mid - 1
+ else if (clsym isLess sym) lo = mid + 1
+ else throw new Error()
+ }
+ -1
+ }
+
+ /** The erasure of this type. This is:
+ * - For a singleton or constant type,
+ * the erasure of its underlying base type
+ * - For a non-empty type intersection,
+ * the erasure of its first parent
+ * - For a polymorphic type, the erasure of its result type
+ * - for types Object, All, Any: AnyRef
+ * - for an abstract type or TypeBounds type,
+ * the erasure of its upper bound
+ * - for all other typerefs, the type without prefix or arguments
+ * - for a method type, the method type consistsing of
+ * erased parameter and result types.
+ * - for all other types, the type itself.
+ */
+ def erasure: Type = this;
+
+ /** If this is a polytype, a copy with cloned type parameters owned
+ * by `owner'. Identity for all other types. */
+ def cloneInfo(owner: Symbol) = this;
+
+ /** The representation of this type used as a prefix */
+ def prefixString = toString() + ".";
+
+ /** Get type of `this' symbol corresponding to this class typeref, extend
+ * homomorphically to results of function types and poly types.
+ * Identity for all other types. */
+ def instanceType = this;
+
+ /** Is this type completed (i.e. not a lazy type)?
+ */
+ def isComplete: boolean = true;
+
+ /** If this is a lazy type, assign a new type to `sym'. */
+ def complete(sym: Symbol): unit = {}
+ }
+
+// Subclasses ------------------------------------------------------------
+
+ /** A mixin for types that carry a members scope
+ * (refinements and class types)
+ */
+ abstract class TypeWithScope(scope: Scope) extends Type {
+
+ override def members: Scope = scope;
+
+ override def rawMembersIterator: Iterator[Symbol] =
+ scope.toList.elements append super.rawMembersIterator;
+
+ override def lookup(name: Name): Symbol = {
+ val sym = scope lookup name;
+ if (sym != NoSymbol) sym else super.lookupNonPrivate(name)
+ }
+
+ override def lookupNonPrivate(name: Name): Symbol = {
+ val sym = scope lookup name;
+ if (sym != NoSymbol && !sym.hasFlag(PRIVATE)) sym
+ else super.lookupNonPrivate(name);
+ }
+
+ override def toString(): String =
+ super.toString() + members.toString();
+ }
+
+ /** A base class for types that defer some operations
+ * to their immediate supertype
+ */
+ abstract trait SubType extends Type {
+ protected def supertype: Type;
+ override def parents: List[Type] = supertype.parents;
+ override def members: Scope = supertype.members;
+ override def rawMembersIterator: Iterator[Symbol] =
+ supertype.rawMembersIterator;
+ override def lookup(name: Name): Symbol = supertype lookup name;
+ override def lookupNonPrivate(name: Name): Symbol =
+ supertype lookupNonPrivate name;
+ override def baseType(clazz: Symbol): Type = supertype.baseType(clazz);
+ override def closure: Array[Type] = supertype.closure;
+ override def erasure: Type = supertype.erasure;
+ }
+
+ /** A base class for types that represent a single value
+ * (single-types and this-types)
+ */
+ abstract trait SingletonType extends SubType {
+ override def singleDeref: Type;
+ protected def supertype: Type = singleDeref;
+ override def isStable: boolean = true;
+ override def widen: Type = singleDeref.widen;
+ override def closure: Array[Type] = addClosure(this, supertype.closure);
+ }
+
+ /** An object representing an erroneous type */
+ case object ErrorType extends Type {
+ override def members: Scope = new ErrorScope(NoSymbol);
+ override def lookupNonPrivate(name: Name): Symbol = members lookup name;
+ override def baseType(clazz: Symbol): Type = this;
+ override def toString(): String = "<error>";
+ override def narrow: Type = this;
+ }
+
+ /** An object representing an unknown type */
+ case object WildcardType extends Type {
+ override def toString(): String = "?"
+ }
+
+ /** An object representing a non-existing type */
+ case object NoType extends Type {
+ override def toString(): String = "<notype>"
+ }
+
+ /** An object representing a non-existing prefix */
+ case object NoPrefix extends Type {
+ override def isStable: boolean = true;
+ override def prefixString = "";
+ }
+
+ /** A class for this-types of the form <sym>.this.type
+ */
+ case class ThisType(sym: Symbol) extends SingletonType {
+ override def symbol = sym;
+ override def singleDeref: Type = sym.typeOfThis;
+ override def toString(): String =
+ if (!settings.debug.value &&
+ (sym.isAnonymousClass || sym.isRefinementClass)) "this.type"
+ else sym.nameString + ".this.type";
+ override def narrow: Type = this;
+ }
+
+ /** A class for singleton types of the form <prefix>.<sym.name>.type.
+ * Cannot be created directly; one should always use
+ * `singleType' for creation.
+ */
+ abstract case class SingleType(pre: Type, sym: Symbol) extends SingletonType {
+ private var singleDerefCache: Type = _;
+ private var valid: Phase = null;
+ override def singleDeref: Type = {
+ if (valid != phase) {
+ valid = phase;
+ singleDerefCache = pre.memberType(sym).resultType;
+ }
+ singleDerefCache
+ }
+ override def symbol = sym;
+ override def prefix: Type = pre;
+ override def toString(): String =
+ pre.prefixString + sym.nameString + ".type";
+ }
+
+ /** A class for the bounds of abstract types and type parameters
+ */
+ case class TypeBounds(lo: Type, hi: Type, vu: Type) extends SubType {
+ protected def supertype: Type = hi;
+ override def bounds: TypeBounds = this;
+ def containsType(that: Type) = lo <:< that && that <:< hi;
+ }
+
+ /** A common base class for intersection types and class types
+ */
+ abstract class TypeIntersection(override val parents: List[Type]) extends Type {
+ override def lookupNonPrivate(name: Name): Symbol = {
+ def lookIn(ps: List[Type]): Symbol = ps match {
+ case List() => NoSymbol
+ case p::ps1 =>
+ val sym = p lookupNonPrivate name;
+ val sym1 = lookIn(ps1);
+ if (sym1 == NoSymbol
+ ||
+ !sym.hasFlag(DEFERRED) && sym1.hasFlag(DEFERRED)
+ ||
+ sym.hasFlag(DEFERRED) == sym1.hasFlag(DEFERRED) &&
+ (sym.owner isSubClass sym1.owner)) sym
+ else sym1
+ }
+ lookIn(parents);
+ }
+
+ private var closureCache: Array[Type] = _;
+ private var valid: Phase = null;
+
+ override def closure: Array[Type] = {
+ if (valid != phase) {
+ valid = phase;
+ closureCache = null;
+ try {
+ closureCache = computeClosure;
+ } catch {
+ case ex: MalformedClosure =>
+ throw new MalformedType(
+ "the type intersection " + this + " is malformed" +
+ "\n --- because ---\n" + ex.getMessage())
+ }
+ }
+ if (closureCache == null)
+ throw new TypeError("illegal cyclic reference involving " + symbol);
+ closureCache;
+ }
+
+ protected def computeClosure: Array[Type];
+
+ override def baseType(sym: Symbol): Type = {
+ val index = closurePos(sym);
+ if (index >= 0) closure(index) else NoType;
+ }
+
+ /*
+ override def baseType(clazz: Symbol): Type =
+ glb(parents map (.baseType(clazz)) filter (.!=(NoType)));
+ */
+
+ override def rawMembersIterator: Iterator[Symbol] =
+ for (val parent <- parents.reverse.elements;
+ val sym <- parent.rawMembersIterator) yield sym;
+
+ override def erasure: Type =
+ if (parents.isEmpty) this else parents.head.erasure;
+
+ override def toString(): String =
+ parents.mkString("", " with ", "");
+ }
+
+ /** A class representing intersection types of the form
+ * <parents_0> with ... with <parents_n>
+ */
+ case class IntersectionType(_parents: List[Type])
+ extends TypeIntersection(_parents) {
+ def computeClosure: Array[Type] = glbArray(parents map (.closure));
+ }
+
+ /** A class representing a refinement
+ * Cannot be created directly;
+ * one should always use `refinedType' for creation.
+ */
+ abstract case class RefinedType(base: Type, refinement: Scope)
+ extends SubType with TypeWithScope(refinement) {
+ protected def supertype: Type = base;
+ override def narrow: Type = symbol.thisType;
+ }
+
+ /** A class representing a class info
+ */
+ case class ClassInfoType(_parents: List[Type], defs: Scope, clazz: Symbol)
+ extends TypeIntersection(_parents) with TypeWithScope(defs) {
+
+ override def symbol: Symbol = clazz;
+
+ def computeClosure: Array[Type] =
+ addClosure(clazz.tpe, glbArray(parents map (.closure)));
+
+ override def toString(): String =
+ super[TypeWithScope].toString();
+ }
+
+ class PackageClassInfoType(defs: Scope, clazz: Symbol) extends ClassInfoType(List(), defs, clazz);
+
+ /** A class representing a constant type */
+ case class ConstantType(base: Type, value: Any)
+ extends SingletonType {
+ override def symbol: Symbol = base.symbol;
+ override def singleDeref: Type = base;
+ override def deconst: Type = base;
+ override def toString(): String = base.toString() + "(" + value + ")";
+ }
+
+ /** A class for named types of the form <prefix>.<sym.name>[args]
+ * Cannot be created directly; one should always use `typeRef' for creation.
+ */
+ abstract case class TypeRef(pre: Type, sym: Symbol, args: List[Type]) extends Type {
+ assert(!sym.isAbstractType || pre.isStable || pre.isError);
+
+ private def transform(tp: Type): Type =
+ tp.asSeenFrom(pre, sym.owner).subst(sym.typeParams, args);
+
+ private def transform(cl: Array[Type]): Array[Type] = {
+ val cl1 = new Array[Type](cl.length);
+ var i = 0;
+ while (i < cl.length) { cl1(i) = transform(cl(i)); i = i + 1 }
+ cl1
+ }
+
+ override def symbol = sym;
+
+ override def bounds: TypeBounds =
+ if (sym.isAbstractType) transform(sym.info.bounds).asInstanceOf[TypeBounds]
+ else super.bounds;
+
+ override def parents: List[Type] = sym.info.parents map transform;
+
+ override def prefix: Type = pre;
+
+ override def typeArgs: List[Type] = args;
+
+ override def members: Scope = sym.info.members;
+
+ override def rawMembersIterator: Iterator[Symbol] =
+ sym.info.rawMembersIterator;
+
+ override def lookup(name: Name): Symbol = sym.info.lookup(name);
+
+ override def lookupNonPrivate(name: Name): Symbol =
+ sym.info.lookupNonPrivate(name);
+
+ override def baseType(clazz: Symbol): Type =
+ if (sym == clazz) this
+ else if (sym.isClass) transform(sym.info.baseType(clazz))
+ else pre.memberInfo(sym).baseType(clazz);
+
+ override def closure: Array[Type] =
+ if (sym.isAbstractType) addClosure(this, bounds.hi.closure)
+ else transform(sym.info.closure);
+
+ override def instanceType: Type =
+ if (sym.thisSym != sym) transform(sym.typeOfThis)
+ else this;
+
+ override def erasure: Type =
+ if (sym.isAbstractType || sym.isAliasType) sym.info.erasure
+ else if (sym == ObjectClass ||
+ sym == AllClass ||
+ sym == AllRefClass ||
+ sym == AnyRefClass) AnyClass.tpe
+ else typeRef(NoPrefix, sym, List());
+
+ override def toString(): String =
+ if (!settings.debug.value && sym == RepeatedParamClass && !args.isEmpty)
+ args(0).toString() + "*"
+ else pre.prefixString + sym.nameString +
+ (if (args.isEmpty) "" else args.mkString("[", ",", "]"));
+ }
+
+ /** A class representing a method type with parameters.
+ */
+ case class MethodType(override val paramTypes: List[Type],
+ override val resultType: Type) extends Type {
+
+ override def paramSectionCount: int = resultType.paramSectionCount + 1;
+
+ override def instanceType: Type = {
+ val res = resultType.instanceType;
+ if (res eq resultType) this else MethodType(paramTypes, res)
+ }
+
+ override def erasure = {
+ val pts = map1(paramTypes, t: Type => t.erasure);
+ val res = resultType.erasure;
+ if ((pts eq paramTypes) && (res eq resultType)) this
+ else MethodType(pts, res)
+ }
+
+ override def toString(): String = paramTypes.mkString("(", ",", ")") + resultType;
+ }
+
+ /** A class representing a polymorphic type or, if tparams.length == 0,
+ * a parameterless method type.
+ */
+ case class PolyType(override val typeParams: List[Symbol],
+ override val resultType: Type) extends Type {
+
+ override def paramSectionCount: int = resultType.paramSectionCount;
+
+ override def paramTypes: List[Type] = resultType.paramTypes;
+
+ override def instanceType: Type = {
+ val res = resultType.instanceType;
+ if (res eq resultType) this else PolyType(typeParams, res)
+ }
+
+ override def erasure = resultType.erasure;
+
+ override def toString(): String =
+ (if (typeParams.isEmpty) "=> " else typeParams.mkString("[", ",", "]"))
+ + resultType;
+
+ override def cloneInfo(owner: Symbol) = {
+ val tparams = typeParams map (.cloneSymbol(owner));
+ for (val tparam <- tparams)
+ tparam.setInfo(tparam.info.substSym(typeParams, tparams));
+ PolyType(tparams, resultType.substSym(typeParams, tparams))
+ }
+ }
+
+ /** A class representing a type variable
+ */
+ case class TypeVar(origin: Type, constr: TypeConstraint) extends Type {
+
+ override def symbol = origin.symbol;
+
+ override def toString(): String =
+ if (constr.inst == NoType) "?" + origin else constr.inst.toString();
+ }
+
+ /** A class representing an as-yet unevaluated type.
+ */
+ abstract class LazyType extends Type {
+ override def isComplete: boolean = false;
+ override def complete(sym: Symbol): unit;
+ }
+
+ /** A class representing a lazy type with known type parameters
+ */
+ class LazyPolyType(tparams: List[Symbol], restp: Type) extends LazyType {
+ override def complete(sym: Symbol): unit = {
+ restp.complete(sym);
+ sym.setInfo(PolyType(tparams, sym.info))
+ }
+ }
+
+// Creators ---------------------------------------------------------------
+
+ /** Rebind symbol `sym' to an overriding member in type `pre' */
+ private def rebind(pre: Type, sym: Symbol): Symbol = {
+ val owner = sym.owner;
+ if (owner.isClass && owner != pre.symbol && !sym.isFinal) {
+ val rebind = pre lookupNonPrivate sym.name;
+ if (rebind == NoSymbol) sym else rebind
+ } else sym
+ }
+
+ /** The canonical creator for single-types */
+ def singleType(pre: Type, sym: Symbol): SingleType = {
+ if (!pre.isStable && !pre.isError)
+ throw new MalformedType(pre, sym.name.toString());
+ new SingleType(pre, rebind(pre, sym)) {}
+ }
+
+ /** The canonical creator for typerefs */
+ def typeRef(pre: Type, sym: Symbol, args: List[Type]): Type = {
+ val sym1 = if (sym.isAbstractType) rebind(pre, sym) else sym;
+ if (sym1.isAbstractType && !pre.isStable && !pre.isError)
+ throw new MalformedType(pre, sym.nameString);
+ if (sym1.isAliasType && sym1.typeParams.length == args.length) {
+ if (sym1.hasFlag(LOCKED))
+ throw new TypeError("illegal cyclic reference involving " + sym1);
+ sym1.setFlag(LOCKED);
+ val result = sym1.info.asSeenFrom(pre, sym1.owner).subst(sym1.typeParams, args);
+ sym1.resetFlag(LOCKED);
+ result
+ } else {
+ new TypeRef(pre, sym1, args) {}
+ }
+ }
+
+ /** the canonical creator for a refined type with an initially empty scope */
+ def refinedType(base: Type, owner: Symbol): RefinedType =
+ refinedType(base, owner, new Scope);
+
+ /** the canonical creator for a refined type with a given scope */
+ def refinedType(base: Type, owner: Symbol, members: Scope): RefinedType = {
+ val clazz = owner.newRefinementClass(Position.NOPOS);
+ val result = new RefinedType(base, members) {
+ override def symbol: Symbol = clazz
+ }
+ clazz.setInfo(result);
+ result
+ }
+
+ /** A creator for intersection type where intersections of a single type are
+ * replaced by the type itself. */
+ def intersectionType(tps: List[Type]): Type = tps match {
+ case List(tp) => tp
+ case _ => IntersectionType(tps)
+ }
+
+ /** A creator for type applications */
+ def appliedType(tycon: Type, args: List[Type]): Type = tycon match {
+ case TypeRef(pre, sym, args1) =>
+ if (args eq args1) tycon
+ else typeRef(pre, sym, args)
+ case ErrorType => tycon
+ }
+
+// Helper Classes ---------------------------------------------------------
+
+ /** A class expressing upper and lower bounds constraints
+ * for type variables, as well as their instantiations */
+ class TypeConstraint {
+ var lobounds: List[Type] = List();
+ var hibounds: List[Type] = List();
+ var inst: Type = NoType;
+
+ def instantiate(tp: Type): boolean =
+ if (lobounds.forall(.<:<(tp)) && hibounds.forall(tp.<:<)) {
+ inst = tp; true
+ } else false;
+ }
+
+ /** A prototype for mapping a function over all possible types
+ */
+ trait TypeMap extends Function1[Type, Type] {
+ // deferred inherited: def apply(tp: Type): Type
+
+ /** Map this function over given type */
+ def mapOver(tp: Type): Type = tp match {
+ case ErrorType | WildcardType | NoType | NoPrefix | TypeVar(_, _) | ThisType(_) =>
+ tp
+ case SingleType(pre, sym) =>
+ val pre1 = this(pre);
+ if (pre1 eq pre) tp
+ else singleType(pre1, sym)
+ case ConstantType(base, value) =>
+ val base1 = this(base);
+ if (base1 eq base) tp
+ else ConstantType(base1, value)
+ case TypeRef(pre, sym, args) =>
+ val pre1 = this(pre);
+ val args1 = map1(args, this);
+ if ((pre1 eq pre) && (args1 eq args)) tp
+ else typeRef(pre1, sym, args1)
+ case TypeBounds(lo, hi, vu) =>
+ val lo1 = this(lo);
+ val hi1 = this(hi);
+ val vu1 = this(vu);
+ if ((lo1 eq lo) && (hi1 eq hi) && (vu1 eq vu)) tp
+ else TypeBounds(lo1, hi1, vu1)
+ case RefinedType(base, refinement) =>
+ val base1 = this(base);
+ val refinement1 = mapOver(refinement);
+ if ((base1 eq base) && (refinement1 eq refinement)) tp
+ else {
+ val result = refinedType(base1, tp.symbol.owner);
+ val syms1 = refinement1.toList;
+ for (val sym <- syms1)
+ result.members.enter(sym.cloneSymbol(result.symbol));
+ val syms2 = result.members.toList;
+ val resultThis = ThisType(result.symbol);
+ for (val sym <- syms2)
+ sym.setInfo(sym.info.substSym(syms1, syms2).substThis(tp.symbol, resultThis));
+ result
+ }
+ case IntersectionType(parents) =>
+ val parents1 = map1(parents, this);
+ if (parents1 eq parents) tp
+ else IntersectionType(parents1)
+ case MethodType(paramtypes, result) =>
+ val paramtypes1 = map1(paramtypes, this);
+ val result1 = this(result);
+ if ((paramtypes1 eq paramtypes) && (result1 eq result)) tp
+ else MethodType(paramtypes1, result1)
+ case PolyType(tparams, result) =>
+ val tparams1 = mapOver(tparams);
+ val result1 = this(result);
+ if ((tparams1 eq tparams) && (result1 eq result)) tp
+ else PolyType(tparams1, result1)
+ case _ =>
+ throw new Error("mapOver inapplicable for " + tp);
+ }
+
+ /** Map this function over given scope */
+ private def mapOver(scope: Scope): Scope = {
+ val elems = scope.toList;
+ val elems1 = mapOver(elems);
+ if (elems1 eq elems) scope
+ else new Scope(elems1)
+ }
+
+ /** Map this function over given list of symbols */
+ private def mapOver(syms: List[Symbol]): List[Symbol] = {
+ val infos = syms map (.info);
+ val infos1 = map1(infos, this);
+ if (infos1 eq infos) syms
+ else {
+ val syms1 = syms map (.cloneSymbol);
+ List.map2(syms1, infos1)
+ ((sym1, info1) => sym1.setInfo(info1.substSym(syms, syms1)))
+ }
+ }
+ }
+
+ /** A map to compute the asSeenFrom method */
+ class AsSeenFromMap(pre: Type, clazz: Symbol) extends TypeMap {
+ def apply(tp: Type): Type =
+ if (pre == NoType || !clazz.isClass) tp
+ else tp match {
+ case ThisType(sym) =>
+ def toPrefix(pre: Type, clazz: Symbol): Type =
+ if (pre == NoType || !clazz.isClass) tp
+ else if ((sym isSubClass clazz) && (pre.widen.symbol isSubClass sym)) pre
+ else toPrefix(pre.baseType(clazz).prefix, clazz.owner);
+ toPrefix(pre, clazz)
+ case SingleType(pre, sym) =>
+ try {
+ mapOver(tp)
+ } catch {
+ case ex: MalformedType => apply(tp.singleDeref) // todo: try needed?
+ }
+ case TypeRef(prefix, sym, args) if (sym.isTypeParameter) =>
+ def toInstance(pre: Type, clazz: Symbol): Type =
+ if (pre == NoType || !clazz.isClass) tp
+ else {
+ val symclazz = sym.owner;
+ def throwError =
+ throw new Error("" + tp + " in " + symclazz +
+ "cannot be instantiated from " + pre.widen);
+ def instParam(ps: List[Symbol], as: List[Type]): Type =
+ if (ps.isEmpty) throwError
+ else if (sym eq ps.head) as.head
+ else instParam(ps.tail, as.tail);
+ if (symclazz == clazz && (pre.widen.symbol isSubClass symclazz))
+ pre.baseType(symclazz) match {
+ case TypeRef(_, basesym, baseargs) =>
+ instParam(basesym.typeParams, baseargs);
+ case _ =>
+ throwError
+ }
+ else toInstance(pre.baseType(clazz).prefix, clazz.owner)
+ }
+ toInstance(pre, clazz)
+ case _ =>
+ mapOver(tp)
+ }
+ }
+
+ /** A base class to compute all substitutions */
+ abstract class SubstMap[T](from: List[Symbol], to: List[T]) extends TypeMap {
+
+ /** Are sym1, sym1 the same. Can be tunded by subclasses */
+ protected def matches(sym: Symbol, sym1: Symbol): boolean = sym eq sym1;
+
+ /** Map target to type, can be tuned by subclasses */
+ protected def toType(fromtp: Type, t: T): Type;
+
+ def apply(tp: Type): Type = {
+ def subst(sym: Symbol, from: List[Symbol], to: List[T]): Type =
+ if (from.isEmpty) tp
+ else if (matches(from.head, sym)) toType(tp, to.head)
+ else subst(sym, from.tail, to.tail);
+ tp match {
+ case TypeRef(NoPrefix, sym, _) =>
+ subst(sym, from, to)
+ case SingleType(NoPrefix, sym) =>
+ subst(sym, from, to)
+ case PolyType(tparams, restp) =>
+ assert(!(tparams exists (from contains)));
+ mapOver(tp)
+ case _ =>
+ mapOver(tp)
+ }
+ }
+ }
+
+ /** A map to implement the substSym method */
+ class SubstSymMap(from: List[Symbol], to: List[Symbol])
+ extends SubstMap(from, to) {
+ protected def toType(fromtp: Type, sym: Symbol) = fromtp match {
+ case TypeRef(pre, _, args) => typeRef(pre, sym, args)
+ case SingleType(pre, _) => singleType(pre, sym)
+ }
+ }
+
+ /** A map to implement the subst method */
+ class SubstTypeMap(from: List[Symbol], to: List[Type])
+ extends SubstMap(from, to) {
+ protected def toType(fromtp: Type, tp: Type) = tp;
+ }
+
+ /** A map to implement the substThis method */
+ class SubstThisMap(from: Symbol, to: Type) extends TypeMap {
+ def apply(tp: Type): Type = tp match {
+ case ThisType(sym) if (sym == from) => to
+ case _ => mapOver(tp)
+ }
+ }
+
+ /** A map to convert every occurrence of a wildcard type to a fresh
+ * type variable */
+ object wildcardToTypeVarMap extends TypeMap {
+ def apply(tp: Type): Type = tp match {
+ case WildcardType => TypeVar(tp, new TypeConstraint)
+ case _ => mapOver(tp)
+ }
+ }
+
+ /** A map to implement the contains method */
+ class ContainsMap(sym: Symbol) extends TypeMap {
+ var result = false;
+ def apply(tp: Type): Type = {
+ if (!result) {
+ tp match {
+ case TypeRef(_, sym1, _) if (sym == sym1) => result = true
+ case SingleType(_, sym1) if (sym == sym1) => result = true
+ case _ => mapOver(tp)
+ }
+ }
+ tp
+ }
+ }
+
+ /** A map to compute the most deeply nested owner that contains all the symbols
+ * of thistype or prefixless typerefs/singletype occurrences in given type */
+ object commonOwnerMap extends TypeMap {
+ var result: Symbol = _;
+ def init = { result = NoSymbol }
+ def apply(tp: Type): Type = tp match {
+ case ThisType(sym) =>
+ register(sym);
+ tp
+ case TypeRef(NoPrefix, sym, args) =>
+ register(sym.owner);
+ for (val arg <- args) apply(arg);
+ tp
+ case SingleType(NoPrefix, sym) =>
+ register(sym.owner);
+ tp
+ case _ =>
+ mapOver(tp)
+ }
+ private def register(sym: Symbol) =
+ if (result == NoSymbol || (result isNestedIn sym)) result = sym
+ else assert(result == sym || (sym isNestedIn result));
+ }
+
+ /** Equivalent to (xs map f), except that the same (wrt eq) input list
+ * (or its suffix) is returned if the function `f' is the identity
+ * on all elements of the list (or the suffix). */
+ def map1[T <: AnyRef](xs: List[T], f: T => T): List[T] = xs match {
+ case List() => xs
+ case hd :: tl =>
+ val hd1 = f(hd);
+ val tl1 = map1(tl, f);
+ if ((hd1 eq hd) && (tl1 eq tl)) xs
+ else hd1 :: tl1
+ }
+
+// Helper Methods -------------------------------------------------------------
+
+ /** Do tp1 and tp2 denote equivalent types? */
+ def isSameType(tp1: Type, tp2: Type): boolean = (tp1 eq tp2) || {
+ Pair(tp1, tp2) match {
+ case Pair(ErrorType, _)
+ | Pair(WildcardType, _)
+ | Pair(_, ErrorType)
+ | Pair(_, WildcardType) =>
+ true
+ case Pair(NoType, _)
+ | Pair(NoPrefix, _)
+ | Pair(_, NoType)
+ | Pair(_, NoPrefix) =>
+ false
+ case Pair(ThisType(sym1), ThisType(sym2)) =>
+ sym1 == sym2
+ case Pair(SingleType(pre1, sym1), SingleType(pre2, sym2))
+ if (sym1 == sym2 && pre1 =:= pre2) =>
+ true
+ case Pair(SingleType(pre1, sym1), ThisType(sym2))
+ if (sym1.isModule &&
+ sym1.moduleClass == sym2 &&
+ pre1 =:= sym2.owner.thisType) =>
+ true
+ case Pair(ThisType(sym1), SingleType(pre2, sym2))
+ if (sym2.isModule &&
+ sym2.moduleClass == sym1 &&
+ pre2 =:= sym1.owner.thisType) =>
+ true
+ case Pair(ConstantType(base1, value1), ConstantType(base2, value2)) =>
+ base1 =:= base2 && value1 == value2
+ case Pair(TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) =>
+ sym1 == sym2 && pre1 =:= pre2 && isSameTypes(args1, args2)
+ case Pair(IntersectionType(parents1), IntersectionType(parents2)) =>
+ isSameTypes(parents1, parents2)
+ case Pair(RefinedType(base1, ref1), RefinedType(base2, ref2)) =>
+ def isSubScope(s1: Scope, s2: Scope): boolean = s2.toList.forall {
+ sym2 =>
+ val sym1 = s1.lookup(sym2.name);
+ sym1.info =:= sym2.info.substThis(sym2.owner, sym1.owner.thisType)
+ }
+ base1 =:= base2 && isSubScope(ref1, ref2) && isSubScope(ref2, ref1)
+ case Pair(MethodType(pts1, res1), MethodType(pts2, res2)) =>
+ pts1.length == pts2.length &&
+ isSameTypes(pts1, pts2) &&
+ res1 =:= res2
+ case Pair(PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
+ tparams1.length == tparams2.length &&
+ List.forall2(tparams1, tparams2)
+ ((p1, p2) => p1.info =:= p2.info.substSym(tparams2, tparams1)) &&
+ res1 =:= res2.substSym(tparams2, tparams1)
+ case Pair(TypeBounds(lo1, hi1, vu1), TypeBounds(lo2, hi2, vu2)) =>
+ lo1 =:= lo2 && hi1 =:= hi2 && vu1 =:= vu2
+ case Pair(TypeVar(_, constr1), _) =>
+ if (constr1.inst != NoType) constr1.inst =:= tp2
+ else constr1 instantiate (wildcardToTypeVarMap(tp2))
+ case Pair(_, TypeVar(_, constr2)) =>
+ if (constr2.inst != NoType) tp1 =:= constr2.inst
+ else constr2 instantiate (wildcardToTypeVarMap(tp1))
+ case Pair(SingleType(_, _), _)
+ if (tp2.isStable && tp1.singleDeref =:= tp2) =>
+ true
+ case Pair(_, SingleType(_, _))
+ if (tp1.isStable && tp1 =:= tp2.singleDeref) =>
+ true
+ case _ =>
+ false
+ }
+ }
+
+ /** Are tps1 and tps2 lists of pairwise equivalent types? */
+ def isSameTypes(tps1: List[Type], tps2: List[Type]): boolean =
+ tps1.length == tps2.length &&
+ List.forall2(tps1, tps2)((tp1, tp2) => tp1 =:= tp2);
+
+ /** Does tp1 conform to tp2? */
+ def isSubType(tp1: Type, tp2: Type): boolean = (tp1 eq tp2) || {
+ Pair(tp1, tp2) match {
+ case Pair(ErrorType, _)
+ | Pair(WildcardType, _)
+ | Pair(_, ErrorType)
+ | Pair(_, WildcardType) =>
+ true
+ case Pair(NoType, _)
+ | Pair(NoPrefix, _)
+ | Pair(_, NoType)
+ | Pair(_, NoPrefix) =>
+ false
+ case Pair(ThisType(_), ThisType(_))
+ | Pair(ThisType(_), SingleType(_, _))
+ | Pair(SingleType(_, _), ThisType(_))
+ | Pair(SingleType(_, _), SingleType(_, _))
+ | Pair(ConstantType(_, _), ConstantType(_, _)) =>
+ tp1 =:= tp2
+ case Pair(TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) =>
+ def isSubArgs(tps1: List[Type], tps2: List[Type],
+ tparams: List[Symbol]): boolean = {
+ tps1.isEmpty && tps2.isEmpty
+ ||
+ !tps1.isEmpty && !tps2.isEmpty &&
+ (if (tparams.head.hasFlag(COVARIANT)) tps1.head <:< tps2.head
+ else if (tparams.head.hasFlag(CONTRAVARIANT)) tps2.head <:< tps1.head
+ else tps1.head =:= tps2.head) &&
+ isSubArgs(tps1.tail, tps2.tail, tparams.tail)
+ }
+ sym1 == sym2 && (pre1 <:< pre2) &&
+ isSubArgs(args1, args2, sym1.typeParams)
+ ||
+ sym1.isAbstractType && (tp1.bounds.hi <:< tp2)
+ ||
+ sym2.isAbstractType && (tp1 <:< tp2.bounds.lo)
+ ||
+ sym2.isClass &&
+ ({ val base = tp1 baseType sym2; !(base eq tp1) && (base <:< tp2) })
+ ||
+ sym1 == AllClass
+ ||
+ sym1 == AllRefClass && sym2 != AllClass && tp2 <:< AnyRefClass.tpe
+ case Pair(MethodType(pts1, res1), MethodType(pts2, res2)) =>
+ pts1.length == pts2.length &&
+ isSameTypes(pts1, pts2) && (res1 <:< res2)
+ case Pair(PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
+ tparams1.length == tparams2.length &&
+ List.forall2(tparams1, tparams2)
+ ((p1, p2) => p2.info.substSym(tparams2, tparams1) <:< p1.info) &&
+ res1 <:< res2.substSym(tparams2, tparams1)
+ case Pair(TypeBounds(lo1, hi1, vu1), TypeBounds(lo2, hi2, vu2)) =>
+ lo2 <:< lo1 && hi1 <:< hi2 && vu1 <:< vu2
+ case Pair(_, TypeVar(_, constr2)) =>
+ if (constr2.inst != NoType) tp1 <:< constr2.inst
+ else { constr2.lobounds = tp1 :: constr2.lobounds; true }
+ case Pair(TypeVar(_, constr1), _) =>
+ if (constr1.inst != NoType) constr1.inst <:< tp2
+ else { constr1.hibounds = tp2 :: constr1.hibounds; true }
+ case Pair(_, IntersectionType(parents2)) =>
+ parents2 forall (tp1.<:<)
+ case Pair(_, RefinedType(base2, ref2)) =>
+ tp1 <:< base2 && (ref2.toList forall (tp1 specializes))
+ case Pair(IntersectionType(parents1), _) =>
+ parents1 exists (.<:<(tp2))
+ case Pair(ThisType(_), _)
+ | Pair(SingleType(_, _), _)
+ | Pair(ConstantType(_, _), _)
+ | Pair(RefinedType(_, _), _) =>
+ tp1.singleDeref <:< tp2
+ case Pair(TypeRef(pre1, sym1, args1), _) =>
+ sym1 == AllClass && tp2 <:< AnyClass.tpe
+ ||
+ sym1 == AllRefClass && tp2.symbol != AllClass && tp2 <:< AnyRefClass.tpe
+ case _ =>
+ false
+ }
+ }
+
+ /** Are tps1 and tps2 lists of equal length such that all elements
+ * of tps1 conform to corresponding elements of tps2? */
+ def isSubTypes(tps1: List[Type], tps2: List[Type]): boolean =
+ tps1.length == tps2.length &&
+ List.forall2(tps1, tps2)((tp1, tp2) => tp1 <:< tp2);
+
+ /** Does type `tp' implement symbol `sym' with same or stronger type?
+ * Exact only if `sym' is a member of some refinement type, otherwise
+ * we might return false negatives */
+ def specializesSym(tp: Type, sym: Symbol): boolean =
+ tp.symbol == AllClass ||
+ tp.symbol == AllRefClass && (sym.owner isSubClass AnyRefClass) ||
+ (tp.lookupNonPrivate(sym.name).alternatives exists
+ (alt => sym == alt || specializesSym(tp.narrow, alt, ThisType(sym.owner), sym)));
+
+ /** Does member `sym1' of `tp1' have a stronger type than member `sym2' of `tp2'? */
+ private def specializesSym(tp1: Type, sym1: Symbol, tp2: Type, sym2: Symbol): boolean = {
+ val info1 = tp1.memberInfo(sym1);
+ val info2 = tp2.memberInfo(sym2).substThis(tp2.symbol, tp1);
+ sym2.isTerm &&
+ info1 <:< info2 ||
+ sym2.isAbstractType &&
+ (info2.bounds containsType info1) ||
+ sym2.isAliasType &&
+ tp2.memberType(sym2) =:= tp1.memberType(sym1)
+ }
+
+ /** A function implementing tp1 matches tp2 */
+ private def matchesType(tp1: Type, tp2: Type): boolean = Pair(tp1, tp2) match {
+ case Pair(MethodType(pts1, res1), MethodType(pts2, res2)) =>
+ isSameTypes(pts1, pts2) && (res1 matches res2)
+ case Pair(PolyType(tparams1, res1), PolyType(tparams2, res2)) =>
+ tparams1.length == tparams2.length &&
+ (res1 matches res2.substSym(tparams2, tparams1))
+ case Pair(MethodType(_, _), _) | Pair(PolyType(_, _), _) =>
+ false
+ case _ =>
+ !phase.exactMatch || tp1 =:= tp2
+ }
+
+ private def addClosure(tp: Type, cl: Array[Type]): Array[Type] = {
+ val cl1 = new Array[Type](cl.length + 1);
+ cl1(0) = tp;
+ System.arraycopy(cl, 0, cl1, 1, cl.length);
+ cl
+ }
+
+// Lubs and Glbs ---------------------------------------------------------
+
+ private val recLimit = 10;
+ private var recCount = 0;
+ private var giveUp: boolean = _;
+
+ /** Return op(tps), but give up if level of recursion is greater than
+ * recLimit */
+ private def limitRecursion(tps: List[Type], boundkind: String,
+ op: List[Type] => Type): Type =
+ if (recCount == recLimit) {
+ giveUp = true;
+ AnyClass.tpe
+ } else {
+ if (recCount == 0) giveUp = false;
+ val result = try {
+ recCount = recCount + 1;
+ op(tps)
+ } finally {
+ recCount = recCount - 1
+ }
+ if (recCount == 0 && giveUp) {
+ throw new TypeError("failure to compute " + boundkind +
+ " bound of types " +
+ tps.mkString("", " and ", ";\n") +
+ "an approximation is: " + result + ";\n" +
+ "additional type annotations are needed");
+ }
+ result
+ }
+
+ /** The greatest sorted upwards closed lower bound of a list of lists of
+ * types relative to the following ordering <= between lists of types:
+ *
+ * xs <= ys iff forall y in ys exists x in xs such that x <: y
+ *
+ * @See closure for a definition of sorted and upwards closed.
+ */
+ private def glbList(tss: List[List[Type]]): List[Type] = {
+ val tss1 = tss filter (ts => !ts.isEmpty);
+ if (tss1.isEmpty) List()
+ else if (tss1.tail.isEmpty) tss.head
+ else {
+ val ts0 = tss1 map (.head);
+ val sym = minSym(ts0);
+ val ts1 = elimSuper(ts0 filter (.symbol.==(sym)));
+ mergePrefixAndArgs(ts1, -1) match {
+ case Some(tp0) =>
+ tp0 :: glbList(tss1 map (ts => if (ts.head.symbol == sym) ts.tail else ts))
+ case None =>
+ throw new MalformedClosure(ts1)
+ }
+ }
+ }
+
+ /** The greatest sorted upwards closed lower bound of a list of closures.
+ * @See glbList for more explanations.
+ */
+ private def glbArray(tss: List[Array[Type]]): Array[Type] = {
+ val tss1 = tss map (ts: Array[Type] => List.fromArray(ts));
+ val glbs = glbList(tss1);
+ val result = new Array[Type](glbs.length);
+ var i = 0;
+ for (val x <- glbs.elements) { result(i) = x; i = i + 1; }
+ result;
+ // Predef.Array(glbs: _*);
+ }
+
+ /** The least sorted upwards closed upper bound of a non-empty list
+ * of lists of types.
+ * @See glbList for more explanations. */
+ private def lubList(tss: List[List[Type]]): List[Type] =
+ if (tss.tail.isEmpty) tss.head
+ else if (tss exists (.isEmpty)) List()
+ else {
+ val ts0 = tss map (.head);
+ val sym = minSym(ts0);
+ if (ts0 forall (t => t.symbol == sym))
+ mergePrefixAndArgs(elimSub(ts0), 1).toList ::: lubList(tss map (.tail))
+ else
+ lubList(tss map (ts => if (ts.head.symbol == sym) ts.tail else ts))
+ }
+
+ /** The least sorted upwards closed upper bound of a non-empty list
+ * of closures.
+ * @See lubList for more explanations. */
+ private def lubArray(tss: List[Array[Type]]): Array[Type] =
+ Predef.Array(lubList(tss map (ts: Array[Type] => List.fromArray(ts))): _* );
+
+ /** The minimal symbol (wrt Symbol.isLess) of a list of types */
+ private def minSym(tps: List[Type]): Symbol =
+ (tps.head.symbol /: tps.tail) {
+ (sym1, tp2) => if (tp2.symbol isLess sym1) tp2.symbol else sym1
+ }
+
+ /** A minimal type which has a given array of types as its closure */
+ private def spanningType(ts: Array[Type]): Type = {
+ def spanningTypes(ts: List[Type]): List[Type] = ts match {
+ case List() => List()
+ case first :: rest =>
+ first :: spanningTypes(
+ rest filter (t => !first.symbol.isSubClass(t.symbol)))
+ }
+ intersectionType(spanningTypes(List.fromArray(ts)))
+ }
+
+ /** Eliminate from list of types all elements which are a supertype
+ * of some other element of the list. */
+ private def elimSuper(ts: List[Type]): List[Type] =
+ ts filter (t => !(ts exists (t1 => t1 <:< t)));
+
+ /** Eliminate from list of types all elements which are a subtype
+ * of some other element of the list. */
+ private def elimSub(ts: List[Type]): List[Type] =
+ ts filter (t => !(ts exists (t1 => t <:< t1)));
+
+ /** The least upper bound wrt <:< of a list of types */
+ def lub(ts: List[Type]): Type = {
+ def lub0(ts0: List[Type]): Type = elimSub(ts0) match {
+ case List() => AllClass.tpe
+ case List(t) => t
+ case ts @ PolyType(tparams, _) :: _ =>
+ PolyType(
+ List.map2(tparams, List.transpose(matchingBounds(ts, tparams)))
+ ((tparam, bounds) => tparam.cloneSymbol.setInfo(glb(bounds))),
+ lub0(ts map (.resultType)))
+ case ts @ MethodType(pts, _) :: rest =>
+ MethodType(pts, lub0(matchingRestypes(ts, pts)))
+ case ts =>
+ val closures: List[Array[Type]] = ts map (.closure);
+ val lubBaseTypes: Array[Type] = lubArray(closures);
+ val lubBase = spanningType(lubBaseTypes);
+ val lubType = refinedType(lubBase, commonOwner(ts));
+ val lubThisType = lubType.symbol.thisType;
+ val narrowts = ts map (.narrow);
+ def lubsym(proto: Symbol): Symbol = {
+ val prototp = lubThisType.memberInfo(proto);
+ val syms = narrowts map (t =>
+ t.lookup(proto.name)
+ .matching(NoPrefix, prototp.substThis(lubThisType.symbol, t)));
+ val symtypes = List.map2(narrowts, syms)
+ ((t, sym) => t.memberInfo(sym).substThis(t.symbol, lubThisType));
+ if (syms contains NoSymbol)
+ NoSymbol
+ else if (proto.isTerm)
+ proto.cloneSymbol.setInfo(lub(symtypes))
+ else if (symtypes.tail forall (symtypes.head =:=))
+ proto.cloneSymbol.setInfo(symtypes.head)
+ else {
+ def lubBounds(bnds: List[TypeBounds]): TypeBounds =
+ TypeBounds(
+ glb(bnds map (.lo)), lub(bnds map (.hi)), lub(bnds map (.vu)));
+ proto.owner.newAbstractType(proto.pos, proto.name)
+ .setInfo(lubBounds(symtypes map (.bounds)))
+ }
+ }
+ def refines(tp: Type, sym: Symbol) = {
+ val sym1 = tp.lookupNonPrivate(sym.name);
+ (sym1 != NoSymbol) &&
+ (sym1.alternatives forall (
+ alt => !specializesSym(lubThisType, sym, tp, alt)))
+ }
+ for (val sym <- lubBase.allPublicMembersIterator)
+ // add a refinement symbol for all non-class members of lubBase
+ // which are refined by every type in ts.
+ if (!sym.isClass && (narrowts forall (t => refines(t, sym))))
+ addMember(lubThisType, lubType.members, lubsym(sym));
+ if (lubType.members.isEmpty) lubBase else lubType;
+ }
+ limitRecursion(ts, "least upper", lub0);
+ }
+
+ /** The greatest lower bound wrt <:< of a list of types */
+ def glb(ts: List[Type]): Type = {
+ def glb0(ts0: List[Type]): Type = elimSuper(ts0) match {
+ case List() => AnyClass.tpe
+ case List(t) => t
+ case ts @ PolyType(tparams, _) :: _ =>
+ PolyType(
+ List.map2(tparams, List.transpose(matchingBounds(ts, tparams)))
+ ((tparam, bounds) => tparam.cloneSymbol.setInfo(lub(bounds))),
+ glb0(ts map (.resultType)))
+ case ts @ MethodType(pts, _) :: rest =>
+ MethodType(pts, glb0(matchingRestypes(ts, pts)))
+ case ts =>
+ try {
+ val glbBase = intersectionType(ts);
+ val glbType = refinedType(glbBase, commonOwner(ts));
+ val glbThisType = glbType.symbol.thisType;
+ def glbsym(proto: Symbol): Symbol = {
+ val prototp = glbThisType.memberInfo(proto);
+ val syms = for (val t <- ts;
+ val alt <- List.fromIterator(t.lookup(proto.name).alternatives);
+ glbThisType.memberInfo(alt) matches prototp) yield alt;
+ val symtypes = syms map glbThisType.memberInfo;
+ assert(!symtypes.isEmpty);
+ proto.cloneSymbol.setInfo(
+ if (proto.isTerm) glb(symtypes)
+ else {
+ def isTypeBound(tp: Type) = tp match {
+ case TypeBounds(_, _, _) => true
+ case _ => false
+ }
+ def glbBounds(bnds: List[Type]): TypeBounds = {
+ val lo = lub(bnds map (.bounds.lo));
+ val hi = glb(bnds map (.bounds.hi));
+ if (lo <:< hi) TypeBounds(lo, hi, glb(bnds map (.bounds.vu)))
+ else throw new MalformedClosure(bnds)
+ }
+ val symbounds = symtypes filter isTypeBound;
+ var result: Type =
+ if (symbounds.isEmpty)
+ TypeBounds(AllClass.tpe, AnyClass.tpe, AnyClass.tpe)
+ else glbBounds(symbounds);
+ for (val t <- symtypes; !isTypeBound(t))
+ if (result.bounds containsType t) result = t
+ else throw new MalformedClosure(symtypes);
+ result
+ })
+ }
+ for (val t <- ts; val sym <- t.allPublicMembersIterator)
+ if (!(sym.isClass || (glbThisType specializes sym)))
+ addMember(glbThisType, glbType.members, glbsym(sym));
+ if (glbType.members.isEmpty) glbBase else glbType;
+ } catch {
+ case _: MalformedClosure =>
+ if (ts forall (t => t <:< AnyRefClass.tpe)) AllRefClass.tpe
+ else AllClass.tpe
+ }
+ }
+ limitRecursion(ts, "greatest lower", glb0)
+ }
+
+ /** The most deeply nested owner that contains all the symbols
+ * of thistype or prefixless typerefs/singletype occurrences in given type */
+ private def commonOwner(t: Type): Symbol = {
+ commonOwnerMap.init;
+ commonOwnerMap.apply(t);
+ commonOwnerMap.result
+ }
+
+ /** The most deeply nested owner that contains all the symbols
+ * of thistype or prefixless typerefs/singletype occurrences in given list of types */
+ private def commonOwner(tps: List[Type]): Symbol = {
+ commonOwnerMap.init;
+ map1(tps, commonOwnerMap);
+ commonOwnerMap.result
+ }
+
+ /** Compute lub (if variance == 1) or glb (if variance == 0) of given list of types
+ * `tps'. All types in `tps' are typerefs or singletypes with the same symbol.
+ * Return Some(x) if the computation succeeds with result `x'.
+ * Return None if the computuation fails.
+ */
+ private def mergePrefixAndArgs(tps: List[Type], variance: int): Option[Type] = tps match {
+ case List(tp) =>
+ Some(tp)
+ case TypeRef(_, sym, _) :: rest =>
+ val pres = tps map (.prefix);
+ val pre = if (variance == 1) lub(pres) else glb(pres);
+ val argss = tps map (.typeArgs);
+ val args =
+ List.map2(sym.typeParams, List.transpose(argss))
+ ((tparam, as) =>
+ if (tparam.variance == variance) lub(as)
+ else if (tparam.variance == -variance) glb(as)
+ else NoType);
+ try {
+ if (args contains NoType) None
+ else Some(typeRef(pre, sym, args))
+ } catch {
+ case ex: MalformedType => None
+ }
+ case SingleType(_, sym) :: rest =>
+ val pres = tps map (.prefix);
+ val pre = if (variance == 1) lub(pres) else glb(pres);
+ try {
+ Some(singleType(pre, sym))
+ } catch {
+ case ex: MalformedType => None
+ }
+ }
+
+ /** Make symbol `sym' a member of scope `members' where `thistp' is the narrowed
+ * owner type of the scope */
+ private def addMember(thistp: Type, members: Scope, sym: Symbol): unit = {
+ if (!(thistp specializes sym)) {
+ if (sym.isTerm)
+ for (val alt <- members.lookup(sym.name).alternatives)
+ if (specializesSym(thistp, sym, thistp, alt))
+ members.unlink(alt);
+ members.enter(sym)
+ }
+ }
+
+ /** All types in list must be polytypes with type parameter lists of
+ * same length as tparams.
+ * Returns list of list of bounds infos, where corresponding type
+ * parameters are renamed to tparams.
+ */
+ private def matchingBounds(tps: List[Type], tparams: List[Symbol]): List[List[Type]] =
+ tps map {
+ case PolyType(tparams1, _) if (tparams1.length == tparams.length) =>
+ tparams1 map (tparam => tparam.info.substSym(tparams1, tparams))
+ case _ =>
+ throw new Error("lub/glb of incompatible types: " + tps.mkString("", " and ", ""))
+ }
+
+ /** All types in list must be method types with equal parameter types.
+ * Returns list of their result types.
+ */
+ private def matchingRestypes(tps: List[Type], pts: List[Type]): List[Type] =
+ tps map {
+ case MethodType(pts1, res) if (isSameTypes(pts1, pts)) =>
+ res
+ case _ =>
+ throw new Error("lub/glb of incompatible types: " + tps.mkString("", " and ", ""))
+ }
+
+// Errors and Diagnostics ---------------------------------------------------------
+
+ /** An exception signalling a type error */
+ class TypeError(msg: String) extends java.lang.Error(msg);
+
+ /** An exception signalling a malformed type */
+ class MalformedType(msg: String) extends TypeError(msg) {
+ def this(pre: Type, tp: String) = this("malformed type: " + pre + "#" + tp);
+ }
+
+ /** An exception signalling a malformed closure */
+ class MalformedClosure(ts: List[Type])
+ extends TypeError("no common type instance of base types " +
+ ts.mkString("", " and ", "") + " exists");
+
+ /** An exception signalling a variance annotation/usage conflict */
+ class VarianceError(msg: String) extends TypeError(msg);
+
+ /** The current indentation string for traces */
+ private var indent: String = "";
+
+ /** Perform operation `p' on arguments `tp1', `arg2' and print trace of computation */
+ private def explain[T](op: String, p: (Type, T) => boolean, tp1: Type, arg2: T): boolean = {
+ System.out.println(indent + tp1 + " " + op + " " + arg2 + "?");
+ indent = indent + " ";
+ val result = p(tp1, arg2);
+ indent = indent.substring(0, indent.length() - 2);
+ System.out.println(indent + result);
+ result
+ }
+
+ /** If option `explaintypes' is set, print a subtype trace for `found' <: `required' */
+ def explainTypes(found: Type, required: Type): unit =
+ if (settings.explaintypes.value) {
+ val s = explainSwitch;
+ explainSwitch = true;
+ found <:< required;
+ explainSwitch = s
+ }
+}
diff --git a/sources/scala/tools/nsc/symtab/classfile/ClassfileConstants.scala b/sources/scala/tools/nsc/symtab/classfile/ClassfileConstants.scala
new file mode 100644
index 0000000000..433ae327b8
--- /dev/null
+++ b/sources/scala/tools/nsc/symtab/classfile/ClassfileConstants.scala
@@ -0,0 +1,45 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+** $Id$
+\* */
+
+package scala.tools.nsc.symtab.classfile;
+
+object ClassfileConstants {
+
+ val JAVA_MAGIC = 0xCAFEBABE;
+ val JAVA_MAJOR_VERSION = 45;
+ val JAVA_MINOR_VERSION = 3;
+
+ val JAVA_ACC_PUBLIC = 0x0001;
+ val JAVA_ACC_PRIVATE = 0x0002;
+ val JAVA_ACC_PROTECTED = 0x0004;
+ val JAVA_ACC_STATIC = 0x0008;
+ val JAVA_ACC_FINAL = 0x0010;
+ val JAVA_ACC_SUPER = 0x0020;
+ val JAVA_ACC_SYNCHRONIZED = 0x0020;
+ val JAVA_ACC_VOLATILE = 0x0040;
+ val JAVA_ACC_BRIDGE = 0x0040;
+ val JAVA_ACC_TRANSIENT = 0x0080;
+ val JAVA_ACC_NATIVE = 0x0100;
+ val JAVA_ACC_INTERFACE = 0x0200;
+ val JAVA_ACC_ABSTRACT = 0x0400;
+ val JAVA_ACC_STRICT = 0x0800;
+ val JAVA_ACC_SYNTHETIC = 0x1000;
+
+ val CONSTANT_UTF8 = 1;
+ val CONSTANT_UNICODE = 2;
+ val CONSTANT_INTEGER = 3;
+ val CONSTANT_FLOAT = 4;
+ val CONSTANT_LONG = 5;
+ val CONSTANT_DOUBLE = 6;
+ val CONSTANT_CLASS = 7;
+ val CONSTANT_STRING = 8;
+ val CONSTANT_FIELDREF = 9;
+ val CONSTANT_METHODREF = 10;
+ val CONSTANT_INTFMETHODREF = 11;
+ val CONSTANT_NAMEANDTYPE = 12;
+}
diff --git a/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
new file mode 100755
index 0000000000..ee16209bdb
--- /dev/null
+++ b/sources/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -0,0 +1,388 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+** **
+** $Id$
+\* */
+
+package scala.tools.nsc.symtab.classfile;
+
+import scala.tools.util._;
+import java.io.IOException;
+
+abstract class ClassfileParser {
+
+ val global: Global;
+ import global._;
+
+ import ClassfileConstants._;
+ import Flags._;
+
+ private var in: AbstractFileReader = _; // the class file
+ private var clazz: Symbol = _; // the class symbol containing dynamic members
+ private var statics: Symbol = _; // the module class symbol containing static members
+ private var classMembers: Scope = _; // the scope of all dynamic members
+ private var staticMembers: Scope = _; // the scope of all static members
+ private var pool: ConstantPool = _; // the classfile's constant pool
+ private var isScala: boolean = _; // does class file describe a scala class?
+ private var hasMeta: boolean = _; // does class file contain jaco meta attribute?s
+ private var busy: boolean = false; // lock to detect recursive reads
+
+ private object metaParser extends MetaParser {
+ val global: ClassfileParser.this.global.type = ClassfileParser.this.global
+ }
+
+ private object unpickle extends UnPickle {
+ val global: ClassfileParser.this.global.type = ClassfileParser.this.global
+ }
+
+ def parse(file: AbstractFile, root: Symbol): unit = {
+ assert(!busy);
+ busy = true;
+ this.in = new AbstractFileReader(file);
+ if (root.isModule) {
+ this.clazz = root.linkedClass;
+ this.statics = root.moduleClass
+ } else {
+ this.clazz = root;
+ this.statics = root.linkedModule.moduleClass;
+ }
+ this.isScala = false;
+ this.hasMeta = false;
+ try {
+ parseHeader;
+ this.pool = new ConstantPool;
+ parseClass()
+ } catch {
+ case e: RuntimeException =>
+ if (settings.debug.value) e.printStackTrace();
+ throw new IOException("class file '" + in.path + "' is broken")
+ }
+ busy = false
+ }
+
+ private def parseHeader: unit = {
+ val magic = in.nextInt();
+ if (magic != JAVA_MAGIC)
+ throw new IOException("class file '" + in.path + "' "
+ + "has wrong magic number 0x" + Integer.toHexString(magic)
+ + ", should be 0x" + Integer.toHexString(JAVA_MAGIC));
+ val minorVersion = in.nextChar();
+ val majorVersion = in.nextChar();
+ if ((majorVersion < JAVA_MAJOR_VERSION) ||
+ ((majorVersion == JAVA_MAJOR_VERSION) &&
+ (minorVersion < JAVA_MINOR_VERSION)))
+ throw new IOException("class file '" + in.path + "' "
+ + "has unknown version "
+ + majorVersion + "." + minorVersion
+ + ", should be at least "
+ + JAVA_MAJOR_VERSION + "." + JAVA_MINOR_VERSION);
+
+ }
+
+ class ConstantPool {
+ private val len = in.nextChar();
+ private val starts = new Array[int](len);
+ private val values = new Array[Object](len);
+ private val internalized = new Array[Name](len);
+ { var i = 1;
+ while (i < starts.length) {
+ starts(i) = in.bp;
+ i = i + 1;
+ in.nextByte() match {
+ case CONSTANT_UTF8 | CONSTANT_UNICODE =>
+ in.skip(in.nextChar());
+ case CONSTANT_CLASS | CONSTANT_STRING =>
+ in.skip(2);
+ case CONSTANT_FIELDREF | CONSTANT_METHODREF | CONSTANT_INTFMETHODREF | CONSTANT_NAMEANDTYPE | CONSTANT_INTEGER | CONSTANT_FLOAT =>
+ in.skip(4);
+ case CONSTANT_LONG | CONSTANT_DOUBLE =>
+ in.skip(8);
+ i = i + 1
+ case _ =>
+ errorBadTag(in.bp - 1);
+ }
+ }
+ }
+
+ def getName(index: int): Name = {
+ if (index <= 0 || len <= index) errorBadIndex(index);
+ var name = values(index).asInstanceOf[Name];
+ if (name == null) {
+ val start = starts(index);
+ if (in.buf(start) != CONSTANT_UTF8) errorBadTag(start);
+ val len = in.getChar(start + 1);
+ val cs = new Array[char](len);
+ val defined = UTF8Codec.decode(in.buf, start + 3, cs, 0, len);
+ name = newTermName(cs, 0, defined);
+ values(index) = name;
+ }
+ name
+ }
+
+ def getExternalName(index: int): Name = {
+ if (index <= 0 || len <= index) errorBadIndex(index);
+ if (internalized(index) == null) {
+ internalized(index) = getName(index).replace('/', '.')
+ }
+ internalized(index)
+ }
+
+ def getClassSymbol(index: int): Symbol = {
+ if (index <= 0 || len <= index) errorBadIndex(index);
+ var c = values(index).asInstanceOf[Symbol];
+ if (c == null) {
+ val start = starts(index);
+ if (in.buf(start) != CONSTANT_CLASS) errorBadTag(start);
+ val name = getExternalName(in.getChar(start + 1));
+ c = definitions.getClass(name);
+ values(index) = c;
+ }
+ c
+ }
+
+ def getType(index: int): Type =
+ sigToType(getExternalName(index));
+
+ def getSuperClass(index: int): Symbol =
+ if (index == 0) definitions.AnyClass else getClassSymbol(index);
+
+ def getLiteral(index: int): Any = {
+ if (index <= 0 || len <= index) errorBadIndex(index);
+ var value = values(index);
+ if (value == null) {
+ val start = starts(index);
+ value = in.buf(start) match {
+ case CONSTANT_STRING =>
+ getName(in.getChar(start + 1)).toString()
+ case CONSTANT_INTEGER =>
+ in.getInt(start + 1)
+ case CONSTANT_FLOAT =>
+ in.getFloat(start + 1)
+ case CONSTANT_LONG =>
+ in.getLong(start + 1)
+ case CONSTANT_DOUBLE =>
+ in.getDouble(start + 1)
+ case _ =>
+ errorBadTag(start);
+ }
+ values(index) = value;
+ }
+ value
+ }
+
+ /** Throws an exception signaling a bad constant index. */
+ private def errorBadIndex(index: int) =
+ throw new RuntimeException("bad constant pool index: " + index);
+
+ /** Throws an exception signaling a bad tag at given address. */
+ private def errorBadTag(start: int) =
+ throw new RuntimeException("bad constant pool tag " + in.buf(start) + " at byte " + start);
+ }
+
+ private def sigToType(name: Name): Type = {
+ var index = 0;
+ val end = name.length;
+ def paramsigs2types: List[Type] =
+ if (name(index) == ')') { index = index + 1; List() }
+ else sig2type :: paramsigs2types;
+ def sig2type: Type = {
+ val tag = name(index); index = index + 1;
+ tag match {
+ case 'B' => definitions.ByteClass.tpe
+ case 'C' => definitions.CharClass.tpe
+ case 'D' => definitions.DoubleClass.tpe
+ case 'F' => definitions.FloatClass.tpe
+ case 'I' => definitions.IntClass.tpe
+ case 'J' => definitions.LongClass.tpe
+ case 'S' => definitions.ShortClass.tpe
+ case 'V' => definitions.UnitClass.tpe
+ case 'Z' => definitions.BooleanClass.tpe
+ case 'L' =>
+ val start = index;
+ while (name(index) != ';') { index = index + 1 }
+ val end = index;
+ index = index + 1;
+ definitions.getClass(name.subName(start, end)).tpe
+ case '[' =>
+ while ('0' <= name(index) && name(index) <= '9') index = index + 1;
+ appliedType(definitions.ArrayClass.tpe, List(sig2type))
+ case '(' =>
+ MethodType(paramsigs2types, sig2type)
+ }
+ }
+ sig2type
+ }
+
+ def parseClass(): unit = {
+ val jflags = in.nextChar();
+ var sflags = transFlags(jflags);
+ if ((sflags & DEFERRED) != 0) sflags = sflags & ~DEFERRED | ABSTRACT;
+ val c = pool.getClassSymbol(in.nextChar());
+ if (c != clazz)
+ throw new IOException("class file '" + in.path + "' contains wrong " + clazz);
+ val superType = pool.getSuperClass(in.nextChar()).tpe;
+ val ifaceCount = in.nextChar();
+ val parents = superType ::
+ (for (val i <- List.range(0, ifaceCount))
+ yield pool.getSuperClass(in.nextChar()).tpe);
+ classMembers = new Scope();
+ staticMembers = new Scope();
+ val classInfo = ClassInfoType(parents, classMembers, clazz);
+ val staticInfo = ClassInfoType(List(), staticMembers, statics);
+
+ val curbp = in.bp;
+ skipMembers(); // fields
+ skipMembers(); // methods
+ parseAttributes(clazz, classInfo);
+ if (!isScala) {
+ clazz.setFlag(sflags);
+ if (!hasMeta) {
+ clazz.setInfo(classInfo);
+ statics.setInfo(staticInfo);
+ }
+ statics.sourceModule.setInfo(statics.tpe);
+ in.bp = curbp;
+ val fieldCount = in.nextChar();
+ for (val i <- Iterator.range(0, fieldCount)) parseField();
+ val methodCount = in.nextChar();
+ for (val i <- Iterator.range(0, methodCount)) parseMethod();
+ }
+ }
+
+ def parseField(): unit = {
+ val jflags = in.nextChar();
+ var sflags = transFlags(jflags);
+ if ((sflags & FINAL) != 0) sflags = sflags | MUTABLE;
+ if ((sflags & PRIVATE) != 0) {
+ in.skip(4); skipAttributes();
+ } else {
+ val name = pool.getName(in.nextChar());
+ val info = pool.getType(in.nextChar());
+ val sym = getOwner(jflags)
+ .newValue(Position.NOPOS, name).setFlag(sflags).setInfo(info);
+ parseAttributes(sym, info);
+ getScope(jflags).enter(sym);
+ }
+ }
+
+ def parseMethod(): unit = {
+ val jflags = in.nextChar();
+ var sflags = transFlags(jflags);
+ if ((sflags & JAVA_ACC_BRIDGE) != 0) sflags = sflags | PRIVATE;
+ if ((sflags & PRIVATE) != 0) {
+ in.skip(4); skipAttributes();
+ } else {
+ val name = pool.getName(in.nextChar());
+ val info = pool.getType(in.nextChar());
+ val sym = getOwner(jflags)
+ .newMethod(Position.NOPOS, name).setFlag(sflags).setInfo(info);
+ parseAttributes(sym, info);
+ getScope(jflags).enter(sym);
+ }
+ }
+
+ def parseAttributes(sym: Symbol, symtype: Type): unit = {
+ def parseAttribute(): unit = {
+ val attrName = pool.getName(in.nextChar());
+ val attrLen = in.nextInt();
+ attrName match {
+ case nme.SyntheticATTR =>
+ sym.setFlag(SYNTHETIC);
+ in.skip(attrLen)
+ case nme.BridgeATTR =>
+ sym.setFlag(BRIDGE);
+ in.skip(attrLen)
+ case nme.DeprecatedATTR =>
+ sym.setFlag(DEPRECATED);
+ in.skip(attrLen)
+ case nme.ConstantValueATTR =>
+ def cast(value: Any, tp: Type): Any = {
+ val s = symtype.symbol;
+ if (s == definitions.ByteClass) value.asInstanceOf[byte]
+ else if (s == definitions.ShortClass) value.asInstanceOf[short]
+ else if (s == definitions.CharClass) value.asInstanceOf[char]
+ else if (s == definitions.IntClass) value.asInstanceOf[int]
+ else if (s == definitions.LongClass) value.asInstanceOf[long]
+ else if (s == definitions.FloatClass) value.asInstanceOf[float]
+ else if (s == definitions.DoubleClass) value.asInstanceOf[double]
+ else if (s == definitions.UnitClass) ()
+ else if (s == definitions.BooleanClass) value.asInstanceOf[int] != 0
+ else if (s == definitions.StringClass) value.asInstanceOf[String]
+ else value
+ }
+ val value = pool.getLiteral(in.nextChar());
+ sym.setInfo(ConstantType(symtype, cast(value, symtype)))
+ case nme.InnerClassesATTR =>
+ parseInnerClasses()
+ case nme.ScalaSignatureATTR =>
+ //unpickle.parse(in.nextBytes(attrLen), clazz, statics.sourceModule);
+ //this.isScala = true;
+ case nme.JacoMetaATTR =>
+ val meta = pool.getName(in.nextChar()).toString().trim();
+ metaParser.parse(meta, sym, symtype);
+ this.hasMeta = true;
+ case _ =>
+ in.skip(attrLen)
+ }
+ }
+ def parseInnerClasses(): unit = {
+ for (val i <- Iterator.range(0, in.nextChar())) {
+ val innerIndex = in.nextChar();
+ val outerIndex = in.nextChar();
+ val nameIndex = in.nextChar();
+ val jflags = in.nextChar();
+ if (innerIndex != 0 && outerIndex != 0 && nameIndex != 0 &&
+ (jflags & (JAVA_ACC_PUBLIC | JAVA_ACC_PROTECTED)) != 0 &&
+ pool.getClassSymbol(outerIndex) == sym) {
+ val innerAlias = getOwner(jflags)
+ .newAliasType(Position.NOPOS, pool.getName(nameIndex).toTypeName)
+ .setInfo(pool.getClassSymbol(innerIndex).tpe);
+ getScope(jflags).enter(innerAlias);
+ }
+ }
+ }
+ val attrCount = in.nextChar();
+ for (val i <- Iterator.range(0, attrCount)) parseAttribute()
+ }
+
+ def skipAttributes(): unit = {
+ val attrCount = in.nextChar();
+ for (val i <- Iterator.range(0, attrCount)) {
+ in.skip(2); in.skip(in.nextInt())
+ }
+ }
+
+ def skipMembers(): unit = {
+ val memberCount = in.nextChar();
+ for (val i <- Iterator.range(0, memberCount)) {
+ in.skip(6); skipAttributes()
+ }
+ }
+
+ private def getOwner(flags: int): Symbol =
+ if ((flags & JAVA_ACC_STATIC) != 0) statics else clazz;
+
+ private def getScope(flags: int): Scope =
+ if ((flags & JAVA_ACC_STATIC) != 0) staticMembers else classMembers;
+
+ private def transFlags(flags: int): int = {
+ var res = 0;
+ if ((flags & JAVA_ACC_PRIVATE) != 0)
+ res = res | PRIVATE
+ else if ((flags & JAVA_ACC_PROTECTED) != 0)
+ res = res | PROTECTED
+ else if ((flags & JAVA_ACC_PUBLIC) == 0)
+ res = res | PRIVATE;
+ if ((flags & JAVA_ACC_ABSTRACT) != 0)
+ res = res | DEFERRED;
+ if ((flags & JAVA_ACC_FINAL) != 0)
+ res = res | FINAL;
+ if ((flags & JAVA_ACC_INTERFACE) != 0)
+ res = res | TRAIT | ABSTRACT;
+ if ((flags & JAVA_ACC_SYNTHETIC) != 0)
+ res = res | SYNTHETIC;
+ res | JAVA;
+ }
+}
diff --git a/sources/scala/tools/nsc/symtab/classfile/MetaParser.scala b/sources/scala/tools/nsc/symtab/classfile/MetaParser.scala
new file mode 100755
index 0000000000..dfa8804bf7
--- /dev/null
+++ b/sources/scala/tools/nsc/symtab/classfile/MetaParser.scala
@@ -0,0 +1,152 @@
+/** $Id: MetaParser.scala
+*/
+package scala.tools.nsc.symtab.classfile;
+
+import java.util.{StringTokenizer, NoSuchElementException}
+import scala.collection.mutable.ListBuffer;
+import scala.tools.util.Position;
+
+abstract class MetaParser{
+
+ val global: Global;
+ import global._;
+
+ private var scanner: StringTokenizer = _;
+ private var owner: Symbol = _;
+ private var ownertype: Type = _;
+ private var token: String = _;
+ private var locals: Scope = null;
+
+ def parse(meta: String, sym: Symbol, symtype: Type): unit = {
+ //System.out.println("parse meta for " + sym + ":" + meta + ", locals = " + locals);//DEBUG
+ this.scanner = new StringTokenizer(meta, "()[], \t<;", true);
+ this.owner = sym;
+ this.ownertype = symtype;
+ nextToken();
+ if (token == "class") parseClass()
+ else if (token == "method") parseMethod()
+ else if (token == "field") parseField()
+ else if (token == "constr") parseConstr()
+ else owner.setInfo(symtype);
+ }
+
+ protected def nextToken(): unit =
+ try {
+ do { token = scanner.nextToken().trim() } while (token.length() == 0)
+ } catch {
+ case ex: NoSuchElementException => token = ""
+ }
+
+ protected def parseType(): Type = {
+ val str = token;
+ nextToken();
+ val sym = locals.lookup(newTypeName(str));
+ if (sym != NoSymbol) sym.tpe
+ else {
+ val tp = definitions.getClass(str).tpe;
+ if (token != "[") tp
+ else {
+ val args = new ListBuffer[Type];
+ do {
+ nextToken(); args append parseType();
+ } while (token == ",");
+ nextToken();
+ appliedType(tp, args.toList)
+ }
+ }
+ }
+
+ protected def parseTypeParam(): Symbol = {
+ val vflag =
+ if (token == "+") { nextToken(); Flags.COVARIANT }
+ else if (token == "-") { nextToken(); Flags.CONTRAVARIANT }
+ else 0;
+ assert(token.startsWith("?"));
+ val sym = owner.newTypeParameter(Position.NOPOS, newTypeName(token))
+ .setFlag(vflag)
+ .setInfo(TypeBounds(
+ definitions.AllClass.tpe,
+ definitions.AnyClass.tpe,
+ definitions.AnyClass.tpe));
+ locals enter sym;
+ nextToken();
+ sym
+ }
+
+ protected def parseTypeParams(): List[Symbol] = {
+ nextToken();
+ val syms = new ListBuffer[Symbol];
+ if (token != "]") {
+ syms append parseTypeParam();
+ while (token == ",") {
+ nextToken(); syms append parseTypeParam();
+ }
+ }
+ assert(token == "]");
+ syms.toList
+ }
+
+ protected def parseParams(): List[Type] = {
+ nextToken();
+ val tps = new ListBuffer[Type];
+ if (token != ")") {
+ tps append parseType();
+ while (token == ",") {
+ nextToken(); tps append parseType();
+ }
+ }
+ assert(token == ")");
+ tps.toList
+ }
+
+ protected def parseClass(): unit = {
+ locals = new Scope();
+ def parse(): Type = {
+ nextToken();
+ if (token == "[") {
+ PolyType(parseTypeParams(), parse())
+ } else if (token == "extends") {
+ val tps = new ListBuffer[Type];
+ do {
+ nextToken(); tps append parseType()
+ } while (token == "with");
+ ownertype match {
+ case ClassInfoType(parents, defs, clazz) =>
+ ClassInfoType(tps.toList, defs, clazz)
+ }
+ } else ownertype
+ }
+ owner.setInfo(parse());
+ assert(token == ";")
+ }
+
+ protected def parseMethod(): unit = {
+ val globals = locals;
+ locals = if (locals == null) new Scope() else new Scope(locals);
+ def parse(): Type = {
+ nextToken();
+ if (token == "[") PolyType(parseTypeParams(), parse())
+ else if (token == "(") MethodType(parseParams(), parse())
+ else parseType()
+ }
+ owner.setInfo(parse());
+ locals = globals;
+ assert(token == ";")
+ }
+
+ protected def parseField(): unit = {
+ nextToken();
+ owner.setInfo(parseType());
+ assert(token == ";")
+ }
+
+ protected def parseConstr(): unit = {
+ def parse(): Type = {
+ nextToken();
+ if (token == "(") MethodType(parseParams(), parse())
+ else definitions.UnitClass.tpe
+ }
+ owner.setInfo(parse());
+ assert(token == ";")
+ }
+}
diff --git a/sources/scala/tools/nsc/symtab/classfile/Pickle.scala b/sources/scala/tools/nsc/symtab/classfile/Pickle.scala
new file mode 100644
index 0000000000..37ba9cf47e
--- /dev/null
+++ b/sources/scala/tools/nsc/symtab/classfile/Pickle.scala
@@ -0,0 +1,6 @@
+package scala.tools.nsc.symtab.classfile;
+
+/***************************************************
+ * Symbol table attribute format: see EntryTags.java
+ */
+class Pickle {}
diff --git a/sources/scala/tools/nsc/symtab/classfile/UnPickle.scala b/sources/scala/tools/nsc/symtab/classfile/UnPickle.scala
new file mode 100755
index 0000000000..07ab81ff67
--- /dev/null
+++ b/sources/scala/tools/nsc/symtab/classfile/UnPickle.scala
@@ -0,0 +1,477 @@
+//import scalac.{symtab => scalac_symtab}
+
+package scala.tools.nsc.symtab.classfile {
+
+//import scalac_symtab.Modifiers;
+//import scalac_symtab.EntryTags._;
+import java.io.PrintStream;
+import scala.tools.util.{Position, UTF8Codec};
+import java.lang.{Float, Double};
+
+/***************************************************
+ * Symbol table attribute format: see EntryTags.java
+ */
+abstract class UnPickle {
+
+ val global: Global;
+ import global._;
+
+ private var classRoot: Symbol = _;
+ private var moduleRoot: Symbol = _;
+ private var bytes: Array[byte] = _;
+ private var bp: int = _;
+ private var index: Array[int] = _;
+ private var entries: Array[Any] = _;
+
+ def parse(bytes: Array[byte], clazz: Symbol, module: Symbol): unit = {
+ warning("cannot yet unpickle: " + clazz.fullNameString('.'));
+ }
+}}
+/*
+ this.classRoot = clazz;
+ this.moduleRoot = module;
+ this.bytes = bytes;
+ this.bp = 0;
+ if (settings.debug.value) global.log("unpickle " + classRoot + " and " + moduleRoot);
+ createIndex();
+ if (settings.debug.value) printAll(System.out);
+ entries = new Array[Any](index.length);
+ for (val i <- Iterator.range(0, index.length)) {
+ if (isSymbolEntry(i)) getSymbol(i)
+ }
+ if (settings.debug.value) global.log("unpickled " + classRoot + ":" + classRoot.rawInfo + ", " + moduleRoot + ":" + moduleRoot.rawInfo);//debug
+ }
+
+ def readByte(): int = {
+ val x = bytes(bp); bp = bp + 1; x
+ }
+
+ def readNat(): int = {
+ var b = 0;
+ var x = 0;
+ do {
+ b = readByte();
+ x = (x << 7) + (b & 0x7f);
+ } while ((b & 0x80) != 0);
+ x
+ }
+
+ def readLong(len: int): long = {
+ var x = 0L;
+ var i = 0;
+ while (i < len) {
+ x = (x << 8) + (readByte() & 0xff);
+ i = i + 1
+ }
+ val leading = 64 - (len << 3);
+ x << leading >> leading
+ }
+
+ private def at[T](start: int)(op: => T): T = {
+ val savedBp = bp;
+ bp = start;
+ val result = op;
+ bp = savedBp;
+ result
+ }
+
+ private def createIndex(): unit = {
+ index = new Array[int](readNat());
+ for (val i <- Iterator.range(0, index.length)) {
+ index(i) = readByte();
+ bp = readNat() + bp
+ }
+ }
+
+ def isTypeEntry(i: int): boolean = {
+ val tag = bytes(index(i));
+ (firstTypeTag <= tag && tag <= lastTypeTag) || tag == NOpre;
+ }
+
+ def isSymbolEntry(i: int): boolean = {
+ val tag = bytes(index(i));
+ firstSymTag <= tag && tag <= lastSymTag
+ }
+
+ def getName(i: int): Name = {
+ var name: Name = entries(i).asInstanceOf[Name];
+ if (name == null) {
+ at(index(i)) {
+ val tag = readByte();
+ val len = readNat();
+ val cs = new Array[char](len);
+ val defined = UTF8Codec.decode(bytes, bp, cs, 0, len);
+ name = tag match {
+ case TERMname => newTermName(cs, 0, defined)
+ case TYPEname => newTypeName(cs, 0, defined)
+ case _ => errorBadSignature("");
+ }
+ entries(i) = name
+ }
+ }
+ name
+ }
+
+ def readNameRef(): Name = getName(readNat());
+
+ def getSymbol(i: int): Symbol = {
+ var sym: Symbol = entries(i).asInstanceOf[Symbol];
+ if (sym == null) {
+ at(index(i)) {
+ val tag = readByte();
+ val end = readNat() + bp;
+ tag match {
+ case NONEsym =>
+ sym = NoSymbol;
+ entries(i) = sym
+ case EXTref | EXTMODCLASSref =>
+ val name = readNameRef();
+ val owner =
+ if (bp == end) definitions.RootClass
+ else { assert(bp < end); readSymbolRef() }
+ sym =
+ if (name.toTermName == nme.ROOT && owner == NoSymbol) {
+ assert(tag != EXTref);
+ global.definitions.RootClass
+ } else if (tag == EXTMODCLASSref) {
+ owner.info.lookup(name).moduleClass
+ } else {
+ owner.info.lookup(name)
+ }
+ entries(i) = sym;
+ if (sym == NoSymbol)
+ errorBadSignature(
+ "reference " + (if (name.isTypeName) "type " else "value ") +
+ name.decode + " of " + owner + " refers to nonexisting symbol.");
+ case _ =>
+ assert(isSymbolEntry(i));
+ val name = readNameRef();
+ if (settings.debug.value) global.log("reading " + name + " at " + i);
+ val owner = readSymbolRef();
+ if (entries(i) != null)
+ sym = entries(i).asInstanceOf[Symbol]
+ else {
+ val pflags = readNat();
+ val inforef = readNat();
+ var syminfo: Type = null;
+ tag match {
+ case TYPEsym =>
+ sym = owner.newAbstractType(Position.NOPOS, name);
+ entries(i) = sym;
+ syminfo = new LazyBoundsTypeRef(
+ inforef, readNat(), (pflags & Modifiers.VIEWBOUND) != 0)
+ case ALIASsym =>
+ sym = owner.newAliasType(Position.NOPOS, name);
+ entries(i) = sym;
+ syminfo = new LazyTypeRef(inforef, sym);
+ val constr = readSymbolRef();
+ if (!constr.typeParams.isEmpty)
+ syminfo = new LazyPolyType(
+ constr.typeParams map (.cloneSymbol(sym)),
+ syminfo);
+ case CLASSsym =>
+ sym =
+ if ((pflags & Modifiers.MODUL) != 0) {
+ val modulesym = readSymbolRef();
+ modulesym.moduleClass
+ } else if (name == classRoot.name && owner == classRoot.owner) {
+ if (settings.debug.value) global.log("overwriting " + classRoot);
+ classRoot
+ } else {
+ owner.newClass(Position.NOPOS, name)
+ }
+ entries(i) = sym;
+ syminfo = new LazyTypeRef(inforef, sym);
+ sym.setTypeOfThis(new LazyTypeRef(readNat(), sym));
+ val constr = readSymbolRef();
+ if (!constr.typeParams.isEmpty)
+ syminfo = new LazyPolyType(
+ constr.typeParams map (.cloneSymbol(sym)),
+ syminfo);
+ case VALsym =>
+ sym =
+ if (name == moduleRoot.name && owner == moduleRoot.owner) {
+ if (settings.debug.value) global.log("overwriting " + moduleRoot);
+ moduleRoot
+ } else if ((pflags & Modifiers.MODUL) != 0) {
+ owner.newModule(Position.NOPOS, name)
+ } else {
+ if (name == nme.CONSTRUCTOR && bp < end) readSymbolRef();
+ owner.newValue(Position.NOPOS, name);
+ }
+ if (sym.isModule) {
+ val clazz = readSymbolRef();
+ assert(clazz == sym.moduleClass, sym)
+ }
+ syminfo = new LazyTypeRef(inforef, sym);
+ case _ =>
+ errorBadSignature("");
+ }
+ sym.setFlag(transFlags(pflags));
+ sym.setInfo(syminfo);
+ enterSymbol(sym);
+ }
+ }
+ }
+ }
+ sym
+ }
+
+ def readSymbolRef(): Symbol = getSymbol(readNat());
+
+ def readSymbolRefs(end: int): List[Symbol] =
+ if (bp == end) List()
+ else {
+ val symref = readNat();
+ if (!isSymbolEntry(symref)) List()
+ else getSymbol(symref) :: readSymbolRefs(end)
+ }
+
+ def enterSymbol(sym: Symbol): unit =
+ if (sym.owner.isClass && !sym.isModuleClass) {
+ if (settings.debug.value) global.log("entering " + sym + ":" + sym.tpe + " in " + sym.owner);//debug
+ val scope = sym.owner.info.members;
+ val other = scope.lookup(sym.name);
+ if (other != sym) {
+ sym.info match {
+ case OverloadedType(alts) => alts foreach scope.enter
+ case _ => scope.enter(sym)
+ }
+ }
+ }
+
+ def getType(i: int, owner: Symbol): Type = {
+ var tpe = entries(i).asInstanceOf[Type];
+ if (tpe == null) {
+ at(index(i)) {
+ val tag = readByte();
+ val end = readNat() + bp;
+ tpe = tag match {
+ case NOtpe =>
+ NoType
+ case NOpre =>
+ NoPrefix
+ case THIStpe =>
+ ThisType(readSymbolRef())
+ case SINGLEtpe =>
+ singleType(readTypeRef(owner), readSymbolRef());
+ case CONSTANTtpe =>
+ ConstantType(readTypeRef(owner), readConstantRef())
+ case TYPEREFtpe =>
+ // create a type-ref as found, without checks or rebinds
+ new ExtTypeRef(readTypeRef(owner), readSymbolRef(), readTypeRefs(end, owner))
+ case COMPOUNDtpe =>
+ val isCompoundSym = readByte() != 0;
+ val ctOwner = if (isCompoundSym) readSymbolRef() else null;
+ val ctClassRef = readNat();
+ val ctClass: Symbol =
+ if (isCompoundSym) entries(ctClassRef).asInstanceOf[Symbol]
+ else getSymbol(ctClassRef);
+ val parents = readTypeRefs(end, owner);
+ if (ctClass == null)
+ refinedType(intersectionType(parents), ctOwner)
+ else if (isCompoundSym)
+ new ExtRefinedType(intersectionType(parents), new Scope, ctClass)
+ else
+ ClassInfoType(parents, new Scope, ctClass);
+ case METHODtpe =>
+ val restype = readTypeRef(owner);
+ val argtps = at(bp)(readTypeRefs(end, owner)) map { argtp =>
+ val flags = getFlags(readNat());
+ if ((flags & DEFflag) != 0)
+ PolyType(List(), argtp)
+ else if ((flags & REPEATEDflag) != 0)
+ appliedType(definitions.RepeatedParamClass.tpe, List(argtp))
+ else
+ argtp
+ }
+ MethodType(argtps, restype)
+ case POLYtpe =>
+ val restype = readTypeRef(owner);
+ PolyType(readSymbolRefs(end), restype)
+ case OVERLOADEDtpe =>
+ val alts = readSymbolRefs(end);
+ readTypeRefs(end, NoSymbol);
+ OverloadedType(alts)
+ case FLAGGEDtpe =>
+ readNat(); // skip flags
+ readTypeRef(owner)
+ case _ =>
+ errorBadSignature("");
+ }
+ if (tag != METHODtpe) entries(i) = tpe;
+ }
+ }
+ tpe
+ }
+
+ def readTypeRef(owner: Symbol): Type = getType(readNat(), owner);
+
+ def readTypeRefs(end: int, owner: Symbol): List[Type] =
+ if (bp == end) List()
+ else {
+ val typeref = readNat();
+ if (!isTypeEntry(typeref)) List()
+ else getType(typeref, owner) :: readTypeRefs(end, owner)
+ }
+
+ def getFlags(i: int): int =
+ at(index(i)) {
+ val tag = readByte();
+ val end = readNat() + bp;
+ if (tag == FLAGGEDtpe) readNat() else 0
+ }
+
+ def getConstant(i: int): Any = {
+ var value = entries(i);
+ if (value == null) {
+ at(index(i)) {
+ val tag = readByte();
+ val len = readNat();
+ value = tag match {
+ case LITERALunit => ()
+ case LITERALboolean => if (readByte() == 0) false else true
+ case LITERALbyte => readLong(len).asInstanceOf[byte]
+ case LITERALshort => readLong(len).asInstanceOf[short]
+ case LITERALchar => readLong(len).asInstanceOf[char]
+ case LITERALint => readLong(len).asInstanceOf[int]
+ case LITERALlong => readLong(len)
+ case LITERALfloat => Float.intBitsToFloat(readLong(len).asInstanceOf[int])
+ case LITERALdouble => Double.longBitsToDouble(readLong(len))
+ case LITERALstring => readNameRef().toString()
+ case LITERALnull => null
+ case _ => errorBadSignature("bad constant tag: " + tag)
+ }
+ entries(i)= value
+ }
+ }
+ value
+ }
+
+ def readConstantRef(): Any = getConstant(readNat());
+
+ def errorBadSignature(msg: String) =
+ throw new RuntimeException("malformed Scala signature at " + bp + "; " + msg);
+
+ private case class OverloadedType(alts: List[Symbol]) extends Type;
+
+ private class LazyTypeRef(tpref: int, owner: Symbol) extends LazyType {
+ override def complete(sym: Symbol): unit =
+ sym.setInfo(getType(tpref, owner));
+ }
+
+ private class LazyBoundsTypeRef(hiref: int, loref: int, vubound: boolean) extends LazyType {
+ override def complete(sym: Symbol): unit = {
+ val hi = if (vubound) definitions.AnyClass.tpe else getType(hiref, sym);
+ val vu = if (vubound) getType(hiref, sym) else definitions.AnyClass.tpe;
+ val lo = getType(loref, sym);
+ sym.setInfo(TypeBounds(lo, hi, vu))
+ }
+ }
+
+// --- print symbl files -------------------------------------------------
+
+ private def tag2string(tag: int): String = tag match {
+ case TERMname => "TERMname";
+ case TYPEname => "TYPEname";
+ case NONEsym => "NONEsym";
+ case TYPEsym => "TYPEsym";
+ case ALIASsym => "ALIASsym";
+ case CLASSsym => "CLASSsym";
+ case VALsym => "VALsym";
+ case EXTref => "EXTref";
+ case EXTMODCLASSref => "EXTMODCLASSref";
+ case NOtpe => "NOtpe";
+ case THIStpe => "THIStpe";
+ case SINGLEtpe => "SINGLEtpe";
+ case TYPEREFtpe => "TYPEREFtpe";
+ case CONSTANTtpe => "CONSTANTtpe";
+ case COMPOUNDtpe => "COMPOUNDtpe";
+ case METHODtpe => "METHODtpe";
+ case POLYtpe => "POLYtpe";
+ case OVERLOADEDtpe => "OVERLOADEDtpe";
+ case UNBOXEDtpe => "UNBOXEDtpe";
+ case UNBOXEDARRAYtpe => "UNBOXEDARRAYtpe";
+ case FLAGGEDtpe => "FLAGGEDtpe";
+ case ERRORtpe => "ERRORtpe";
+ case LITERALunit => "LITERALunit";
+ case LITERALboolean => "LITERALboolean";
+ case LITERALbyte => "LITERALbyte";
+ case LITERALshort => "LITERALshort";
+ case LITERALchar => "LITERALchar";
+ case LITERALint => "LITERALint";
+ case LITERALlong => "LITERALlong";
+ case LITERALfloat => "LITERALfloat";
+ case LITERALdouble => "LITERALdouble";
+ case LITERALstring => "LITERALstring";
+ case LITERALnull => "LITERALnull";
+ case LITERALzero => "LITERALzero";
+ case _ => "***BAD TAG***(" + tag + ")";
+ }
+
+ def printAll(out: PrintStream): unit = {
+ out.println("symbl attribute for " + classRoot + ":");
+ for (val i <- Iterator.range(0, index.length)) {
+ out.print(i + "," + index(i) + ": ");
+ bp = index(i);
+ val tag = readByte();
+ out.print(tag2string(tag));
+ val len = readNat();
+ val end = len + bp;
+ out.print(" " + len);
+ tag match {
+ case TERMname | TYPEname =>
+ out.print(" " + UTF8Codec.decode(bytes, bp, len));
+ bp = end;
+ case NONEsym =>
+ case TYPEsym | ALIASsym | CLASSsym | VALsym =>
+ out.print(" " + readNat()); //name
+ out.print(" " + readNat()); //owner
+ out.print(" " + Integer.toHexString(readNat())); //flags
+ out.print(" " + readNat()); //type
+ case FLAGGEDtpe =>
+ out.print(" " + Integer.toHexString(readNat())); //flags
+ }
+ while (bp < end) out.print(" " + readNat());
+ out.println();
+ }
+ }
+
+ def transFlags(pflags: int): long = {
+ var res = 0L;
+ if ((pflags & Modifiers.DEFERRED ) != 0) res = res | Flags.DEFERRED ;
+ if ((pflags & Modifiers.FINAL ) != 0) res = res | Flags.FINAL ;
+ if ((pflags & Modifiers.PRIVATE ) != 0) res = res | Flags.PRIVATE ;
+ if ((pflags & Modifiers.PROTECTED ) != 0) res = res | Flags.PROTECTED ;
+ if ((pflags & Modifiers.SEALED ) != 0) res = res | Flags.SEALED ;
+ if ((pflags & Modifiers.OVERRIDE ) != 0) res = res | Flags.OVERRIDE ;
+ if ((pflags & Modifiers.CASE ) != 0) res = res | Flags.CASE ;
+ if ((pflags & Modifiers.ABSTRACT ) != 0) res = res | Flags.ABSTRACT ;
+ if ((pflags & Modifiers.SYNTHETIC ) != 0) res = res | Flags.SYNTHETIC ;
+ if ((pflags & Modifiers.DEPRECATED ) != 0) res = res | Flags.DEPRECATED ;
+ if ((pflags & Modifiers.JAVA ) != 0) res = res | Flags.JAVA ;
+ if ((pflags & Modifiers.MODUL ) != 0) res = res | Flags.MODULE ;
+ if ((pflags & Modifiers.MUTABLE ) != 0) res = res | Flags.MUTABLE ;
+ if ((pflags & Modifiers.PARAM ) != 0) res = res | Flags.PARAM ;
+ if ((pflags & Modifiers.INITIALIZED ) != 0) res = res | Flags.INITIALIZED;
+ if ((pflags & Modifiers.LOCKED ) != 0) res = res | Flags.LOCKED ;
+ if ((pflags & Modifiers.ACCESSED ) != 0) res = res | Flags.ACCESSED ;
+ if ((pflags & Modifiers.SELECTOR ) != 0) res = res | Flags.SELECTOR ;
+ if ((pflags & Modifiers.PACKAGE ) != 0) res = res | Flags.PACKAGE ;
+ if ((pflags & Modifiers.STABLE ) != 0) res = res | Flags.STABLE ;
+ if ((pflags & Modifiers.CAPTURED ) != 0) res = res | Flags.CAPTURED ;
+ if ((pflags & Modifiers.INCONSTRUCTOR) != 0) res = res | Flags.INCONSTRUCTOR;
+ if ((pflags & Modifiers.PARAMACCESSOR) != 0) res = res | Flags.PARAMACCESSOR;
+ if ((pflags & Modifiers.ACCESSOR ) != 0) res = res | Flags.ACCESSOR ;
+ if ((pflags & Modifiers.BRIDGE ) != 0) res = res | Flags.BRIDGE ;
+ if ((pflags & Modifiers.LIFTED ) != 0) res = res | Flags.LIFTED ;
+ if ((pflags & Modifiers.ALTERNATIVE ) != 0) res = res | Flags.ALTERNATIVE;
+ if ((pflags & Modifiers.INTERFACE ) != 0) res = res | Flags.TRAIT ;
+ if ((pflags & Modifiers.TRAIT ) != 0) res = res | Flags.TRAIT ;
+ if ((pflags & Modifiers.COVARIANT ) != 0) res = res | Flags.COVARIANT ;
+ if ((pflags & Modifiers.CONTRAVARIANT) != 0) res = res | Flags.CONTRAVARIANT;
+ res
+ }
+}
+}
+*/
diff --git a/sources/scala/tools/nsc/typechecker/Analyzer.scala b/sources/scala/tools/nsc/typechecker/Analyzer.scala
new file mode 100644
index 0000000000..6c48cff25f
--- /dev/null
+++ b/sources/scala/tools/nsc/typechecker/Analyzer.scala
@@ -0,0 +1,3020 @@
+/* ____ ____ ____ ____ ______ *\
+** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
+** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
+** /_____/\____/\___/\____/____/ **
+\* */
+
+// $Id$
+
+// todo: eliminate Typed nodes.
+// todo: use SELECTOR flag to avoid access methods for privates
+// todo: use mangled name or drop.
+// todo: emit warnings for unchecked.
+// todo: synchronize on module instantiation.
+// todo: empty package
+
+import ch.epfl.lamp.util.Pair;
+import scala.tools.util.Position;
+import scalac._;
+import scalac.util._;
+import scalac.ast._;
+import scalac.atree.AConstant;
+import scalac.atree.AConstant$CHAR;
+import scalac.atree.AConstant$INT;
+import scalac.symtab.classfile._;
+import scalac.symtab._;
+import Tree._;
+import java.util.HashMap;
+import scala.tools.scalac.util.NewArray;
+import scalac.{Global => scalac_Global}
+
+package scala.tools.scalac.typechecker {
+
+import java.lang.{Boolean, Byte, Short, Character, Integer, Object}
+
+/** The main attribution phase.
+ */
+class Analyzer(global: scalac_Global, descr: AnalyzerPhase) extends Transformer(global) {
+
+ import Modifiers._;
+ import Kinds._;
+
+ private var context: Context = _;
+ private var pt: Type = _;
+ private var mode: int = _;
+
+ private var inAlternative: boolean = _;
+ private val patternVars = new HashMap(); // for pattern matching; maps x to {true,false}
+
+ val definitions = global.definitions;
+ val infer = new scala.tools.scalac.typechecker.Infer(this) {
+ override def getContext = context;
+ override def error(pos: int, msg: String) = Analyzer.this.error(pos, msg);
+ }
+ val desugarize = new DeSugarize(make, copy, gen, infer, global);
+ val constfold = new ConstantFolder(global);
+
+ var unit: CompilationUnit = _;
+
+ type AttrInfo = Pair/*<Symbol, Array[AConstant]>*/ ;
+
+ def enterUnit(unit: CompilationUnit): unit =
+ enter(
+ new Context(
+ Tree.Empty,
+ if (unit.console) descr.consoleContext else descr.startContext),
+ unit);
+
+ def enter(context: Context, unit: CompilationUnit): unit = {
+ assert(this.unit == null, "start unit non null for " + unit);
+ context.infer = infer;
+ this.unit = unit;
+ this.context = context;
+ descr.contexts.put(unit, context);
+ enterSyms(unit.body);
+ this.unit = null;
+ this.context = null;
+ }
+
+ def lateEnter(unit: CompilationUnit): unit = {
+ enterUnit(unit);
+ }
+
+ def loadMixinCode(pos: Int, clasz: Symbol): unit = {
+ assert(clasz.isClass() && !clasz.isModuleClass(), Debug.show(clasz));
+ if (clasz.isExternal()) {
+ var c: Symbol = clasz;
+ try {
+ while (!c.owner().isPackageClass()) c = c.owner();
+ global.compileLate(global.getSourceFile(c), true);
+ } catch {
+ case exception: java.io.IOException =>
+ if (global.debug) exception.printStackTrace();
+ unit.error(pos, exception.getMessage() + "; source file for "
+ + c + " is needed because it is used as a mixin");
+ }
+ }
+ }
+
+ override def apply(unit: CompilationUnit): unit = {
+ global.log("checking " + unit);
+ assert(this.unit == null, "start unit non null for " + unit);
+ this.unit = unit;
+ this.context = descr.contexts.remove(unit).asInstanceOf[Context];
+ assert(this.context != null, "could not find context for " + unit);
+ unit.body = transformStatSeq(unit.body, Symbol.NONE);
+ if (global.target != scalac_Global.TARGET_INT && global.reporter.errors() == 0) {
+ genSymData(unit.body);
+ }
+ this.unit = null;
+ this.context = null;
+ global.operation("checked " + unit);
+ }
+
+ def genSymData(stats: Array[Tree]): unit = {
+ var i = 0; while (i < stats.length) {
+ stats(i) match {
+ case Tree.ClassDef(_, _, _, _, _, _) | Tree.ModuleDef(_, _, _, _) =>
+ val sym = stats(i).symbol();
+ val key = if (sym.isModule()) sym.moduleClass() else sym;
+ var termSym = sym.owner().info().lookup(sym.name.toTermName());
+ var typeSym = sym.owner().info().lookup(sym.name.toTypeName());
+ if (termSym.isExternal()) termSym = Symbol.NONE;
+ if (typeSym.isExternal()) typeSym = Symbol.NONE;
+ if (sym.isClass() || (sym.isModule() && typeSym.isNone())) {
+ val pickle: Pickle = new Pickle();
+ if (!termSym.isNone()) pickle.add(termSym);
+ if (!typeSym.isNone()) pickle.add(typeSym);
+ pickle.pickle();
+ global.symdata.put(key, pickle);
+ }
+ case Tree.PackageDef(packaged, templ) =>
+ genSymData(templ.body);
+ case _ =>
+ }
+ i = i + 1
+ }
+ }
+
+ /** Mode constants
+ */
+ val NOmode = 0x000;
+ val EXPRmode = 0x001; // these 4 modes are mutually exclusive.
+ val PATTERNmode = 0x002;
+ val CONSTRmode = 0x004;
+ val TYPEmode = 0x008;
+
+ val FUNmode = 0x10; // orthogonal to above. When set
+ // we are looking for a method or constructor
+
+ val POLYmode = 0x020; // orthogonal to above. When set
+ // expression types can be polymorphic.
+
+ val QUALmode = 0x040; // orthogonal to above. When set
+ // expressions may be packages and
+ // Java statics modules.
+
+ val SUPERmode = 0x080; // Goes with CONSTRmode. When set
+ // we are checking a superclass
+ // constructor invocation.
+
+ val baseModes = EXPRmode | PATTERNmode | CONSTRmode;
+
+ val SEQUENCEmode = 0x1000; // orthogonal to above. When set
+ // we turn "x" into "x@_"
+ // and allow args to be of type Seq( a) instead of a
+
+// Diagnostics ----------------------------------------------------------------
+
+ private def errorName(tree: Tree): Name =
+ Name.fromString("<error: " + tree + ">");
+
+ private def errorTree(tree: Tree): Tree =
+ try {
+ if (tree.isType()) errorTypeTree(tree) else errorTermTree(tree);
+ } catch {
+ case ex: Type$Error =>
+ Tree.Empty;
+ }
+
+ private def errorTypeTree(tree: Tree): Tree = {
+ val symbol = context.owner.newErrorClass(errorName(tree).toTypeName());
+ tree match {
+ case Tree.Ident(_) =>
+ make.Ident(tree.pos, symbol).setType(symbol.getType());
+ case Tree.Select(qualifier, _) =>
+ make.Select(tree.pos, symbol, qualifier).setType(symbol.getType());
+ case _ =>
+ gen.mkType(tree.pos, symbol.getType());
+ }
+ }
+
+ private def errorTermTree(tree: Tree): Tree =
+ gen.mkLocalRef(tree.pos, Symbol.NONE.newErrorValue(errorName(tree)));
+
+ private def setError(tree: Tree): Tree = {
+ if (tree.hasSymbol() && tree.symbol() == null)
+ tree.setSymbol(
+ if (tree.isType()) Symbol.NONE.newErrorClass(errorName(tree).toTypeName())
+ else Symbol.NONE.newErrorValue(errorName(tree)));
+ tree.setType(Type.ErrorType);
+ }
+
+ def error(pos: int, msg: String): unit =
+ unit.error(pos, msg);
+
+ def typeError(pos: int, found: Type, req: Type): unit = {
+ if (found.isError() || req.isError()) return;
+ var msg: String = infer.typeErrorMsg("type mismatch", found, req);
+ val foundResult: Type = found.resultType();
+ if (foundResult != found && infer.isCompatible(foundResult, req))
+ msg = msg + "\n possible cause: missing arguments for method or constructor";
+ error(pos, msg);
+ }
+
+ def reportTypeError(pos: int, ex: Type$Error): unit = {
+ if (global.debug) ex.printStackTrace();
+ if (ex.isInstanceOf[CyclicReference]) {
+ val cyc: CyclicReference = ex.asInstanceOf[CyclicReference];
+ if (cyc.info.isInstanceOf[LazyTreeType]) {
+ (cyc.info.asInstanceOf[LazyTreeType]).tree match {
+ case Tree.ValDef(_, _, Tree.Empty, _) =>
+ return error(pos, "recursive " + cyc.sym + " needs type");
+ case Tree.DefDef(_, _, _, _, Tree.Empty, _) =>
+ return error(pos, "recursive function " + cyc.sym.name + " needs result type");
+ case _ =>
+ }
+ }
+ }
+ error(pos, ex.msg);
+ }
+
+ def decode(name: Name): String =
+ if (name.isTypeName()) "type " + NameTransformer.decode(name);
+ else "value " + NameTransformer.decode(name);
+
+// Checking methods ----------------------------------------------------------
+
+ /** Check that symbol's definition is well-formed. This means:
+ * - no conflicting modifiers
+ * - `abstract' modifier only for classes
+ * - `override' modifier never for classes
+ * - `def' modifier never for parameters of case classes
+ * - declarations only in traits or abstract classes
+ * - symbols with `override' modifier override some other symbol.
+ */
+ def validate(sym: Symbol): unit = {
+ if ((sym.flags & (ABSTRACT | OVERRIDE)) == ABSTRACT && sym.kind != CLASS) {
+ error(sym.pos, "`abstract' modifier can be used only for classes; " +
+ "\nit should be omitted for abstract members");
+ }
+ if ((sym.flags & OVERRIDE) != 0 && sym.kind == CLASS) {
+ error(sym.pos, "`override' modifier not allowed for classes");
+ }
+ if ((sym.flags & DEF) != 0 && sym.owner().isPrimaryConstructor() &&
+ (sym.owner().constructorClass().flags & CASE) != 0) {
+ error(sym.pos, "pass-by-name arguments not allowed for case class parameters");
+ }
+ /*!!!
+ if ((sym.flags & REPEATED) != 0 && sym.owner().isPrimaryConstructor()) {
+ error(sym.pos, "`*' modifier not allowed for class parameters");
+ }
+ */
+ if ((sym.flags & DEFERRED) != 0) {
+ if (sym.owner().kind != CLASS || (sym.owner().flags & MODUL) != 0 || sym.owner().isAnonymousClass()) {
+ error(sym.pos,
+ "only classes can have declared but undefined members" +
+ (if ((sym.flags & MUTABLE) == 0) ""
+ else "\n(Note that variables need to be initialized to be defined)"));
+ sym.flags = sym.flags & ~DEFERRED;
+ }
+ }
+ checkNoConflict(sym, DEFERRED, PRIVATE);
+ checkNoConflict(sym, FINAL, SEALED);
+ if ((sym.flags & MODUL) == 0) checkNoConflict(sym, FINAL, PRIVATE);
+ checkNoConflict(sym, PRIVATE, PROTECTED);
+ checkNoConflict(sym, PRIVATE, OVERRIDE);
+ checkNoConflict(sym, DEFERRED, FINAL);
+ }
+
+ /** Check that
+ * - all parents are class types
+ * - supertype conforms to supertypes of all mixin types.
+ * - final classes are only inherited by classes which are
+ * nested within definition of base class, or that occur within same
+ * statement sequence.
+ * - self-type of current class is a subtype of self-type of each parent class.
+ * - parent constructors do not refer to value parameters of class.
+ * - no two parents define same symbol.
+ */
+ def validateParentClasses(constrs: Array[Tree], parents: Array[Type], selfType: Type): unit = {
+ var i = 0;
+ while (i < parents.length) {
+ if (!checkClassType(constrs(i).pos, parents(i))) return;
+ val bsym: Symbol = parents(i).symbol();
+ if (i > 0) {
+ if ((bsym.flags & (JAVA | INTERFACE)) == JAVA)
+ error(constrs(i).pos, "Java class may not be used as mixin");
+ val grandparents = parents(i).parents();
+ if (grandparents.length > 0 && !parents(0).isSubType(grandparents(0)))
+ error(constrs(i).pos, "illegal inheritance;\n " + parents(0) +
+ " does not conform to " + parents(i) + "'s supertype " + grandparents(0));
+ }
+ if ((bsym.flags & FINAL) != 0) {
+ error(constrs(i).pos, "illegal inheritance from final class");
+ } else if (bsym.isSealed() ||
+ bsym.isSubClass(definitions.ANYVAL_CLASS) ||
+ bsym.isSubClass(definitions.ARRAY_CLASS)) {
+ // are we in same scope as base type definition?
+ val e: Scope$Entry = context.scope.lookupEntry(bsym.name);
+ if (e.sym != bsym) {
+ // we are not within same statement sequence
+ var c: Context = context;
+ while (c != Context.NONE && c.owner != bsym)
+ c = c.outer.enclClass;
+ if (c == Context.NONE) {
+ error(constrs(i).pos, "illegal inheritance from sealed class");
+ }
+ }
+ }
+ if (!selfType.isSubType(parents(i).instanceType())) {
+ error(constrs(i).pos, "illegal inheritance;\n self-type " +
+ selfType + " does not conform to " + parents(i) +
+ "'s selftype " + parents(i).instanceType());
+ }
+ var j = 0; while (j < i) {
+ if (parents(i).symbol() == parents(j).symbol())
+ error(constrs(i).pos, "" + parents(i).symbol() + " is inherited twice");
+ j = j + 1
+ }
+ i = i + 1;
+ }
+ }
+
+ /** Check that type is a class type.
+ */
+ private def checkClassType(pos: int, tp: Type): boolean = {
+ tp.unalias() match {
+ case Type$TypeRef(_, sym, _) =>
+ if (sym.kind == CLASS) return true;
+ case _ =>
+ }
+ if (!tp.isError()) error(pos, "class type expected");
+ false
+ }
+
+ /** Check that type is an object type
+ */
+ private def checkObjectType(pos: int, tp: Type): Type =
+ if (tp.isObjectType()) tp
+ else {
+ if (!tp.isError()) error(pos, "object type expected");
+ Type.ErrorType
+ }
+
+ /** Check that type is eta-expandable (i.e. no `def' or `*' parameters)
+ */
+ def checkEtaExpandable(pos: int, tp: Type): unit = tp match {
+ case Type$MethodType(params, restype) =>
+ var i = 0; while (i < params.length) {
+ if ((params(i).flags & DEF) != 0)
+ error(pos, "method with pass-by-name parameters needs to be fully applied");
+ if ((params(i).flags & REPEATED) != 0)
+ error(pos, "method with `*' parameters needs to be fully applied");
+ i = i + 1
+ }
+ checkEtaExpandable(pos, restype);
+ case _ =>
+ }
+
+ /** Check that `sym' does not contain both `flag1' and `flag2'
+ */
+ def checkNoConflict(sym: Symbol, flag1: int, flag2: int): unit = {
+ if ((sym.flags & (flag1 | flag2)) == (flag1 | flag2)) {
+ if (flag1 == DEFERRED)
+ error(sym.pos, "abstract member may not have " +
+ Modifiers$Helper.toString(flag2) + " modifier");
+ else
+ error(sym.pos, "illegal combination of modifiers: " +
+ Modifiers$Helper.toString(flag1) + " and " +
+ Modifiers$Helper.toString(flag2));
+ }
+ }
+
+ /** Check that type `tp' is not a subtype of itself.
+ */
+ def checkNonCyclic(pos: int, tp: Type): unit = tp match {
+ case Type$TypeRef(pre, sym, args) =>
+ sym.initialize();
+ if ((sym.flags & LOCKED) != 0) {
+ error(pos, "cyclic aliasing or subtyping involving " + sym);
+ } else if (sym.kind == ALIAS || sym.kind == TYPE) {
+ sym.flags = sym.flags | LOCKED;
+ //System.out.println("checking " + sym);//DEBUG
+ checkNonCyclic(
+ pos, pre.memberInfo(sym).subst(sym.typeParams(), args));
+ if (sym.kind == TYPE) {
+ checkNonCyclic(
+ pos, pre.memberLoBound(sym).subst(sym.typeParams(), args));
+ checkNonCyclic(
+ pos, pre.memberVuBound(sym).subst(sym.typeParams(), args));
+ }
+ sym.flags = sym.flags & ~LOCKED;
+ }
+
+ case Type$CompoundType(parents, members) =>
+ var i = 0; while (i < parents.length) {
+ checkNonCyclic(pos, parents(i));
+ i = i + 1
+ }
+
+ case Type$SingleType(pre, sym) =>
+ sym.initialize();
+ if ((sym.flags & LOCKED) != 0) {
+ error(pos, "cyclic aliasing or subtyping involving " + sym);
+ }
+
+ case _ =>
+ }
+
+ /** Check that type does not refer to components defined in current scope.
+ */
+ def checkNoEscape(pos: int, tp: Type): Type = {
+
+ val checkNoEscapeMap = new Type$Map() {
+ override def apply(t: Type): Type = {
+ t.unalias() match {
+ case Type$TypeRef(Type.NoPrefix, sym, args) =>
+ checkNoEscape(t, sym);
+ case Type$SingleType(Type.NoPrefix, sym) =>
+ checkNoEscape(t, sym);
+ case _ =>
+ }
+ return map(t);
+ }
+ private def checkNoEscape(t: Type, sym: Symbol): unit = {
+ val e: Scope$Entry = context.scope.lookupEntry(sym.name);
+ if (e.sym == sym && e.owner == context.scope &&
+ !(e.sym.kind == TYPE && (e.sym.flags & PARAM) != 0)) {
+ throw new Type$Error(
+ "type " + t + " escapes its defining scope");
+ }
+ }
+ };
+
+ try {
+ checkNoEscapeMap.apply(tp)
+ } catch {
+ case ex: Type$Error =>
+ if ((mode & EXPRmode) != 0 && infer.isFullyDefined(pt)) pt
+ else {
+ error(pos, ex.msg + " as part of " + tp.unalias());
+ Type.ErrorType
+ }
+ }
+ }
+
+ /** Check that there are no dependent parameter types among parameters
+ */
+ def checkNoEscapeParams(vparams: Array[Array[Tree.ValDef]]): unit = {
+ var i = 0; while (i < vparams.length) {
+ var j = 0; while (j < vparams(i).length) {
+ checkNoEscape(vparams(i)(j).pos, vparams(i)(j).tpe.getType());
+ j = j + 1
+ }
+ i = i + 1
+ }
+ }
+
+ /** Check that tree represents a legal trait definition.
+ */
+ def checkTraitDef(pos: int, clazz: Symbol, templ: Tree.Template) = {
+
+ /** Check that type does not have value parameters
+ */
+ def checkNoParams(tpe: Type): unit = tpe match {
+ case Type$MethodType(vparams, _) =>
+ if (vparams.length > 0)
+ error(pos, "trait may not have value parameters")
+ case Type$PolyType(tparams, restpe) =>
+ checkNoParams(infer.skipViewParams(tparams, restpe))
+ case _ =>
+ }
+
+ /** Check that tree represents a pure constructor.
+ */
+ def checkPureConstr(tree: Tree): unit = {
+ if (!TreeInfo.isPureConstr(tree) && !tree.getType().isError())
+ error(tree.pos, "" + clazz + " may invoke only pure superclass constructors");
+ }
+
+ /** Check that tree refers to a trait
+ */
+ def checkTraitRef(tree: Tree): unit = {
+ if (!tree.getType().symbol().isTrait() && !tree.getType().isError())
+ error(tree.pos, " " + clazz + " may inherit only traits as mixins");
+ }
+
+ /** Check that tree represents a pure definition.
+ */
+ def checkPureDef(tree: Tree): unit = {
+ if (!TreeInfo.isPureDef(tree) && !tree.getType().isError())
+ error(tree.pos, "" + clazz + " may contain only pure definitions");
+ }
+
+ checkNoParams(clazz.primaryConstructor().getType());
+ var i = 0; while (i < templ.parents.length) {
+ checkPureConstr(templ.parents(i));
+ if (i >= 1) checkTraitRef(templ.parents(i));
+ i = i + 1
+ }
+ var j = 0; while (j < templ.body.length) {
+ checkPureDef(templ.body(j));
+ j = j + 1
+ }
+ }
+
+ /** Check that tree is a stable expression .p
+ */
+ def checkStable(tree: Tree): Tree =
+ if (TreeInfo.isPureExpr(tree) || tree.getType().isError()) tree;
+ else {
+ error(tree.pos, "stable identifier required, but " + tree + " found.");
+ errorTermTree(tree);
+ }
+
+ /** Check that class can be instantiated.
+ */
+ def checkInstantiatable(pos: int, tp: Type): unit = {
+ val clazz: Symbol = tp.symbol();
+ if (clazz.kind == CLASS) {
+ if (clazz.isAbstractClass())
+ error(pos, "" + clazz + " is abstract, so it cannot be instantiated");
+ else if (!tp.isSubType(tp.instanceType()))
+ error(pos, "" + tp + " does not conform to its self-type " +
+ tp.instanceType() + ", so it cannot be instantiated");
+ }
+ }
+
+ /** Check that all subtrees have their types defined.
+ * Used for asserting an internal invariant
+ */
+ private class CheckDefined extends Traverser {
+ var all: Tree = null;
+ override def traverse(tree: Tree): unit = {
+ if (tree.getType() == null) assert(false, "" + tree + " in " + all);
+ if (!tree.getType().isError())
+ super.traverse(tree);
+ }
+ }
+
+ private val checkDefined: CheckDefined = new CheckDefined();
+
+ // Helper definitions for calculating types -----------------------------------------
+
+ /** The qualifier type of a potential application of the `match' method.
+ * or NoType, if this is something else.
+ */
+ private def matchQualType(fn: Tree): Type = {
+ fn match {
+ case Tree.Select(qual, _) =>
+ if (fn.symbol() == definitions.ANY_MATCH)
+ return qual.getType().widen();
+
+ case Tree.TypeApply(fn1, _) =>
+ return matchQualType(fn1);
+
+ case Tree.Ident(_) =>
+ if (fn.symbol() == definitions.ANY_MATCH)
+ return context.enclClass.owner.typeOfThis();
+
+ case _ =>
+ }
+ if (fn.getType().isError()) Type.ErrorType else Type.NoType
+ }
+
+ private def isSetterMethod(sym: Symbol): boolean =
+ sym != null &&
+ !sym.isLocal() &&
+ !sym.isStable() &&
+ sym.getType().isInstanceOf[Type$PolyType] &&
+ sym.typeParams().length == 0;
+
+// Views -----------------------------------------------------------------------
+
+ private def applyView(v: View, tree: Tree, mode: int, pt: Type): Tree = {
+ val vexpr = infer.viewExpr(tree.pos, v);
+ val vapp = transform(
+ make.Apply(tree.pos, vexpr, NewArray.Tree(tree)), mode, pt);
+ if (v.symtype.isObjectType()) {
+ val tree1 = gen.mkAsInstanceOf(tree.duplicate(), vapp.getType());
+ gen.If(
+ gen.Apply(
+ gen.Select(
+ vexpr.duplicate(),
+ definitions.ANY_EQEQ),
+ NewArray.Tree(gen.mkNullLit(tree.pos))),
+ tree1,
+ vapp)
+ } else vapp
+ }
+
+// Contexts -------------------------------------------------------------------
+
+ /** Push new context associated with given tree, owner, and scope on stack.
+ */
+ def pushContext(tree: Tree, owner: Symbol, scope: Scope): Context = {
+ val prevContext = context;
+ context = new Context(tree, owner, scope, context);
+ prevContext
+ }
+
+// Lazy Types ------------------------------------------------------------------
+
+ /** A lazy type which, when forced returns the type of a symbol defined
+ * in `tree'.
+ */
+ class LazyTreeType(_tree: Tree) extends Type$LazyType {
+ val tree: Tree = _tree;
+ val u: CompilationUnit = unit;
+ val c: Context = context;
+
+ override def complete(sym: Symbol): unit = {
+ defineSym(tree, u, c);
+ }
+ }
+
+ /** A lazy type for case constructor methods (whose name is a term name)
+ * which sets the method's type to the class constructor type.
+ */
+ class LazyConstrMethodType(_tree: Tree) extends LazyTreeType(_tree) {
+ override def complete(sym: Symbol): unit = {
+ val constr: Symbol = tree.symbol().primaryConstructor();
+ if (!sym.isInitialized())
+ sym.setInfo(constr.getType().instanceType().cloneType(constr, sym));
+ }
+ }
+
+ /** A lazy type for self types
+ */
+ class LazySelfType(clazz: Symbol, tree: Tree) extends LazyTreeType(tree) {
+ override def complete(sym: Symbol): unit = {
+ defineSelfType(sym, clazz, tree, u, c);
+ }
+ }
+
+// Entering Symbols ----------------------------------------------------------
+
+ def transformPackageId(tree: Tree): Tree = {
+ if (tree.getType() != null) return tree;
+ tree match {
+ case Tree.Ident(name) =>
+ tree
+ .setSymbol(packageSymbol(tree.pos, context.owner, name))
+ .setType(tree.symbol().getType())
+
+ case Tree.Select(qual, name) =>
+ val qual1: Tree = transformPackageId(qual);
+ val sym: Symbol = packageSymbol(tree.pos, qual1.symbol().moduleClass(), name);
+ copy.Select(tree, sym, qual1).setType(sym.getType())
+
+ case _ =>
+ transform(tree);
+ }
+ }
+
+ def packageSymbol(pos: int, base: Symbol, name: Name): Symbol = {
+ var p: Symbol = base.members().lookup(name);
+ if (p.isNone()) {
+ p = base.newPackage(pos, name);
+ base.members().enterNoHide(p);
+ } else if (p.isPackage()) {
+ // as the package is used, we change its position to make sure
+ // its symbol is not reused for a module definition with the
+ // same name
+ p.pos = Position.FIRSTPOS;
+ p.moduleClass().pos = Position.FIRSTPOS;
+ } else {
+ val dst = if ((p.flags & CASE) != 0) "case class " + name;
+ else "" + p;
+ error(pos, "package " + name + " has the same name as existing " + dst);
+ p = base.newPackage(pos, name);
+ }
+ p
+ }
+
+ def moduleSymbol(pos: int, name: Name, owner: Symbol, flags: int, scope: Scope): Symbol = {
+ val symbol = termSymbolOrNone(scope, pos, name, flags | MODUL | FINAL);
+ if (symbol.isNone()) owner.newModule(pos, flags, name) else symbol;
+ }
+
+ def termSymbol(pos: int, name: Name, owner: Symbol, flags: int, scope: Scope): Symbol = {
+ val symbol = termSymbolOrNone(scope, pos, name, flags);
+ if (symbol.isNone()) owner.newTerm(pos, flags, name) else symbol
+ }
+
+ def classSymbol(pos: int, name: Name, owner: Symbol, flags: int, scope: Scope): Symbol = {
+ val symbol = typeSymbolOrNone(scope, pos, CLASS, name, flags);
+ if (symbol.isNone()) owner.newClass(pos, flags, name) else symbol
+ }
+
+ def typeAliasSymbol(pos: int, name: Name, owner: Symbol, flags: int, scope: Scope): Symbol = {
+ val symbol = typeSymbolOrNone(scope, pos, ALIAS, name, flags);
+ if (symbol.isNone()) owner.newTypeAlias(pos, flags, name) else symbol
+ }
+
+ def absTypeSymbol(pos: int, name: Name, owner: Symbol, flags: int, scope: Scope): Symbol = {
+ val symbol = typeSymbolOrNone(scope, pos, TYPE, name, flags);
+ if (symbol.isNone()) owner.newAbstractType(pos, flags, name) else symbol
+ }
+
+ def termSymbolOrNone(scope: Scope, pos: int, name: Name, flags: int): Symbol = {
+ var symbol = getDefinedSymbol(scope, VAL, name);
+ if (!symbol.isNone()) {
+ if (symbol.isInitialized()) {
+ symbol.getType() match {
+ case Type$OverloadedType(alts, _) =>
+ var i = 0;
+ while (i < alts.length && !alts(i).isExternal()) i = i + 1;
+ if (i == alts.length)
+ throw Debug.abort("missing alternative", Debug.show(symbol));
+ if (i == alts.length - 1) symbol.pos = pos;
+ symbol = alts(i);
+ case _ =>
+ }
+ }
+ updateFlagsAndPos(symbol, pos, flags);
+ }
+ symbol
+ }
+
+ def typeSymbolOrNone(scope: Scope, pos: int, kind: int, name: Name, flags: int): Symbol = {
+ val symbol = getDefinedSymbol(scope, kind, name);
+ if (!symbol.isNone()) {
+ updateFlagsAndPos(symbol, pos, flags);
+ symbol.allConstructors().pos = pos;
+ }
+ symbol
+ }
+
+ def getDefinedSymbol(scope: Scope, kind: int, name: Name): Symbol = {
+ val entry = scope.lookupEntry(name);
+ val symbol = entry.sym;
+ if (entry.owner == scope && symbol.isExternal() && symbol.kind == kind) {
+ symbol
+ } else {
+ Symbol.NONE;
+ }
+ }
+
+ def updateFlagsAndPos(symbol: Symbol, pos: int, flags: int): unit = {
+ symbol.pos = pos;
+ val oldflags = symbol.flags & (INITIALIZED | LOCKED);
+ val newflags = flags & ~(INITIALIZED | LOCKED);
+ symbol.flags = oldflags | newflags;
+ if (symbol.isModule()) {
+ // here we repeat what is done in the constructor of ModuleClassSymbol
+ val clasz = symbol.moduleClass();
+ val classFlags = (flags & MODULE2CLASSFLAGS) | MODUL | FINAL;
+ updateFlagsAndPos(clasz, pos, classFlags);
+ clasz.primaryConstructor().flags =
+ clasz.primaryConstructor().flags | PRIVATE;
+ }
+ if (symbol.isType()) {
+ // here we repeat what is done in the constructor of TypeSymbol
+ val constr = symbol.primaryConstructor();
+ val constrFlags = flags & CONSTRFLAGS;
+ updateFlagsAndPos(constr, pos, constrFlags);
+ }
+ }
+
+ /** Enter symbol `sym' in current scope. Check for double definitions.
+ * Handle overloading.
+ */
+ def enterInScope(sym: Symbol): unit = {
+
+ def covers(presym: Symbol, newsym: Symbol) = {
+ if (presym == newsym) true
+ else if (!presym.isInitialized()) false
+ else presym.getType() match {
+ case Type$OverloadedType(alts, _) =>
+ var i = 0;
+ while (i < alts.length && alts(i) != newsym) i = i + 1;
+ i < alts.length
+ case _ =>
+ false
+ }
+ }
+
+ // handle double and overloaded definitions
+ val e: Scope$Entry = context.scope.lookupEntry(sym.name);
+ val other: Symbol = e.sym;
+ if (covers(other, sym)) {
+ if (global.debug) global.log("redefined: " + sym + ":" + sym.rawInfo());
+ } else if (e.owner == context.scope) {
+ assert(!other.isExternal(), other);
+ if (sym.owner().isPackageClass()) {
+ if (other.isPackage()) {
+ val src = if ((sym.flags & CASE) != 0) "case class " + sym.name;
+ else "" + sym;
+ error(sym.pos, "" + src + " has the same name as existing " + other);
+ } else {
+ if (global.compiledNow.get(other) != null) {
+ error(sym.pos, "" + sym + " is compiled twice");
+ }
+ context.scope.unlink(e);
+ context.scope.enter(sym);
+ }
+ } else if (context.owner.kind == CLASS &&
+ sym.kind == VAL && other.kind == VAL &&
+ ((sym.flags & ACCESSOR) == 0 || (other.flags & ACCESSOR) == 0)
+ ||
+ (sym.name == Names.view &&
+ (sym.flags & (PARAM | SYNTHETIC)) == (PARAM | SYNTHETIC))) {
+ e.setSymbol(other.overloadWith(sym));
+ } else if (context.owner.kind == CLASS)
+ error(sym.pos,
+ sym.nameString() + " is already defined as " +
+ other + other.locationString());
+ else
+ error(sym.pos,
+ sym.nameString() +
+ " is already defined in local scope");
+ } else {
+ context.scope.enter(sym);
+ }
+ if (sym.owner().isPackageClass())
+ global.compiledNow.put(sym, unit.source);
+ }
+
+ def outerEnterSym(tree: Tree): Symbol = enterSym(tree);
+
+ /** If `tree' is a definition, create a symbol for it with a lazily
+ * constructed type, and enter into current scope.
+ */
+ def enterSym(tree: Tree): Symbol = {
+
+ /** Enter `sym' in current scope and make it the symbol of `tree'.
+ */
+ def enterSym(tree: Tree, sym: Symbol): Symbol = {
+ //if (global.debug) System.out.println("entering " + sym);//DEBUG
+ if (!sym.isInitialized()) {
+ sym.setInfo(new LazyTreeType(tree));
+ }
+ if (!sym.isConstructor()) {
+ val owner: Symbol = sym.owner();
+ if (sym.kind == VAL && (sym.flags & (PRIVATE | SEALED)) == 0 &&
+ owner != null && owner.kind == CLASS &&
+ (owner.flags & FINAL) != 0)
+ sym.flags = sym.flags | FINAL;
+ enterInScope(sym);
+ }
+ tree.setSymbol(sym);
+ sym
+ }
+
+ /** Make `sym' the symbol of import `tree' and push an
+ * import context.
+ */
+ def enterImport(tree: Tree, sym: Symbol): Symbol = {
+ sym.setInfo(new LazyTreeType(tree));
+ tree.setSymbol(sym);
+ pushContext(tree, context.owner, context.scope);
+ sym
+ }
+
+ val owner: Symbol = context.owner;
+ tree match {
+ case Tree.PackageDef(_packaged, templ) =>
+ var packaged = _packaged;
+ templ match {
+ case Tree.Template(_, body) =>
+ val prevContext = pushContext(tree, context.owner, context.scope);
+ packaged = transformPackageId(packaged);
+ tree.asInstanceOf[Tree.PackageDef].packaged = packaged;
+ context = prevContext;
+ val pkg: Symbol = checkStable(packaged).symbol();
+ if (pkg != null && !pkg.isError()) {
+ if (pkg.isPackage()) {
+ val prevContext = pushContext(templ, pkg.moduleClass(), pkg.members());
+ enterSyms(body);
+ context = prevContext;
+ } else {
+ error(tree.pos, "only Java packages allowed for now");
+ }
+ }
+ templ.setSymbol(Symbol.NONE);
+ null
+ case _ =>
+ throw new ApplicationError();
+ }
+
+ case Tree.Attributed(attr, definition) =>
+ outerEnterSym(definition);
+
+ case Tree.DocDef(comment, definition) =>
+ val sym = outerEnterSym(definition);
+ global.mapSymbolComment.put(sym, new Pair(comment, unit));
+ sym
+
+ case Tree.ClassDef(mods, name, tparams, vparams, _, templ) =>
+ val clazz =
+ if (mods == SYNTHETIC && name == Names.ANON_CLASS_NAME.toTypeName())
+ context.owner.newAnonymousClass(templ.pos, name)
+ else
+ classSymbol(tree.pos, name, owner, mods, context.scope);
+ if (!clazz.primaryConstructor().isInitialized())
+ clazz.primaryConstructor().setInfo(new LazyTreeType(tree));
+ if ((mods & CASE) != 0) {
+ if ((mods & ABSTRACT) == 0) {
+ // enter case constructor method.
+ val cf: Symbol = termSymbol(
+ tree.pos, name.toTermName(), owner,
+ mods & ACCESSFLAGS | CASE, context.scope);
+ enterInScope(cf);
+ if (!cf.isInitialized() || cf.info().symbol().isModuleClass()) {
+ cf.setInfo(new LazyConstrMethodType(tree));
+ }
+ }
+ }
+ enterSym(tree, clazz)
+
+ case Tree.ModuleDef(mods, name, _, _) =>
+ var modul = moduleSymbol(tree.pos, name, owner, mods, context.scope);
+ val clazz: Symbol = modul.moduleClass();
+ if (!clazz.isInitialized()) {
+ val info = new LazyTreeType(tree);
+ clazz.setInfo(info);
+ modul.setInfo(info);
+ }
+ enterSym(tree, modul)
+
+ case Tree.ValDef(mods, name, _, _) =>
+ enterSym(tree, termSymbol(tree.pos, name, owner, mods, context.scope))
+
+ case Tree.DefDef(mods, name, _, _, _, _) =>
+ var sym: Symbol = null;
+ if (name == Names.CONSTRUCTOR) {
+ var c = context;
+ while (c.isImportContext) c = c.outer;
+ val clazz: Symbol = c.enclClass.owner;
+ if (!(c.tree.isInstanceOf[Tree.Template]) ||
+ clazz.isModuleClass() ||
+ clazz.isAnonymousClass() ||
+ clazz.isCompoundSym() ||
+ clazz.isPackageClass())
+ error(tree.pos, "constructor definition not allowed here");
+ sym = clazz.newConstructor(tree.pos, clazz.flags & CONSTRFLAGS);
+ clazz.addConstructor(sym);
+ sym.flags = sym.flags | mods;
+ } else {
+ sym = termSymbol(tree.pos, name, owner, mods, context.scope);
+ }
+ enterSym(tree, sym);
+
+ case Tree.AliasTypeDef(mods, name, _, _) =>
+ val tsym: Symbol = typeAliasSymbol(tree.pos, name, owner, mods, context.scope);
+ if (!tsym.primaryConstructor().isInitialized())
+ tsym.primaryConstructor().setInfo(new LazyTreeType(tree));
+ enterSym(tree, tsym)
+
+ case Tree.AbsTypeDef(mods, name, _, _) =>
+ enterSym(
+ tree,
+ absTypeSymbol(tree.pos, name, owner, mods, context.scope))
+
+ case Tree.Import(expr, selectors) =>
+ enterImport(tree,
+ Symbol.NONE.newTerm(
+ tree.pos, SYNTHETIC, Name.fromString("import " + expr)))
+
+ case _ =>
+ null
+ }
+ }
+
+ /** Enter all symbols in statement list
+ */
+ def enterSyms(stats: Array[Tree]): unit = {
+ var i = 0; while (i < stats.length) {
+ stats(i) = desugarize.Definition(stats(i));
+ enterSym(stats(i));
+ i = i + 1
+ }
+ }
+
+ def enterParams[t <: Tree](params: Array[t]): Array[Symbol] = {
+ var i = 0; while (i < params.length) {
+ enterSym(params(i));
+ (params(i) : Tree) match {
+ case Tree.ValDef(mods, _, _, _) =>
+ if ((mods & REPEATED) != 0 && i != params.length - 1)
+ error(params(i).pos,
+ "`*' parameter must be the last parameter of a `('...`)' section");
+ case _ =>
+ }
+ i = i + 1
+ }
+ Tree.symbolOf(params.asInstanceOf[Array[Tree]])
+ }
+
+ def enterParams(vparams: Array[Array[Tree.ValDef]]): Array[Array[Symbol]] = {
+ val vparamSyms = new Array[Array[Symbol]](vparams.length);
+ var i = 0; while (i < vparams.length) {
+ vparamSyms(i) = enterParams(vparams(i));
+ i = i + 1
+ }
+ vparamSyms
+ }
+
+ /** Re-enter type parameters in current scope.
+ */
+ def reenterParams(tparams: Array[Tree.AbsTypeDef], tsyms: Array[Symbol]): unit = {
+ var i = 0; while (i < tparams.length) {
+ tsyms(i).pos = tparams(i).pos;
+ tsyms(i).name = tparams(i).name;
+ //necessary since tsyms might have been unpickled
+ tparams(i).setSymbol(tsyms(i));
+ context.scope.enter(tsyms(i));
+ i = i + 1
+ }
+ }
+
+ /** Re-enter type and value parameters in current scope.
+ */
+ def reenterParams(tparams: Array[Tree.AbsTypeDef], vparamss: Array[Array[Tree.ValDef]], mt: Type): unit = {
+ var rest: Type = mt;
+ rest match {
+ case Type$PolyType(tsyms, restp) =>
+ reenterParams(tparams, tsyms);
+ rest = restp;
+ case _ =>
+ }
+ var j = 0; while (j < vparamss.length) {
+ val vparams = vparamss(j);
+ rest match {
+ case Type$MethodType(vsyms, restp) =>
+ var i = 0; while (i < vparams.length) {
+ vsyms(i).pos = vparams(i).pos;
+ vsyms(i).name = vparams(i).name;
+ //necessary since vsyms might have been unpickled
+ vparams(i).setSymbol(vsyms(i));
+ //potential overload in case this is a view parameter
+ context.scope.enterOrOverload(vsyms(i));
+ i = i + 1
+ }
+ rest = restp;
+ case _ =>
+ }
+ j = j + 1
+ }
+ }
+
+ def addInheritedOverloaded(sym: Symbol, tp: Type): unit =
+ if (sym.owner().kind == CLASS &&
+ !sym.isConstructor() &&
+ sym.owner().lookup(sym.name) == sym)
+ // it's a class member which is not an overloaded alternative
+ sym.addInheritedOverloaded(tp);
+
+// Definining Symbols -------------------------------------------------------
+
+ /** Define symbol associated with `tree' using given `unit' and `context'.
+ */
+ def defineSym(tree: Tree, unit: CompilationUnit, curcontext: Context): unit = {
+ val savedUnit: CompilationUnit = this.unit;
+ this.unit = unit;
+ val savedContext: Context = this.context;
+ this.context = curcontext;
+ val savedMode: int = this.mode;
+ this.mode = EXPRmode;
+ val savedPt: Type = this.pt;
+ this.pt = Type.AnyType;
+
+ try {
+ val sym: Symbol = tree.symbol();
+ if (global.debug) global.log("defining " + sym);
+ var owntype: Type = null;
+ tree match {
+ case Tree.ClassDef(mods, name, tparams, vparams, tpe, templ) =>
+ val prevContext = pushContext(
+ tree, sym.primaryConstructor(), new Scope(context.scope));
+ val tparamSyms = enterParams(tparams);
+ var vparamSyms = enterParams(vparams);
+ if (vparamSyms.length == 0) {
+ vparamSyms = NewArray.SymbolArray{Symbol.EMPTY_ARRAY};
+ } else if (infer.isViewBounded(tparamSyms) && vparamSyms.length == 1) {
+ val vparamSyms1 = new Array[Array[Symbol]](2);
+ vparamSyms1(0) = vparamSyms(0);
+ vparamSyms1(1) = Symbol.EMPTY_ARRAY;
+ vparamSyms = vparamSyms1
+ }
+ if (vparams.length > 0)
+ templ.body = desugarize.addParamAccessors(
+ templ.body, vparams(vparams.length - 1));
+
+ val constrtype: Type = makeMethodType(
+ tparamSyms,
+ vparamSyms,
+ Type.typeRef(sym.owner().thisType(), sym, Symbol.getType(tparamSyms)));
+ //System.out.println("set info " + sym.constructor() + " to " + constrtype + " was " + sym.constructor().rawInfo());//DEBUG
+ sym.primaryConstructor().setInfo(constrtype);
+ // necessary so that we can access tparams
+ sym.primaryConstructor().flags =
+ sym.primaryConstructor().flags | INITIALIZED;
+
+ if (tpe != Tree.Empty)
+ sym.setTypeOfThis(new LazySelfType(sym, tpe));
+
+ defineTemplate(templ, sym, new Scope());
+ owntype = templ.getType();
+ context = prevContext;
+
+ case Tree.ModuleDef(mods, name, _tpe, templ) =>
+ var tpe = _tpe;
+ val clazz: Symbol = sym.moduleClass();
+ val prevContext = pushContext(
+ tree, clazz.primaryConstructor(), context.scope);
+ defineTemplate(templ, clazz, new Scope());
+ context = prevContext;
+ clazz.setInfo(templ.getType());
+ tpe = transform(tpe, TYPEmode);
+ (tree.asInstanceOf[Tree.ModuleDef]).tpe = tpe;
+ if (tpe != Tree.Empty)
+ clazz.setTypeOfThis(new LazySelfType(sym, tpe));
+ owntype = if (tpe == Tree.Empty) clazz.getType() else tpe.getType();
+
+ case Tree.DefDef(mods, name, tparams, vparams, _tpe, _rhs) =>
+ var tpe = _tpe;
+ var rhs = _rhs;
+ var restype: Type = null;
+ val prevContext = pushContext(tree, sym, new Scope(context.scope));
+ val tparamSyms = enterParams(tparams);
+ val vparamSyms = enterParams(vparams);
+ if (tpe != Tree.Empty) {
+ tpe = transform(tpe, TYPEmode);
+ (tree.asInstanceOf[Tree.DefDef]).tpe = tpe;
+ restype = tpe.getType();
+ } else if (name == Names.CONSTRUCTOR) {
+ if (context.enclClass.owner.typeParams().length != 0)
+ error(tree.pos, "secondary constructors for parameterized classes not yet implemented");
+ restype = context.enclClass.owner.getType();/*.subst(
+ context.enclClass.owner.typeParams(), tparamSyms)*/;
+ } else {
+ if ((sym.flags & PARAMACCESSOR) != 0) {
+ rhs.setType(rhs.symbol().getType());
+ } else {
+ rhs = transform(rhs, EXPRmode);
+ (tree.asInstanceOf[Tree.DefDef]).rhs = rhs;
+ }
+ restype = rhs.getType();
+ if (!sym.isFinal()) restype = restype.deconst();
+ }
+ restype = checkNoEscape(tpe.pos, restype);
+ if (name == Names.view &&
+ infer.containsSymbol(tparamSyms, restype.symbol())) {
+ error(tree.pos, "result type of view may not be a type variable");
+ restype = definitions.ANY_TYPE();
+ }
+ context = prevContext;
+
+ owntype = makeMethodType(tparamSyms, vparamSyms, restype);
+ //System.out.println("methtype " + name + ":" + owntype);//DEBUG
+ addInheritedOverloaded(sym, owntype);
+
+ case Tree.ValDef(mods, name, _tpe, _rhs) =>
+ var tpe = _tpe;
+ var rhs = _rhs;
+ if (tpe != Tree.Empty) {
+ tpe = transform(tpe, TYPEmode);
+ (tree.asInstanceOf[Tree.ValDef]).tpe = tpe;
+ owntype = tpe.getType();
+ } else {
+ val prevContext = pushContext(tree, sym, context.scope);
+ if (rhs == Tree.Empty) {
+ if ((sym.owner().flags & ACCESSOR) != 0) {
+ // this is the parameter of a variable setter method.
+ assert((sym.flags & PARAM) != 0);
+ owntype = sym.owner().accessed().getType();
+ } else {
+ error(tree.pos, "missing parameter type");
+ owntype = Type.ErrorType;
+ }
+ } else {
+ rhs = transform(rhs, EXPRmode);
+ (tree.asInstanceOf[Tree.ValDef]).rhs = rhs;
+ owntype = rhs.getType();
+ if (sym.isVariable() || !sym.isFinal())
+ owntype = owntype.deconst();
+ }
+ context = prevContext;
+ addInheritedOverloaded(sym, owntype);
+ }
+
+ case Tree.AliasTypeDef(mods, name, tparams, _rhs) =>
+ var rhs = _rhs;
+ val prevContext = pushContext(tree, sym.primaryConstructor(), new Scope(context.scope));
+ val tparamSyms = enterParams(tparams);
+ rhs = transform(rhs, TYPEmode);
+ (tree.asInstanceOf[Tree.AliasTypeDef]).rhs = rhs;
+ owntype = rhs.getType();
+ sym.primaryConstructor().setInfo(
+ new Type$PolyType(tparamSyms, owntype));
+ context = prevContext;
+
+ case Tree.AbsTypeDef(mods, name, _rhs, _lobound) =>
+ var rhs = _rhs;
+ var lobound = _lobound;
+ //can't have `sym' as owner since checkNonCyclic would fail.
+ rhs = transform(rhs, TYPEmode);
+ tree.asInstanceOf[Tree.AbsTypeDef].rhs = rhs;
+ lobound = transform(lobound, TYPEmode);
+ (tree.asInstanceOf[Tree.AbsTypeDef]).lobound = lobound;
+ if (sym.isViewBounded()) {
+ sym.setVuBound(rhs.getType());
+ owntype = definitions.ANY_TYPE();
+ } else {
+ owntype = rhs.getType();
+ }
+ sym.setLoBound(lobound.getType());
+ owntype.symbol().initialize();//to detect cycles todo: needed?
+
+ case Tree.Import(_expr, selectors) =>
+ val expr = transform(_expr, EXPRmode | QUALmode);
+ tree.asInstanceOf[Tree.Import].expr = expr;
+ checkStable(expr);
+ owntype = expr.getType();
+ val tp: Type = owntype.widen();
+ { var i = 0; while (i < selectors.length) {
+ if (selectors(i) != Names.IMPORT_WILDCARD &&
+ tp.lookup(selectors(i)) == Symbol.NONE &&
+ tp.lookup(selectors(i).toTypeName()) == Symbol.NONE)
+ error(tree.pos, "" + NameTransformer.decode(selectors(i)) + " is not a member of " + expr);
+ i = i + 2
+ }}
+ case _ =>
+ throw new ApplicationError();
+ }
+ sym.setInfo(owntype);
+ validate(sym);
+ if (global.debug) global.log("defined " + sym);
+ } catch {
+ case ex: Type$Error =>
+ reportTypeError(tree.pos, ex);
+ setError(tree);
+ if (tree.hasSymbol()) {
+ tree.symbol().setInfo(Type.ErrorType);
+ }
+ }
+
+ this.unit = savedUnit;
+ this.context = savedContext;
+ this.mode = savedMode;
+ this.pt = savedPt;
+ }
+
+ /** Definition phase for a template. This enters all symbols in template
+ * into symbol table.
+ */
+ def defineTemplate(templ: Tree.Template, clazz: Symbol, members: Scope): unit = {
+ // attribute parent constructors
+ templ.parents = transformConstrInvocations(templ.pos, templ.parents);
+ if (templ.parents.length > 0 &&
+ (templ.parents(0).getType().symbol().flags & (JAVA | INTERFACE)) == (JAVA | INTERFACE)) {
+ val constrs1 = new Array[Tree](templ.parents.length + 1);
+ constrs1(0) = gen.mkApply__(
+ gen.mkPrimaryConstructorGlobalRef(
+ templ.parents(0).pos, definitions.OBJECT_CLASS));
+ System.arraycopy(templ.parents, 0, constrs1, 1, templ.parents.length);
+ templ.parents = constrs1;
+ }
+ val parents = Tree.typeOf(templ.parents);
+
+ // enter all members
+ val prevContext = pushContext(templ, clazz, members);
+ templ.body = desugarize.Statements(unit, templ.body, false);
+ enterSyms(templ.body);
+ context = prevContext;
+ templ.setType(Type.compoundType(parents, members, clazz));
+ }
+
+ def makeMethodType(tparams: Array[Symbol], vparams: Array[Array[Symbol]], restpe: Type): Type =
+ if (tparams.length == 0 && vparams.length == 0) {
+ new Type$PolyType(tparams, restpe);
+ } else {
+ var result: Type = restpe;
+ var i = vparams.length - 1;
+ while (i >= 0) {
+ result = new Type$MethodType(vparams(i), result);
+ i = i - 1;
+ }
+ if (tparams.length != 0)
+ result = new Type$PolyType(tparams, result);
+ result
+ }
+
+ /** Define self type of class or module `sym'
+ * associated with `tree' using given `unit' and `context'.
+ */
+ def defineSelfType(sym: Symbol, clazz: Symbol, tree: Tree, unit: CompilationUnit, curcontext: Context): unit = {
+ val savedUnit: CompilationUnit = this.unit;
+ this.unit = unit;
+ val savedContext: Context = this.context;
+ this.context = curcontext;
+
+ val selftype: Type = transform(tree, TYPEmode).getType();
+ //todo: can we really make a compound type with class
+ val selftype1: Type =
+ if (clazz.getType().isSubType(selftype))
+ clazz.getType()
+ else if (selftype.isSubType(clazz.getType()))
+ selftype
+ else if (selftype.isSingletonType() && selftype.singleDeref().symbol().isSubClass(clazz))
+ selftype
+ else
+ selftype match {
+ case Type$CompoundType(parts, members) =>
+ val parts1 = new Array[Type](parts.length + 1);
+ System.arraycopy(parts, 0, parts1, 0, parts.length);
+ parts1(parts.length) = clazz.getType();
+ Type.compoundTypeWithOwner(clazz.owner().enclClass(), parts1, members);
+
+ case _ =>
+ Type.compoundTypeWithOwner(
+ clazz.owner().enclClass(), NewArray.Type(selftype, clazz.getType()), Scope.EMPTY);
+ }
+ if (global.debug) global.log("assigning self type " + selftype1);
+ sym.setInfo(selftype1);
+
+ this.unit = savedUnit;
+ this.context= savedContext;
+ }
+
+// Attribution and Transform -------------------------------------------------
+
+ /** Turn tree type into stable type if possible and required by
+ * context.
+ */
+ def mkStable(tree: Tree, pre: Type, mode: int, pt: Type): Tree = {
+ tree.getType() match {
+ case Type$ConstantType(_, value) =>
+ return make.Literal(tree.pos, value).setType(tree.getType())
+ case Type$PolyType(tparams, restp) =>
+ if (tparams.length == 0) {
+ restp match {
+ case Type$ConstantType(_, value) =>
+ return make.Literal(tree.pos, value).setType(tree.getType());
+ case _ =>
+ }
+ }
+ case _ =>
+ }
+ if ((pt != null && pt.isStable() ||
+ (mode & QUALmode) != 0 ||
+ tree.getType().symbol().isModuleClass()) &&
+ (pre != null) && pre.isStable()) {
+ var sym: Symbol = tree.symbol();
+ tree.getType() match {
+ case Type$OverloadedType(alts, alttypes) =>
+ if ((mode & FUNmode) == 0) {
+ try {
+ infer.exprAlternative(tree, alts, alttypes, pt);
+ sym = tree.symbol();
+ } catch {
+ case ex: Type$Error =>
+ reportTypeError(tree.pos, ex);
+ }
+ }
+ case _ =>
+ }
+ if (sym.isStable()) {
+ tree.setType(Type.singleType(pre, sym));
+ }
+ }
+ tree
+ }
+
+ /** The qualifying class of a this or super
+ */
+ def qualifyingClass(tree: Tree, name: Name): Symbol = {
+ if (name == TypeNames.EMPTY) {
+ val clazz: Symbol = context.enclClass.owner;
+ if (clazz != null)
+ clazz
+ else {
+ error(tree.pos, "" + tree +
+ " can be used only in a class, object, or template");
+ Symbol.NONE
+ }
+ } else {
+ var i: Context = context;
+ while (i != Context.NONE &&
+ !(i.owner.kind == CLASS && i.owner.name == name))
+ i = i.outer.enclClass;
+ if (i != Context.NONE)
+ i.owner
+ else {
+ error(tree.pos, "" + name + " is not an enclosing class");
+ Symbol.NONE
+ }
+ }
+ }
+
+ /** Adapt tree to given mode and given prototype
+ */
+ def adapt(tree: Tree, mode: int, pt: Type): Tree = {
+ //System.out.println(tree + ":" + tree.getType() + " adapt " + pt + " " + mode);//DEBUG
+ tree.getType() match {
+ case Type$OverloadedType(alts, alttypes) =>
+ // resolve overloading
+ if ((mode & FUNmode) == 0) {
+ try {
+ infer.exprAlternative(tree, alts, alttypes, pt);
+ } catch {
+ case ex: Type$Error =>
+ reportTypeError(tree.pos, ex);
+ }
+ tree.getType() match {
+ case Type$OverloadedType(_, _) =>
+ // overload resolution failed bcs no alternative matched prototype.
+ typeError(tree.pos, tree.getType(), pt);
+ return errorTermTree(tree);
+ case _ =>
+ }
+ return adapt(tree, mode, pt);
+ }
+
+ case Type$PolyType(tparams, restp) =>
+ // apply parameterless functions
+ // instantiate polymorphic expressions
+ if (tparams.length == 0) {
+ return adapt(constfold.tryToFold(tree.setType(restp)), mode, pt);
+ } else if ((mode & (FUNmode | POLYmode)) == 0) {
+ var tree1: Tree = null;
+ try {
+ tree1 = infer.exprInstance(tree, tparams, restp, pt);
+ } catch {
+ case ex: Type$Error =>
+ error(tree.pos, ex.msg);
+ tree1 = errorTermTree(tree);
+ }
+ return adapt(tree1, mode, pt);
+ }
+
+ case Type$MethodType(_, _) =>
+ // convert unapplied methods to functions.
+ if ((mode & (EXPRmode | FUNmode)) == EXPRmode &&
+ (infer.isCompatible(tree.getType(), pt) ||
+ pt.symbol() == definitions.UNIT_CLASS)) {
+ checkEtaExpandable(tree.pos, tree.getType());
+ if (TreeInfo.methPart(tree).symbol() == definitions.ANY_MATCH) {
+ error(tree.pos, "`match' needs to be applied fully");
+ return errorTree(tree)
+ } else {
+ return transform(desugarize.etaExpand(tree, tree.getType()), mode, pt);
+ }
+ } else if ((mode & (CONSTRmode | FUNmode)) == CONSTRmode) {
+ error(tree.pos, "missing arguments for class constructor");
+ return errorTermTree(tree);
+ }
+
+ case _ =>
+ }
+ if ((mode & PATTERNmode) != 0) {
+ if (tree.isType()) {
+ val clazz: Symbol = tree.getType().withDefaultArgs().unalias().symbol();
+
+ if (clazz.isCaseClass()) {
+ // set type to instantiated case class constructor
+ tree.setType(tree.getType().prefix().memberType(clazz.primaryConstructor()));
+ // MZ: this is a hack, but I didn't know how to do it better
+ if ((clazz.flags & (JAVA | CASE)) == (JAVA | CASE)) {
+ val altconstr = clazz.allConstructors().alternativeSymbols();
+ tree.setType(tree.getType().prefix().memberType(
+ altconstr(altconstr.length - 1)));
+ }
+ tree.getType() match {
+ case Type$PolyType(tparams, restp) =>
+ try {
+ infer.constructorInstance(tree, tparams, restp, pt);
+ //System.out.println("constr inst " + ArrayApply.toString(tparams) + restp + " against " + pt + " = " + tree.getType());//DEBUG
+ } catch {
+ case ex: Type$Error =>
+ if (!pt.isError()) error(tree.pos, ex.msg);
+ setError(tree);
+ }
+ case _ =>
+ }
+ } else if (clazz.isSubClass(definitions.SEQ_CLASS)) {
+ // set type to instantiated sequence class constructor
+ // todo: should we admit even supertypes of the target type?
+ val seqtp: Type = pt.baseType(clazz);
+ if (seqtp != Type.NoType) {
+ def seqConstructorType(paramtp: Type, resulttp: Type) = {
+ val constr: Symbol = resulttp.symbol().primaryConstructor();
+ val param: Symbol = constr.newVParam(
+ tree.pos, REPEATED, Names.PATTERN_WILDCARD,
+ paramtp.baseType(definitions.SEQ_CLASS));
+ new Type$MethodType(NewArray.Symbol(param), resulttp);
+ }
+ tree.setType(seqConstructorType(seqtp, pt));
+ } else {
+ error(tree.pos, "expected pattern type " + pt +
+ " does not conform to sequence " + clazz);
+ return errorTermTree(tree);
+ }
+ } else if (!tree.getType().isError()) {
+ error(tree.pos, "" + tree.getType().symbol() +
+ " is neither a case class constructor nor a sequence class constructor");
+ return errorTermTree(tree);
+ }
+ }
+ if ((mode & FUNmode) != 0) {
+ return tree;
+ } else {
+ val sym: Symbol = tree.symbol();
+ // check that idents or selects are stable.
+ tree match {
+ case Tree.Ident(_) | Tree.Select(_, _) =>
+ checkStable(tree);
+ case _ =>
+ }
+ }
+ } else if ((mode & EXPRmode) != 0) {
+ if ((mode & FUNmode) != 0) {
+ if (tree.getType().isObjectType()) {
+ // insert apply method
+ val applyMeth: Symbol = tree.getType().lookup(Names.apply);
+ if (applyMeth != Symbol.NONE) {
+ val applyType: Type = infer.checkAccessible(
+ tree.pos, applyMeth, tree.getType().memberType(applyMeth),
+ tree, tree.getType());
+ val tree1 = make.Select(tree.pos, tree, Names.apply)
+ .setSymbol(applyMeth)
+ .setType(applyType);
+ return adapt(tree1, mode, pt);
+ }
+ }
+ } else if ((mode & QUALmode) == 0) {
+ // check that packages and static modules are not used as values
+ tree match {
+ case Tree.Ident(_) | Tree.Select(_, _) =>
+ val sym: Symbol = tree.symbol();
+ if (sym != null && !sym.isError() && !sym.isValue()) {
+ error(tree.pos, "" + tree.symbol() + " is not a value");
+ return errorTermTree(tree);
+ }
+ case _ =>
+ }
+ }
+ }
+
+ var owntype: Type = tree.getType();
+ if ((mode & (CONSTRmode | FUNmode)) == (CONSTRmode) && pt != Type.AnyType) {
+ owntype = owntype.instanceType();
+ // this works as for superclass constructor calls the expected
+ // type `pt' is always AnyType (see transformConstrInvocations).
+ }
+ if (!(owntype.isInstanceOf[Type$PolyType] || owntype.isSubType(pt))) {
+ tree match {
+ case Tree.Literal(constant) =>
+ var n: int = constant match {
+ case AConstant$INT(value) => value
+ case AConstant$CHAR(value) => value
+ case _ => Integer.MAX_VALUE
+ }
+ val value1: AConstant =
+ if (pt.symbol() == definitions.BYTE_CLASS && -128 <= n && n <= 127)
+ AConstant.BYTE(n.asInstanceOf[byte])
+ else if (pt.symbol() == definitions.SHORT_CLASS && -32768 <= n && n <= 32767)
+ AConstant.SHORT(n.asInstanceOf[short])
+ else if (pt.symbol() == definitions.CHAR_CLASS && 0 <= n && n <= 65535)
+ AConstant.CHAR(n.asInstanceOf[char])
+ else null;
+ if (value1 != null)
+ return gen.Literal(tree.pos, value1);
+ case _ =>
+ }
+ if ((mode & EXPRmode) != 0) {
+ if (pt.symbol() == definitions.UNIT_CLASS) {
+ return gen.mkUnitBlock(tree);
+ } else if (infer.isCompatible(tree.getType(), pt)) {
+ tree match {
+ case Tree.Literal(value) =>
+ val value1 = constfold.cast(value, pt);
+ if (value1 != null)
+ return adapt(gen.Literal(tree.pos, value1), mode, pt);
+ case _ =>
+ }
+ val v = infer.bestView(tree.getType(), pt, Names.EMPTY);
+ if (v != null) return applyView(v, tree, mode, pt);
+ // todo: remove
+ val coerceMeth: Symbol = tree.getType().lookup(Names.coerce);
+ if (coerceMeth != Symbol.NONE) {
+ val coerceType = infer.checkAccessible(
+ tree.pos, coerceMeth, tree.getType().memberType(coerceMeth),
+ tree, tree.getType());
+ val tree1 = make.Select(tree.pos, tree, Names.coerce)
+ .setSymbol(coerceMeth)
+ .setType(coerceType);
+ return adapt(tree1, mode, pt);
+ }
+ }
+ }
+ if ((mode & CONSTRmode) == 0) {
+ typeError(tree.pos, owntype, pt);
+ Type.explainTypes(owntype, pt);
+ setError(tree);
+ } // for constructors, delay until after the `new'.
+ }
+ tree
+ }
+
+ /** Attribute an identifier consisting of a simple name or an outer reference.
+ * @param tree The tree representing the identifier.
+ * @param name The name of the identifier.
+ */
+ def transformIdent(_tree: Tree, name: Name): Tree = {
+ var tree = _tree;
+ //System.out.println("transforming " + name);//DEBUG
+ // find applicable definition and assign to `sym'
+ var sym: Symbol = Symbol.NONE;
+ var pre: Type = null;
+ var qual: Tree = Tree.Empty;
+ var stopPos: int = Integer.MIN_VALUE;
+ var nextcontext: Context = context;
+ while (sym.kind == NONE && nextcontext != Context.NONE) {
+ sym = nextcontext.scope.lookup(name);
+ if (sym.kind != NONE) {
+ stopPos = sym.pos;
+ } else {
+ nextcontext = nextcontext.enclClass;
+ if (nextcontext != Context.NONE) {
+ sym = nextcontext.owner.typeOfThis().lookup(name);
+ if (sym.kind != NONE) {
+ stopPos = nextcontext.owner.pos;
+ } else {
+ nextcontext = nextcontext.outer;
+ }
+ }
+ }
+ }
+
+ if (stopPos > tree.pos) {
+ // set stopPos to beginning of block enclosed in the scope which defines the
+ // referenced symbol.
+ var lastc = Context.NONE;
+ var c = nextcontext;
+ while (c.outer.scope != null && c.outer.scope.lookup(name) == sym) {
+ c.tree match {
+ case Tree.Block(_, _) | Tree.CaseDef(_, _, _) | Tree.ClassDef(_, _, _, _, _, _) | Tree.ModuleDef(_, _, _, _) =>
+ lastc = c;
+ case _ =>
+ }
+ c = c.outer
+ }
+ if (lastc != Context.NONE) {
+ //System.out.println("revising stop to [" + lastc.tree + "]; symbol = " + sym + ", context = " + nextcontext);//DEBUG
+ stopPos = lastc.tree.pos;
+ }
+ }
+
+ var impcontext: Context = context.prevImport;
+ var lastimpcontext: Context = null;
+ var sym1: Symbol = Symbol.NONE;
+ while (sym1.kind == NONE && impcontext != Context.NONE && impcontext.tree.pos > stopPos) {
+ sym1 = impcontext.importedSymbol(name);
+ lastimpcontext = impcontext;
+ impcontext = impcontext.outer.prevImport;
+ }
+
+ // evaluate what was found
+ if (sym1.kind == NONE) {
+ if (sym.kind == NONE) {
+ //System.out.println(name);//DEBUG
+ error(tree.pos, "not found: " + decode(name));
+ return errorTree(tree);
+ } else {
+ if (sym.owner().kind == CLASS) {
+ pre = nextcontext.enclClass.owner.thisType();
+ if (!sym.owner().isPackageClass()) {
+ val qual1: Tree = gen.This(tree.pos, nextcontext.enclClass.owner);
+ tree = make.Select(tree.pos, qual1, name);
+ //System.out.println(name + " :::> " + tree + " " + qual1.symbol());//DEBUG
+ }
+ } else {
+ pre = Type.NoPrefix;
+ }
+ }
+ } else if (sym.kind != NONE && !sym.isExternal()) {
+ error(tree.pos,
+ "reference to " + name + " is ambiguous;\n" +
+ "it is both defined in " + sym.owner() +
+ " and imported subsequently by \n" + lastimpcontext.tree);
+ return errorTree(tree);
+ } else {
+ // check that there are no other applicable imports in same scope.
+ while (impcontext != Context.NONE && impcontext.scope == lastimpcontext.scope) {
+ if (!impcontext.sameImport(lastimpcontext) && impcontext.importedSymbol(name).kind != NONE) {
+ error(tree.pos,
+ "reference to " + name + " is ambiguous;\n" +
+ "it is imported twice in the same scope by\n " +
+ lastimpcontext.tree + "\nand " + impcontext.tree);
+ return errorTree(tree);
+ }
+ impcontext = impcontext.outer.prevImport;
+ }
+ sym = sym1;
+ qual = lastimpcontext.importPrefix().duplicate();
+ pre = qual.getType();
+ //System.out.println(name + " => " + lastimpcontext.tree + "." + name);//DEBUG
+ tree = make.Select(tree.pos, qual, name);
+ }
+
+ var symtype: Type =
+ (if (sym.isType()) sym.typeConstructor() else sym.getType())
+ .asSeenFrom(pre, sym.owner());
+ symtype = infer.checkAccessible(
+ tree.pos, sym, symtype, qual,
+ if (qual == Tree.Empty && sym.owner().isPackageClass()) sym.owner().getType()
+ else qual.getType());
+ if (symtype == Type.NoType) {
+ error(tree.pos, "not found: " + decode(name));
+ return errorTree(tree);
+ }
+ //System.out.println(name + ":" + symtype);//DEBUG
+ mkStable(tree.setSymbol(sym).setType(symtype), pre, mode, pt)
+ }
+
+ /** Attribute a selection where `tree' is `qual.name'.
+ * `qual' is already attributed.
+ */
+ def transformSelect(tree: Tree, _qual: Tree, name: Name): Tree = {
+ var qual = _qual;
+ var uninst: Array[Symbol] = Symbol.EMPTY_ARRAY;
+ qual.getType() match {
+ case Type$PolyType(tparams, restype) =>
+ qual = infer.mkTypeApply(qual, tparams, restype, Symbol.getType(tparams));
+ uninst = tparams;
+ case _ =>
+ }
+ var sym: Symbol = qual.getType().lookup(name);
+ if (sym.kind == NONE) {
+ if (name != Names.view) {
+ val qtype = qual.getType().singleDeref();
+ val v = infer.bestView(qtype, Type.AnyType, name);
+ if (v != null) {
+ qual = applyView(v, qual.setType(qtype), EXPRmode, Type.AnyType);
+ sym = qual.getType().lookup(name);
+ assert(sym.kind != NONE);
+ } else {
+ //System.out.println(qual.getType() + " has members " + qual.getType().members());//DEBUG
+ error(tree.pos,
+ decode(name) + " is not a member of " + qual.getType().widen());
+ return errorTree(tree);
+ }
+ }
+ }
+ val qualtype =
+ if (qual.isInstanceOf[Tree.Super]) context.enclClass.owner.thisType()
+ else qual.getType();
+ var symtype: Type =
+ (if (sym.isType()) sym.typeConstructor() else sym.getType())
+ .asSeenFrom(qualtype, sym.owner());
+ if (symtype == Type.NoType) {
+ error(tree.pos, "not found: " + decode(name));
+ return errorTree(tree);
+ } else
+ symtype = infer.checkAccessible(tree.pos, sym, symtype, qual, qualtype);
+ //System.out.println(sym.name + ":" + symtype);//DEBUG
+ if (uninst.length != 0) {
+ def polymorphize(tp: Type): Type = tp match {
+ case Type$PolyType(tparams, restype) =>
+ new Type$PolyType(tparams, polymorphize(restype))
+ case Type$OverloadedType(alts, alttypes) =>
+ val alttypes1 = new Array[Type](alttypes.length);
+ var i = 0; while (i < alttypes.length) {
+ alttypes1(i) = polymorphize(alttypes(i));
+ i = i + 1
+ }
+ new Type$OverloadedType(alts, alttypes1)
+ case _ =>
+ new Type$PolyType(uninst, tp);
+ }
+ symtype = polymorphize(symtype);
+ }
+ //System.out.println(qual.getType() + ".member: " + sym + ":" + symtype);//DEBUG
+ val tree1: Tree = tree match {
+ case Tree.Select(_, _) =>
+ copy.Select(tree, sym, qual);
+ case Tree.SelectFromType(_, _) =>
+ copy.SelectFromType(tree, sym, qual)
+ }
+ mkStable(tree1.setType(symtype), qualtype, mode, pt)
+ }
+
+ /** Attribute a pattern matching expression where `pattpe' is the
+ * expected type of the patterns and `pt' is the expected type of the
+ * results.
+ */
+ def transformVisitor(tree: Tree, pattpe: Type, pt: Type): Tree =
+ //System.out.println("trans visitor with " + pattpe + "," + pt);//DEBUG
+ tree match {
+ case Tree.Visitor(cases) =>
+ val cases1 = cases;
+ var i = 0; while (i < cases.length) {
+ cases1(i) = transformCase(cases(i), pattpe, pt);
+ i = i + 1
+ }
+ return copy.Visitor(tree, cases1)
+ .setType(Type.lub(Tree.typeOf(cases1.asInstanceOf[Array[Tree]])));
+ case _ =>
+ throw new ApplicationError();
+ }
+
+ /** Attribute a case where `pattpe' is the expected type of the pattern
+ * and `pt' is the expected type of the result.
+ */
+ def transformCase(tree: Tree.CaseDef, pattpe: Type, pt: Type): Tree.CaseDef =
+ tree match {
+ case Tree.CaseDef(pat, guard, body) =>
+ val prevContext = pushContext(tree, context.owner, new Scope(context.scope));
+ this.inAlternative = false; // no vars allowed below Alternative
+ val pat1: Tree = transform(pat, PATTERNmode, pattpe);
+ val guard1: Tree =
+ if (guard == Tree.Empty) Tree.Empty
+ else transform(guard, EXPRmode, definitions.boolean_TYPE());
+ val body1: Tree = transform(body, EXPRmode, pt);
+ context = prevContext;
+ return copy.CaseDef(tree, pat1, guard1, body1)
+ .setType(body1.getType()).asInstanceOf[Tree.CaseDef];
+ }
+
+ def transformStatSeq(stats: Array[Tree], exprOwner: Symbol): Array[Tree] = {
+ var stats1 = stats;
+ var i = 0; while (i < stats.length) {
+ val stat: Tree = stats(i);
+ if (context.owner.isCompoundSym() && !TreeInfo.isDeclaration(stat)) {
+ error(stat.pos, "only declarations allowed here");
+ }
+ val mode: int = if (TreeInfo.isDefinition(stat)) NOmode else EXPRmode;
+ var stat1: Tree = null;
+ if (exprOwner.kind != NONE && !TreeInfo.isDefinition(stat)) {
+ val prevContext = pushContext(stat, exprOwner, context.scope);
+ stat1 = transform(stat, mode);
+ context = prevContext;
+ } else {
+ stat1 = transform(stat, mode);
+ }
+ // todo: if we comment next 4 lines out, test/pos/scoping2 fails.
+ // find out why
+ if (stat1 != stat && stats1 == stats) {
+ stats1 = new Array[Tree](stats.length);
+ System.arraycopy(stats, 0, stats1, 0, i);
+ }
+ stats1(i) = stat1;
+ i = i + 1
+ }
+ stats1
+ }
+
+ /** Attribute a sequence of constructor invocations.
+ */
+ def transformConstrInvocations(pos: int, constrs: Array[Tree]): Array[Tree] = {
+ var i = 0; while (i < constrs.length) {
+ constrs(i) = transform(constrs(i), CONSTRmode | SUPERmode, Type.AnyType);
+ val f: Symbol = TreeInfo.methSymbol(constrs(i));
+ if (f != null) {
+ val c: Symbol = f.constructorClass();
+ if (c.kind == CLASS) {
+ c.initialize();//to detect cycles
+ if (i > 0 && (c.flags & JAVA) == 0) loadMixinCode(pos, c);
+ }
+ }
+ i = i + 1
+ }
+ constrs
+ }
+
+ def transformConstrInvocationArgs(constrs: Array[Tree]): unit = {
+ var i = 0; while (i < constrs.length) {
+ constrs(i) match {
+ case Tree.Apply(fn, args) =>
+ if (fn.getType().isInstanceOf[Type$MethodType])
+ transformArgs(
+ constrs(i).pos, TreeInfo.methSymbol(fn), Symbol.EMPTY_ARRAY,
+ fn.getType(), EXPRmode, args, Type.AnyType);
+ case _ =>
+ }
+ i = i + 1
+ }
+ }
+
+ /** Attribute a template
+ */
+ def transformTemplate(templ: Tree.Template, owner: Symbol): Tree.Template = {
+ //if (global.debug) global.log("transforming template of " + owner);//DEBUG
+ if (templ.getType() == null)
+ defineTemplate(templ, owner, owner.members());//may happen for mixins
+ //System.out.println(owner.info());//DEBUG
+ val parents = templ.parents;
+ transformConstrInvocationArgs(parents);
+ if (!owner.isError()) {
+ validateParentClasses(
+ parents, owner.info().parents(), owner.thisType());
+ }
+ val prevContext = pushContext(templ, owner, owner.members());
+ /*
+ val params: Scope = new Scope();
+ def computeParams(t: Type): unit = t match {
+ case Type$PolyType(tparams, t1) =>
+ var i = 0; while (i < tparams.length) {
+ params.enter(tparams(i));
+ i = i + 1;
+ }
+ computeParams(t1);
+ case Type$MethodType(vparams, _) =>
+ var i = 0; while (i < vparams.length) {
+ params.enter(vparams(i));
+ i = i + 1;
+ }
+ case _ =>
+ }
+ computeParams(owner.primaryConstructor().getType());
+ val prevContext = pushContext(templ, owner.primaryConstructor(), params);
+ */
+ templ.setSymbol(owner.newLocalDummy());
+ val body1 = transformStatSeq(templ.body, templ.symbol());
+ /*
+ context = prevContext;
+ */
+ context = prevContext;
+ val templ1: Tree.Template = copy.Template(templ, parents, body1);
+ templ1.setType(owner.getType());
+ // initialize all members; necessary to initialize overloaded symbols
+ val members: Array[Symbol] = owner.members().elements();
+ var i = 0; while (i < members.length) {
+ val sym = members(i);
+ sym.initialize();
+ //System.out.println(owner.toString() + " defines " + sym + ":" + sym.getType());//DEBUG
+ i = i + 1
+ }
+ templ1
+ }
+
+ /** Attribute an argument list.
+ * @param pos Position for error reporting
+ * @param meth The symbol of the called method, or `null' if none exists.
+ * @param tparams The type parameters that need to be instantiated
+ * @param methtype The method's type w/o type parameters
+ * @param argMode The argument mode (either EXPRmode or PATTERNmode)
+ * @param args The actual arguments
+ * @param pt The proto-resulttype.
+ * @return The vector of instantiated argument types, or null if error.
+ */
+ def transformArgs(pos: int, meth: Symbol, tparams: Array[Symbol], methtype: Type, argMode: int, args: Array[Tree], pt: Type): Array[Type] = {
+ //System.out.println("trans args " + meth + ArrayApply.toString(tparams.asInstanceOf[Array[Object]]) + ":" + methtype + "," + pt);//DEBUG
+ val argtypes = new Array[Type](args.length);
+ methtype match {
+ case Type$MethodType(params, restp) =>
+ val formals = infer.formalTypes(params, args.length);
+ if (formals.length != args.length) {
+ error(pos, "wrong number of arguments for " +
+ (if (meth == null) "<function>" else meth) +
+ ArrayApply.toString(formals.asInstanceOf[Array[Object]], "(", ",", ")"));
+ return null;
+ }
+ if (tparams.length == 0) {
+ var i = 0; while (i < args.length) {
+ args(i) = transform(args(i), argMode, formals(i));
+ argtypes(i) = args(i).getType().deconst();
+ i = i + 1
+ }
+ } else {
+ // targs: the type arguments inferred from the prototype
+ val targs: Array[Type] = infer.protoTypeArgs(tparams, restp, pt, params);
+
+ // argpts: prototypes for arguments
+ val argpts = new Array[Type](formals.length);
+ var i = 0; while (i < formals.length) {
+ argpts(i) = formals(i).subst(tparams, targs);
+ i = i + 1
+ }
+
+ // transform arguments with (targs/tparams)formals as prototypes
+ { var i = 0; while (i < args.length) {
+ args(i) = transform(
+ args(i), argMode | POLYmode, formals(i).subst(tparams, targs));
+ i = i + 1
+ }}
+
+ // targs1: same as targs except that every AnyType is mapped to
+ // formal parameter type.
+ val targs1 = new Array[Type](targs.length);
+ { var i = 0; while (i < targs.length) {
+ targs1(i) = if (targs(i) != Type.AnyType) targs(i)
+ else tparams(i).getType();
+ i = i + 1
+ }}
+
+ { var i = 0; while (i < args.length) {
+ argtypes(i) = args(i).getType().deconst();
+ argtypes(i) match {
+ case Type$PolyType(tparams1, restype1) =>
+ argtypes(i) = infer.argumentTypeInstance(
+ tparams1, restype1,
+ formals(i).subst(tparams, targs1),
+ argpts(i));
+ case _ =>
+ }
+ i = i + 1
+ }}
+ }
+ // desugarizing ident patterns
+ if (params.length > 0 && (params(params.length-1).flags & REPEATED) != 0) {
+ if ((mode & PATTERNmode) != 0) {
+ def desug_allIdentPatterns(trees: Array[Tree], currentOwner: Symbol): unit = {
+ var i = 0; while (i < trees.length) {
+ trees(i) match {
+ case Tree.Ident(name) =>
+ if (name != Names.PATTERN_WILDCARD) {
+ val vble: Symbol = context.scope.lookup(name);
+ trees(i) = desugarize.IdentPattern(trees(i)).setSymbol(vble)
+ .setType(vble.getType());
+ } else {
+ trees(i) = gen.Ident(trees(i).pos, definitions.PATTERN_WILDCARD);
+ }
+ case _ =>
+ }
+ i = i + 1
+ }
+ }
+ desug_allIdentPatterns(args, context.owner);
+ } else {
+ assert(args.length != params.length ||
+ !(args(params.length-1).isInstanceOf[Tree.Sequence]));
+ }
+ }
+ argtypes;
+
+ case Type$PolyType(tparams1, restp) =>
+ var tparams2: Array[Symbol] = tparams1;
+ if (tparams.length != 0) {
+ tparams2 = new Array[Symbol](tparams.length + tparams1.length);
+ System.arraycopy(tparams, 0, tparams2, 0, tparams.length);
+ System.arraycopy(tparams1, 0, tparams2, tparams.length, tparams1.length);
+ }
+ transformArgs(pos, meth, tparams2,
+ infer.skipViewParams(tparams2, restp), argMode, args, pt)
+
+ case Type.ErrorType =>
+ var i = 0; while (i < args.length) {
+ args(i) = transform(args(i), argMode, Type.ErrorType);
+ argtypes(i) = args(i).getType().deconst();
+ i = i + 1
+ }
+ argtypes
+
+ case Type.OverloadedType(alts, alttypes) if (alts.length == 1) =>
+ transformArgs(pos, alts(0), tparams, alttypes(0), argMode, args, pt)
+
+ case _ =>
+ var i = 0; while (i < args.length) {
+ args(i) = transform(args(i), argMode, Type.AnyType);
+ argtypes(i) = args(i).getType().deconst();
+ i = i + 1
+ }
+ argtypes
+ }
+ }
+
+ /** Atribute an expression or pattern with prototype `pt'.
+ * Check that expression's type conforms to `pt'.
+ * Resolve overloading and apply parameterless functions.
+ * Insert `apply' function if needed.
+ */
+ def transform(tree: Tree, mode: int, pt: Type): Tree = {
+ val savedMode: int = this.mode;
+ val savedPt: Type = this.pt;
+ this.mode = mode;
+ this.pt = pt;
+ val tree1: Tree = adapt(transform(tree), mode, pt);
+
+ //System.out.println(tree1 + ": " + tree1.getType());//DEBUG
+
+ this.mode = savedMode;
+ this.pt = savedPt;
+ tree1
+ }
+
+ /** Transform expression or type with a given mode.
+ */
+ def transform(tree: Tree, mode: int): Tree = {
+ if ((mode & (EXPRmode | PATTERNmode | CONSTRmode)) != 0)
+ return transform(tree, mode, Type.AnyType);
+
+ val savedMode: int = this.mode;
+ this.mode = mode;
+ val tree1: Tree = transform(tree);
+ this.mode = savedMode;
+
+ if ((mode & TYPEmode) != 0) {
+ val sym: Symbol = tree1.symbol();
+ def typeParamCount = sym.primaryConstructor().rawInfo() match {
+ case t: LazyTreeType =>
+ t.tree match {
+ case Tree.ClassDef(_, _, tparams, _, _, _) => tparams.length
+ case Tree.AliasTypeDef(_, _, tparams, _) => tparams.length
+ case _ => 0
+ }
+ case _ => sym.typeParams().length
+ }
+ if ((mode & FUNmode) == 0 && sym != null && typeParamCount != 0) {
+ error(tree.pos, "" + sym + " takes type parameters.");
+ return errorTree(tree);
+ }
+// else if (tree1.isType())
+// return gen.mkType(tree1.pos, tree1.getType());
+ }
+ tree1
+ }
+
+ def transform(trees: Array[Tree], mode: int): Array[Tree] = {
+ var i = 0; while (i < trees.length) {
+ trees(i) = transform(trees(i), mode);
+ i = i + 1
+ }
+ trees
+ }
+
+ override def transform(trees: Array[Tree]): Array[Tree] =
+ super.transform(trees);
+
+ override def transform(trees: Array[Tree.CaseDef]): Array[Tree.CaseDef] =
+ super.transform(trees);
+
+ override def transform(trees: Array[Tree.AbsTypeDef]): Array[Tree.AbsTypeDef] =
+ super.transform(trees);
+
+ override def transform(trees: Array[Tree.ValDef]): Array[Tree.ValDef] =
+ super.transform(trees);
+
+ override def transform(trees: Array[Array[Tree.ValDef]]): Array[Array[Tree.ValDef]] =
+ super.transform(trees);
+
+ /** The main attribution function
+ */
+ override def transform(tree: Tree): Tree = {
+ //System.out.println("transforming " + tree + ":" + pt);//DEBUG
+ if (tree.getType() != null) {
+ checkDefined.all = tree; checkDefined.traverse(tree);//debug
+ return tree;
+ }
+ val sym: Symbol = tree.symbol();
+ if (sym != null && !sym.isInitialized()) sym.initialize();
+ if (global.debug && TreeInfo.isDefinition(tree)) global.log("transforming definition of " + sym);
+ try {
+ tree match {
+ case Tree.Empty =>
+ tree.setType(Type.NoType)
+
+ case Tree.Attributed(attr, definition) =>
+
+ def attrInfo(attr: Tree): AttrInfo = attr match {
+ case Tree.Ident(_) | Tree.Select(_, _) =>
+ new Pair(attr.symbol(), new Array[AConstant](0))
+ case Tree.Apply(fn, args) =>
+ new Pair(attrInfo(fn).fst, attrArgInfos(args))
+ case _ =>
+ unit.error(attr.pos, "malformed attribute");
+ new Pair(Symbol.NONE.newErrorClass(errorName(attr).toTypeName()),
+ new Array[AConstant](0))
+ }
+
+ def attrArgInfos(args: Array[Tree]): Array[AConstant] = {
+ val infos = new Array[AConstant](args.length);
+ var i = 0; while (i < args.length) {
+ args(i) match {
+ case Tree.Literal(value) => infos(i) = value;
+ case _ => unit.error(args(i).pos,
+ "attribute argument needs to be a constant; found: " + args(i) + " " + args(i).getClass());
+ }
+ i = i + 1
+ }
+ infos
+ }
+
+ val attr1 = transform(attr, CONSTRmode, definitions.ATTRIBUTE_TYPE());
+ val res = transform(definition);
+ val defsym = res.symbol();
+ var attrs = global.mapSymbolAttr.get(defsym).asInstanceOf[List[AttrInfo]];
+ if (attrs == null) attrs = List();
+ global.mapSymbolAttr.put(defsym, attrInfo(attr1) :: attrs);
+ res
+
+ case Tree.DocDef(comment, definition) =>
+ transform(definition)
+
+ case Tree.PackageDef(pkg, templ @ Tree.Template(parents, body)) =>
+ val pkgSym: Symbol = pkg.symbol();
+ if (pkgSym != null && pkgSym.isPackage()) {
+ val prevContext = pushContext(templ, pkgSym.moduleClass(), pkgSym.members());
+ val body1: Array[Tree] = transform(body);
+ context = prevContext;
+ val templ1: Tree.Template = copy.Template(templ, parents, body1);
+ templ1.setType(Type.NoType).setSymbol(Symbol.NONE);
+ copy.PackageDef(tree, pkg, templ1)
+ .setType(Type.NoType);
+ } else {
+ setError(tree);
+ }
+
+ case Tree.PackageDef(_, _) =>
+ setError(tree)
+
+ case Tree.ClassDef(_, _, tparams, vparams, tpe, templ) =>
+ val prevContext = pushContext(
+ tree, sym.primaryConstructor(), new Scope(context.scope));
+ reenterParams(tparams, vparams, sym.primaryConstructor().getType());
+ val tparams1 = transform(tparams);
+ val vparams1 = transform(vparams);
+ checkNoEscapeParams(vparams1);
+ val tpe1: Tree = transform(tpe, TYPEmode);
+ if (vparams.length > 0 && templ.getType() == null)
+ templ.body = desugarize.addParamAccessors(
+ templ.body, vparams(vparams.length - 1));
+
+ val templ1: Tree.Template = transformTemplate(templ, sym);
+ if (sym.isTrait()) checkTraitDef(tree.pos, sym, templ1);
+ checkNoEscape(tree.pos, sym.info());
+ context = prevContext;
+ copy.ClassDef(tree, sym, tparams1, vparams1, tpe1, templ1)
+ .setType(Type.NoType);
+
+ case Tree.ModuleDef(_, _, tpe, templ) =>
+ val clazz = sym.moduleClass();
+ clazz.initialize();
+ val prevContext = pushContext(
+ tree, clazz.primaryConstructor(), context.scope);
+ val tpe1: Tree = transform(tpe, TYPEmode);
+ context = prevContext;
+ val templ1: Tree.Template = transformTemplate(templ, sym.moduleClass());
+ if (tpe1 != Tree.Empty && !templ1.getType().isSubType(tpe1.getType()))
+ error(tree.pos, "" + sym + " does not implement " + tpe1.getType());
+
+ val lclass = sym.linkedClass();
+ // Taken from SymbolLoader.initializeRoot()
+ if (lclass != null) {
+ if (lclass.rawInfo().isInstanceOf[SymbolLoader]) {
+ lclass.setInfo(Type.ErrorType);
+ val allConstr = lclass.allConstructors();
+ allConstr.setInfo(Type.ErrorType);
+ allConstr.flags = allConstr.flags | Modifiers.PRIVATE;
+ }
+ }
+
+ copy.ModuleDef(tree, sym, tpe, templ1)
+ .setType(Type.NoType);
+
+ case Tree.DefDef(_, name, tparams, vparams, tpe, rhs) =>
+ val prevContext = pushContext(tree, sym, new Scope(context.scope));
+ reenterParams(tparams, vparams, sym.getType());
+ if (name == Names.CONSTRUCTOR) {
+ val enclClass = context.enclClass.owner;
+ enclClass.flags =
+ enclClass.flags | INCONSTRUCTOR;
+ enclClass.primaryConstructor().flags =
+ enclClass.primaryConstructor().flags | INCONSTRUCTOR;
+ }
+ val tparams1 = transform(tparams);
+ val vparams1 = transform(vparams);
+ checkNoEscapeParams(vparams1);
+ val tpe1: Tree =
+ if (tpe == Tree.Empty) gen.mkType(tree.pos, sym.getType().resultType())
+ else transform(tpe, TYPEmode);
+ var rhs1: Tree =
+ if (rhs == Tree.Empty) rhs
+ else transform(
+ rhs,
+ if (name == Names.CONSTRUCTOR) CONSTRmode else EXPRmode,
+ if (name == Names.CONSTRUCTOR) definitions.void_TYPE() else tpe1.getType());
+ context = prevContext;
+ if (name == Names.CONSTRUCTOR) {
+ val enclClass = context.enclClass.owner;
+ enclClass.flags =
+ enclClass.flags & ~ INCONSTRUCTOR;
+ enclClass.primaryConstructor().flags =
+ enclClass.primaryConstructor().flags & ~ INCONSTRUCTOR;
+ }
+ sym.flags = sym.flags | LOCKED;
+ checkNonCyclic(tree.pos, tpe1.getType());
+ sym.flags = sym.flags & ~LOCKED;
+ copy.DefDef(tree, sym, tparams1, vparams1, tpe1, rhs1)
+ .setType(Type.NoType);
+
+ case Tree.ValDef(_, _, tpe, rhs) =>
+ assert(sym != null, tree);
+ val tpe1: Tree =
+ if (tpe == Tree.Empty) gen.mkType(tree.pos, sym.getType())
+ else transform(tpe, TYPEmode);
+ var rhs1: Tree = rhs;
+ if (rhs != Tree.Empty) {
+ val prevContext = pushContext(tree, sym, context.scope);
+ rhs1 = transform(rhs, EXPRmode, tpe1.getType());
+ context = prevContext;
+ } else if ((sym.flags & (MUTABLE | DEFERRED)) == MUTABLE) {
+ rhs1 = gen.mkDefaultValue(tree.pos, sym.getType());
+ }
+ sym.flags = sym.flags | LOCKED;
+ checkNonCyclic(tree.pos, tpe1.getType());
+ sym.flags = sym.flags & ~LOCKED;
+ copy.ValDef(tree, sym, tpe1, rhs1)
+ .setType(Type.NoType);
+
+ case Tree.AbsTypeDef(_, _, rhs, lobound) =>
+ val rhs1: Tree = transform(rhs, TYPEmode);
+ val lobound1: Tree = transform(lobound, TYPEmode);
+ checkNonCyclic(tree.pos, sym.getType());
+ copy.AbsTypeDef(tree, sym, rhs1, lobound1)
+ .setType(Type.NoType);
+
+ case Tree.AliasTypeDef(_, _, tparams, rhs) =>
+ val prevContext = pushContext(tree, sym.primaryConstructor(), new Scope(context.scope));
+ reenterParams(tparams, sym.typeParams());
+ val tparams1 = transform(tparams);
+ val rhs1: Tree = transform(rhs, TYPEmode);
+ context = prevContext;
+ checkNonCyclic(tree.pos, sym.getType());
+ copy.AliasTypeDef(tree, sym, tparams1, rhs1)
+ .setType(Type.NoType);
+
+ case Tree.Import(expr, selectors) =>
+ pushContext(tree, context.owner, context.scope);
+ Tree.Empty
+/*
+
+ case _ =>
+ transform1(tree, sym)
+ }
+ }
+
+ // extracted from transform0 to avoid overflows in GenJVM
+ private def transform1(tree: Tree, sym: Symbol): Tree = {
+
+ tree match {
+*/
+ case Tree.Block(stats, value) =>
+ val prevContext = pushContext(tree, context.owner, new Scope(context.scope));
+ val newContext = context;
+ val stats1 = desugarize.Statements(unit, stats, true);
+ enterSyms(stats1);
+ context = newContext;
+ val curmode: int = mode;
+ var start: Int = 0;
+ var valuemode: Int = curmode;
+ if ((curmode & CONSTRmode) != 0) {
+ stats1(0) = transform(stats1(0), curmode, pt);
+ context.enclClass.owner.flags = context.enclClass.owner.flags & ~INCONSTRUCTOR;
+ start = 1;
+ valuemode = (curmode & ~CONSTRmode) | EXPRmode;
+ }
+ var i = start; while (i < stats1.length) {
+ stats1(i) = transform(stats1(i), EXPRmode);
+ i = i + 1
+ }
+ val value1: Tree = transform(value, valuemode & ~(FUNmode | QUALmode), pt);
+ val owntype: Type =
+ checkNoEscape(tree.pos, value1.getType().deconst());
+ context = prevContext;
+ copy.Block(tree, stats1, value1)
+ .setType(owntype);
+
+ case Tree.Sequence(trees) =>
+ var i = 0; while (i < trees.length) {
+ trees(i) = transform(trees(i),
+ this.mode | SEQUENCEmode,
+ pt);
+ i = i + 1
+ }
+ copy.Sequence(tree, trees).setType(pt);
+
+ case Tree.Alternative(choices) =>
+ val save: boolean = this.inAlternative;
+ this.inAlternative = true;
+
+ val newts = new Array[Tree](choices.length);
+ var i = 0; while (i < choices.length) {
+ newts(i) = transform(choices(i), this.mode, pt);
+ i = i + 1
+ }
+
+ //val tpe: Type = Type.lub(Tree.typeOf(newts));
+
+ this.inAlternative = save;
+ copy.Alternative(tree, newts).setType(pt);
+
+ case Tree.Bind(name, body) =>
+ var vble: Symbol = null;
+ if(name != Names.PATTERN_WILDCARD) {
+ vble = context.owner.newPatternVariable(tree.pos, name).setType(pt);
+ enterInScope(vble);
+ //System.out.println("Bind("+name+",...) enters in scope:"+Debug.show(vble));
+
+ patternVars.put(vble, new Boolean(this.inAlternative));
+ //System.out.println("case Bind.. put symbol vble="+vble+" in scope and patternVars.");
+ }
+ val body1: Tree = transform(body);
+ if(name == Names.PATTERN_WILDCARD) body1
+ else {
+ //assert body1.getType() != null;
+ if(TreeInfo.isSequenceValued(body1)) {
+ vble.setType(definitions.LIST_TYPE(pt));
+ } else {
+ vble.setType(body1.getType());
+ }
+ copy.Bind(tree, name, body1)
+ .setSymbol(vble).setType(body1.getType());
+ }
+
+ case Tree.Visitor(cases) =>
+ if (pt.symbol().isSubClass(definitions.PARTIALFUNCTION_CLASS)) {
+ val pft: Type = pt.baseType(definitions.PARTIALFUNCTION_CLASS);
+ val pftargs = pft.typeArgs();
+ if (pftargs.length == 2 && infer.isFullyDefined(pftargs(0))) {
+ val pattype: Type = pftargs(0);
+ var restype: Type = pftargs(1);
+ val isDefinedAtVisitor: Tree = transformVisitor(
+ desugarize.isDefinedAtVisitor(tree),
+ pattype, definitions.boolean_TYPE());
+ val applyVisitor: Tree = transformVisitor(tree, pattype, restype);
+ if (!infer.isFullyDefined(restype))
+ restype = applyVisitor.getType().deconst();
+ loadMixinCode(tree.pos, definitions.PARTIALFUNCTION_CLASS);
+ gen.mkPartialFunction(
+ tree.pos, applyVisitor, isDefinedAtVisitor,
+ pattype, restype, context.owner);
+ } else {
+ error(tree.pos, "expected pattern type of cases could not be determined");
+ errorTermTree(tree)
+ }
+ } else {
+ transform(desugarize.Visitor(unit, tree))
+ }
+
+ case Tree.Assign(Tree.Apply(_, _), _) =>
+ transform(desugarize.Update(tree))
+
+ case Tree.Assign(lhs, rhs) =>
+ val lhs1: Tree = transform(lhs, EXPRmode);
+ val varsym: Symbol = lhs1.symbol();
+ if (isSetterMethod(varsym)) {
+ // todo: change this to require setters in same template
+ transform(desugarize.Assign(tree.pos, lhs, rhs));
+ } else if (varsym != null && (varsym.flags & MUTABLE) != 0) {
+ val rhs1: Tree = transform(rhs, EXPRmode, lhs1.getType());
+ copy.Assign(tree, lhs1, rhs1)
+ .setType(definitions.void_TYPE());
+ } else {
+ if (!lhs1.getType().isError())
+ error(tree.pos, "assignment to non-variable ");
+ gen.mkUnitLit(tree.pos)
+ }
+
+ case Tree.If(cond, thenp, elsep) =>
+ val cond1: Tree = transform(cond, EXPRmode, definitions.boolean_TYPE());
+ var thenp1: Tree = _;
+ var elsep1: Tree = _;
+ if (elsep == Tree.Empty) {
+ thenp1 = transform(thenp, EXPRmode, definitions.void_TYPE());
+ elsep1 = gen.mkUnitLit(tree.pos);
+ } else {
+ thenp1 = transform(thenp, EXPRmode, pt);
+ elsep1 = transform(elsep, EXPRmode, pt);
+ }
+ copy.If(tree, cond1, thenp1, elsep1)
+ .setType(Type.lub(NewArray.Type(thenp1.getType(), elsep1.getType())));
+
+ case Tree.Throw(expr) =>
+ val expr1: Tree = transform(
+ expr, EXPRmode, definitions.THROWABLE_TYPE());
+ gen.Select(tree.pos, expr1, definitions.THROWABLE_THROW);
+
+ case Tree.Return(expr) =>
+ if (!context.owner.isInitialized()) {
+ error(tree.pos, "method with return needs result type");
+ errorTermTree(tree)
+ } else {
+ val enclFun: Symbol = context.owner.enclMethod();
+ if (enclFun.kind == VAL && !enclFun.isConstructor()) {
+ val expr1: Tree = transform(
+ expr, EXPRmode, enclFun.getType().resultType());
+ copy.Return(tree, expr1)
+ .setSymbol(enclFun).setType(definitions.ALL_TYPE());
+ } else {
+ error(tree.pos, "return outside method definition");
+ errorTermTree(tree)
+ }
+ }
+
+ case Tree.New(init) =>
+ val init1: Tree = transform(init, CONSTRmode, pt);
+ checkInstantiatable(tree.pos, init1.getType());
+ val tree1 = gen.New(tree.pos, init1);
+ val clazz = tree1.getType().symbol();
+ if (clazz.isAnonymousClass()) {
+ val parentTypes = clazz.info().parents();
+ val refinement: Scope = new Scope();
+ val base: Type = Type.compoundTypeWithOwner(context.enclClass.owner, parentTypes, Scope.EMPTY);
+ val it: Scope$SymbolIterator = clazz.members().iterator();
+ while (it.hasNext()) {
+ val sym1: Symbol = it.next();
+ val basesym1: Symbol = base.lookupNonPrivate(sym1.name);
+ if (!basesym1.isNone() &&
+ sym1.kind != VAL && // todo: remove once refinements work!
+ !base.symbol().thisType().memberType(basesym1)
+ .isSameAs(sym1.getType()))
+ refinement.enter(sym1);
+ }
+ val owntype =
+ if (refinement.isEmpty() && parentTypes.length == 1)
+ parentTypes(0)
+ else
+ checkNoEscape(
+ tree.pos,
+ Type.compoundTypeWithOwner(
+ context.enclClass.owner, parentTypes, refinement));
+ gen.Typed(tree1, owntype)
+ } else
+ tree1
+
+ case Tree.Typed(expr, tpe) =>
+ expr match {
+ case Tree.Ident(n)
+ if (n != Names.PATTERN_WILDCARD && (mode & PATTERNmode) != 0) =>
+ transform(desugarize.TypedPattern(tree.asInstanceOf[Tree.Typed]),
+ mode,
+ pt);
+ case _ =>
+ var expr1: Tree = _;
+ var tpe1: Tree = _;
+ tpe match {
+ case Tree.Ident(TypeNames.WILDCARD_STAR) =>
+ expr1 = transform(
+ expr, mode & baseModes, definitions.SEQ_TYPE(pt));
+ val elemtps =
+ expr1.getType().baseType(definitions.SEQ_CLASS).typeArgs();
+ val elemtp: Type = if (elemtps.length == 1) elemtps(0)
+ else Type.ErrorType;
+
+ tpe1 = tpe.setType(elemtp);
+ case _ =>
+ tpe1 = transform(tpe, TYPEmode);
+ expr1 = transform(expr, mode & baseModes, tpe1.getType());
+ }
+ copy.Typed(tree, expr1, tpe1).setType(tpe1.getType())
+ }
+
+ case Tree.Function(vparams, body) =>
+ val prevContext = pushContext(tree, context.owner, new Scope(context.scope));
+ var restype: Type = desugarize.preFunction(vparams, pt);
+ enterParams(vparams);
+ val vparams1 = transform(vparams);
+ val body1: Tree = transform(body, EXPRmode, restype);
+ if (!infer.isFullyDefined(restype))
+ restype = body1.getType().deconst();
+ restype = checkNoEscape(tree.pos, restype);
+ context = prevContext;
+ gen.mkFunction(tree.pos, vparams1, body1, restype, context.owner, false);
+
+ case Tree.TypeApply(fn, args) =>
+
+ val fn1: Tree = transform(
+ fn, (mode & (EXPRmode | CONSTRmode)) | FUNmode, Type.AnyType);
+ val args1 = transform(args, TYPEmode);
+ val argtypes = Tree.typeOf(args1);
+
+ // propagate errors in arguments
+ var i = 0;
+ while (i < argtypes.length && !argtypes(i).isError())
+ i = i + 1;
+ if (i < argtypes.length)
+ setError(tree);
+ else {
+
+ // resolve overloading
+ fn1.getType() match {
+ case Type$OverloadedType(alts, alttypes) =>
+ try {
+ infer.polyAlternative(fn1, alts, alttypes, args.length);
+ } catch {
+ case ex: Type$Error => reportTypeError(tree.pos, ex);
+ }
+ case _ =>
+ }
+
+ // match against arguments
+ fn1.getType() match {
+ case Type$PolyType(tparams, restp) if (tparams.length == argtypes.length) =>
+ constfold.tryToFold(
+ infer.completeTypeApply(
+ copy.TypeApply(tree, fn1, args1)
+ .setType(restp.subst(tparams, argtypes))));
+
+ case Type.ErrorType =>
+ setError(tree)
+
+ case fn1tp =>
+ if (!fn1tp.isError()) error(tree.pos,
+ infer.toString(fn1.symbol(), fn1.getType()) +
+ " cannot be applied to " +
+ ArrayApply.toString(
+ argtypes.asInstanceOf[Array[Object]], "(", ",", ")"));
+ errorTermTree(tree)
+ }
+ }
+
+ case Tree.Apply(fn, args) =>
+ mode = mode & ~SEQUENCEmode;
+ var fn1: Tree = _;
+ var argMode: int = _;
+ var selfcc: boolean = false;
+ //todo: Should we pass in both cases a methodtype with
+ // AnyType's for args as a prototype?
+ if ((mode & EXPRmode) != 0) {
+ fn1 = transform(fn, mode | FUNmode, Type.AnyType);
+ argMode = EXPRmode;
+ } else if ((mode & PATTERNmode) != 0) {
+ fn1 = transform(fn, mode | FUNmode, pt);
+ argMode = PATTERNmode;
+ } else {
+ assert((mode & CONSTRmode) != 0);
+ fn1 = transform(fn, mode | FUNmode, Type.AnyType);
+ argMode = EXPRmode;
+
+ // convert type to constructor
+ val tsym: Symbol = TreeInfo.methSymbol(fn1);
+ if (!tsym.isError()) {
+ assert(tsym.isType(), tsym);
+ fn1.getType().withDefaultArgs().unalias() match {
+ case Type$TypeRef(pre, c, argtypes) =>
+ if (c.kind != CLASS) {
+ error(tree.pos,
+ "" + tsym + " is not a class; cannot be instantiated");
+ } else if (!pre.isStable()) {
+ error(tree.pos, "" + pre + " is not a legal prefix for a constructor");
+ } else {
+ c.initialize();
+ val constr: Symbol = c.allConstructors();
+ val fn0: Tree = fn1;
+ fn1 = gen.mkRef(fn1.pos, pre, constr);
+ var enclClassOrConstructorContext = Context.NONE;
+ if (constr.owner().isPackageClass()) {
+ var c = context;
+ while (c != Context.NONE &&
+ !c.tree.isInstanceOf[Tree.ClassDef] &&
+ !c.tree.isInstanceOf[Tree.ModuleDef] &&
+ !c.tree.isInstanceOf[Tree.Template])
+ c = c.outer;
+ enclClassOrConstructorContext = c
+ }
+ if (enclClassOrConstructorContext == Context.NONE) {
+ fn1 match {
+ case Tree.Select(fn1qual, _) =>
+ fn1.setType(infer.checkAccessible(
+ fn1.pos, constr, fn1.getType(), fn1qual, fn1qual.getType()));
+ case _ =>
+ if (constr.owner().isPackageClass())
+ fn1.setType(infer.checkAccessible(
+ fn1.pos, constr, fn1.getType(), Tree.Empty, constr.owner().getType()));
+ }
+ } else {
+ val cowner = enclClassOrConstructorContext.owner;
+ if (cowner.isConstructor())
+ // we are in a superclass constructor call
+ fn1.setType(
+ infer.checkAccessible(
+ fn1.pos, constr, fn1.getType(),
+ make.Super(tree.pos,
+ Names.EMPTY.toTypeName(),
+ Names.EMPTY.toTypeName()),
+ cowner.constructorClass().typeConstructor()));
+ else
+ fn1.setType(infer.checkAccessible(
+ fn1.pos, constr, fn1.getType(),
+ enclClassOrConstructorContext.tree,
+ cowner.typeConstructor()));
+ }
+ if (tsym == c) {
+ fn0 match {
+ case Tree.AppliedType(_, targs) =>
+ fn1 = infer.completeTypeApply(gen.TypeApply(fn1, targs));
+ case _ =>
+ }
+ } else {
+ // it was an alias type
+ // todo: handle overloaded constructors
+ if (argtypes.length != 0)
+ fn1 = gen.TypeApply(
+ fn1, gen.mkTypes(fn1.pos, argtypes));
+ if (tsym.typeParams().length != 0 &&
+ !(fn0.isInstanceOf[Tree.AppliedType]))
+ fn1.setType(new Type$PolyType(
+ tsym.typeParams(), fn1.getType()));
+ }
+ //System.out.println(TreeInfo.methSymbol(fn1) + ":" + tp + " --> " + fn1.getType() + " of " + fn1);//DEBUG
+ selfcc = TreeInfo.isSelfConstrCall(fn0);
+ }
+
+ case _ =>
+ error(tree.pos,
+ "" + tsym + " is not a class; cannot be instantiated");
+ }
+ }
+ }
+
+ // if function is overloaded with one alternative
+ // whose arity matches argument length and whose result type matches prototype,
+ // preselect this alternative.
+ fn1.getType() match {
+ case Type$OverloadedType(alts, alttypes) =>
+ val argtypes = new Array[Type](args.length);
+ { var i = 0; while (i < argtypes.length) {
+ argtypes(i) = definitions.ALL_TYPE(); i = i + 1
+ }}
+ var matching1: int = -1;
+ var matching2: int = -1;
+ { var i = 0; while (i < alttypes.length) {
+ if (infer.isApplicable(alttypes(i), argtypes, pt)) {
+ //System.out.println("matches: " + alttypes(i) + " with " + pt);//debug
+ matching2 = matching1;
+ matching1 = i;
+ }
+ i = i + 1;
+ }}
+ if (matching1 >= 0 && matching2 < 0) {
+ fn1.setSymbol(alts(matching1)).setType(alttypes(matching1));
+ }
+ case _ =>
+ }
+
+ def handleApply: Tree = {
+ // handle the case of application of match to a visitor specially
+ if (args.length == 1 && args(0).isInstanceOf[Tree.Visitor]) {
+ val pattp: Type = matchQualType(fn1);
+ if (pattp.isError()) {
+ return setError(tree)
+ } else if (pattp != Type.NoType) {
+ if (infer.isFullyDefined(pattp) &&
+ !(fn1.getType().isInstanceOf[Type$PolyType] &&
+ pattp.containsSome(fn1.getType().typeParams()))) {
+ val fn2: Tree = desugarize.postMatch(fn1, context.enclClass.owner);
+ val arg1: Tree = transformVisitor(args(0), pattp, pt);
+ return copy.Apply(tree, fn2, NewArray.Tree(arg1))
+ .setType(arg1.getType());
+ } else {
+ error(tree.pos, "expected pattern type of cases could not be determined");
+ return errorTermTree(tree)
+ }
+ }
+ }
+
+ // return prematurely if function is a superclass constructor
+ // and no type arguments need to be inferred.
+ if ((mode & SUPERmode) != 0 && fn1.getType().isInstanceOf[Type$MethodType]) {
+ return copy.Apply(tree, fn1, args).setType(fn1.getType().resultType()) : Tree;
+ }
+
+ // type arguments with formals as prototypes if they exist.
+ fn1.setType(infer.freshInstance(fn1.getType()));
+ val argtypes = transformArgs(
+ tree.pos, fn1.symbol(), Symbol.EMPTY_ARRAY, fn1.getType(), argMode, args, pt);
+
+ if (argtypes == null)
+ return setError(tree)
+ else {
+ var i: int = 0;
+ while (i < argtypes.length && !argtypes(i).isError())
+ i = i + 1;
+ if (i < argtypes.length) return setError(tree);
+ }
+
+ // resolve overloading1g
+ fn1.getType() match {
+ case Type$OverloadedType(alts, alttypes) =>
+ try {
+ infer.methodAlternative(fn1, alts, alttypes, argtypes, pt);
+ } catch {
+ case ex: Type$Error => reportTypeError(tree.pos, ex);
+ }
+ case _ =>
+ }
+
+ // check that self constructors go backwards.
+ if (selfcc) {
+ val constr: Symbol = TreeInfo.methSymbol(fn1);
+ if (constr != null && constr.kind == VAL &&
+ !(constr.getType().isInstanceOf[Type$OverloadedType]) &&
+ constr.pos > tree.pos)
+ error(tree.pos,
+ "illegal forward reference to self constructor");
+ }
+
+ fn1.getType() match {
+ case Type$PolyType(tparams, restp) =>
+ // if method is polymorphic,
+ // infer instance, and adapt arguments to instantiated formals
+ try {
+ fn1 = infer.methodInstance(fn1, tparams, restp, argtypes, pt);
+ //System.out.println(fn1 + ":" + fn1.getType());//DEBUG
+ } catch {
+ case ex: Type$Error =>
+ //ex.printStackTrace();//DEBUG
+ reportTypeError(tree.pos, ex);
+ }
+ case _ =>
+ }
+
+ fn1.getType() match {
+ case Type$MethodType(params, restp) =>
+ if ((mode & PATTERNmode) != 0) {
+ return copy.Apply(tree, fn1, args).setType(restp);
+ } else {
+ val formals = infer.formalTypes(params, args.length);
+ if (formals.length == args.length) {
+ var i = 0; while (i < args.length) {
+ args(i) = adapt(args(i), argMode, formals(i));
+ args(i) match {
+ case Tree.Typed( arg, Tree.Ident( TypeNames.WILDCARD_STAR ) ) =>
+ if( i != args.length - 1 ) {
+ error( arg.pos, "escape only allowed in last position");
+ } else if ( args.length > params.length ) {
+ error( arg.pos, "escaping cannot be mixed with values");
+ }
+ case _ => /* nop */
+ }
+ i = i + 1
+ }
+ }
+ return constfold.tryToFold(
+ copy.Apply(tree, fn1, args)
+ .setType(restp));
+ }
+
+ case _ =>
+ }
+
+ if (!fn1.getType().isError())
+ error(
+ tree.pos,
+ infer.applyErrorMsg(
+ "", fn1, " cannot be applied to ", argtypes, pt));
+ errorTermTree(tree)
+ }
+
+ handleApply
+
+ case Tree.Super(qualifier, mixin) =>
+ val clazz: Symbol = qualifyingClass(tree, qualifier);
+ if (clazz.isNone()) {
+ setError(tree);
+ } else {
+ tree.setSymbol(clazz);
+ val parents = clazz.parents();
+ if (mixin == TypeNames.EMPTY) {
+ tree.setType(parents(0).instanceType());
+ } else {
+ var i = 0;
+ while (i < parents.length && parents(i).symbol().name != mixin)
+ i = i + 1;
+ if (i < parents.length)
+ tree.setType(parents(i).instanceType());
+ else {
+ error(tree.pos,
+ "" + mixin + " does not name a mixin base class of " + clazz);
+ errorTermTree(tree)
+ }
+ }
+ }
+
+ case Tree.This(name) =>
+ val clazz: Symbol = qualifyingClass(tree, name);
+ if (clazz.isNone())
+ setError(tree)
+ else {
+ tree.setSymbol(clazz);
+ tree.setType(
+ if (pt != null && pt.isStable() || (mode & QUALmode) != 0) clazz.thisType()
+ else clazz.typeOfThis());
+ }
+
+ case Tree.Select(qual, name) =>
+ val qualmode: int = if (name == Names._match) EXPRmode
+ else EXPRmode | POLYmode | QUALmode;
+ var qual1: Tree = transform(qual, qualmode);
+ if (name.isTypeName())
+ qual1 = checkStable(qual1);
+ transformSelect(
+ tree, adapt(qual1, qualmode, Type.AnyType), name);
+
+ case Tree.Ident(name) =>
+ if (name == Names.CONSTRUCTOR) {
+ assert((mode & CONSTRmode) != 0, tree);
+ copy.Ident(tree, context.enclClass.owner)
+ .setType(context.enclClass.owner.getType());
+ } else if (((mode & (PATTERNmode | FUNmode)) == PATTERNmode) && name.isVariable()) {
+ var vble: Symbol = null;
+ var vble2: Symbol = null;
+
+ // if vble is bound with @, there is already a symbol
+ if (name != Names.PATTERN_WILDCARD) {
+ vble2 = context.scope.lookup(name);
+ }
+ var tree1 = tree;
+ if (patternVars.containsKey(vble2))
+ vble = vble2;
+ else {
+ vble =
+ if (name == Names.PATTERN_WILDCARD)
+ definitions.PATTERN_WILDCARD
+ else context.owner.newPatternVariable(tree.pos, name).setType(pt);
+ //if(((mode & SEQUENCEmode) != 0)&&(name != Names.PATTERN_WILDCARD)) {
+ if(name != Names.PATTERN_WILDCARD) {
+ // x => x @ _ in sequence patterns
+ tree1 = desugarize.IdentPattern(tree);
+ }
+ }
+ if (name != Names.PATTERN_WILDCARD) enterInScope(vble);
+ tree1.setSymbol(vble).setType(pt);
+ } else {
+ transformIdent(tree, name)
+ }
+
+ case Tree.Literal(value) =>
+ tree.setType(Type.constantType(value))
+
+ case Tree.LabelDef(name, params, body) =>
+ assert(params.length == 0);
+ val prevContext = pushContext(tree, context.owner, new Scope(context.scope));
+ val lsym: Symbol = context.owner.newLabel(tree.pos, name);
+ lsym.setInfo(
+ new Type$MethodType(Symbol.EMPTY_ARRAY, definitions.void_TYPE()));
+ context.scope.enter(lsym);
+ val body1: Tree = transform(body, mode, pt);
+ context = prevContext;
+ copy.LabelDef(tree, lsym, params, body1)
+ .setSymbol(lsym).setType(definitions.void_TYPE());
+
+ case Tree.TypeTerm() =>
+ tree
+
+ case Tree.SingletonType(ref) =>
+ val ref1: Tree = checkStable(
+ transform(ref, EXPRmode | QUALmode, definitions.ANYREF_TYPE()));
+ copy.SingletonType(tree, ref1)
+ .setType(ref1.getType().resultType());
+
+ case Tree.SelectFromType(qual, name) =>
+ val qual1: Tree = transform(qual, TYPEmode);
+ transformSelect(tree, qual1, name);
+
+ case Tree.CompoundType(parents, refinements) =>
+ val parents1 = transform(parents, TYPEmode);
+ val ptypes = new Array[Type](parents1.length);
+ { var i = 0; while (i < parents1.length) {
+ val tp = parents(i).getType();
+ if (i > 0 || tp.unalias().symbol().kind != TYPE)
+ checkClassType(parents(i).pos, tp);
+ ptypes(i) = tp;
+ i = i + 1
+ }}
+ val members: Scope = new Scope();
+ val cowner =
+ if (context.owner.isPrimaryConstructor() && context.owner.owner().isPackageClass())
+ context.owner.constructorClass()
+ else context.enclClass.owner;
+ val self: Type = Type.compoundTypeWithOwner(cowner, ptypes, members);
+ val clazz: Symbol = self.symbol();
+ val prevContext = pushContext(tree, clazz, members);
+ { var i = 0; while (i < refinements.length) {
+ val m = enterSym(refinements(i));
+ m.flags = m.flags | OVERRIDE;
+ i = i + 1
+ }}
+ val refinements1 = transformStatSeq(refinements, Symbol.NONE);
+ context = prevContext;
+ copy.CompoundType(tree, parents1, refinements1)
+ .setType(self)
+
+ case Tree.AppliedType(tpe, args) =>
+ val tpe1: Tree = transform(tpe, mode | FUNmode);
+ val args1 = transform(args, TYPEmode);
+ val argtypes = Tree.typeOf(args);
+ val tparams = tpe1.getType().symbol().typeParams();
+ var owntype: Type = Type.ErrorType;
+ if (!tpe1.getType().isError()) {
+ if (tparams.length == args.length)
+ owntype = Type.appliedType(tpe1.getType(), argtypes);
+ else if (tparams.length == 0)
+ error(tree.pos, "" + tpe1.getType() + " does not take type parameters");
+ else
+ error(tree.pos, "wrong number of type arguments for " +
+ tpe1.getType());
+ }
+ copy.AppliedType(tree, tpe1, args1).setType(owntype);
+
+ case Tree.FunType(_, _) =>
+ transform(desugarize.FunType(tree))
+
+ case _ =>
+ throw new ApplicationError("illegal tree: " + tree)
+ }
+ } catch {
+ case ex: Type$Error =>
+ reportTypeError(tree.pos, ex);
+ errorTree(tree)
+ }
+ }
+}
+}
+
+// LocalWords: SOcos
diff --git a/sources/scala/tools/nsc/util/CharArrayReader.scala b/sources/scala/tools/nsc/util/CharArrayReader.scala
new file mode 100644
index 0000000000..c8202aaa7a
--- /dev/null
+++ b/sources/scala/tools/nsc/util/CharArrayReader.scala
@@ -0,0 +1,82 @@
+package scala.tools.nsc.util;
+
+import scala.tools.util.SourceFile.{LF, FF, CR, SU}
+
+class CharArrayReader(buf: Array[char], start: int, startline: int, startcol: int,
+ decodeUni: boolean, error: String => unit) {
+
+ def this(buf: Array[char], decodeUni: boolean, error: String => unit) =
+ this(buf, 0, 1, 1, decodeUni, error);
+
+ /** layout constant
+ */
+ val tabinc = 8;
+
+ /** the line and column position of the current character
+ */
+ var ch: char = _;
+ var bp = start;
+ var cline: int = _;
+ var ccol: int = _;
+ private var nextline = startline;
+ private var nextcol = startcol;
+
+ def hasNext: boolean = bp < buf.length;
+
+ def next: unit = {
+ cline = nextline;
+ ccol = nextcol;
+ ch = buf(bp);
+ bp = bp + 1;
+ ch match {
+ case '\t' =>
+ nextcol = ((nextcol - 1) / tabinc * tabinc) + tabinc + 1;
+ case CR =>
+ nextline = nextline + 1;
+ nextcol = 1;
+ if (buf(bp) == LF) {
+ ch = LF;
+ bp = bp + 1
+ }
+ case LF | FF =>
+ nextline = nextline + 1;
+ nextcol = 1
+ case '\\' =>
+ def evenSlashPrefix: boolean = {
+ var p = bp - 2;
+ while (p >= 0 && buf(p) == '\\') p = p - 1;
+ p % 2 == 0
+ }
+ def udigit: int = {
+ val d = digit2int(buf(bp), 16);
+ if (d >= 0) { bp = bp + 1; nextcol = nextcol + 1 }
+ else error("error in unicode escape");
+ d
+ }
+ nextcol = nextcol + 1;
+ if (buf(bp) == 'u' && decodeUni && evenSlashPrefix) {
+ do {
+ bp = bp + 1; nextcol = nextcol + 1;
+ } while (buf(bp) == 'u');
+ val code = udigit << 12 | udigit << 8 | udigit << 4 | udigit;
+ ch = code.asInstanceOf[char]
+ }
+ case _ =>
+ nextcol = nextcol + 1
+ }
+ }
+
+ def copy: CharArrayReader =
+ new CharArrayReader(buf, bp, nextcol, nextline, decodeUni, error);
+
+ def digit2int(ch: char, base: int): int = {
+ if ('0' <= ch && ch <= '9' && ch < '0' + base)
+ ch - '0'
+ else if ('A' <= ch && ch < 'A' + base - 10)
+ ch - 'A' + 10
+ else if ('a' <= ch && ch < 'a' + base - 10)
+ ch - 'a' + 10
+ else
+ -1
+ }
+}
diff --git a/sources/scala/tools/nsc/util/FreshNameCreator.scala b/sources/scala/tools/nsc/util/FreshNameCreator.scala
new file mode 100644
index 0000000000..ece9f8e05d
--- /dev/null
+++ b/sources/scala/tools/nsc/util/FreshNameCreator.scala
@@ -0,0 +1,28 @@
+package scala.tools.nsc.util;
+
+import scala.collection.mutable.HashMap;
+
+class FreshNameCreator {
+
+ protected var counter = 0;
+ protected val counters = new HashMap[String,int];
+
+ /**
+ * Create a fresh name with the given prefix. It is guaranteed
+ * that the returned name has never been returned by a previous
+ * call to this function (provided the prefix does not end in a digit).
+ */
+ def newName(prefix: String): String = {
+ val count = counters.get(prefix) match {
+ case Some(last) => last + 1
+ case None => 0
+ }
+ counters.update(prefix, count);
+ prefix + count
+ }
+
+ def newName(): String = {
+ counter = counter + 1;
+ "$" + counter + "$"
+ }
+}
diff --git a/sources/scala/tools/nsc/util/NameTransformer.scala b/sources/scala/tools/nsc/util/NameTransformer.scala
new file mode 100755
index 0000000000..21f89f3a01
--- /dev/null
+++ b/sources/scala/tools/nsc/util/NameTransformer.scala
@@ -0,0 +1,91 @@
+package scala.tools.nsc.util;
+
+object NameTransformer {
+ private val nops = 128;
+ private val ncodes = 26 * 26;
+
+ private class OpCodes(val op: char, val code: String, val next: OpCodes);
+
+ private val op2code = new Array[String](nops);
+ private val code2op = new Array[OpCodes](ncodes);
+
+ private def enterOp(op: char, code: String) = {
+ op2code(op) = code;
+ val c = (code.charAt(1) - 'a') * 26 + code.charAt(2) - 'a';
+ code2op(c) = new OpCodes(op, code, code2op(c))
+ }
+
+ enterOp('~', "$tilde");
+ enterOp('=', "$eq");
+ enterOp('<', "$less");
+ enterOp('>', "$greater");
+ enterOp('!', "$bang");
+ enterOp('#', "$hash");
+ enterOp('%', "$percent");
+ enterOp('^', "$up");
+ enterOp('&', "$amp");
+ enterOp('|', "$bar");
+ enterOp('*', "$times");
+ enterOp('/', "$div");
+ enterOp('+', "$plus");
+ enterOp('-', "$minus");
+ enterOp(':', "$colon");
+ enterOp('\\', "$bslash");
+
+ /** Replace operator symbols by corresponding "$op_name" */
+ def encode(name: String): String = {
+ var buf: StringBuffer = null;
+ val len = name.length();
+ var i = 0;
+ while (i < len) {
+ val c = name charAt i;
+ if (c < nops && op2code(c) != null) {
+ if (buf == null) {
+ buf = new StringBuffer();
+ buf.append(name.substring(0, i));
+ }
+ buf.append(op2code(c));
+ } else if (buf != null) {
+ buf.append(c)
+ }
+ i = i + 1
+ }
+ if (buf == null) name else buf.toString()
+ }
+
+ /** Replace $op_name by corresponding operator symbol */
+ def decode(name: String): String = {
+ //System.out.println("decode: " + name);//DEBUG
+ var buf: StringBuffer = null;
+ val len = name.length();
+ var i = 0;
+ while (i < len) {
+ var ops: OpCodes = null;
+ val c = name charAt i;
+ if (c == '$' && i + 2 < len) {
+ val ch1 = name.charAt(i+1);
+ if ('a' <= ch1 && ch1 <= 'z') {
+ val ch2 = name.charAt(i+2);
+ if ('a' <= ch2 && ch2 <= 'z') {
+ ops = code2op((ch1 - 'a') * 26 + ch2 - 'a');
+ while (ops != null && !name.startsWith(ops.code, i)) ops = ops.next;
+ if (ops != null) {
+ if (buf == null) {
+ buf = new StringBuffer();
+ buf.append(name.substring(0, i));
+ }
+ buf.append(ops.op);
+ i = i + ops.code.length()
+ }
+ }
+ }
+ }
+ if (ops == null) {
+ if (buf != null) buf.append(c);
+ i = i + 1
+ }
+ }
+ //System.out.println("= " + (if (buf == null) name else buf.toString()));//DEBUG
+ if (buf == null) name else buf.toString()
+ }
+}
diff --git a/sources/scala/tools/util/ConsoleReporter.java b/sources/scala/tools/util/ConsoleReporter.java
index 7abcc06bf9..d7ae018e44 100644
--- a/sources/scala/tools/util/ConsoleReporter.java
+++ b/sources/scala/tools/util/ConsoleReporter.java
@@ -13,8 +13,6 @@ import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintWriter;
-import scala.tools.util.debug.Debug;
-
/**
* This class implements a Reporter that displays messages on a text
* console.
@@ -161,7 +159,7 @@ public class ConsoleReporter extends AbstractReporter {
if ("resume".startsWith(line)) return;
}
} catch (IOException e) {
- Debug.abort("input read error");
+ throw new Error("input read error");
}
}