diff options
author | Martin Odersky <odersky@gmail.com> | 2005-09-13 14:35:48 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2005-09-13 14:35:48 +0000 |
commit | b058c90501ec726024b2af18fd163f01567911aa (patch) | |
tree | 724d395d16ebd2ed1bd1732bcda013e38b37a855 /sources | |
parent | b6f8d5a603fab46e6e8e30fc85a35d36fda6f05e (diff) | |
download | scala-b058c90501ec726024b2af18fd163f01567911aa.tar.gz scala-b058c90501ec726024b2af18fd163f01567911aa.tar.bz2 scala-b058c90501ec726024b2af18fd163f01567911aa.zip |
*** empty log message ***
Diffstat (limited to 'sources')
19 files changed, 1063 insertions, 368 deletions
diff --git a/sources/scala/tools/nsc/Global.scala b/sources/scala/tools/nsc/Global.scala index 4fd39beb89..0a8151e2f4 100755 --- a/sources/scala/tools/nsc/Global.scala +++ b/sources/scala/tools/nsc/Global.scala @@ -61,6 +61,465 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable object checkers extends Checkers { val global: Global.this.type = Global.this } + val icodeChecker = new checkers.ICodeChecker(); + + val copy = new LazyTreeCopier(); + + type AttrInfo = Pair[Type, List[Any]]; + + /** A map from symbols to their attributes */ + val attributes = new HashMap[Symbol, List[AttrInfo]]; + +// reporting ------------------------------------------------------- + + def error(msg: String) = reporter.error(null, msg); + def warning(msg: String) = reporter.warning(null, msg); + private def inform(msg: String) = reporter.info(null, msg, true); + + def informProgress(msg: String) = + if (settings.verbose.value) inform("[" + msg + "]"); + + def informTime(msg: String, start: long) = + informProgress(msg + " in " + (System.currentTimeMillis() - start) + "ms"); + + def log(msg: Object): unit = + if (settings.log contains phase.name) inform("[log " + phase + "] " + msg); + + def abort(msg: String) = throw new Error(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) + } + + object loaders extends SymbolLoaders { + val global: Global.this.type = Global.this + } + + def rootLoader: LazyType = new loaders.PackageLoader(classPath.getRoot()); + +// Phases ------------------------------------------------------------ + + var globalPhase: Phase = NoPhase; + + override def phase_=(p: Phase): unit = { + assert(p.id <= globalPhase.id + 1); + super.phase_=(p) + } + + abstract class GlobalPhase(prev: Phase) extends Phase(prev) { + def run: unit = units foreach applyPhase; + def apply(unit: CompilationUnit): unit; + private val isErased = prev.name == "erasure" || prev.erasedTypes; + override def erasedTypes: boolean = isErased; + private val isFlat = prev.name == "flatten" || prev.flatClasses; + override def flatClasses: boolean = isFlat; + def applyPhase(unit: CompilationUnit): unit = { + if (settings.debug.value) inform("[running phase " + name + " on " + unit + "]"); + apply(unit) + } + } + + object syntaxAnalyzer extends SyntaxAnalyzer { + val global: Global.this.type = Global.this + } + + object analyzer extends Analyzer { + val global: Global.this.type = Global.this; + } + + object pickler extends Pickler { + val global: Global.this.type = Global.this + } + + object syntheticMethods extends SyntheticMethods { + val global: Global.this.type = Global.this + } + + object refchecks extends RefChecks { + val global: Global.this.type = Global.this; + } + + object uncurry extends UnCurry { + val global: Global.this.type = Global.this; + } + + object tailCalls extends TailCalls { + val global: Global.this.type = Global.this; + } + + object transMatcher extends TransMatcher { + val global: Global.this.type = Global.this; + } + + object explicitOuter extends ExplicitOuter { + val global: Global.this.type = Global.this; + } + + object erasure extends Erasure { + val global: Global.this.type = Global.this; + } + + object lambdaLift extends LambdaLift { + val global: Global.this.type = Global.this; + } + + object flatten extends Flatten { + val global: Global.this.type = Global.this; + } + + object constructors extends Constructors { + val global: Global.this.type = Global.this; + } + + object mixin extends Mixin { + val global: Global.this.type = Global.this; + } + + object sampleTransform extends SampleTransform { + val global: Global.this.type = Global.this; + } + + object genicode extends GenICode { + val global: Global.this.type = Global.this; + } + + object icodePrinter extends backend.icode.Printers { + val global: Global.this.type = Global.this; + } + + object scalaPrimitives extends ScalaPrimitives { + val global: Global.this.type = Global.this; + } + + def phaseDescriptors: List[SubComponent] = List( + analyzer.namerFactory, // needs to be first + analyzer.typerFactory, // needs to be second + pickler, + syntheticMethods, + refchecks, + uncurry, + tailCalls, + transMatcher, + explicitOuter, + erasure, + lambdaLift, + flatten, + constructors, + mixin, + if (settings.Xshowicode.value) genicode + else sampleTransform); + + val parserPhase = syntaxAnalyzer.newPhase(NoPhase); + val firstPhase = parserPhase; + phase = parserPhase; + definitions.init; // needs firstPhase and phase to be defined != NoPhase, + // that's why it is placed here. + + private var p = phase; + private var stopped = false; + for (val pd <- phaseDescriptors) { + if (!stopped) { + if (!(settings.skip contains pd.phaseName)) p = pd.newPhase(p); + stopped = settings.stop contains pd.phaseName; + } + } + + val terminalPhase = new GlobalPhase(p) { + def name = "terminal"; + def apply(unit: CompilationUnit): unit = {} + } + + def phaseNamed(name: String): Phase = { + var p: Phase = firstPhase; + while (p.next != p && p.name != name) p = p.next; + if (p.name != name) NoPhase else p + } + + val namerPhase = phaseNamed("namer"); + val typerPhase = phaseNamed("typer"); + val refchecksPhase = phaseNamed("refchecks"); + val erasurePhase = phaseNamed("erasure"); + val flattenPhase = phaseNamed("flatten"); + val delegateMixins = phaseNamed("mixin") != NoPhase; + + val typer = new analyzer.Typer(analyzer.NoContext.make(EmptyTree, definitions.RootClass, new Scope())) { + override def typed(tree: Tree, mode: int, pt: Type): Tree = { + if (settings.debug.value) log("typing [[" + tree + "]]"); + val result = super.typed(tree, mode, pt); + if (settings.debug.value) log(" ==> " + result + ":" + result.tpe); + result + } + } + val infer = typer.infer; + +// 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: Iterator[CompilationUnit] = unitbuf.elements; + + /** 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, PickleBuffer]; + + 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)); + + globalPhase = NoPhase.next; + while (globalPhase != terminalPhase && reporter.errors() == 0) { + val startTime = System.currentTimeMillis(); + phase = globalPhase; + globalPhase.run; + if (settings.print contains globalPhase.name) treePrinter.printAll(); + if (settings.browse contains globalPhase.name) treeBrowser.browse(units); + informTime(globalPhase.description, startTime); + globalPhase = globalPhase.next; + if (settings.check contains globalPhase.name) { + phase = globalPhase; + if (globalPhase.name == "terminal" && settings.Xshowicode.value) + icodeChecker.checkICodes; + else + checker.checkTrees; + } + } + + if (settings.Xshowcls.value != "") showDef(newTermName(settings.Xshowcls.value), false); + if (settings.Xshowobj.value != "") showDef(newTermName(settings.Xshowobj.value), true); + if (settings.Xshowicode.value) printICode(); + + if (reporter.errors() == 0) { + for (val Pair(sym, pickled) <- symData.elements.toList) { + sym.pos = Position.NOPOS; + if (symData contains sym) { + symData -= sym; + symData -= sym.linkedSym; + writeSymblFile(sym, pickled) + } + } + } else { + for (val Pair(sym, file) <- symSource.elements) { + sym.reset(new loaders.SourcefileLoader(file)); + if (sym.isTerm) sym.moduleClass.reset(loaders.errorLoader); + } + } + informTime("total", startTime); + informStatistics; + } + + def compileLate(file: AbstractFile): unit = + if (fileset == null) + throw new FatalError("No symbol file for " + file + " was found\n(This file cannot be loaded as a source file)"); + else if (!(fileset contains file)) { + val unit = new CompilationUnit(getSourceFile(file)); + addUnit(unit); + var localPhase = parserPhase.asInstanceOf[GlobalPhase]; + while (localPhase.id < globalPhase.id || localPhase.id <= parserPhase.next.id) { + atPhase(localPhase)(localPhase.applyPhase(unit)); + localPhase = localPhase.next.asInstanceOf[GlobalPhase]; + } + } + + 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.member(selector) + } + } + val sym = getSym(name, module); + System.err.println("" + sym.name + ":" + + (if (module) sym.tpe.symbol.info else sym.info)) + } + + /** Returns the file with the given suffix for the given class. */ + private def getFile(clazz: Symbol, suffix: String) = { + val outdirname = settings.outdir.value; + var outdir = new File(if (outdirname == "") "." else outdirname); + val filename = clazz.fullNameString('.'); + var start = 0; + var end = filename.indexOf('.', start); + while (end >= start) { + outdir = new File(outdir, filename.substring(start, end)); + if (!outdir.exists()) outdir.mkdir(); + start = end + 1; + end = filename.indexOf('.', start); + } + new File(outdir, filename.substring(start) + suffix) + } + + private def writeSymblFile(clazz: Symbol, pickled: PickleBuffer) = { + val file = getFile(clazz, ".symbl"); + try { + val stream = new FileOutputStream(file); + stream.write(pickled.bytes, 0, pickled.writeIndex); + stream.close(); + informProgress("wrote " + file); + } catch { + case ex: IOException => + if (settings.debug.value) ex.printStackTrace(); + error("could not write file " + file); + } + } + + private def printICode(): Unit = { + val printer = new icodePrinter.TextPrinter(new PrintWriter(System.out, true)); + icodes.classes.foreach(printer.printClass); + } + + private def informStatistics = { + inform("#identifiers : " + analyzer.idcnt); + inform("#selections : " + analyzer.selcnt); + inform("#applications: " + analyzer.appcnt); + inform("#implicits : " + analyzer.implcnt); + inform("#typecreates : " + accesses); + inform("#uniquetypes : " + uniques); + inform("#collisions : " + collisions); + } +} +======= +/* NSC -- new scala compiler + * Copyright 2005 LAMP/EPFL + * @author Martin Odersky + */ +// $Id$ +package scala.tools.nsc; + +import java.io._; +import java.nio.charset._; +import scala.tools.util._; +import scala.collection.mutable.{HashSet,HashMap} + +import symtab._; +import symtab.classfile.{PickleBuffer, Pickler}; +import util.ListBuffer; +import ast._; +import ast.parser._; +import typechecker._; +import matching.TransMatcher; +import transform._; +import backend.icode.{ICodes, GenICode, Checkers}; +import backend.ScalaPrimitives; + +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 treeBrowsers extends TreeBrowsers { + val global: Global.this.type = Global.this + } + val treeBrowser = treeBrowsers.create(); + + object treeInfo extends TreeInfo { + val global: Global.this.type = Global.this + } + + object gen extends TreeGen { + val global: Global.this.type = Global.this + } + + object constfold extends ConstantFolder { + val global: Global.this.type = Global.this + } + + object checker extends TreeCheckers { + val global: Global.this.type = Global.this + } + + object icodes extends ICodes { + val global: Global.this.type = Global.this + } + + object checkers extends Checkers { + val global: Global.this.type = Global.this + } val copy = new LazyTreeCopier(); @@ -457,3 +916,4 @@ class Global(val settings: Settings, val reporter: Reporter) extends SymbolTable inform("#collisions : " + collisions); } } + diff --git a/sources/scala/tools/nsc/ast/TreeGen.scala b/sources/scala/tools/nsc/ast/TreeGen.scala index 453ecced91..a2541d8e74 100755 --- a/sources/scala/tools/nsc/ast/TreeGen.scala +++ b/sources/scala/tools/nsc/ast/TreeGen.scala @@ -96,7 +96,6 @@ abstract class TreeGen { result } - /** Builds an instance test with given value and type. */ def mkIsInstanceOf(value: Tree, tpe: Type, erased: Boolean): Tree = { val sym = diff --git a/sources/scala/tools/nsc/symtab/Flags.scala b/sources/scala/tools/nsc/symtab/Flags.scala index c64936f62a..0cadf154a9 100644 --- a/sources/scala/tools/nsc/symtab/Flags.scala +++ b/sources/scala/tools/nsc/symtab/Flags.scala @@ -56,7 +56,8 @@ object Flags { final val IS_ERROR = 0x100000000l; // symbol is an error symbol final val OVERLOADED = 0x200000000l; // symbol is overloaded - final val FLATTENED = 0x400000000l; // class has been lifted out to package level + final val LIFTED = 0x400000000l; // class has been lifted out to package level + // local value has been lifted out to class level final val MIXEDIN = 0x800000000l; // member has been mixed in final val EXPANDEDNAME = 0x1000000000l; // name has been expanded with class suffix @@ -79,7 +80,11 @@ object Flags { final val lateFINAL = (FINAL: long) << LateShift; final val notPRIVATE = (PRIVATE: long) << AntiShift; final val notPROTECTED = (PROTECTED: long) << AntiShift; - final val notFINAL = (FINAL: long) << AntiShift; + final val notABSTRACT = (ABSTRACT: long) << AntiShift; + final val notOVERRIDE = (OVERRIDE: long) << AntiShift; + + final val STATICMODULE = lateMODULE; + final val STATICMEMBER = notOVERRIDE; // masks /** This flags can be set when class or module symbol is first created. */ @@ -115,11 +120,14 @@ object Flags { else if (flag == INTERFACE) "<interface>" else if (flag == IS_ERROR) "<is-error>" else if (flag == OVERLOADED) "<overloaded>" + else if (flag == LIFTED) "<lifted>" else if (flag == TRANS_FLAG) "<trans-flag>" else if (flag == MIXEDIN) "<mixedin>" else if (flag == EXPANDEDNAME) "<expandedname>" else if (flag == INITIALIZED) "<initialized>" else if (flag == LOCKED) "<locked>" + else if (flag == STATICMODULE) "<staticobject>" + else if (flag == STATICMEMBER) "<staticmember>" else flag.asInstanceOf[int] match { case IMPLICIT => "implicit" case FINAL => "final" diff --git a/sources/scala/tools/nsc/symtab/Names.scala b/sources/scala/tools/nsc/symtab/Names.scala index d123fd2a31..3c15ad920f 100755 --- a/sources/scala/tools/nsc/symtab/Names.scala +++ b/sources/scala/tools/nsc/symtab/Names.scala @@ -203,6 +203,8 @@ class Names { */ final def lastPos(c: char): int = lastPos(c, len - 1); + final def lastPos(s: String): int = lastPos(s, len - s.length()); + /** return the index of last occurrence of char c in this name from `start', * -1 if not found */ @@ -212,6 +214,22 @@ class Names { i } + /** return the index of last occurrence of string s in this name from `start', + * -1 if not found + */ + final def lastPos(s: String, start: int): int = { + var i = lastPos(s.charAt(0), start); + while (i >= 0) { + var j = 1; + while (s.charAt(j) == chrs(index + i + j)) { + j = j + 1; + if (j == s.length()) return i; + } + i = lastPos(s.charAt(0), i - 1) + } + -s.length() + } + /** does this name start with prefix? */ final def startsWith(prefix: Name): boolean = startsWith(prefix, 0); diff --git a/sources/scala/tools/nsc/symtab/StdNames.scala b/sources/scala/tools/nsc/symtab/StdNames.scala index 995b1e0fda..2942e11473 100755 --- a/sources/scala/tools/nsc/symtab/StdNames.scala +++ b/sources/scala/tools/nsc/symtab/StdNames.scala @@ -62,56 +62,72 @@ abstract class StdNames: SymbolTable { val HASHkw = newTermName("#"); val ATkw = newTermName("@"); - private val LOCAL_PREFIX_STRING = "local$"; - private val MIXIN_PREFIX_STRING = "mixin$"; - 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); + val LOCALDUMMY_PREFIX_STRING = "local$"; + val SUPER_PREFIX_STRING = "super$"; + val EXPAND_SEPARATOR_STRING = "$$"; + val TUPLE_FIELD_PREFIX_STRING = "_"; + def LOCAL(clazz: Symbol) = newTermName(LOCALDUMMY_PREFIX_STRING + clazz.name); def TUPLE_FIELD(index: int) = newTermName(TUPLE_FIELD_PREFIX_STRING + index); - def isLocalName(name: Name) = originalName(name).endsWith(LOCAL_SUFFIX); - def isSetterName(name: Name) = originalName(name).endsWith(_EQ); + val LOCAL_SUFFIX = newTermName(" "); + val SETTER_SUFFIX = encode("_="); + val IMPL_CLASS_SUFFIX = newTermName("$class"); + val MODULE_SUFFIX = newTermName("$module"); + val LOCALDUMMY_PREFIX = newTermName(LOCALDUMMY_PREFIX_STRING); - def originalName(name: Name) = name.subName(0, name.pos("$$")); + def isLocalName(name: Name) = name.endsWith(LOCAL_SUFFIX); + def isSetterName(name: Name) = name.endsWith(SETTER_SUFFIX); + def isLocalDummyName(name: Name) = name.startsWith(LOCALDUMMY_PREFIX); - private def applyToOriginal(name: Name, f: Name => Name): Name = { - val oname = originalName(name); - if (oname == name) f(name) - else newTermName(f(oname).toString() + name.subName(oname.length, name.length)) +// def originalName(name: Name): Name = { + def originalName(name: Name): Name = { + var i = name.length; + while (i >= 2 && !(name(i - 1) == '$' && name(i - 2) == '$')) i = i - 1; + if (i >= 2) { + while (i >= 3 && name(i - 3) == '$') i = i - 1; + name.subName(i, name.length) + } else name } +// val result = originalName(name); +// System.out.println("oroginal " + name + " = " + result); +// result +// } def localToGetter(name: Name): Name = { assert(isLocalName(name));//debug - applyToOriginal(name, oname => oname.subName(0, oname.length - LOCAL_SUFFIX.length)); + name.subName(0, name.length - LOCAL_SUFFIX.length); } def getterToLocal(name: Name): Name = { assert(!isLocalName(name) && !isSetterName(name));//debug - applyToOriginal(name, oname => newTermName(oname.toString() + LOCAL_SUFFIX)); + newTermName(name.toString() + LOCAL_SUFFIX); } def getterToSetter(name: Name): Name = { assert(!isLocalName(name) && !isSetterName(name));//debug - applyToOriginal(name, oname => newTermName(oname.toString() + SETTER_SUFFIX)); + newTermName(name.toString() + SETTER_SUFFIX); } def setterToGetter(name: Name): Name = { - assert(isSetterName(name));//debug - applyToOriginal(name, oname => oname.subName(0, oname.length - SETTER_SUFFIX.length)); + name.subName(0, name.length - SETTER_SUFFIX.length); } def getterName(name: Name): Name = if (isLocalName(name)) localToGetter(name) else name; + def isImplClassName(name: Name): boolean = + name endsWith IMPL_CLASS_SUFFIX; + def implClassName(name: Name): Name = newTypeName(name.toString() + IMPL_CLASS_SUFFIX); + def moduleVarName(name: Name): Name = + newTermName(name.toString() + MODULE_SUFFIX); + + def isModuleVarName(name: Name): boolean = + name.endsWith(MODULE_SUFFIX); //todo handle also local modules + def superName(name: Name) = newTermName("super$" + name); val ERROR = newTermName("<error>"); @@ -133,14 +149,13 @@ abstract class StdNames: SymbolTable { val ROOT = newTermName("<root>"); val REPEATED_PARAM_CLASS_NAME = newTermName("<repeated>"); val BYNAME_PARAM_CLASS_NAME = newTermName("<byname>"); - val SELF = newTermName("$self"); + val SELF = newTermName("$this"); val CONSTRUCTOR = newTermName("<init>"); val MIXIN_CONSTRUCTOR = newTermName("$init$"); val INITIALIZER = newTermName("<init>"); val INLINED_INITIALIZER = newTermName("$init$"); - val _EQ = encode("_="); val MINUS = encode("-"); val PLUS = encode("+"); val TILDE = encode("~"); @@ -291,10 +306,6 @@ abstract class StdNames: SymbolTable { val JacoMetaATTR = newTermName("JacoMeta"); val ScalaSignatureATTR = newTermName("ScalaSignature"); val JavaInterfaceATTR = newTermName("JacoInterface"); - - val LOCAL_SUFFIX = newTermName(" "); - val SETTER_SUFFIX = _EQ; - val IMPL_CLASS_SUFFIX = newTermName("$class"); } def encode(str: String): Name = newTermName(NameTransformer.encode(str)); diff --git a/sources/scala/tools/nsc/symtab/Symbols.scala b/sources/scala/tools/nsc/symtab/Symbols.scala index 789df61e80..bc4d4b79f1 100755 --- a/sources/scala/tools/nsc/symtab/Symbols.scala +++ b/sources/scala/tools/nsc/symtab/Symbols.scala @@ -97,10 +97,12 @@ abstract class Symbols: SymbolTable { def isClass = false; //to be overridden final def isValue = isTerm && !(isModule && hasFlag(PACKAGE | JAVA)); - final def isVariable = isTerm && hasFlag(MUTABLE); + final def isVariable = isTerm && hasFlag(MUTABLE) && !isMethod; + final def isSetter = isTerm && hasFlag(ACCESSOR) && nme.isSetterName(name); + //todo: make independent of name, as this can be forged. final def hasGetter = isTerm && nme.isLocalName(name); final def isValueParameter = isTerm && hasFlag(PARAM); - final def isLocalDummy = isTerm && (name startsWith nme.LOCAL_PREFIX); + final def isLocalDummy = isTerm && nme.isLocalDummyName(name); final def isMethod = isTerm && hasFlag(METHOD); final def isSourceMethod = isTerm && (flags & (METHOD | STABLE)) == METHOD; final def isLabel = isTerm && hasFlag(LABEL); @@ -115,7 +117,8 @@ abstract class Symbols: SymbolTable { final def isAliasType = isType && !isClass && !hasFlag(DEFERRED); final def isAbstractType = isType && !isClass && hasFlag(DEFERRED); final def isTypeParameter = isType && hasFlag(PARAM); - final def isAnonymousClass = isClass && (name startsWith nme.ANON_CLASS_NAME); // startsWith necessary because name may grow when lifted and also because of anonymous function classes + final def isAnonymousClass = isClass && (originalName startsWith nme.ANON_CLASS_NAME); + // startsWith necessary because name may grow when lifted and also because of anonymous function classes final def isRefinementClass = isClass && name == nme.REFINE_CLASS_NAME.toTypeName; // no lifting for refinement classes final def isModuleClass = isClass && hasFlag(MODULE); final def isPackageClass = isClass && hasFlag(PACKAGE); @@ -133,8 +136,13 @@ abstract class Symbols: SymbolTable { isConstructor && owner.primaryConstructor == this; /** Is this symbol an implementation class for a trait ? */ - final def isImplClass: boolean = - name.endsWith(nme.IMPL_CLASS_SUFFIX); + final def isImplClass: boolean = isClass && nme.isImplClassName(name); + + final def needsImplClass: boolean = + isTrait && (!hasFlag(INTERFACE) || hasFlag(lateINTERFACE)) && !isImplClass; + + /** Is this symbol a module variable ? */ + final def isModuleVar: boolean = isVariable && nme.isModuleVarName(name); /** Is this symbol static (i.e. with no outer instance)? */ final def isStatic: boolean = hasFlag(STATIC) || isRoot || owner.isStaticOwner; @@ -203,6 +211,8 @@ abstract class Symbols: SymbolTable { def name: Name = rawname; final def name_=(name: Name): unit = { rawname = name } + def originalName = nme.originalName(name); + final def flags = { val fs = rawflags & phase.flagMask; (fs | ((fs & LateFlags) >>> LateShift)) & ~(fs >>> AntiShift) @@ -296,7 +306,7 @@ abstract class Symbols: SymbolTable { phase = current; limit = current; } - assert(infos != null/*, name.toString() + " " + limit + " " + phase*/); + assert(infos != null, name); infos.info } else { var infos = this.infos; @@ -454,11 +464,11 @@ abstract class Symbols: SymbolTable { */ final def accessed: Symbol = { assert(hasFlag(ACCESSOR)); - //todo: make independent of name, as this can be forged. - owner.info.decl( - nme.getterToLocal(if (nme.isSetterName(name)) nme.setterToGetter(name) else name)) + owner.info.decl(nme.getterToLocal(if (isSetter) nme.setterToGetter(name) else name)) } + final def implClass: Symbol = owner.info.decl(nme.implClassName(name)); + /** For a paramaccessor: a superclass paramaccessor for which this symbol is * an alias, NoSymbol for all others */ def alias: Symbol = NoSymbol; @@ -492,6 +502,13 @@ abstract class Symbols: SymbolTable { owner.info.decl(name.toTermName).suchThat(sym => sym.rawInfo != NoType) else NoSymbol; + final def toInterface: Symbol = + if (isImplClass) { + val iface = tpe.parents.last.symbol; + assert(nme.implClassName(iface.name) == name, this); + iface + } else this; + /** The module corresponding to this module class (note that this * is not updated when a module is cloned). */ @@ -525,17 +542,13 @@ abstract class Symbols: SymbolTable { sym } - /** The superaccessor for this symbol in the definition of `base'. */ - final def superAccessor(base: Symbol): Symbol = - base.info.decl(nme.superName(name)) suchThat (.alias.==(this)); - /** The getter of this value definition in class `base', or NoSymbol if none exists */ final def getter(base: Symbol): Symbol = - base.info.decl(nme.localToGetter(name)) filter (.hasFlag(ACCESSOR)); + base.info.decl(nme.getterName(name)) filter (.hasFlag(ACCESSOR)); /** The setter of this value definition, or NoSymbol if none exists */ final def setter(base: Symbol): Symbol = - base.info.decl(nme.getterToSetter(nme.localToGetter(name))) filter (.hasFlag(ACCESSOR)); + base.info.decl(nme.getterToSetter(nme.getterName(name))) filter (.hasFlag(ACCESSOR)); /** Remove private modifier from symbol `sym's definition. If `sym' is a * term symbol rename it by expanding its name to avoid name clashes @@ -559,9 +572,12 @@ abstract class Symbols: SymbolTable { getter(owner).expandName(base); setter(owner).expandName(base); } - name = newTermName(name.toString() + "$$" + base.fullNameString('$')) + name = base.expandedName(name) } + def expandedName(name: Name): Name = + newTermName(fullNameString('$') + nme.EXPAND_SEPARATOR_STRING + name); + /* def referenced: Symbol = throw new Error("referenced inapplicable for " + this); @@ -709,9 +725,10 @@ abstract class Symbols: SymbolTable { } override def alias: Symbol = - if (hasFlag(SUPERACCESSOR | PARAMACCESSOR)) referenced else NoSymbol; + if (hasFlag(SUPERACCESSOR | PARAMACCESSOR | MIXEDIN)) initialize.referenced else NoSymbol; def setAlias(alias: Symbol): TermSymbol = { + assert(alias != NoSymbol); assert(hasFlag(SUPERACCESSOR | PARAMACCESSOR | MIXEDIN)); referenced = alias; this @@ -738,12 +755,14 @@ abstract class Symbols: SymbolTable { override def tpe: Type = { assert(tpeCache != NoType, this); if (tpePhase != phase) { - if (isValid(tpePhase)) tpePhase = phase - else { + if (isValid(tpePhase)) { + tpePhase = phase + } else { if (hasFlag(INITIALIZED)) tpePhase = phase; tpeCache = NoType; - tpeCache = typeRef(if (isTypeParameter) NoPrefix else owner.thisType, - this, unsafeTypeParams map (.tpe)) + val targs = if (phase.erasedTypes && this != ArrayClass) List() + else unsafeTypeParams map (.tpe); + tpeCache = typeRef(if (isTypeParameter) NoPrefix else owner.thisType, this, targs) } } assert(tpeCache != null/*, "" + this + " " + phase*/);//debug @@ -803,12 +822,11 @@ abstract class Symbols: SymbolTable { val p = thisTypePhase; if (p != phase) { thisTypePhase = phase; - if (!isValid(p)) { + if (!(isValid(p) /*|| + thisTypePhase != null && thisTypePhase.erasedTypes && phase.erasedTypes*/)) { thisTypeCache = - if (isModuleClass && !isRoot && !phase.erasedTypes) { - assert(sourceModule != NoSymbol, this); - singleType(owner.thisType, sourceModule); - } + if (isModuleClass && !isRoot && !phase.erasedTypes) + singleType(owner.thisType, sourceModule); else ThisType(this); } } diff --git a/sources/scala/tools/nsc/symtab/Types.scala b/sources/scala/tools/nsc/symtab/Types.scala index 0c66540d66..cf8b9da1d7 100755 --- a/sources/scala/tools/nsc/symtab/Types.scala +++ b/sources/scala/tools/nsc/symtab/Types.scala @@ -166,14 +166,6 @@ abstract class Types: SymbolTable { /** The type of `sym', seen as a memeber of this type. */ def memberType(sym: Symbol): Type = sym.tpe.asSeenFrom(this, sym.owner); - /* - def memberType(sym: Symbol): Type = { - if (sym.nameString startsWith "PolyType") - System.out.println("" + this + ".memberType(" + sym + ":" + sym.tpe + ") = " + memberType(sym) + ", owner = " + sym.owner);//debug - memberType(sym) - } - */ - /** Substitute types `to' for occurrences of references to symbols `from' * in this type. */ def subst(from: List[Symbol], to: List[Type]): Type = @@ -576,7 +568,6 @@ abstract class Types: SymbolTable { override def narrow: Type = symbol.thisType; override def toString(): String = - "<" + symbol.toString() + ">" + //debug parents.mkString("", " with ", "") + (if (settings.debug.value || parents.isEmpty || decls.elems != null) decls.mkString("{", "; ", "}") else "") @@ -704,7 +695,7 @@ abstract class Types: SymbolTable { */ case class MethodType(override val paramTypes: List[Type], override val resultType: Type) extends Type { - + assert(paramTypes forall (pt => !pt.symbol.isImplClass));//debug override def paramSectionCount: int = resultType.paramSectionCount + 1; override def finalResultType: Type = resultType.finalResultType; diff --git a/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala b/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala index 0a95ee5434..ea459829d4 100755 --- a/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala +++ b/sources/scala/tools/nsc/symtab/classfile/UnPickler.scala @@ -130,6 +130,7 @@ abstract class UnPickler { } sym.setFlag(flags); if (readIndex != end) assert(sym hasFlag (SUPERACCESSOR | PARAMACCESSOR)); + if (sym hasFlag SUPERACCESSOR) assert(readIndex != end); sym.setInfo( if (readIndex != end) new LazyTypeRefAndAlias(inforef, readNat()) else new LazyTypeRef(inforef)); diff --git a/sources/scala/tools/nsc/transform/AddInterfaces.scala b/sources/scala/tools/nsc/transform/AddInterfaces.scala index 49db339b2c..bb6c6721ff 100755 --- a/sources/scala/tools/nsc/transform/AddInterfaces.scala +++ b/sources/scala/tools/nsc/transform/AddInterfaces.scala @@ -15,7 +15,7 @@ abstract class AddInterfaces extends InfoTransform { import definitions._; // standard classes and methods import posAssigner.atPos; // for filling in tree positions - override def phaseNewFlags: long = lateDEFERRED | lateINTERFACE | notFINAL; + override def phaseNewFlags: long = lateDEFERRED | lateINTERFACE; // Type transformation @@ -24,18 +24,15 @@ abstract class AddInterfaces extends InfoTransform { private val implClassMap = new HashMap[Symbol, Symbol]; private val implMethodMap = new HashMap[Symbol, Symbol]; - private def needsImplClass(sym: Symbol): boolean = - sym.isTrait && (!(sym hasFlag INTERFACE) || (sym hasFlag lateINTERFACE)) && !sym.isImplClass; - private def needsImplMethod(sym: Symbol): boolean = sym.isMethod && isInterfaceMember(sym) && - (!(sym hasFlag DEFERRED) || (sym hasFlag lateDEFERRED)); + (!(sym hasFlag (DEFERRED | SUPERACCESSOR)) || (sym hasFlag lateDEFERRED)); private def isInterfaceMember(sym: Symbol): boolean = sym.isType || sym.isMethod && !(sym hasFlag (PRIVATE | BRIDGE | LABEL)) && !sym.isConstructor; - private def implClass(iface: Symbol): Symbol = implClassMap.get(iface) match { + def implClass(iface: Symbol): Symbol = implClassMap.get(iface) match { case Some(c) => c case None => atPhase(erasurePhase) { @@ -45,7 +42,9 @@ abstract class AddInterfaces extends InfoTransform { impl.name = nme.implClassName(iface.name); //includeInTypeOfThis(iface, impl); //includeInTypeOfThis(impl, impl); + //todo: use implClassMap only for local impl classes implClassMap(iface) = impl; + if (iface.owner.isClass) iface.owner.info.decls enter impl; if (settings.debug.value) log("generating impl class " + impl); impl } @@ -61,7 +60,7 @@ abstract class AddInterfaces extends InfoTransform { val impl = sym.cloneSymbol(implClass).setInfo(sym.info); if (!impl.isExternal) implMethodMap(sym) = impl; decls enter impl; - sym setFlag (lateDEFERRED | notFINAL) + sym setFlag lateDEFERRED } } else { sym.owner = implClass; @@ -74,7 +73,11 @@ abstract class AddInterfaces extends InfoTransform { override def complete(sym: Symbol): unit = { def implType(tp: Type): Type = tp match { case ClassInfoType(parents, decls, _) => - ClassInfoType(traitToImplClass(parents) ::: List(iface.tpe), implDecls(sym, decls), sym) + //ClassInfoType(traitToImplClass(parents) ::: List(iface.tpe), implDecls(sym, decls), sym) + ClassInfoType( + ObjectClass.tpe :: (parents.tail map traitToImplClass) ::: List(iface.tpe), + implDecls(sym, decls), + sym) case PolyType(tparams, restpe) => PolyType(tparams, implType(restpe)) } @@ -85,36 +88,30 @@ abstract class AddInterfaces extends InfoTransform { } private def traitToImplClass(tp: Type): Type = tp match { - case TypeRef(pre, sym, args) if (needsImplClass(sym)) => + case TypeRef(pre, sym, args) if (sym.needsImplClass) => typeRef(pre, implClass(sym), args) case _ => tp } - private def traitToImplClass(parents: List[Type]): List[Type] = - parents.head :: (parents.tail map traitToImplClass); - - private def addImplClasses(decls: Scope): Scope = { - for (val sym <- decls.elements) - if (needsImplClass(sym)) decls enter implClass(sym); - decls - } - def transformTraitInfo(tp: Type): Type = tp match { case ClassInfoType(parents, decls, clazz) => - if (needsImplClass(clazz)) clazz setFlag lateINTERFACE; - var parents1 = + if (clazz.needsImplClass) { + clazz setFlag lateINTERFACE; + implClass(clazz) // generate an impl class + } + val parents1 = if (parents.isEmpty) List() else { - assert(!parents.head.symbol.isTrait); + assert(!parents.head.symbol.isTrait || clazz == RepeatedParamClass, clazz); if (clazz hasFlag INTERFACE) erasedTypeRef(ObjectClass) :: parents.tail else if (clazz.isImplClass || clazz == ArrayClass) parents - else traitToImplClass(parents) + else parents map traitToImplClass } - val decls1 = addImplClasses( - if (clazz hasFlag INTERFACE) new Scope(decls.toList filter isInterfaceMember) - else new Scope(decls.toList)); - ClassInfoType(parents1, decls1, clazz) + val decls1 = if (clazz hasFlag INTERFACE) new Scope(decls.toList filter isInterfaceMember) + else decls; + if ((parents1 eq parents) && (decls1 eq decls)) tp + else ClassInfoType(parents1, decls1, clazz) case _ => tp } @@ -170,7 +167,7 @@ abstract class AddInterfaces extends InfoTransform { for (val tree <- trees) tree match { case ClassDef(_, _, _, _, impl) => - if (needsImplClass(tree.symbol)) + if (tree.symbol.needsImplClass) buf += { val clazz = implClass(tree.symbol).initialize; ClassDef(clazz, implTemplate(clazz, impl)) @@ -187,7 +184,7 @@ abstract class AddInterfaces extends InfoTransform { override def transform(tree: Tree): Tree = { val tree1 = tree match { case ClassDef(mods, name, tparams, tpt, impl) => - if (needsImplClass(tree.symbol)) { + if (tree.symbol.needsImplClass) { implClass(tree.symbol).initialize; // to force lateDEFERRED flags copy.ClassDef(tree, mods | INTERFACE, name, tparams, tpt, ifaceTemplate(impl)) } @@ -196,7 +193,7 @@ abstract class AddInterfaces extends InfoTransform { val parents1 = tree.symbol.owner.info.parents map (t => TypeTree(t) setPos tree.pos); copy.Template(tree, parents1, body) case This(_) => - if (needsImplClass(tree.symbol)) { + if (tree.symbol.needsImplClass) { val impl = implClass(tree.symbol); var owner = currentOwner; while (owner != tree.symbol && owner != impl) owner = owner.owner; @@ -211,10 +208,10 @@ abstract class AddInterfaces extends InfoTransform { tree.symbol.info.parents dropWhile (p => p.symbol.name != mix) } assert(!ps.isEmpty, tree); - if (needsImplClass(ps.head.symbol)) implClass(ps.head.symbol).name + if (ps.head.symbol.needsImplClass) implClass(ps.head.symbol).name else mix } - if (needsImplClass(tree.symbol)) Super(implClass(tree.symbol), mix1) setPos tree.pos + if (tree.symbol.needsImplClass) Super(implClass(tree.symbol), mix1) setPos tree.pos else copy.Super(tree, qual, mix1) case _ => tree diff --git a/sources/scala/tools/nsc/transform/Constructors.scala b/sources/scala/tools/nsc/transform/Constructors.scala index 1074fbb0a0..9d9230719c 100755 --- a/sources/scala/tools/nsc/transform/Constructors.scala +++ b/sources/scala/tools/nsc/transform/Constructors.scala @@ -43,8 +43,8 @@ abstract class Constructors extends Transform { val paramAccessors = clazz.constrParamAccessors; def parameter(acc: Symbol) = { - val accname = nme.originalName(nme.getterName(acc.name)); - val ps = constrParams.filter { param => param.name == accname } + val accname = nme.getterName(acc.originalName); + val ps = constrParams.filter { param => accname == param.name } if (ps.isEmpty) assert(false, "" + accname + " not in " + constrParams); ps.head } @@ -79,12 +79,24 @@ abstract class Constructors extends Transform { constrBody.stats foreach (constrStatBuf +=); for (val stat <- stats) stat match { - case DefDef(_, _, _, _, _, _) => - if (!stat.symbol.isPrimaryConstructor) defBuf += stat + case DefDef(mods, name, tparams, vparamss, tpt, rhs) => + stat.symbol.tpe match { + case MethodType(List(), tp @ ConstantType(c)) => + defBuf += copy.DefDef( + stat, mods, name, tparams, vparamss, tpt, + Literal(c) setPos rhs.pos setType tp) + case _ => + if (!stat.symbol.isPrimaryConstructor) defBuf += stat + } case ValDef(mods, name, tpt, rhs) => - if (rhs != EmptyTree) - constrStatBuf += mkAssign(stat.symbol, intoConstructor(stat.symbol, rhs)); - defBuf += copy.ValDef(stat, mods, name, tpt, EmptyTree) + if (stat.symbol.tpe.isInstanceOf[ConstantType]) + assert(stat.symbol.getter != NoSymbol, stat) + else { + if (rhs != EmptyTree) { + constrStatBuf += mkAssign(stat.symbol, intoConstructor(stat.symbol, rhs)); + } + defBuf += copy.ValDef(stat, mods, name, tpt, EmptyTree) + } case _ => constrStatBuf += intoConstructor(impl.symbol, stat) } diff --git a/sources/scala/tools/nsc/transform/Erasure.scala b/sources/scala/tools/nsc/transform/Erasure.scala index 96f3e3ebf3..b50edd055b 100755 --- a/sources/scala/tools/nsc/transform/Erasure.scala +++ b/sources/scala/tools/nsc/transform/Erasure.scala @@ -46,6 +46,8 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { */ private val erasure = new TypeMap { def apply(tp: Type): Type = tp match { + case ConstantType(_) => + tp case st: SubType => apply(st.supertype) case TypeRef(pre, sym, args) => @@ -192,7 +194,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { /** Adapt `tree' to expected type `pt' */ private def adaptToType(tree: Tree, pt: Type): Tree = { - if (settings.debug.value && pt != WildcardType) log("adapting " + tree + ":" + tree.tpe + " to " + pt); + //if (settings.debug.value && pt != WildcardType) log("adapting " + tree + ":" + tree.tpe + " to " + pt);//DEBUG if (tree.tpe <:< pt) tree else if (isUnboxedClass(tree.tpe.symbol) && !isUnboxedClass(pt.symbol)) @@ -392,10 +394,14 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer { atPhase(phase.next) { atPos(bridge.pos) { DefDef(bridge, vparamss => - ((Select(This(owner), bridgeTarget(bridge)): Tree) /: vparamss) - ((fun, vparams) => Apply(fun, vparams map Ident))) - } :: bridges; - } + member.tpe match { + case MethodType(List(), ConstantType(c)) => Literal(c) + case _ => + ((Select(This(owner), member): Tree) /: vparamss) + ((fun, vparams) => Apply(fun, vparams map Ident)) + }) + } + } :: bridges; } } } diff --git a/sources/scala/tools/nsc/transform/ExplicitOuter.scala b/sources/scala/tools/nsc/transform/ExplicitOuter.scala index 44a64ffa69..469cabdcb7 100755 --- a/sources/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/sources/scala/tools/nsc/transform/ExplicitOuter.scala @@ -33,8 +33,9 @@ abstract class ExplicitOuter extends InfoTransform { */ def transformInfo(sym: Symbol, tp: Type): Type = tp match { case MethodType(formals, restpe) => + if (sym.owner.isTrait && (sym hasFlag PROTECTED)) sym setFlag notPROTECTED; if (sym.isConstructor && !sym.owner.isStatic) - MethodType(formals ::: List(sym.owner.owner.enclClass.thisType), restpe) + MethodType(formals ::: List(sym.owner.owner.enclClass.toInterface.thisType), restpe) else tp; case ClassInfoType(parents, decls, clazz) => var decls1 = decls; @@ -67,7 +68,9 @@ abstract class ExplicitOuter extends InfoTransform { private def outerMember(tp: Type): Symbol = { var e = tp.decls.elems; - while (!(e.sym.name.startsWith(nme.OUTER) && (e.sym hasFlag ACCESSOR))) e = e.next; + while (e != null && !(e.sym.originalName.startsWith(nme.OUTER) && (e.sym hasFlag ACCESSOR))) + e = e.next; + assert(e != null, tp); e.sym } @@ -290,7 +293,7 @@ abstract class ExplicitOuter extends InfoTransform { else rhs; copy.DefDef(tree, mods, name, tparams, vparamss1, tpt, rhs1); case This(qual) => - if (sym == currentOwner.enclClass || sym.isStatic) tree + if (sym == currentOwner.enclClass || (sym hasFlag MODULE) && sym.isStatic) tree else atPos(tree.pos)(outerPath(outerValue, sym)); // (5) case Select(qual @ Super(_, mix), name) => val qsym = qual.symbol; diff --git a/sources/scala/tools/nsc/transform/Flatten.scala b/sources/scala/tools/nsc/transform/Flatten.scala index 020f4c54ad..a94b0cf0e9 100755 --- a/sources/scala/tools/nsc/transform/Flatten.scala +++ b/sources/scala/tools/nsc/transform/Flatten.scala @@ -17,23 +17,44 @@ abstract class Flatten extends InfoTransform { /** the following two members override abstract members in Transform */ val phaseName: String = "flatten"; + private def liftClass(sym: Symbol): unit = + if (!(sym hasFlag LIFTED)) { + sym setFlag LIFTED; + atPhase(phase.next) { + if (settings.debug.value) log("re-enter " + sym + " in " + sym.owner); + assert(sym.owner.isPackageClass, sym);//debug + val scope = sym.owner.info.decls; + val old = scope lookup sym.name; + if (old != NoSymbol) scope unlink old; + scope enter sym; + } + } + private val flattened = new TypeMap { def apply(tp: Type): Type = tp match { case TypeRef(pre, sym, args) if (pre.symbol.isClass && !pre.symbol.isPackageClass) => assert(args.isEmpty); typeRef(sym.toplevelClass.owner.thisType, sym, args) case ClassInfoType(parents, decls, clazz) => + var parents1 = parents; + val decls1 = new Scope(); if (clazz.isPackageClass) { - val decls1 = new Scope(); - for (val member <- decls.toList) { - atPhase(phase.next)(decls1 enter member) - } - ClassInfoType(parents, decls1, clazz) - } else { - val parents1 = List.mapConserve(parents)(this); - if (parents1 eq parents) tp - else ClassInfoType(parents1, decls, clazz) - } + atPhase(phase.next)(decls.toList foreach (decls1 enter)) + } else { + atPhase(phase.next)(clazz.owner.info); + parents1 = List.mapConserve(parents)(this); + for (val sym <- decls.toList) { + if (sym.isTerm) decls1 enter sym + else if (sym.isClass) { + liftClass(sym); + if (sym.needsImplClass) liftClass(erasure.implClass(sym)) + } + } + } + ClassInfoType(parents1, decls1, clazz) + case PolyType(tparams, restp) => + val restp1 = apply(restp); + if (restp1 eq restp) tp else PolyType(tparams, restp1) case _ => mapOver(tp) } @@ -73,15 +94,9 @@ abstract class Flatten extends InfoTransform { tree } tree1 setType flattened(tree1.tpe); - if (sym != null && sym.isNestedClass && !(sym hasFlag FLATTENED)) { - sym setFlag FLATTENED; - atPhase(phase.next) { - if (settings.debug.value) log("re-enter " + sym + " in " + sym.owner); - val scope = sym.owner.info.decls; - val old = scope lookup sym.name; - if (old != NoSymbol) scope unlink old; - scope enter sym; - } + if (sym != null && sym.isNestedClass && !(sym hasFlag LIFTED)) { + liftClass(sym);//todo: remove + if (sym.implClass != NoSymbol) liftClass(sym.implClass); } tree1 } diff --git a/sources/scala/tools/nsc/transform/LambdaLift.scala b/sources/scala/tools/nsc/transform/LambdaLift.scala index 353baf620b..e4647a41f2 100755 --- a/sources/scala/tools/nsc/transform/LambdaLift.scala +++ b/sources/scala/tools/nsc/transform/LambdaLift.scala @@ -13,8 +13,8 @@ import collection.mutable.HashMap; abstract class LambdaLift extends InfoTransform { import global._; import definitions._; - import typer.{typed}; // methods to type trees - import posAssigner.atPos; // for filling in tree positions + import typer.{typed, typedOperator}; + import posAssigner.atPos; /** the following two members override abstract members in Transform */ val phaseName: String = "lambdalift"; @@ -127,15 +127,24 @@ abstract class LambdaLift extends InfoTransform { liftedDefs(tree.symbol) = new ListBuffer; if (sym.isLocal) renamable addEntry sym; case DefDef(_, _, _, _, _, _) => - if (sym.isLocal) renamable addEntry sym; - if (sym.isPrimaryConstructor) symSet(called, sym) addEntry sym.owner; + if (sym.isLocal) { + renamable addEntry sym; + sym setFlag (PRIVATE | LOCAL | FINAL) + } else if (sym.isPrimaryConstructor) { + symSet(called, sym) addEntry sym.owner + } case Ident(name) => if (sym == NoSymbol) { assert(name == nme.WILDCARD) } else if (sym.isLocal) { val owner = enclMethOrClass(currentOwner); - if (owner.isMethod && sym.isMethod) symSet(called, owner) addEntry sym; - else if (sym.isTerm) markFree(sym, owner) + if (sym.isTerm && !sym.isMethod) markFree(sym, owner) + else if (owner.isMethod && sym.isMethod) symSet(called, owner) addEntry sym; + } + case Select(_, _) => + if (sym.isConstructor && sym.owner.isLocal) { + val owner = enclMethOrClass(currentOwner); + if (owner.isMethod) symSet(called, owner) addEntry sym; } case _ => } @@ -203,14 +212,20 @@ abstract class LambdaLift extends InfoTransform { else searchIn(currentOwner) } + private def memberRef(sym: Symbol) = { + val clazz = sym.owner.enclClass; + val qual = if (clazz == currentOwner.enclClass) gen.This(clazz) + else { + sym resetFlag(LOCAL | PRIVATE); + if (clazz.isStaticOwner) gen.mkQualifier(clazz.thisType) + else outerPath(outerValue, clazz) + } + Select(qual, sym) setType sym.tpe + } + private def proxyRef(sym: Symbol) = { val psym = proxy(sym); - if (psym.isLocal) gen.Ident(psym) - else if (psym.owner == currentOwner.enclClass) gen.mkRef(psym) - else { - psym resetFlag (PRIVATE | LOCAL); - Select(outerPath(outerValue, psym.owner), psym) setType psym.tpe - } + if (psym.isLocal) gen.Ident(psym) else memberRef(psym) } private def addFreeArgs(pos: int, sym: Symbol, args: List[Tree]) = { @@ -237,10 +252,12 @@ abstract class LambdaLift extends InfoTransform { private def liftDef(tree: Tree): Tree = { val sym = tree.symbol; - if (sym.isMethod) sym setFlag (PRIVATE | LOCAL); sym.owner = sym.owner.enclClass; + if (sym.isClass) sym.owner = sym.owner.toInterface; + if (sym.isMethod) sym setFlag LIFTED; liftedDefs(sym.owner) += tree; sym.owner.info.decls enter sym; + if (settings.debug.value) log("lifted: " + sym + sym.locationString); EmptyTree } @@ -281,9 +298,12 @@ abstract class LambdaLift extends InfoTransform { copy.Assign(tree, qual, rhs) case Ident(name) => val tree1 = - if (sym != NoSymbol && sym.isLocal && sym.isTerm && !sym.isMethod && - enclMethOrClass(sym.owner) != enclMethOrClass(currentOwner)) - atPos(tree.pos)(proxyRef(sym)) + if (sym != NoSymbol && sym.isTerm && !sym.isLabel) + if (sym.isMethod) + atPos(tree.pos)(memberRef(sym)) + else if (sym.isLocal && enclMethOrClass(sym.owner) != enclMethOrClass(currentOwner)) + atPos(tree.pos)(proxyRef(sym)) + else tree else tree; if (sym hasFlag CAPTURED) atPos(tree.pos) { diff --git a/sources/scala/tools/nsc/transform/Mixin.scala b/sources/scala/tools/nsc/transform/Mixin.scala index 4cf1ea4ff4..296f614f73 100755 --- a/sources/scala/tools/nsc/transform/Mixin.scala +++ b/sources/scala/tools/nsc/transform/Mixin.scala @@ -18,53 +18,20 @@ abstract class Mixin extends InfoTransform { /** the following two members override abstract members in Transform */ val phaseName: String = "mixin"; - override def phaseNewFlags: long = lateMODULE; + override def phaseNewFlags: long = lateMODULE | notABSTRACT; - def isForwarded(sym: Symbol) = + private def isForwarded(sym: Symbol) = sym.owner.isImplClass && sym.isMethod && !(sym hasFlag (ACCESSOR | SUPERACCESSOR)); - def isStatic(sym: Symbol) = isForwarded(sym) && (sym.hasFlag(PRIVATE) || sym.isConstructor); + private def isStatic(sym: Symbol) = isForwarded(sym) && (sym.hasFlag(PRIVATE) || sym.isConstructor); - def isSelfRef(tree: Tree) = tree match { - case This(_) => true - case Super(_, mix) => mix != nme.EMPTY.toTypeName - case _ => false - } -/* - def toImplClass(sym: Symbol): Symbol = { - val impl = clazz.owner.info.decl(nme.IMPL_CLASS_NAME(clazz.name)); - - } - - def toInterface(sym: Symbol): Symbol; -*/ - def toInterface(tp: Type): Type = - if (tp.symbol.isImplClass) { - val iface = tp.parents.last; - if (!tp.symbol.name.startsWith(iface.symbol.name)) assert(false, "bad interface: " + tp + " " + iface); - iface - } else tp; - - def makeUnique(decls: Scope, sym: Symbol): unit = { - if ((sym hasFlag PRIVATE) && decls.lookup(sym.name) != NoSymbol) { - val prefix = sym.name.toString() + "$"; - var index = 0; - while (decls.lookup(newTermName(prefix + index)) != NoSymbol) index = index + 1; - sym.name = newTermName(prefix + index) - } - } - - private def staticRef(sym: Symbol) = { - System.out.println("static ref " + sym.owner + " . " + sym);//debug - sym.owner.info; - Select(gen.mkRef(sym.owner.sourceModule), sym); - } + private def toInterface(tp: Type): Type = tp.symbol.toInterface.tpe; private def rebindSuper(base: Symbol, member: Symbol, prevowner: Symbol): Symbol = { var bcs = base.info.baseClasses.dropWhile(prevowner !=).tail; var sym: Symbol = NoSymbol; while (!bcs.isEmpty && sym == NoSymbol) { - System.out.println("rebindsuper " + bcs.head + " " + bcs.head.info.nonPrivateDecl(member.name));//debug + if (settings.debug.value) log("rebindsuper " + bcs.head + " " + bcs.head.info.nonPrivateDecl(member.name)); sym = member.overridingSymbol(bcs.head).suchThat(sym => !sym.hasFlag(DEFERRED)); bcs = bcs.tail } @@ -72,78 +39,115 @@ abstract class Mixin extends InfoTransform { sym } - private def implClass(iface: Symbol): Symbol = - atPhase(flattenPhase)(iface.owner.info.decl(nme.implClassName(iface.name))); + private def implClass(iface: Symbol): Symbol = erasure.implClass(iface); override def transformInfo(sym: Symbol, tp: Type): Type = tp match { case ClassInfoType(parents, decls, clazz) => + assert(sym == clazz, "not equal: " + sym + " " + clazz); var parents1 = parents; var decls1 = decls; def addMember(member: Symbol): Symbol = { if (decls1 eq decls) decls1 = new Scope(decls.toList); - System.out.println("new member of " + clazz + ":" + member);//debug + if (settings.debug.value) log("new member of " + clazz + ":" + member.defString);//debug decls1 enter member; member } - def newGetter(field: Symbol): Symbol = - clazz.newMethod(field.pos, nme.getterName(field.name)) - setFlag (field.flags & ~(PRIVATE | LOCAL | MUTABLE) | (ACCESSOR | DEFERRED | SYNTHETIC)) - setInfo MethodType(List(), field.info); - def newSetter(field: Symbol): Symbol = - clazz.newMethod(field.pos, nme.getterToSetter(nme.getterName(field.name))) - setFlag (field.flags & ~(PRIVATE | LOCAL | MUTABLE) | (ACCESSOR | DEFERRED | SYNTHETIC)) - setInfo MethodType(List(field.info), UnitClass.tpe); - - if (clazz.isPackageClass) { - for (val sym <- decls.elements) { + def addPackageClassMembers = { + for (val sym <- decls.toList) { if (sym.isImplClass) { - sym setFlag lateMODULE; + sym setFlag lateMODULE | notABSTRACT; addMember( clazz.newModule(sym.pos, sym.name.toTermName, sym.asInstanceOf[ClassSymbol]) setInfo sym.tpe) } } - } else if (clazz hasFlag lateINTERFACE) { + } + def addLateInterfaceMembers = { + def newGetter(field: Symbol): Symbol = + clazz.newMethod(field.pos, nme.getterName(field.name)) + setFlag (field.flags & ~(PRIVATE | LOCAL) | ACCESSOR | DEFERRED | SYNTHETIC) + setInfo MethodType(List(), field.info); + def newSetter(field: Symbol): Symbol = + clazz.newMethod(field.pos, nme.getterToSetter(nme.getterName(field.name))) + setFlag (field.flags & ~(PRIVATE | LOCAL) | ACCESSOR | DEFERRED | SYNTHETIC) + setInfo MethodType(List(field.info), UnitClass.tpe); + clazz.info; val impl = implClass(clazz); - assert(impl != NoSymbol, clazz); - for (val member <- decls.toList) { - if (!member.isMethod) { - assert(member.isTerm && !member.hasFlag(DEFERRED)); - member.makeNotPrivate(clazz); + assert(impl != NoSymbol, "" + clazz + " " + flattenPhase.flatClasses + atPhase(flattenPhase)(clazz.owner.info.decls)); + for (val member <- impl.info.decls.toList) { + if (!member.isMethod && !member.isModule && !member.isModuleVar)) { + assert(member.isTerm && !member.hasFlag(DEFERRED), member); + if (member.getter(impl) hasFlag PRIVATE) member.makeNotPrivate(clazz); var getter = member.getter(clazz); if (getter == NoSymbol) getter = addMember(newGetter(member)); - getter setFlag FINAL; + else getter setFlag (member getFlag MUTABLE); if (!member.tpe.isInstanceOf[ConstantType]) { var setter = member.setter(clazz); - if (getter == NoSymbol) setter = addMember(newSetter(member)); - setter setFlag FINAL + if (setter == NoSymbol) setter = addMember(newSetter(member)); } - } - } - } else if (clazz.isImplClass) { - transformInfo(clazz.owner, clazz.owner.info); - parents1 = List(); - decls1 = new Scope(decls.toList filter isForwarded) - } else if (!parents.isEmpty) { - parents1 = parents.head :: (parents.tail map toInterface); + } else if ((member hasFlag LIFTED) && !(member hasFlag PRIVATE)) { + member.expandName(clazz); + addMember(member.cloneSymbol(clazz)); + } + } + } + def addMixedinMembers = { for (val bc <- clazz.info.baseClasses.tail.takeWhile(parents.head.symbol !=)) { if (bc.isImplClass) { for (val member <- bc.info.decls.toList) { - if (isForwarded(member) && (clazz.info.member(member.name).alternatives contains member)) { - val member1 = member.cloneSymbol(clazz) setFlag MIXEDIN; + if (isForwarded(member) && !isStatic(member) && + (clazz.info.member(member.name).alternatives contains member)) { + val member1 = addMember(member.cloneSymbol(clazz) setFlag MIXEDIN); member1.asInstanceOf[TermSymbol] setAlias member; + } + } + } else if (bc.hasFlag(lateINTERFACE)) { + for (val member <- atPhase(phase.next)(bc.info.decls.toList)) { + if (member hasFlag ACCESSOR) { + val member1 = addMember( + member.cloneSymbol(clazz) setFlag (MIXEDIN | FINAL) resetFlag DEFERRED); + if (!member.isSetter) + member.tpe match { + case MethodType(List(), ConstantType(_)) => + ; + case _ => + addMember( + clazz.newValue(member.pos, nme.getterToLocal(member.name)) + setFlag (LOCAL | PRIVATE | MIXEDIN | member.getFlag(MUTABLE)) + setInfo member.tpe.resultType) + } } else if (member hasFlag SUPERACCESSOR) { - member.asInstanceOf[TermSymbol] setAlias rebindSuper(clazz, member.alias, bc); - addMember(member) + val member1 = addMember(member.cloneSymbol(clazz)) setFlag MIXEDIN; + assert(member1.alias != NoSymbol, member1); + member1.asInstanceOf[TermSymbol] setAlias rebindSuper(clazz, member.alias, bc); + } else if (member.isMethod && member.sModule && !(member hasFlag LIFTED)) { + addMember(member.cloneSymbol(clazz) setFlag MIXEDIN) } } } } } - if ((parents1 eq parents) && (decls1 eq decls)) tp else ClassInfoType(parents, decls1, clazz) + + if (clazz.isPackageClass) { + addPackageClassMembers + } else { + atPhase(phase.next)(clazz.owner.info); + if (clazz.isImplClass) { + parents1 = List(); + decls1 = new Scope(decls.toList filter isForwarded) + } else if (!parents.isEmpty) { + parents1 = parents.head :: (parents.tail map toInterface); + if (!(clazz hasFlag INTERFACE)) addMixedinMembers + else if (clazz hasFlag lateINTERFACE) addLateInterfaceMembers + } + } + if (settings.debug.value && !clazz.isPackageClass) log("new defs of " + clazz + " = " + decls1); + decls1 = atPhase(phase.next)(new Scope(decls1.toList));//debug + if ((parents1 eq parents) && (decls1 eq decls)) tp + else ClassInfoType(parents1, decls1, clazz); + case MethodType(formals, restp) => - if (isForwarded(sym)) - MethodType(toInterface(sym.owner.thisType) :: formals, restp) + if (isForwarded(sym)) MethodType(toInterface(sym.owner.typeOfThis) :: formals, restp) else tp case _ => tp @@ -152,95 +156,180 @@ abstract class Mixin extends InfoTransform { protected def newTransformer(unit: CompilationUnit): Transformer = new MixinTransformer; class MixinTransformer extends Transformer { + private var self: Symbol = _; + private var localTyper: analyzer.Typer = _; + private var enclInterface: Symbol = _; + + private def preTransform(tree: Tree): Tree = { + val sym = tree.symbol; + tree match { + case Template(parents, body) => + localTyper = typer.atOwner(tree, currentOwner); + tree + case DefDef(mods, name, tparams, List(vparams), tpt, rhs) if currentOwner.isImplClass => + if (isForwarded(sym)) { + sym setFlag notOVERRIDE; + self = sym.newValue(sym.pos, nme.SELF) + setFlag (PARAM | SYNTHETIC) + setInfo toInterface(currentOwner.typeOfThis); + enclInterface = currentOwner.toInterface; + val selfdef = ValDef(self) setType NoType; + copy.DefDef(tree, mods, name, tparams, List(selfdef :: vparams), tpt, rhs) + } else { + EmptyTree + } + case ValDef(_, _, _, _) if (currentOwner.isImplClass) => + EmptyTree + case _ => + tree + } + } - var self: Symbol = _; - var localTyper: analyzer.Typer = _; + private def selfRef(pos: int) = gen.Ident(self) setPos pos; + + private def staticRef(sym: Symbol) = { + sym.owner.info; + if (sym.owner.sourceModule == NoSymbol) + assert(false, "" + sym.owner + " " + sym.owner.owner.info.decls);//debug + Select(gen.mkRef(sym.owner.sourceModule), sym); + } private def addNewDefs(clazz: Symbol, stats: List[Tree]): List[Tree] = { val newDefs = new ListBuffer[Tree]; def addDef(pos: int, tree: Tree): unit = { - System.out.println("add new def to " + clazz + ": " + tree); - newDefs += localTyper.typed(atPos(pos)(tree)) + if (settings.debug.value) log("add new def to " + clazz + ": " + tree); + newDefs += localTyper.typed { + atPos(pos) { + tree + } + } } def position(sym: Symbol) = if (sym.pos == Position.NOPOS) clazz.pos else sym.pos; def addDefDef(sym: Symbol, rhs: List[Symbol] => Tree): unit = addDef(position(sym), DefDef(sym, vparamss => rhs(vparamss.head))); - if (!clazz.isImplClass) { - atPhase(phase.next) { - for (val sym <- clazz.info.decls.toList) { - if (sym hasFlag MIXEDIN) { - if (sym hasFlag SUPERACCESSOR) { - addDefDef(sym, vparams => - Apply(Select(Super(clazz, nme.EMPTY.toTypeName), sym.alias), vparams map Ident)) - } else if (sym hasFlag ACCESSOR) { - addDefDef(sym, vparams => - Select(This(clazz), sym.accessed)) - } else if (isForwarded(sym)) { - addDefDef(sym, vparams => - Apply(staticRef(sym.alias), gen.This(clazz) :: (vparams map Ident))) - } else { - addDef(position(sym), ValDef(sym)) - } + def completeSuperAccessor(stat: Tree) = stat match { + case DefDef(mods, name, tparams, List(vparams), tpt, EmptyTree) + if (stat.symbol hasFlag SUPERACCESSOR) => + assert(stat.symbol hasFlag MIXEDIN, stat); + val rhs1 = + localTyper.typed { + atPos(stat.pos) { + Apply(Select(Super(clazz, nme.EMPTY.toTypeName), stat.symbol.alias), + vparams map (vparam => Ident(vparam.symbol))) + } + } + copy.DefDef(stat, mods, name, tparams, List(vparams), tpt, rhs1) + case _ => + assert(!(stat.symbol hasFlag SUPERACCESSOR), stat); + stat + } + var stats1 = stats; + if (clazz hasFlag lateINTERFACE) { + for (val sym <- clazz.info.decls.toList) { + if ((sym hasFlag SYNTHETIC) && (sym hasFlag ACCESSOR)) + addDefDef(sym, vparamss => EmptyTree) + } + } else if (!clazz.isImplClass && !(clazz hasFlag INTERFACE)) { + for (val sym <- clazz.info.decls.toList) { + if (sym hasFlag MIXEDIN) { + if (sym hasFlag ACCESSOR) { + addDefDef(sym, vparams => { + val accessedRef = sym.tpe match { + case MethodType(List(), ConstantType(c)) => Literal(c) + case _ => Select(This(clazz), sym.accessed) + } + if (sym.isSetter) Assign(accessedRef, Ident(vparams.head)) else accessedRef}) + } else if (sym.isModule && !(sym hasFlag LIFTED)) { + val vdef = refchecks.newModuleVarDef(sym); + addDef(position(sym), vdef); + addDef(position(sym), refchecks.newModuleAccessDef(sym, vdef.symbol)); + } else if (!sym.isMethod) { + addDef(position(sym), ValDef(sym)) + } else if (!(sym hasFlag SUPERACCESSOR)) { + assert(sym.alias != NoSymbol, sym); + addDefDef(sym, vparams => + Apply(staticRef(sym.alias), gen.This(clazz) :: (vparams map Ident))) } } } + stats1 = stats map completeSuperAccessor; } - if (newDefs.hasNext) stats ::: newDefs.toList else stats + if (newDefs.hasNext) stats1 ::: newDefs.toList else stats1 } - override def transform(tree: Tree): Tree = { - try { //debug + private def postTransform(tree: Tree): Tree = atPhase(phase.next) { val sym = tree.symbol; - val tree1 = tree match { + tree match { case Template(parents, body) => - localTyper = typer.atOwner(tree, currentOwner); - tree - case DefDef(mods, name, tparams, List(vparams), tpt, rhs) => - if (isForwarded(sym)) { - self = sym.newValue(sym.pos, nme.SELF) - setFlag PARAM - setInfo toInterface(currentOwner.thisType); - val selfdef = ValDef(self) setType NoType; - copy.DefDef(tree, mods, name, tparams, List(selfdef :: vparams), tpt, rhs) - } else if (currentOwner.isImplClass) { - EmptyTree - } else tree - case ValDef(_, _, _, _) if (currentOwner.isImplClass) => - EmptyTree - case Super(_, mix) if (mix == nme.EMPTY.toTypeName && currentOwner.isImplClass) => - atPos(tree.pos){ + val parents1 = currentOwner.info.parents map (t => TypeTree(t) setPos tree.pos); + val body1 = addNewDefs(currentOwner, body); + copy.Template(tree, parents1, body1) + case Apply(Select(qual, _), args) => + assert(sym != NoSymbol, tree);//debug + if (isStatic(sym)) { + assert(sym.isConstructor || currentOwner.enclClass.isImplClass, tree); localTyper.typed { - Select(Ident(self), sym.superAccessor(self.tpe.symbol)) - } - } - case Apply(Select(qual, _), args) - if (isSelfRef(qual) && currentOwner.enclClass.isImplClass && - sym.owner.isImplClass && isStatic(sym)) => - atPos(tree.pos) { - atPhase(phase.next) { - localTyper.typed { - Apply(staticRef(sym), Ident(self) :: args) + atPos(tree.pos) { + Apply(staticRef(sym), qual :: args) } } + } else tree + case This(_) if tree.symbol.isImplClass => + assert(tree.symbol == currentOwner.enclClass, "" + tree.symbol + " " + currentOwner.enclClass); + selfRef(tree.pos) + case Select(qual @ Super(_, mix), name) => + if (currentOwner.enclClass.isImplClass) { + if (mix == nme.EMPTY.toTypeName) { + val superAccName = enclInterface.expandedName(nme.superName(sym.name)); + val superAcc = enclInterface.info.decl(superAccName) suchThat (.alias.==(sym)); + assert(superAcc != NoSymbol, tree);//debug + localTyper.typedOperator { + atPos(tree.pos){ + Select(selfRef(qual.pos), superAcc) + } + } + } else { + copy.Select(tree, selfRef(qual.pos), name) + } + } else { + if (mix == nme.EMPTY.toTypeName) tree + else copy.Select(tree, gen.This(currentOwner.enclClass) setPos qual.pos, name) + } + case Select(qual, name) if sym.owner.isImplClass && !isStatic(sym) => + if (sym.isMethod) { + assert(sym hasFlag LIFTED, sym); + val sym1 = enclInterface.info.decl(sym.name); + assert(sym1 != NoSymbol && !(sym1 hasFlag OVERLOADED), sym);//debug + tree setSymbol sym1 + } else { + val getter = sym.getter(enclInterface); + assert(getter != NoSymbol, "" + enclInterface + " " + sym); + localTyper.typed { + atPos(tree.pos) { + Apply(Select(qual, getter), List()) + } + } } - case This(_) if (sym.isImplClass) => - atPos(tree.pos)(gen.Ident(self)) - case _ => - tree - } - val tree2 = super.transform(tree1); - tree2 match { - case Template(parents, body) => - copy.Template(tree2, parents, addNewDefs(currentOwner, body)) + case Assign(Apply(lhs @ Select(qual, _), List()), rhs) => + localTyper.typed { + atPos(tree.pos) { + Apply(Select(qual, lhs.symbol.setter(enclInterface)) setPos lhs.pos, List(rhs)) + } + } case _ => - tree2 + tree + } + } + + override def transform(tree: Tree): Tree = { + try { //debug + postTransform(super.transform(preTransform(tree))) + } catch { + case ex: Throwable => + System.out.println("exception when traversing " + tree); + throw ex } - } catch {//debug - case ex: Throwable => - System.out.println("exception when traversing " + tree); - throw ex - } } } } diff --git a/sources/scala/tools/nsc/typechecker/Namers.scala b/sources/scala/tools/nsc/typechecker/Namers.scala index cb3226c705..b547301645 100755 --- a/sources/scala/tools/nsc/typechecker/Namers.scala +++ b/sources/scala/tools/nsc/typechecker/Namers.scala @@ -65,7 +65,7 @@ trait Namers: Analyzer { p.pos = pos; p.moduleClass.pos = pos; p } else { val pkg = context.owner.newPackage(pos, name); - pkg.moduleClass.setInfo(new PackageClassInfoType(new Scope(), pkg)); + pkg.moduleClass.setInfo(new PackageClassInfoType(new Scope(), pkg.moduleClass)); pkg.setInfo(pkg.moduleClass.tpe); enterInScope(pkg) } @@ -240,7 +240,10 @@ trait Namers: Analyzer { } private def deconstIfNotFinal(sym: Symbol, tpe: Type): Type = - if (sym.isVariable || !(sym hasFlag FINAL)) tpe.deconst else tpe; + if (sym.isVariable || + !(sym hasFlag FINAL) || + sym.isMethod && !(sym hasFlag ACCESSOR)) tpe.deconst + else tpe; def enterValueParams(owner: Symbol, vparamss: List[List[ValDef]]): List[List[Symbol]] = { def enterValueParam(param: ValDef): Symbol = { diff --git a/sources/scala/tools/nsc/typechecker/RefChecks.scala b/sources/scala/tools/nsc/typechecker/RefChecks.scala index 71ac61b4f6..f78c74c821 100755 --- a/sources/scala/tools/nsc/typechecker/RefChecks.scala +++ b/sources/scala/tools/nsc/typechecker/RefChecks.scala @@ -51,6 +51,31 @@ abstract class RefChecks extends InfoTransform { } else tp } + // var m$: T = null; or, if class member: local var m$: T = _; + def newModuleVarDef(accessor: Symbol) = { + val mvar = accessor.owner.newVariable(accessor.pos, nme.moduleVarName(accessor.name)) + setInfo accessor.tpe.finalResultType; + if (mvar.owner.isClass) { + mvar setFlag (PRIVATE | LOCAL | SYNTHETIC); + mvar.owner.info.decls.enter(mvar); + } + ValDef(mvar, if (mvar.owner.isClass) EmptyTree else Literal(Constant(null))) + } + + // def m: T = { if (m$ == null) m$ = new m$class; m$ } + def newModuleAccessDef(accessor: Symbol, mvar: Symbol) = + DefDef(accessor, vparamss => + Block( + List( + If( + Apply(Select(Ident(mvar), nme.eq), List(Literal(Constant(null)))), + Assign(Ident(mvar), + New(TypeTree(mvar.tpe), + List(for (val pt <- mvar.tpe.symbol.primaryConstructor.info.paramTypes) + yield This(accessor.owner.enclClass)))),//??? + EmptyTree)), + Ident(mvar))); + class RefCheckTransformer(unit: CompilationUnit) extends Transformer { // Override checking ------------------------------------------------------------ @@ -186,7 +211,7 @@ abstract class RefChecks extends InfoTransform { if (member hasFlag DEFERRED) { abstractClassError( infoString(member) + " is not defined" + - (if (member hasFlag MUTABLE) + (if (member.isVariable) "\n(Note that variables need to be initialized to be defined)" else "")) } else if (member.isIncompleteIn(clazz)) { val other = member.superSymbol(clazz); @@ -394,31 +419,20 @@ abstract class RefChecks extends InfoTransform { setType NoType; if (sym.isStatic) List(transform(cdef)) else { - val moduleType = sym.tpe; - - // var m$: T = null; or, if class member: local var m$: T = _; - val mvar = currentOwner.newVariable(sym.pos, name.toString() + "$") setInfo moduleType; - if (currentOwner.isClass) { - mvar setFlag (PRIVATE | LOCAL | SYNTHETIC); - sym.owner.info.decls.enter(mvar); - } - val vdef = localTyper.typed( - ValDef(mvar, if (sym.isLocal) Literal(Constant(null)) else EmptyTree)); + val vdef = + localTyper.typed { + atPos(tree.pos) { + newModuleVarDef(sym) + } + } - // def m: T = { if (m$ == null) m$ = new m$class; m$ } val ddef = atPhase(phase.next) { localTyper.typed { - DefDef(sym, vparamss => - Block( - List( - If( - Apply(Select(Ident(mvar), nme.EQ), List(Literal(Constant(null)))), - Assign(Ident(mvar), New(TypeTree(moduleType), List(List()))), - EmptyTree)), - Ident(mvar))) - } - } + newModuleAccessDef(sym, vdef.symbol) + } + } + transformTrees(List(cdef, vdef, ddef)) } @@ -466,7 +480,7 @@ abstract class RefChecks extends InfoTransform { validateVariance(sym, sym.tpe, CoVariance); case ValDef(_, _, _, _) => - validateVariance(sym, sym.tpe, if ((sym.flags & MUTABLE) != 0) NoVariance else CoVariance); + validateVariance(sym, sym.tpe, if (sym.isVariable) NoVariance else CoVariance); case AbsTypeDef(_, _, _, _) => validateVariance(sym, sym.info, CoVariance); @@ -504,19 +518,28 @@ abstract class RefChecks extends InfoTransform { case Select(qual, name) => if (sym.isSourceMethod && sym.hasFlag(CASE)) result = toConstructor - else if (sym hasFlag DEFERRED) { - qual match { - case Super(qualifier, mixin) => - val base = currentOwner.enclClass; + else qual match { + case Super(qualifier, mixin) => + val base = currentOwner.enclClass; + if (sym hasFlag DEFERRED) { val member = sym.overridingSymbol(base); if (mixin != nme.EMPTY.toTypeName || member == NoSymbol || !((member hasFlag ABSOVERRIDE) && member.isIncompleteIn(base))) unit.error(tree.pos, "symbol accessed from super may not be abstract"); - case _ => - } - } else if (sym.alias != NoSymbol) { - qual match { - case This(_) => + } + //System.out.println("super: " + tree + " in " + base);//DEBUG + if (base.isTrait && mixin == nme.EMPTY.toTypeName) { + val superAccName = nme.superName(sym.name); + val superAcc = base.info.decl(superAccName) suchThat (.alias.==(sym)); + assert(superAcc != NoSymbol, "" + sym + " " + base + " " + superAccName);//debug + val tree1 = Select(This(base), superAcc); + if (settings.debug.value) log("super-replacement: " + tree + "=>" + tree1); + result = atPos(tree.pos) { + Select(gen.This(base), superAcc) setType superAcc.tpe + } + } + case This(_) => + if ((sym hasFlag PARAMACCESSOR) && (sym.alias != NoSymbol)) { result = typed { Select( Super(qual.symbol, qual.symbol.info.parents.head.symbol.name) setPos qual.pos, @@ -524,8 +547,8 @@ abstract class RefChecks extends InfoTransform { } if (settings.debug.value) System.out.println("alias replacement: " + tree + " ==> " + result);//debug - case _ => - } + } + case _ => } case _ => } diff --git a/sources/scala/tools/nsc/typechecker/TreeCheckers.scala b/sources/scala/tools/nsc/typechecker/TreeCheckers.scala index d109a46ec8..95a3af20bf 100644 --- a/sources/scala/tools/nsc/typechecker/TreeCheckers.scala +++ b/sources/scala/tools/nsc/typechecker/TreeCheckers.scala @@ -62,7 +62,9 @@ abstract class TreeCheckers extends Analyzer { try { tree match { case DefDef(_, _, _, _, _, _) => - if (tree.symbol.hasFlag(ACCESSOR) && !tree.symbol.hasFlag(DEFERRED)) { + if (tree.symbol.hasFlag(ACCESSOR) && + !tree.symbol.hasFlag(DEFERRED) && + !tree.symbol.tpe.resultType.isInstanceOf[ConstantType]) { assert(tree.symbol.accessed != NoSymbol); assert(tree.symbol.accessed.getter(tree.symbol.owner) == tree.symbol || tree.symbol.accessed.setter(tree.symbol.owner) == tree.symbol); @@ -73,6 +75,16 @@ abstract class TreeCheckers extends Analyzer { } case Apply(_, args) => assert(args forall (EmptyTree !=)) + case Select(_, _) => + assert(tree.symbol != NoSymbol, tree); + case This(_) => + if (!(tree.symbol.isStatic && (tree.symbol hasFlag MODULE))) { + var o = currentOwner; + while (o != tree.symbol) { + o = o.owner; + assert(o != NoSymbol, tree) + } + } case _ => } if (tree.pos == Position.NOPOS && tree != EmptyTree) { diff --git a/sources/scala/tools/nsc/typechecker/Typers.scala b/sources/scala/tools/nsc/typechecker/Typers.scala index 2c22fe5f53..1b108537b7 100755 --- a/sources/scala/tools/nsc/typechecker/Typers.scala +++ b/sources/scala/tools/nsc/typechecker/Typers.scala @@ -223,17 +223,20 @@ abstract class Typers: Analyzer { } else tree } - class AddSuperAccessors(clazz: Symbol) extends Traverser { + class AddSuperAccessors(clazz: Symbol, accdefs: ListBuffer[Tree]) extends Traverser { override def traverse(tree: Tree) = tree match { case Select(Super(_, mix), _) => if (tree.isTerm && mix == nme.EMPTY.toTypeName) { - if (tree.symbol.superAccessor(clazz) == NoSymbol) { - System.out.println("add super acc " + tree.symbol + tree.symbol.locationString + " to " + clazz);//debug - clazz.info.decls enter - clazz.newMethod(tree.pos, nme.superName(tree.symbol.name)) + val supername = nme.superName(tree.symbol.name); + if (clazz.info.decl(supername).suchThat(.alias.==(tree.symbol)) == NoSymbol) { + if (settings.debug.value) log("add super acc " + tree.symbol + tree.symbol.locationString + " to " + clazz);//debug + val superAcc = + clazz.newMethod(tree.pos, supername) .setFlag(SUPERACCESSOR | PRIVATE) .setAlias(tree.symbol) - .setInfo(clazz.thisType.memberType(tree.symbol)) + .setInfo(clazz.thisType.memberType(tree.symbol)); + clazz.info.decls enter superAcc; + accdefs += typed(DefDef(superAcc, vparamss => EmptyTree)); } } case Template(_, _) => @@ -383,32 +386,34 @@ abstract class Typers: Analyzer { tree.tpe } - def parentTypes(templ: Template): List[Tree] = { - var supertpt = typedTypeConstructor(templ.parents.head); - var mixins = templ.parents.tail map typedType; - // If first parent is trait, make it first mixin and add its superclass as first parent - while (supertpt.tpe.symbol != null && supertpt.tpe.symbol.initialize.isTrait) { - mixins = typedType(supertpt) :: mixins; - supertpt = TypeTree(supertpt.tpe.parents.head) setPos supertpt.pos; - } - if (supertpt.hasSymbol) { - val tparams = supertpt.symbol.typeParams; - if (!tparams.isEmpty) { - val constr @ DefDef(_, _, _, vparamss, _, Apply(_, superargs)) = - treeInfo.firstConstructor(templ.body); - val outercontext = context.outer.outer; - supertpt = TypeTree( - newTyper(context.outer.outer.makeNewScope(constr, context.outer.outer.owner)) - .completeSuperType( - supertpt, - tparams, - vparamss map (.map(.duplicate.asInstanceOf[ValDef])), - superargs map (.duplicate))) setPos supertpt.pos; - } + def parentTypes(templ: Template): List[Tree] = + if (templ.parents.isEmpty) List() + else { + var supertpt = typedTypeConstructor(templ.parents.head); + var mixins = templ.parents.tail map typedType; + // If first parent is trait, make it first mixin and add its superclass as first parent + while (supertpt.tpe.symbol != null && supertpt.tpe.symbol.initialize.isTrait) { + mixins = typedType(supertpt) :: mixins; + supertpt = TypeTree(supertpt.tpe.parents.head) setPos supertpt.pos; + } + if (supertpt.hasSymbol) { + val tparams = supertpt.symbol.typeParams; + if (!tparams.isEmpty) { + val constr @ DefDef(_, _, _, vparamss, _, Apply(_, superargs)) = + treeInfo.firstConstructor(templ.body); + val outercontext = context.outer.outer; + supertpt = TypeTree( + newTyper(context.outer.outer.makeNewScope(constr, context.outer.outer.owner)) + .completeSuperType( + supertpt, + tparams, + vparamss map (.map(.duplicate.asInstanceOf[ValDef])), + superargs map (.duplicate))) setPos supertpt.pos; + } + } + //System.out.println("parents(" + context.owner + ") = " + supertpt :: mixins);//DEBUG + List.mapConserve(supertpt :: mixins)(tpt => checkNoEscaping.privates(context.owner, tpt)) } - //System.out.println("parents(" + context.owner + ") = " + supertpt :: mixins);//DEBUG - List.mapConserve(supertpt :: mixins)(tpt => checkNoEscaping.privates(context.owner, tpt)) - } /** Check that * - all parents are class types, @@ -498,7 +503,7 @@ abstract class Typers: Analyzer { atPos(vdef.pos)( DefDef(setter, vparamss => if ((mods & DEFERRED) != 0) EmptyTree - else typed(Assign(Select(This(value.owner), getterDef.symbol), + else typed(Assign(Select(This(value.owner), value), Ident(vparamss.head.head))))) } val gs = if ((mods & MUTABLE) != 0) List(getterDef, setterDef) @@ -524,9 +529,12 @@ abstract class Typers: Analyzer { new Namer(context.outer.make(templ, clazz, clazz.info.decls)).enterSyms(templ.body); validateParentClasses(parents1, selfType); val body1 = templ.body flatMap addGetterSetter; - val body2 = typedStats(body1, templ.symbol); - if (clazz.isTrait && phase.id <= typerPhase.id) - new AddSuperAccessors(clazz).traverseTrees(body2); + var body2 = typedStats(body1, templ.symbol); + if (clazz.isTrait && phase.id <= typerPhase.id) { + val superAccs = new ListBuffer[Tree]; + new AddSuperAccessors(clazz, superAccs).traverseTrees(body2); + body2 = superAccs.toList ::: body2; + } copy.Template(templ, parents1, body2) setType clazz.tpe } @@ -535,7 +543,7 @@ abstract class Typers: Analyzer { var tpt1 = checkNoEscaping.privates(sym, typedType(vdef.tpt)); val rhs1 = if (vdef.rhs.isEmpty) { - if ((sym hasFlag MUTABLE) && sym.owner.isTerm && phase.id <= typerPhase.id) + if (sym.isVariable && sym.owner.isTerm && phase.id <= typerPhase.id) error(vdef.pos, "local variables must be initialized"); vdef.rhs } else { @@ -575,14 +583,14 @@ abstract class Typers: Analyzer { if (vparamss.exists(.exists(vp => vp.symbol == superArg.symbol))) { var alias = superAcc.initialize.alias; if (alias == NoSymbol) - alias = if (superAcc.hasGetter) superAcc.getter(superAcc.owner) else superAcc; + alias = superAcc.getter(superAcc.owner); if (alias != NoSymbol && superClazz.info.nonPrivateMember(alias.name) != alias) alias = NoSymbol; if (alias != NoSymbol) { var ownAcc = clazz.info.decl(name); if (ownAcc hasFlag ACCESSOR) ownAcc = ownAcc.accessed; - System.out.println("" + ownAcc + " has alias " + alias + alias.locationString);//debug + if (settings.debug.value) log("" + ownAcc + " has alias " + alias + alias.locationString);//debug ownAcc.asInstanceOf[TermSymbol].setAlias(alias) } } @@ -720,18 +728,19 @@ abstract class Typers: Analyzer { val vparams = List.mapConserve(fun.vparams)(typedValDef); val body = typed(fun.body, respt); val formals = vparamSyms map (.tpe); - val funtpe = typeRef(clazz.tpe.prefix, clazz, formals ::: List(body.tpe)); + val restpe = body.tpe.deconst; + val funtpe = typeRef(clazz.tpe.prefix, clazz, formals ::: List(restpe)); assert(context.owner != RootClass);//debug val anonClass = context.owner.newAnonymousFunctionClass(fun.pos) setFlag (FINAL | SYNTHETIC); anonClass setInfo ClassInfoType( List(ObjectClass.tpe, funtpe, ScalaObjectClass.tpe), new Scope(), anonClass); val applyMethod = anonClass.newMethod(fun.pos, nme.apply) - setFlag FINAL setInfo MethodType(formals, body.tpe); + setFlag FINAL setInfo MethodType(formals, restpe); anonClass.info.decls enter applyMethod; for (val vparam <- vparamSyms) vparam.owner = applyMethod; new ChangeOwnerTraverser(context.owner, applyMethod).traverse(body); var members = List( - DefDef(FINAL, nme.apply, List(), List(vparams), TypeTree(body.tpe), body) + DefDef(FINAL, nme.apply, List(), List(vparams), TypeTree(restpe), body) setSymbol applyMethod); if (pt.symbol == PartialFunctionClass) { val isDefinedAtMethod = anonClass.newMethod(fun.pos, nme.isDefinedAt) |