diff options
57 files changed, 3081 insertions, 1479 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 9c7fc42f00..9b77890486 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -127,7 +127,6 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable // ------------------ Reporting ------------------------------------- - import util.NoPosition def error(msg: String) = reporter.error(NoPosition, msg) def warning(msg: String) = reporter.warning(NoPosition, msg) def inform(msg: String) = reporter.info(NoPosition, msg, true) @@ -928,7 +927,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable def getFile(clazz: Symbol, suffix: String): File = { val outdirname = settings.outputDirs.outputDirFor(clazz.sourceFile) var outdir = new File(if (outdirname.path == "") "." else outdirname.path) - val filename = clazz.fullNameString('.') + val filename = clazz.fullName var start = 0 var end = filename.indexOf('.', start) while (end >= start) { diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 7f2bcf99c5..104e00a03d 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -192,7 +192,7 @@ abstract class TreeGen mkTypeApply(value, tpe, (if (any) Any_asInstanceOf else Object_asInstanceOf)) def mkClassOf(tp: Type): Tree = - Literal(Constant(tp)) setType Predef_classOfType(tp) + Literal(Constant(tp)) setType ClassType(tp) def mkCheckInit(tree: Tree): Tree = { val tpe = diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala index aa0e484578..2e543a0960 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala @@ -98,7 +98,7 @@ abstract class TreeInfo { def mayBeVarGetter(sym: Symbol) = sym.info match { case PolyType(List(), _) => sym.owner.isClass && !sym.isStable - case _: ImplicitMethodType => sym.owner.isClass && !sym.isStable + case mt: MethodType => mt.isImplicit && sym.owner.isClass && !sym.isStable case _ => false } diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala index c0b2fb41be..fd5a5b391e 100644 --- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala +++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala @@ -12,14 +12,13 @@ import java.io.{ OutputStream, PrintWriter, StringWriter, Writer } import symtab.Flags._ import symtab.SymbolTable -abstract class TreePrinters { - val trees: SymbolTable - import trees._ +trait TreePrinters { trees: SymbolTable => + import treeInfo.{ IsTrue, IsFalse } final val showOuterTests = false - class TreePrinter(out: PrintWriter) { + class TreePrinter(out: PrintWriter) extends trees.AbsTreePrinter(out) { protected var indentMargin = 0 protected val indentStep = 2 protected var indentString = " " // 40 @@ -32,7 +31,7 @@ abstract class TreePrinters { protected def doPrintPositions = settings.Xprintpos.value def printPosition(tree: Tree) = if (doPrintPositions) print(tree.pos.show) - def println { + def println() { out.println() while (indentMargin > indentString.length()) indentString += indentString @@ -49,8 +48,8 @@ abstract class TreePrinters { } def printColumn(ts: List[Tree], start: String, sep: String, end: String) { - print(start); indent; println - printSeq(ts){print}{print(sep); println}; undent; println; print(end) + 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) { @@ -138,7 +137,7 @@ abstract class TreePrinters { annots foreach (annot => print("@"+annot+" ")) if (annots.nonEmpty) - println + println() } def print(str: String) { out.print(str) } @@ -221,7 +220,7 @@ abstract class TreePrinters { } case DocDef(comment, definition) => - print(comment.raw); println; print(definition) + print(comment.raw); println(); print(definition) case Template(parents, self, body) => val currentOwner1 = currentOwner @@ -287,10 +286,10 @@ abstract class TreePrinters { print(lhs); print(" = "); print(rhs) case If(cond, thenp, elsep) => - print("if ("); print(cond); print(")"); indent; println + print("if ("); print(cond); print(")"); indent; println() print(thenp); undent if (!elsep.isEmpty) { - println; print("else"); indent; println; print(elsep); undent + println(); print("else"); indent; println(); print(elsep); undent } case Return(expr) => @@ -383,9 +382,6 @@ abstract class TreePrinters { case SelectFromArray(qualifier, name, _) => print(qualifier); print(".<arr>"); print(symName(tree, name)) - case tree: StubTree => - print(tree.toString) - case tree => print("<unknown tree of class "+tree.getClass+">") } @@ -399,7 +395,7 @@ abstract class TreePrinters { printRaw( if (tree.isDef && tree.symbol != NoSymbol && tree.symbol.isInitialized) { tree match { - case ClassDef(_, _, _, impl @ Template(ps, trees.emptyValDef, body)) + case ClassDef(_, _, _, impl @ Template(ps, emptyValDef, body)) if (tree.symbol.thisSym != tree.symbol) => ClassDef(tree.symbol, Template(ps, ValDef(tree.symbol.thisSym), body)) case ClassDef(_, _, _, impl) => ClassDef(tree.symbol, impl) @@ -415,15 +411,14 @@ abstract class TreePrinters { def print(unit: CompilationUnit) { print("// Scala source: " + unit.source + LINE_SEPARATOR) if (unit.body ne null) { - print(unit.body); println + print(unit.body); println() } else { print("<null>") } - println; flush + println(); flush } } - /** A tree printer which is stingier about vertical whitespace and unnecessary * punctuation than the standard one. */ @@ -517,7 +512,7 @@ abstract class TreePrinters { // If thenp or elsep has only one statement, it doesn't need more than one line. case If(cond, thenp, elsep) => def ifIndented(x: Tree) = { - indent ; println ; printRaw(x) ; undent + indent ; println() ; printRaw(x) ; undent } val List(thenStmts, elseStmts) = List(thenp, elsep) map allStatements @@ -531,12 +526,12 @@ abstract class TreePrinters { if (elseStmts.nonEmpty) { print("else") - indent ; println + indent ; println() elseStmts match { case List(x) => printRaw(x) case _ => printRaw(elsep) } - undent ; println + undent ; println() } case _ => s() } @@ -648,16 +643,22 @@ abstract class TreePrinters { printer.flush() buffer.toString } - def asString(t: Tree): String = asStringInternal(t, create) - def asCompactString(t: Tree): String = asStringInternal(t, createCompact) - - def create(writer: PrintWriter): TreePrinter = new TreePrinter(writer) - def create(stream: OutputStream): TreePrinter = create(new PrintWriter(stream)) - def create(): TreePrinter = create(new PrintWriter(ConsoleWriter)) - - def createCompact(writer: PrintWriter): CompactTreePrinter = new CompactTreePrinter(writer) - def createCompact(stream: OutputStream): CompactTreePrinter = createCompact(new PrintWriter(stream)) - def createCompact(): CompactTreePrinter = createCompact(new PrintWriter(ConsoleWriter)) + def asString(t: Tree): String = asStringInternal(t, newStandardTreePrinter) + def asCompactString(t: Tree): String = asStringInternal(t, newCompactTreePrinter) + + def newStandardTreePrinter(writer: PrintWriter): TreePrinter = new TreePrinter(writer) + def newStandardTreePrinter(stream: OutputStream): TreePrinter = newStandardTreePrinter(new PrintWriter(stream)) + def newStandardTreePrinter(): TreePrinter = newStandardTreePrinter(new PrintWriter(ConsoleWriter)) + + def newCompactTreePrinter(writer: PrintWriter): CompactTreePrinter = new CompactTreePrinter(writer) + def newCompactTreePrinter(stream: OutputStream): CompactTreePrinter = newCompactTreePrinter(new PrintWriter(stream)) + def newCompactTreePrinter(): CompactTreePrinter = newCompactTreePrinter(new PrintWriter(ConsoleWriter)) + + def newTreePrinter(writer: PrintWriter): TreePrinter = + if (settings.Ycompacttrees.value) newCompactTreePrinter(writer) + else newStandardTreePrinter(writer) + def newTreePrinter(stream: OutputStream): TreePrinter = newTreePrinter(new PrintWriter(stream)) + def newTreePrinter(): TreePrinter = newTreePrinter(new PrintWriter(ConsoleWriter)) /** A writer that writes to the current Console and * is sensitive to replacement of the Console's diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index 21f2919535..4f2cd8d01f 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -7,20 +7,12 @@ package scala.tools.nsc package ast -import java.io.{PrintWriter, StringWriter} - import scala.collection.mutable.ListBuffer -import scala.tools.nsc.symtab.{Flags, SymbolTable} +import scala.tools.nsc.symtab.SymbolTable import scala.tools.nsc.symtab.Flags._ -import scala.tools.nsc.util.{FreshNameCreator, HashSet, Position, NoPosition, SourceFile} - - -trait Trees { - self: SymbolTable => - - //statistics +import scala.tools.nsc.util.{FreshNameCreator, HashSet, SourceFile} - var nodeCount = 0 +trait Trees extends reflect.generic.Trees { self: SymbolTable => trait CompilationUnitTrait { var body: Tree @@ -32,13 +24,7 @@ trait Trees { // sub-components -------------------------------------------------- - object treePrinters extends { - val trees: Trees.this.type = Trees.this - } with TreePrinters - - lazy val treePrinter = - if (settings.Ycompacttrees.value) treePrinters.createCompact() - else treePrinters.create() + lazy val treePrinter = newTreePrinter() object treeInfo extends { val trees: Trees.this.type = Trees.this @@ -46,131 +32,39 @@ trait Trees { val treeCopy = new LazyTreeCopier() - // modifiers -------------------------------------------------------- - - /** @param privateWithin the qualifier for a private (a type name) - * or nme.EMPTY.toTypeName, if none is given. - * @param annotations the annotations for the definition. - * <strong>Note:</strong> the typechecker drops these annotations, - * use the AnnotationInfo's (Symbol.annotations) in later phases. - */ - case class Modifiers(flags: Long, privateWithin: Name, annotations: List[Tree], positions: Map[Long, Position]) { - def isCovariant = hasFlag(COVARIANT ) // marked with `+' - def isContravariant = hasFlag(CONTRAVARIANT) // marked with `-' - def isPrivate = hasFlag(PRIVATE ) - def isProtected = hasFlag(PROTECTED) - def isVariable = hasFlag(MUTABLE ) - def isArgument = hasFlag(PARAM ) - def isAccessor = hasFlag(ACCESSOR ) - def isOverride = hasFlag(OVERRIDE ) - def isAbstract = hasFlag(ABSTRACT ) - def isDeferred = hasFlag(DEFERRED ) - def isCase = hasFlag(CASE ) - def isLazy = hasFlag(LAZY ) - def isSealed = hasFlag(SEALED ) - def isFinal = hasFlag(FINAL ) - def isTrait = hasFlag(TRAIT | notDEFERRED) // (part of DEVIRTUALIZE) - def isImplicit = hasFlag(IMPLICIT ) - def isPublic = !isPrivate && !isProtected - def hasFlag(flag: Long) = (flag & flags) != 0L - def & (flag: Long): Modifiers = { - val flags1 = flags & flag - if (flags1 == flags) this - else Modifiers(flags1, privateWithin, annotations, positions) - } - def &~ (flag: Long): Modifiers = { - val flags1 = flags & (~flag) - if (flags1 == flags) this - else Modifiers(flags1, privateWithin, annotations, positions) - } - def | (flag: Long): Modifiers = { - val flags1 = flags | flag - if (flags1 == flags) this - else Modifiers(flags1, privateWithin, annotations, positions) - } - def withAnnotations(annots: List[Tree]) = - if (annots.isEmpty) this - else Modifiers(flags, privateWithin, annotations ::: annots, positions) - def withPosition(flag: Long, position: Position) = - Modifiers(flags, privateWithin, annotations, positions + (flag -> position)) - } - - def Modifiers(flags: Long, privateWithin: Name): Modifiers = Modifiers(flags, privateWithin, List(), new Map.EmptyMap) - def Modifiers(flags: Long): Modifiers = Modifiers(flags, nme.EMPTY.toTypeName) - - val NoMods = Modifiers(0) - - // @M helper method for asserts that check consistency in kinding - //def kindingIrrelevant(tp: Type) = (tp eq null) || phase.name == "erasure" || phase.erasedTypes - - abstract class Tree extends Product { - if (util.Statistics.enabled) { - util.Statistics.nodeByType(getClass) += 1 - } - - val id = nodeCount -// assert(id != 1223) - nodeCount += 1 - - private var rawpos: Position = NoPosition + implicit def treeWrapper(tree: Tree): TreeOps = new TreeOps(tree) - def pos = rawpos + class TreeOps(tree: Tree) { - private[this] var rawtpe: Type = _ - - def tpe = rawtpe - def tpe_=(t: Type) = rawtpe = t - - def setPos(pos: Position): this.type = { - rawpos = pos -/* - for (c <- this.children) - if (c.pos.isOpaqueRange && !pos.includes(c.pos)) { - assert(false, "non-enclosing positions in "+this) - } -*/ - this - } - - /** Set tpe to give `tp` and return this. - */ - def setType(tp: Type): this.type = { - /*assert(kindingIrrelevant(tp) || !kindStar || !tp.isHigherKinded, - tp+" should not be higher-kinded"); */ - tpe = tp - this + def isTerm: Boolean = tree match { + case _: TermTree => true + case Bind(name, _) => name.isTermName + case Select(_, name) => name.isTermName + case Ident(name) => name.isTermName + case Annotated(_, arg) => arg.isTerm + case DocDef(_, defn) => defn.isTerm + case _ => false } - /** Like `setType`, but if this is a previously empty TypeTree - * that fact is remembered so that resetType will snap back. - */ - def defineType(tp: Type): this.type = setType(tp) - - /** Reset type to `null`, with special handling of TypeTrees and the EmptyType - */ - def resetType() { tpe = null } - - def symbol: Symbol = null - def symbol_=(sym: Symbol) { - throw new Error("symbol_= inapplicable for " + this) + def isType: Boolean = tree match { + case _: TypTree => true + case Bind(name, _) => name.isTypeName + case Select(_, name) => name.isTypeName + case Ident(name) => name.isTypeName + case Annotated(_, arg) => arg.isType + case DocDef(_, defn) => defn.isType + case _ => false } - def setSymbol(sym: Symbol): this.type = { symbol = sym; this } - def hasSymbol = false - def isDef = false - def isTerm = false - def isType = false - def isEmpty = false - - def isErroneous = (tpe ne null) && tpe.isErroneous + def isErroneous = (tree.tpe ne null) && tree.tpe.isErroneous /** Apply `f' to each subtree */ - def foreach(f: Tree => Unit) { new ForeachTreeTraverser(f).traverse(this) } + def foreach(f: Tree => Unit) { new ForeachTreeTraverser(f).traverse(tree) } /** Find all subtrees matching predicate `p' */ def filter(f: Tree => Boolean): List[Tree] = { val ft = new FilterTreeTraverser(f) - ft.traverse(this) + ft.traverse(tree) ft.hits.toList } @@ -179,63 +73,20 @@ trait Trees { */ def find(p: Tree => Boolean): Option[Tree] = { val ft = new FindTreeTraverser(p) - ft.traverse(this) + ft.traverse(tree) ft.result } /** Is there part of this tree which satisfies predicate `p'? */ def exists(p: Tree => Boolean): Boolean = !find(p).isEmpty - /** The direct child trees of this tree - * EmptyTrees are always omitted. Lists are collapsed. - */ - def children: List[Tree] = { - def subtrees(x: Any): List[Tree] = x match { - case EmptyTree => List() - case t: Tree => List(t) - case xs: List[_] => xs flatMap subtrees - case _ => List() - } - productIterator.toList flatMap subtrees - } - - override def toString(): String = - if (settings.Ycompacttrees.value) treePrinters.asCompactString(this) - else treePrinters.asString(this) - - override def hashCode(): Int = super.hashCode() - - override def equals(that: Any): Boolean = that match { - case t: Tree => this eq t - case _ => false - } - def hashCodeStructure: Int = { - var hc = getClass.hashCode - def f(what : Any) : Unit = what match { - case what : Tree => hc += what.hashCodeStructure - case what : Iterable[_] => what.foreach(f) - case what : Product => g(what) - case null => - case what => hc += what.hashCode - } - def g(what: Product) { - hc += what.productArity - var i = 0 - while (i < what.productArity) { - f(what.productElement(i)) - i += 1 - } - } - g(this) - hc - } def equalsStructure(that : Tree) = equalsStructure0(that){case (t0,t1) => false} def equalsStructure0(that: Tree)(f : (Tree,Tree) => Boolean): Boolean = { - if (this == that) return true - if (this.getClass != that.getClass) return false - val this0 = this.asInstanceOf[Product] + if (tree == that) return true + if (tree.getClass != that.getClass) return false + val tree0 = tree.asInstanceOf[Product] val that0 = that.asInstanceOf[Product] - assert(this0.productArity == that0.productArity) + assert(tree0.productArity == that0.productArity) def equals0(thiz: Any, that: Any): Boolean = thiz match { case thiz: Tree => f(thiz,that.asInstanceOf[Tree]) || thiz.equalsStructure0(that.asInstanceOf[Tree])(f) @@ -250,130 +101,26 @@ trait Trees { case thiz => thiz == that } - val results = for (i <- 0.until(this0.productArity).toList) yield - equals0(this0.productElement(i), that0.productElement(i)) + val results = for (i <- 0.until(tree0.productArity).toList) yield + equals0(tree0.productElement(i), that0.productElement(i)) val b = results.foldLeft(true)((x,y) => x && y) - if (b) (this,that) match { - case (this0 : TypeTree, that0 : TypeTree) if this0.original != null && that0.original != null => - this0.original.equalsStructure0(that0.original)(f) + if (b) (tree,that) match { + case (tree0 : TypeTree, that0 : TypeTree) if tree0.original != null && that0.original != null => + tree0.original.equalsStructure0(that0.original)(f) case _ => true } else false } - /** Make a copy of this tree, keeping all attributes, - * except that all positions are focussed (so nothing - * in this tree will be found when searching by position). - */ - def duplicate: this.type = - (duplicator transform this).asInstanceOf[this.type] - - def shallowDuplicate: this.type = - ((new ShallowDuplicator(this)) transform this).asInstanceOf[this.type] - - def copyAttrs(tree: Tree): this.type = { - rawpos = tree.rawpos - tpe = tree.tpe - if (hasSymbol) symbol = tree.symbol - this - } - } - - trait SymTree extends Tree { - override def hasSymbol = true - override var symbol: Symbol = NoSymbol - } - - trait RefTree extends SymTree { - def name: Name - } - - abstract class DefTree extends SymTree { - def name: Name - override def isDef = true - } - - trait TermTree extends Tree { - override def isTerm = true - } - - /** A tree for a type. Note that not all type trees implement - * this trait; in particular, Ident's are an exception. */ - trait TypTree extends Tree { - override def isType = true - } - -// ----- auxiliary objects and methods ------------------------------ - - private lazy val duplicator = new Transformer { - override val treeCopy = new StrictTreeCopier - override def transform(t: Tree) = { - val t1 = super.transform(t) - if ((t1 ne t) && t1.pos.isRange) t1 setPos t.pos.focus - t1 - } - } - - private class ShallowDuplicator(orig: Tree) extends Transformer { - override val treeCopy = new StrictTreeCopier - override def transform(tree: Tree) = - if (tree eq orig) - super.transform(tree) - else - tree + def shallowDuplicate: Tree = + (new ShallowDuplicator(tree)) transform tree } -// def nextPhase = if (phase.id > globalPhase.id) phase else phase.next; + private[scala] override def duplicateTree(tree: Tree): Tree = duplicator transform tree -// ----- tree node alternatives -------------------------------------- +// ---- values and creators --------------------------------------- - /** The empty tree */ - case object EmptyTree extends TermTree { - super.tpe_=(NoType) - override def tpe_=(t: Type) = - if (t != NoType) throw new Error("tpe_=("+t+") inapplicable for <empty>") - override def resetType() {} - override def isEmpty = true - } - - abstract class MemberDef extends DefTree { - def mods: Modifiers - def keyword: String = this match { - case TypeDef(_, _, _, _) => "type" - case ClassDef(mods, _, _, _) => if (mods.isTrait) "trait" else "class" - case DefDef(_, _, _, _, _, _) => "def" - case ModuleDef(_, _, _) => "object" - case PackageDef(_, _) => "package" - case ValDef(mods, _, _, _) => if (mods.isVariable) "var" else "val" - case _ => "" - } - final def hasFlag(mask: Long): Boolean = (mods.flags & mask) != 0L - } - - /** Package clause - */ - case class PackageDef(pid: RefTree, stats: List[Tree]) - extends MemberDef { - def name = pid.name - def mods = NoMods - } - -/* disabled, as this is now dangerous - def PackageDef(sym: Symbol, stats: List[Tree]): PackageDef = - PackageDef(Ident(sym.name), stats) setSymbol sym -*/ - - abstract class ImplDef extends MemberDef { - def impl: Template - } - - /** Class definition */ - case class ClassDef(mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template) - extends ImplDef - - /** - * @param sym the class symbol - * @param impl ... - * @return ... + /** @param sym the class symbol + * @return the implementation template */ def ClassDef(sym: Symbol, impl: Template): ClassDef = atPos(sym.pos) { @@ -393,7 +140,6 @@ trait Trees { * @param argss the supercall arguments * @param body the template statements without primary constructor * and value parameter fields. - * @return ... */ def ClassDef(sym: Symbol, constrMods: Modifiers, vparamss: List[List[ValDef]], argss: List[List[Tree]], body: List[Tree], superPos: Position): ClassDef = ClassDef(sym, @@ -401,45 +147,15 @@ trait Trees { if (sym.thisSym == sym || phase.erasedTypes) emptyValDef else ValDef(sym.thisSym), constrMods, vparamss, argss, body, superPos)) - /** Singleton object definition - * - * @param mods - * @param name - * @param impl - */ - case class ModuleDef(mods: Modifiers, name: Name, impl: Template) - extends ImplDef - /** * @param sym the class symbol - * @param impl ... - * @return ... + * @param impl the implementation template */ def ModuleDef(sym: Symbol, impl: Template): ModuleDef = atPos(sym.pos) { ModuleDef(Modifiers(sym.flags), sym.name, impl) setSymbol sym } - abstract class ValOrDefDef extends MemberDef { - def tpt: Tree - def rhs: Tree - } - - /** Value definition - * - * @param mods - * @param name - * @param tpt - * @param rhs - */ - case class ValDef(mods: Modifiers, name: Name, tpt: Tree, rhs: Tree) - extends ValOrDefDef { - assert(tpt.isType, tpt) - //assert(kindingIrrelevant(tpt.tpe) || !tpt.tpe.isHigherKinded, tpt.tpe) //@M a value definition should never be typed with a higher-kinded type (values must be classified by types with kind *) - //tpt.kindStar=true //@M turn on consistency checking in Tree - assert(rhs.isTerm, rhs) - } - def ValDef(sym: Symbol, rhs: Tree): ValDef = atPos(sym.pos) { ValDef(Modifiers(sym.flags), sym.name, @@ -449,30 +165,12 @@ trait Trees { def ValDef(sym: Symbol): ValDef = ValDef(sym, EmptyTree) - object emptyValDef - extends ValDef(Modifiers(PRIVATE), nme.WILDCARD, TypeTree(NoType), EmptyTree) { + object emptyValDef extends ValDef(Modifiers(PRIVATE), nme.WILDCARD, TypeTree(NoType), EmptyTree) { override def isEmpty = true super.setPos(NoPosition) override def setPos(pos: Position) = { assert(false); this } } - /** Method definition - * - * @param mods - * @param name - * @param tparams - * @param vparamss - * @param tpt - * @param rhs - */ - case class DefDef(mods: Modifiers, name: Name, tparams: List[TypeDef], - vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) - extends ValOrDefDef { - assert(tpt.isType, tpt) - //assert(kindingIrrelevant(tpt.tpe) || !tpt.tpe.isHigherKinded, tpt.tpe) //@M a method definition should never be typed with a higher-kinded type (values must be classified by types with kind *) - //tpt.kindStar=true //@M turn on consistency checking in Tree - assert(rhs.isTerm, rhs) - } def DefDef(sym: Symbol, mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree): DefDef = atPos(sym.pos) { @@ -498,10 +196,6 @@ trait Trees { DefDef(sym, rhs(sym.info.paramss)) } - /** Abstract type, type parameter, or type alias */ - case class TypeDef(mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree) - extends MemberDef - /** A TypeDef node which defines given `sym' with given tight hand side `rhs'. */ def TypeDef(sym: Symbol, rhs: Tree): TypeDef = atPos(sym.pos) { @@ -512,91 +206,11 @@ trait Trees { def TypeDef(sym: Symbol): TypeDef = TypeDef(sym, TypeBoundsTree(TypeTree(sym.info.bounds.lo), TypeTree(sym.info.bounds.hi))) - /** <p> - * Labelled expression - the symbols in the array (must be Idents!) - * are those the label takes as argument - * </p> - * <p> - * The symbol that is given to the labeldef should have a MethodType - * (as if it were a nested function) - * </p> - * <p> - * Jumps are apply nodes attributed with label symbol, the arguments - * will get assigned to the idents. - * </p> - * <p> - * Note: on 2005-06-09 Martin, Iuli, Burak agreed to have forward - * jumps within a Block. - * </p> - */ - case class LabelDef(name: Name, params: List[Ident], rhs: Tree) - extends DefTree with TermTree { - assert(rhs.isTerm) - } - - /** - * @param sym the class symbol - * @param params ... - * @param rhs ... - * @return ... - */ def LabelDef(sym: Symbol, params: List[Symbol], rhs: Tree): LabelDef = atPos(sym.pos) { LabelDef(sym.name, params map Ident, rhs) setSymbol sym } - /** Import selector - * - * Representation of an imported name its optional rename and their optional positions - * - * @param name the imported name - * @param namePos its position or -1 if undefined - * @param rename the name the import is renamed to (== name if no renaming) - * @param renamePos the position of the rename or -1 if undefined - */ - case class ImportSelector(name: Name, namePos: Int, rename: Name, renamePos: Int) - - /** Import clause - * - * @param expr - * @param selectors - */ - case class Import(expr: Tree, selectors: List[ImportSelector]) - extends SymTree - // The symbol of an Import is an import symbol @see Symbol.newImport - // It's used primarily as a marker to check that the import has been typechecked. - - /** Documented definition, eliminated by analyzer */ - case class DocDef(comment: DocComment, definition: Tree) - extends Tree { - override def symbol: Symbol = definition.symbol - override def symbol_=(sym: Symbol) { definition.symbol = sym } - // sean: seems to be important to the IDE - override def isDef = definition.isDef - override def isTerm = definition.isTerm - override def isType = definition.isType - } - - /** Instantiation template of a class or trait - * - * @param parents - * @param body - */ - case class Template(parents: List[Tree], self: ValDef, body: List[Tree]) - extends SymTree { - // the symbol of a template is a local dummy. @see Symbol.newLocalDummy - // the owner of the local dummy is the enclosing trait or class. - // the local dummy is itself the owner of any local blocks - // For example: - // - // class C { - // def foo // owner is C - // { - // def bar // owner is local dummy - // } - // System.err.println("TEMPLATE: " + parents) - } - /** Generates a template with constructor corresponding to * * constrmods (vparams1_) ... (vparams_n) preSuper { presupers } @@ -667,119 +281,15 @@ trait Trees { Template(parents, self, gvdefs ::: vparamss2.flatten ::: constrs ::: etdefs ::: rest) } - /** Block of expressions (semicolon separated expressions) */ - case class Block(stats: List[Tree], expr: Tree) - extends TermTree - - /** Case clause in a pattern match, eliminated by TransMatch - * (except for occurences in switch statements) - */ - case class CaseDef(pat: Tree, guard: Tree, body: Tree) - extends Tree - /** casedef shorthand */ def CaseDef(pat: Tree, body: Tree): CaseDef = CaseDef(pat, EmptyTree, body) - /** Alternatives of patterns, eliminated by TransMatch, except for - * occurences in encoded Switch stmt (=remaining Match(CaseDef(...)) - */ - case class Alternative(trees: List[Tree]) - extends TermTree - - /** Repetition of pattern, eliminated by TransMatch */ - case class Star(elem: Tree) - extends TermTree - - /** Bind of a variable to a rhs pattern, eliminated by TransMatch - * - * @param name - * @param body - */ - case class Bind(name: Name, body: Tree) - extends DefTree { - override def isTerm = name.isTermName - override def isType = name.isTypeName - } - def Bind(sym: Symbol, body: Tree): Bind = Bind(sym.name, body) setSymbol sym - case class UnApply(fun: Tree, args: List[Tree]) - extends TermTree - /** Array of expressions, needs to be translated in backend, - */ - case class ArrayValue(elemtpt: Tree, elems: List[Tree]) - extends TermTree - - /** Anonymous function, eliminated by analyzer */ - case class Function(vparams: List[ValDef], body: Tree) - extends TermTree with SymTree - // The symbol of a Function is a synthetic value of name nme.ANON_FUN_NAME - // It is the owner of the function's parameters. - - /** Assignment */ - case class Assign(lhs: Tree, rhs: Tree) - extends TermTree - - /** Either an assignment or a named argument. Only appears in argument lists, - * eliminated by typecheck (doTypedApply) - */ - case class AssignOrNamedArg(lhs: Tree, rhs: Tree) - extends TermTree - - /** Conditional expression */ - case class If(cond: Tree, thenp: Tree, elsep: Tree) - extends TermTree - - /** <p> - * Pattern matching expression (before <code>TransMatch</code>) - * Switch statements (after TransMatch) - * </p> - * <p> - * After <code>TransMatch</code>, cases will satisfy the following - * constraints: - * </p> - * <ul> - * <li>all guards are EmptyTree,</li> - * <li>all patterns will be either <code>Literal(Constant(x:Int))</code> - * or <code>Alternative(lit|...|lit)</code></li> - * <li>except for an "otherwise" branch, which has pattern - * <code>Ident(nme.WILDCARD)</code></li> - * </ul> - */ - case class Match(selector: Tree, cases: List[CaseDef]) - extends TermTree - - /** Return expression */ - case class Return(expr: Tree) - extends TermTree with SymTree - // The symbol of a Return node is the enclosing method. - - case class Try(block: Tree, catches: List[CaseDef], finalizer: Tree) - extends TermTree - - /** Throw expression */ - case class Throw(expr: Tree) - extends TermTree - - /** Object instantiation - * One should always use factory method below to build a user level new. - * - * @param tpt a class type - */ - case class New(tpt: Tree) - extends TermTree { - assert(tpt.isType) - } - - /** Factory method for object creation <code><new tpt(args_1)...(args_n)></code>. - * A New(t, as) is expanded to: - * (new t).<init>(as) - * - * @param tpt ... - * @param argss ... - * @return ... + /** Factory method for object creation `new tpt(args_1)...(args_n)` + * A `New(t, as)` is expanded to: `(new t).<init>(as)` */ def New(tpt: Tree, argss: List[List[Tree]]): Tree = { assert(!argss.isEmpty) @@ -787,279 +297,56 @@ trait Trees { (superRef /: argss) (Apply) } - /** Type annotation, eliminated by explicit outer */ - case class Typed(expr: Tree, tpt: Tree) - extends TermTree - - // Martin to Sean: Should GenericApply/TypeApply/Apply not be SymTree's? After all, - // ApplyDynamic is a SymTree. - abstract class GenericApply extends TermTree { - val fun: Tree - val args: List[Tree] - } - - /** Type application */ - case class TypeApply(fun: Tree, args: List[Tree]) - extends GenericApply { - override def symbol: Symbol = fun.symbol - override def symbol_=(sym: Symbol) { fun.symbol = sym } - } - - /** Value application */ - case class Apply(fun: Tree, args: List[Tree]) - extends GenericApply { - override def symbol: Symbol = fun.symbol - override def symbol_=(sym: Symbol) { fun.symbol = sym } - } - - /** Dynamic value application. - * In a dynamic application q.f(as) - * - q is stored in qual - * - as is stored in args - * - f is stored as the node's symbol field. - */ - case class ApplyDynamic(qual: Tree, args: List[Tree]) - extends TermTree with SymTree - // The symbol of an ApplyDynamic is the function symbol of `qual', or NoSymbol, if there is none. - - /** Super reference */ - case class Super(qual: Name, mix: Name) - extends TermTree with SymTree - // The symbol of a Super is the class _from_ which the super reference is made. - // For instance in C.super(...), it would be C. - def Super(sym: Symbol, mix: Name): Tree = Super(sym.name, mix) setSymbol sym - /** Self reference */ - case class This(qual: Name) - extends TermTree with SymTree { - // The symbol of a This is the class to which the this refers. - // For instance in C.this, it would be C. - } - def This(sym: Symbol): Tree = This(sym.name) setSymbol sym - /** Designator <qualifier> . <name> */ - case class Select(qualifier: Tree, name: Name) - extends RefTree { - override def isTerm = name.isTermName - override def isType = name.isTypeName - } - def Select(qualifier: Tree, sym: Symbol): Select = Select(qualifier, sym.name) setSymbol sym - /** Identifier <name> */ - case class Ident(name: Name) - extends RefTree { - override def isTerm = name.isTermName - override def isType = name.isTypeName - } - - class BackQuotedIdent(name: Name) extends Ident(name) - def Ident(sym: Symbol): Ident = Ident(sym.name) setSymbol sym - /** Literal */ - case class Literal(value: Constant) - extends TermTree { - assert(value ne null) - } - - def Literal(value: Any): Literal = - Literal(Constant(value)) - /** A synthetic term holding an arbitrary type. Not to be confused with * with TypTree, the trait for trees that are only used for type trees. * TypeTree's are inserted in several places, but most notably in * <code>RefCheck</code>, where the arbitrary type trees are all replaced by * TypeTree's. */ - case class TypeTree() extends TypTree { - override def symbol = if (tpe == null) null else tpe.typeSymbol - + case class TypeTree() extends AbsTypeTree { private var orig: Tree = null - private var wasEmpty: Boolean = false + private[Trees] var wasEmpty: Boolean = false def original: Tree = orig - def setOriginal(tree: Tree): this.type = { orig = tree; setPos(tree.pos); this } override def defineType(tp: Type): this.type = { wasEmpty = isEmpty setType(tp) } - - /** Reset type to null, unless type original was empty and then - * got its type via a defineType - */ - override def resetType() { - if (wasEmpty) tpe = null - } - - override def isEmpty = (tpe eq null) || tpe == NoType - } - - def TypeTree(tp: Type): TypeTree = TypeTree() setType tp - // def TypeTree(tp: Type, tree : Tree): TypeTree = TypeTree(tree) setType tp - - /** A tree that has an annotation attached to it. Only used for annotated types and - * annotation ascriptions, annotations on definitions are stored in the Modifiers. - * Eliminated by typechecker (typedAnnotated), the annotations are then stored in - * an AnnotatedType. - */ - case class Annotated(annot: Tree, arg: Tree) extends Tree { - override def isType = arg.isType - override def isTerm = arg.isTerm } - /** Singleton type, eliminated by RefCheck */ - case class SingletonTypeTree(ref: Tree) - extends TypTree + object TypeTree extends TypeTreeExtractor - /** Type selection <qualifier> # <name>, eliminated by RefCheck */ - case class SelectFromTypeTree(qualifier: Tree, name: Name) - extends TypTree with RefTree - - /** Intersection type <parent1> with ... with <parentN> { <decls> }, eliminated by RefCheck */ - case class CompoundTypeTree(templ: Template) - extends TypTree + def TypeTree(tp: Type): TypeTree = TypeTree() setType tp - /** Applied type <tpt> [ <args> ], eliminated by RefCheck */ - case class AppliedTypeTree(tpt: Tree, args: List[Tree]) - extends TypTree { - override def symbol: Symbol = tpt.symbol - override def symbol_=(sym: Symbol) { tpt.symbol = sym } + /** Documented definition, eliminated by analyzer */ + case class DocDef(comment: DocComment, definition: Tree) + extends Tree { + override def symbol: Symbol = definition.symbol + override def symbol_=(sym: Symbol) { definition.symbol = sym } + // sean: seems to be important to the IDE + override def isDef = definition.isDef } - case class TypeBoundsTree(lo: Tree, hi: Tree) - extends TypTree - - case class ExistentialTypeTree(tpt: Tree, whereClauses: List[Tree]) - extends TypTree + /** Either an assignment or a named argument. Only appears in argument lists, + * eliminated by typecheck (doTypedApply) + */ + case class AssignOrNamedArg(lhs: Tree, rhs: Tree) + extends TermTree case class Parens(args: List[Tree]) extends Tree // only used during parsing - /** Array selection <qualifier> . <name> only used during erasure */ - case class SelectFromArray(qualifier: Tree, name: Name, erasure: Type) - extends TermTree with RefTree - - trait StubTree extends Tree { - def underlying : AnyRef - override def equalsStructure0(that: Tree)(f : (Tree,Tree) => Boolean): Boolean = this eq that - } - -/* A standard pattern match - case EmptyTree => - case PackageDef(pid, stats) => - // package pid { stats } - case ClassDef(mods, name, tparams, impl) => - // mods class name [tparams] impl where impl = extends parents { defs } - case ModuleDef(mods, name, impl) => (eliminated by refcheck) - // mods object name impl where impl = extends parents { defs } - case ValDef(mods, name, tpt, rhs) => - // mods val name: tpt = rhs - // note missing type information is expressed by tpt = TypeTree() - case DefDef(mods, name, tparams, vparamss, tpt, rhs) => - // mods def name[tparams](vparams_1)...(vparams_n): tpt = rhs - // note missing type information is expressed by tpt = TypeTree() - case TypeDef(mods, name, tparams, rhs) => (eliminated by erasure) - // mods type name[tparams] = rhs - // mods type name[tparams] >: lo <: hi, where lo, hi are in a TypeBoundsTree, - and DEFERRED is set in mods - case LabelDef(name, params, rhs) => - // used for tailcalls and like - // while/do are desugared to label defs as follows: - // while (cond) body ==> LabelDef($L, List(), if (cond) { body; L$() } else ()) - // do body while (cond) ==> LabelDef($L, List(), body; if (cond) L$() else ()) - case Import(expr, selectors) => (eliminated by typecheck) - // import expr.{selectors} - // Selectors are a list of pairs of names (from, to). - // The last (and maybe only name) may be a nme.WILDCARD - // for instance - // import qual.{x, y => z, _} would be represented as - // Import(qual, List(("x", "x"), ("y", "z"), (WILDCARD, null))) - case DocDef(comment, definition) => (eliminated by typecheck) - // /** comment */ definition - case Template(parents, self, body) => - // extends parents { self => body } - // if self is missing it is represented as emptyValDef - case Block(stats, expr) => - // { stats; expr } - case CaseDef(pat, guard, body) => (eliminated by transmatch/explicitouter) - // case pat if guard => body - case Alternative(trees) => (eliminated by transmatch/explicitouter) - // pat1 | ... | patn - case Star(elem) => (eliminated by transmatch/explicitouter) - // pat* - case Bind(name, body) => (eliminated by transmatch/explicitouter) - // name @ pat - case UnApply(fun: Tree, args) (introduced by typer, eliminated by transmatch/explicitouter) - // used for unapply's - case ArrayValue(elemtpt, trees) => (introduced by uncurry) - // used to pass arguments to vararg arguments - // for instance, printf("%s%d", foo, 42) is translated to after uncurry to: - // Apply( - // Ident("printf"), - // Literal("%s%d"), - // ArrayValue(<Any>, List(Ident("foo"), Literal(42)))) - case Function(vparams, body) => (eliminated by lambdaLift) - // vparams => body where vparams:List[ValDef] - case Assign(lhs, rhs) => - // lhs = rhs - case AssignOrNamedArg(lhs, rhs) => (eliminated by typecheck) - // lhs = rhs - case If(cond, thenp, elsep) => - // if (cond) thenp else elsep - case Match(selector, cases) => - // selector match { cases } - case Return(expr) => - // return expr - case Try(block, catches, finalizer) => - // try block catch { catches } finally finalizer where catches: List[CaseDef] - case Throw(expr) => - // throw expr - case New(tpt) => - // new tpt always in the context: (new tpt).<init>[targs](args) - case Typed(expr, tpt) => (eliminated by erasure) - // expr: tpt - case TypeApply(fun, args) => - // fun[args] - case Apply(fun, args) => - // fun(args) - // for instance fun[targs](args) is expressed as Apply(TypeApply(fun, targs), args) - case ApplyDynamic(qual, args) (introduced by erasure, eliminated by cleanup) - // fun(args) - case Super(qual, mix) => - // qual.super[mix] if qual and/or mix is empty, ther are nme.EMPTY.toTypeName - case This(qual) => - // qual.this - case Select(qualifier, selector) => - // qualifier.selector - case Ident(name) => - // name - // note: type checker converts idents that refer to enclosing fields or methods - // to selects; name ==> this.name - case Literal(value) => - // value - case TypeTree() => (introduced by refcheck) - // a type that's not written out, but given in the tpe attribute - case Annotated(annot, arg) => (eliminated by typer) - // arg @annot for types, arg: @annot for exprs - case SingletonTypeTree(ref) => (eliminated by uncurry) - // ref.type - case SelectFromTypeTree(qualifier, selector) => (eliminated by uncurry) - // qualifier # selector, a path-dependent type p.T is expressed as p.type # T - case CompoundTypeTree(templ: Template) => (eliminated by uncurry) - // parent1 with ... with parentN { refinement } - case AppliedTypeTree(tpt, args) => (eliminated by uncurry) - // tpt[args] - case TypeBoundsTree(lo, hi) => (eliminated by uncurry) - // >: lo <: hi - case ExistentialTypeTree(tpt, whereClauses) => (eliminated by uncurry) - // tpt forSome { whereClauses } - -*/ +// ----- auxiliary objects and methods ------------------------------ abstract class TreeCopier { def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template): ClassDef @@ -1543,10 +830,6 @@ trait Trees { treeCopy.ExistentialTypeTree(tree, transform(tpt), transformTrees(whereClauses)) case SelectFromArray(qualifier, selector, erasure) => treeCopy.SelectFromArray(tree, transform(qualifier), selector, erasure) - case tree : StubTree => - tree.symbol = NoSymbol - tree.tpe = null - tree } def transformTrees(trees: List[Tree]): List[Tree] = @@ -1694,7 +977,6 @@ trait Trees { traverse(qualifier) case Parens(ts) => traverseTrees(ts) - case tree : StubTree => } def traverseTrees(trees: List[Tree]) { @@ -1718,6 +1000,24 @@ trait Trees { } } + private lazy val duplicator = new Transformer { + override val treeCopy = new StrictTreeCopier + override def transform(t: Tree) = { + val t1 = super.transform(t) + if ((t1 ne t) && t1.pos.isRange) t1 setPos t.pos.focus + t1 + } + } + + private class ShallowDuplicator(orig: Tree) extends Transformer { + override val treeCopy = new StrictTreeCopier + override def transform(tree: Tree) = + if (tree eq orig) + super.transform(tree) + else + tree + } + class TreeSubstituter(from: List[Symbol], to: List[Tree]) extends Transformer { override def transform(tree: Tree): Tree = tree match { case Ident(_) => @@ -1853,7 +1153,14 @@ trait Trees { case _ => if (tree.hasSymbol && isLocal(tree.symbol)) tree.symbol = NoSymbol } - tree.resetType() + tree match { + case tpt: TypeTree => + if (tpt.wasEmpty) tree.tpe = null + case EmptyTree => + ; + case _ => + tree.tpe = null + } super.traverse(tree) } } @@ -1875,14 +1182,5 @@ trait Trees { super.traverse(tree) } } - - /* hook to memoize trees in IDE */ - trait TreeKind { - def isType : Boolean - def isTerm : Boolean - def isDef : Boolean - def hasSymbol : Boolean - def isTop : Boolean - } } diff --git a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala index f7f6fea2c2..53fc6542b2 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala @@ -10,7 +10,7 @@ package ast.parser import scala.collection.mutable import mutable.{ Buffer, ArrayBuffer, ListBuffer, HashMap } import scala.util.control.ControlException -import scala.tools.nsc.util.{Position,NoPosition,SourceFile,CharArrayReader} +import scala.tools.nsc.util.{SourceFile,CharArrayReader} import scala.xml.{ Text, TextBuffer } import scala.xml.Utility.{ isNameStart, isNameChar, isSpace } import util.Chars.{ SU, LF } diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 35048c7a7d..58552e18e5 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -10,7 +10,7 @@ package scala.tools.nsc package ast.parser import scala.collection.mutable.ListBuffer -import scala.tools.nsc.util.{Position, OffsetPosition, NoPosition, BatchSourceFile} +import scala.tools.nsc.util.{OffsetPosition, BatchSourceFile} import symtab.Flags import Tokens._ diff --git a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala index 57b705094c..9c34739a15 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala @@ -10,7 +10,6 @@ package ast.parser import collection.mutable.Map import xml.{ EntityRef, Text } import xml.XML.{ xmlns } -import util.Position import symtab.Flags.MUTABLE /** This class builds instance of <code>Tree</code> that represent XML. diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index bb87a9248e..a23b8339a3 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -9,7 +9,6 @@ package ast.parser import symtab.Flags._ import scala.collection.mutable.ListBuffer -import scala.tools.nsc.util.Position /** Methods for building trees, used in the parser. All the trees * returned by this class must be untyped. diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index a91abac94a..ec9c371534 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -15,7 +15,6 @@ import scala.collection.immutable.{Set, ListSet} import scala.collection.mutable.{Map, HashMap, HashSet} import scala.tools.nsc.io.AbstractFile import scala.tools.nsc.symtab._ -import scala.tools.nsc.util.{Position, NoPosition} import scala.tools.nsc.symtab.classfile.ClassfileConstants._ import ch.epfl.lamp.fjbg._ @@ -77,7 +76,7 @@ abstract class GenJVM extends SubComponent { val MIN_SWITCH_DENSITY = 0.7 val INNER_CLASSES_FLAGS = (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_FINAL | ACC_INTERFACE | ACC_ABSTRACT) - val StringBuilderClass = definitions.getClass2("scala.StringBuilder", "scala.collection.mutable.StringBuilder").fullNameString + val StringBuilderClass = definitions.getClass2("scala.StringBuilder", "scala.collection.mutable.StringBuilder").fullName val BoxesRunTime = "scala.runtime.BoxesRunTime" val StringBuilderType = new JObjectType(StringBuilderClass) @@ -210,7 +209,7 @@ abstract class GenJVM extends SubComponent { dumpMirrorClass(c.symbol, c.cunit.source.toString); else log("No mirror class for module with linked class: " + - c.symbol.fullNameString) + c.symbol.fullName) } } else { @@ -437,7 +436,7 @@ abstract class GenJVM extends SubComponent { && !(sym.isMethod && sym.hasFlag(Flags.LIFTED)) && !(sym.ownerChain exists (_.isImplClass))) { // @M don't generate java generics sigs for (members of) implementation classes, as they are monomorphic (TODO: ok?) val memberTpe = atPhase(currentRun.erasurePhase)(owner.thisType.memberInfo(sym)) - // println("addGenericSignature sym: " + sym.fullNameString + " : " + memberTpe + " sym.info: " + sym.info) + // println("addGenericSignature sym: " + sym.fullName + " : " + memberTpe + " sym.info: " + sym.info) // println("addGenericSignature: "+ (sym.ownerChain map (x => (x.name, x.isImplClass)))) erasure.javaSig(sym, memberTpe) match { case Some(sig) => @@ -543,7 +542,7 @@ abstract class GenJVM extends SubComponent { def genField(f: IField) { if (settings.debug.value) - log("Adding field: " + f.symbol.fullNameString); + log("Adding field: " + f.symbol.fullName); var attributes = 0 f.symbol.annotations foreach { a => a match { @@ -568,7 +567,7 @@ abstract class GenJVM extends SubComponent { def genMethod(m: IMethod) { if (m.isStaticCtor) return - log("Generating method " + m.symbol.fullNameString) + log("Generating method " + m.symbol.fullName) method = m endPC.clear computeLocalVarsIndex(m) @@ -1142,11 +1141,11 @@ abstract class GenJVM extends SubComponent { case BOX(kind) => val boxedType = definitions.boxedClass(kind.toType.typeSymbol) val mtype = new JMethodType(javaType(boxedType), Array(javaType(kind))) - jcode.emitINVOKESTATIC(BoxesRunTime, "boxTo" + boxedType.cleanNameString, mtype) + jcode.emitINVOKESTATIC(BoxesRunTime, "boxTo" + boxedType.decodedName, mtype) case UNBOX(kind) => val mtype = new JMethodType(javaType(kind), Array(JObjectType.JAVA_LANG_OBJECT)) - jcode.emitINVOKESTATIC(BoxesRunTime, "unboxTo" + kind.toType.typeSymbol.cleanNameString, mtype) + jcode.emitINVOKESTATIC(BoxesRunTime, "unboxTo" + kind.toType.typeSymbol.decodedName, mtype) case NEW(REFERENCE(cls)) => val className = javaName(cls) @@ -1715,7 +1714,7 @@ abstract class GenJVM extends SubComponent { } (if (sym.isClass || (sym.isModule && !sym.isMethod)) - sym.fullNameString('/') + sym.fullName('/') else sym.simpleName.toString.trim()) + suffix } @@ -1775,7 +1774,7 @@ abstract class GenJVM extends SubComponent { /** Calls to methods in 'sym' need invokeinterface? */ def needsInterfaceCall(sym: Symbol): Boolean = { - log("checking for interface call: " + sym.fullNameString) + log("checking for interface call: " + sym.fullName) // the following call to 'info' may cause certain symbols to fail loading because we're // too late in the compilation chain (aliases to overloaded symbols will not be properly // resolved, see scala.Range, method super$++ that fails in UnPickler at LazyTypeRefAndAlias.complete diff --git a/src/compiler/scala/tools/nsc/dependencies/Changes.scala b/src/compiler/scala/tools/nsc/dependencies/Changes.scala index c5669d6214..ddab003752 100644 --- a/src/compiler/scala/tools/nsc/dependencies/Changes.scala +++ b/src/compiler/scala/tools/nsc/dependencies/Changes.scala @@ -42,7 +42,7 @@ abstract class Changes { case class ParentChanged(e: Entity) extends Change private def sameSymbol(sym1: Symbol, sym2: Symbol): Boolean = - sym1.fullNameString == sym2.fullNameString + sym1.fullName == sym2.fullName private def sameFlags(sym1: Symbol, sym2: Symbol): Boolean = sym1.flags == sym2.flags private def sameAnnotations(sym1: Symbol, sym2: Symbol): Boolean = @@ -197,6 +197,6 @@ abstract class Changes { def parentChangeSet(sym: Symbol): Change = ParentChanged(toEntity(sym)) private def toEntity(sym: Symbol): Entity = - if (sym.isClass) Class(sym.fullNameString) - else Definition(sym.fullNameString) + if (sym.isClass) Class(sym.fullName) + else Definition(sym.fullName) } diff --git a/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala b/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala index 2aaab33dc3..761b9dac3c 100644 --- a/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala +++ b/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala @@ -160,7 +160,7 @@ trait DependencyAnalysis extends SubComponent with Files { && ((tree.symbol.sourceFile eq null) || (tree.symbol.sourceFile.path != file.path)) && (!tree.symbol.isClassConstructor)) { - updateReferences(tree.symbol.fullNameString) + updateReferences(tree.symbol.fullName) atPhase(currentRun.uncurryPhase.prev) { checkType(tree.symbol.tpe) } @@ -204,18 +204,18 @@ trait DependencyAnalysis extends SubComponent with Files { case t: TypeRef => if (t.sym.isAliasType) { - updateReferences(t.typeSymbolDirect.fullNameString) + updateReferences(t.typeSymbolDirect.fullName) checkType(t.typeSymbolDirect.info) } - updateReferences(t.typeSymbol.fullNameString) + updateReferences(t.typeSymbol.fullName) for (tp <- t.args) checkType(tp) case t: PolyType => checkType(t.resultType) - updateReferences(t.typeSymbol.fullNameString) + updateReferences(t.typeSymbol.fullName) case t => - updateReferences(t.typeSymbol.fullNameString) + updateReferences(t.typeSymbol.fullName) } def updateReferences(s: String): Unit = diff --git a/src/compiler/scala/tools/nsc/matching/MatchSupport.scala b/src/compiler/scala/tools/nsc/matching/MatchSupport.scala index e51919b7c2..5f2c18e597 100644 --- a/src/compiler/scala/tools/nsc/matching/MatchSupport.scala +++ b/src/compiler/scala/tools/nsc/matching/MatchSupport.scala @@ -13,9 +13,7 @@ import java.io.{ StringWriter, PrintWriter } /** Ancillary bits of ParallelMatching which are better off * out of the way. */ -trait MatchSupport extends ast.TreeDSL -{ - self: ParallelMatching => +trait MatchSupport extends ast.TreeDSL { self: ParallelMatching => import global.{ typer => _, _ } import CODE._ @@ -102,7 +100,7 @@ trait MatchSupport extends ast.TreeDSL pp(x match { case s: String => return clean(s) - case x: Tree => treePrinters asCompactString x + case x: Tree => asCompactString(x) case xs: List[_] => pplist(xs map pp) case x: Tuple2[_,_] => "%s -> %s".format(pp(x._1), pp(x._2)) case x => x.toString diff --git a/src/compiler/scala/tools/nsc/matching/Matrix.scala b/src/compiler/scala/tools/nsc/matching/Matrix.scala index 61ca97ea24..8464ecc46e 100644 --- a/src/compiler/scala/tools/nsc/matching/Matrix.scala +++ b/src/compiler/scala/tools/nsc/matching/Matrix.scala @@ -7,7 +7,6 @@ package scala.tools.nsc package matching import transform.ExplicitOuter -import util.Position import symtab.Flags trait Matrix extends MatrixAdditions { diff --git a/src/compiler/scala/tools/nsc/matching/Patterns.scala b/src/compiler/scala/tools/nsc/matching/Patterns.scala index 3158f8a6cf..adc3e5df2c 100644 --- a/src/compiler/scala/tools/nsc/matching/Patterns.scala +++ b/src/compiler/scala/tools/nsc/matching/Patterns.scala @@ -7,7 +7,6 @@ package scala.tools.nsc package matching import symtab.Flags -import util.NoPosition import scala.util.NameTransformer.decode import PartialFunction._ @@ -131,7 +130,7 @@ trait Patterns extends ast.TreeDSL { case class ConstructorPattern(tree: Apply) extends ApplyPattern with NamePattern { require(fn.isType && this.isCaseClass) def name = tpe.typeSymbol.name - def cleanName = tpe.typeSymbol.cleanNameString + def cleanName = tpe.typeSymbol.decodedName def hasPrefix = tpe.prefix.prefixString != "" def prefixedName = if (hasPrefix) "%s.%s".format(tpe.prefix.prefixString, cleanName) diff --git a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala index b4a15733f9..c4569b0441 100644 --- a/src/compiler/scala/tools/nsc/matching/TransMatcher.scala +++ b/src/compiler/scala/tools/nsc/matching/TransMatcher.scala @@ -7,8 +7,6 @@ package scala.tools.nsc package matching -import util.Position -import ast.{ TreePrinters, Trees } import symtab.SymbolTable import transform.ExplicitOuter import java.io.{ StringWriter, PrintWriter } diff --git a/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala b/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala index 93839057d8..f0265c5e5d 100644 --- a/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala +++ b/src/compiler/scala/tools/nsc/symtab/AnnotationInfos.scala @@ -11,8 +11,7 @@ import scala.tools.nsc.transform.Reifiers import util._ /** AnnotationInfo and its helpers */ -trait AnnotationInfos { - self: SymbolTable => +trait AnnotationInfos extends reflect.generic.AnnotationInfos { self: SymbolTable => /** Arguments to classfile annotations (which are written to * bytecode as java annotations) are either: @@ -33,12 +32,16 @@ trait AnnotationInfos { override def toString = const.escapedStringValue } + object LiteralAnnotArg extends LiteralAnnotArgExtractor + /** Represents an array of classfile annotation arguments */ case class ArrayAnnotArg(args: Array[ClassfileAnnotArg]) extends ClassfileAnnotArg { override def toString = args.mkString("[", ", ", "]") } + object ArrayAnnotArg extends ArrayAnnotArgExtractor + /** Represents a nested classfile annotation */ case class NestedAnnotArg(annInfo: AnnotationInfo) extends ClassfileAnnotArg { @@ -47,6 +50,8 @@ trait AnnotationInfos { override def toString = annInfo.toString } + object NestedAnnotArg extends NestedAnnotArgExtractor + class AnnotationInfoBase /** <p> @@ -106,6 +111,11 @@ trait AnnotationInfos { } } + object AnnotationInfo extends AnnotationInfoExtractor + + lazy val classfileAnnotArgManifest: ClassManifest[ClassfileAnnotArg] = + reflect.ClassManifest.classType(classOf[ClassfileAnnotArg]) + /** Symbol annotations parsed in Namer (typeCompleter of * definitions) have to be lazy (#1782) */ diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala index a1ef4a07ae..026b6c3e25 100644 --- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala +++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala @@ -11,10 +11,10 @@ import scala.collection.mutable.{HashMap, HashSet} import scala.tools.nsc.util.{Position, NoPosition} import Flags._ -trait Definitions { +trait Definitions extends reflect.generic.StandardDefinitions { self: SymbolTable => - object definitions { + object definitions extends AbsDefinitions { def isDefinitionsInitialized = isInitialized // Working around bug #2133 @@ -30,7 +30,7 @@ trait Definitions { val rp=NoSymbol.newValue(NoPosition, nme.ROOTPKG) .setFlag(FINAL | MODULE | PACKAGE | JAVA) .setInfo(PolyType(List(), RootClass.tpe)) - RootClass.setSourceModule(rp) + RootClass.sourceModule = rp rp } lazy val RootClass: ModuleClassSymbol = NoSymbol.newModuleClass(NoPosition, nme.ROOT.toTypeName) @@ -140,10 +140,6 @@ trait Definitions { // fundamental modules lazy val PredefModule: Symbol = getModule("scala.Predef") def Predef_classOf = getMember(PredefModule, nme.classOf) - def Predef_classOfType(classType: Type): Type = - if (!ClassClass.unsafeTypeParams.isEmpty && !phase.erasedTypes) - appliedType(ClassClass.tpe, List(classType)) - else ClassClass.tpe def Predef_error = getMember(PredefModule, nme.error) def Predef_identity = getMember(PredefModule, nme.identity) def Predef_conforms = getMember(PredefModule, nme.conforms) @@ -349,6 +345,10 @@ trait Definitions { def seqType(arg: Type) = typeRef(SeqClass.typeConstructor.prefix, SeqClass, List(arg)) def arrayType(arg: Type) = typeRef(ArrayClass.typeConstructor.prefix, ArrayClass, List(arg)) + def ClassType(arg: Type) = + if (ClassClass.unsafeTypeParams.isEmpty || phase.erasedTypes) ClassClass.tpe + else appliedType(ClassClass.tpe, List(arg)) + // // .NET backend // @@ -598,7 +598,7 @@ trait Definitions { val abbrvTag = new HashMap[Symbol, Char] val numericWidth = new HashMap[Symbol, Int] - private def newValueClass(name: Name, tag: Char, width: Int): Symbol = { + private[symtab] def newValueClass(name: Name, tag: Char, width: Int): Symbol = { val boxedName = sn.Boxed(name) val clazz = newClass(ScalaPackageClass, name, anyvalparam) setFlag (ABSTRACT | FINAL) @@ -737,6 +737,7 @@ trait Definitions { case _ => false } + // todo: reconcile with javaSignature!!! def signature(tp: Type): String = { def erasure(tp: Type): Type = tp match { case st: SubType => erasure(st.supertype) @@ -744,7 +745,7 @@ trait Definitions { case _ => tp } def flatNameString(sym: Symbol, separator: Char): String = - if (sym.owner.isPackageClass) sym.fullNameString('.') + (if (sym.isModuleClass) "$" else "") + if (sym.owner.isPackageClass) sym.fullName('.') + (if (sym.isModuleClass) "$" else "") else flatNameString(sym.owner, separator) + "$" + sym.simpleName; def signature1(etp: Type): String = { if (etp.typeSymbol == ArrayClass) "[" + signature1(erasure(etp.normalize.typeArgs.head)) diff --git a/src/compiler/scala/tools/nsc/symtab/Flags.scala b/src/compiler/scala/tools/nsc/symtab/Flags.scala index 9901027db6..0b1315a18b 100644 --- a/src/compiler/scala/tools/nsc/symtab/Flags.scala +++ b/src/compiler/scala/tools/nsc/symtab/Flags.scala @@ -7,83 +7,7 @@ package scala.tools.nsc package symtab -object Flags { - - // modifiers - final val IMPLICIT = 0x00000200 - final val FINAL = 0x00000020 - final val PRIVATE = 0x00000004 - final val PROTECTED = 0x00000001 - - final val SEALED = 0x00000400 - final val OVERRIDE = 0x00000002 - final val CASE = 0x00000800 - final val ABSTRACT = 0x00000008 // abstract class, or used in conjunction - // with abstract override. - // Note difference to DEFERRED! - - final val DEFERRED = 0x00000010 // was `abstract' for members | trait is virtual - final val METHOD = 0x00000040 // a method - final val MODULE = 0x00000100 // symbol is module or class implementing a module - final val INTERFACE = 0x00000080 // symbol is an interface (i.e. a trait which defines only abstract methods) - - - final val MUTABLE = 0x00001000 // symbol is a mutable variable. - final val PARAM = 0x00002000 // symbol is a (value or type) parameter to a method - final val PACKAGE = 0x00004000 // symbol is a java package - // available: 0x00008000 - - final val COVARIANT = 0x00010000 // symbol is a covariant type variable - final val CAPTURED = 0x00010000 // variable is accessed from nested function. - // Set by LambdaLift - final val BYNAMEPARAM = 0x00010000 // parameter is by name - final val CONTRAVARIANT = 0x00020000 // symbol is a contravariant type variable - final val LABEL = 0x00020000 // method symbol is a label. Set by TailCall - final val INCONSTRUCTOR = 0x00020000 // class symbol is defined in this/superclass - // constructor. - final val ABSOVERRIDE = 0x00040000 // combination of abstract & override - final val LOCAL = 0x00080000 // symbol is local to current class (i.e. private[this] or protected[this] - // pre: PRIVATE or PROTECTED are also set - final val JAVA = 0x00100000 // symbol was defined by a Java class - final val SYNTHETIC = 0x00200000 // symbol is compiler-generated - final val STABLE = 0x00400000 // functions that are assumed to be stable - // (typically, access methods for valdefs) - // or classes that do not contain abstract types. - final val STATIC = 0x00800000 // static field, method or class - - final val CASEACCESSOR = 0x01000000 // symbol is a case parameter (or its accessor) - final val TRAIT = 0x02000000 // symbol is a trait - final val DEFAULTPARAM = 0x02000000 // the parameter has a default value - final val BRIDGE = 0x04000000 // function is a bridge method. Set by Erasure - final val ACCESSOR = 0x08000000 // a value or variable accessor (getter or setter) - - final val SUPERACCESSOR = 0x10000000 // a super accessor - final val PARAMACCESSOR = 0x20000000 // for value definitions: is an access method - // for a final val parameter - // for parameters: is a val parameter - final val MODULEVAR = 0x40000000 // for variables: is the variable caching a module value - final val SYNTHETICMETH = 0x40000000 // for methods: synthetic method, but without SYNTHETIC flag - final val MONOMORPHIC = 0x40000000 // for type symbols: does not have type parameters - final val LAZY = 0x80000000L // symbol is a lazy val. can't have MUTABLE unless transformed by typer - - final val IS_ERROR = 0x100000000L // symbol is an error symbol - final val OVERLOADED = 0x200000000L // symbol is overloaded - final val LIFTED = 0x400000000L // class has been lifted out to package level - // local value has been lifted out to class level - // todo: make LIFTED = latePRIVATE? - final val MIXEDIN = 0x800000000L // term member has been mixed in - final val EXISTENTIAL = 0x800000000L // type is an existential parameter or skolem - - final val EXPANDEDNAME = 0x1000000000L // name has been expanded with class suffix - final val IMPLCLASS = 0x2000000000L // symbol is an implementation class - final val PRESUPER = 0x2000000000L // value is evaluated before super call - final val TRANS_FLAG = 0x4000000000L // transient flag guaranteed to be reset - // after each phase. - - final val LOCKED = 0x8000000000L // temporary flag to catch cyclic dependencies - final val SPECIALIZED = 0x10000000000L// symbol is a generated specialized member - final val DEFAULTINIT = 0x20000000000L// symbol is a generated specialized member - final val VBRIDGE = 0x40000000000L// symbol is a varargs bridge +object Flags extends reflect.generic.Flags { final val InitialFlags = 0x0001FFFFFFFFFFFFL // flags that are enabled from phase 1. final val LateFlags = 0x00FE000000000000L // flags that override flags in 0x1FC. @@ -108,118 +32,6 @@ object Flags { final val notOVERRIDE = (OVERRIDE: Long) << AntiShift final val notMETHOD = (METHOD: Long) << AntiShift - // The flags from 0x001 to 0x800 are different in the raw flags - // and in the pickled format. - - private final val IMPLICIT_PKL = 0x00000001 - private final val FINAL_PKL = 0x00000002 - private final val PRIVATE_PKL = 0x00000004 - private final val PROTECTED_PKL = 0x00000008 - - private final val SEALED_PKL = 0x00000010 - private final val OVERRIDE_PKL = 0x00000020 - private final val CASE_PKL = 0x00000040 - private final val ABSTRACT_PKL = 0x00000080 - - private final val DEFERRED_PKL = 0x00000100 - private final val METHOD_PKL = 0x00000200 - private final val MODULE_PKL = 0x00000400 - private final val INTERFACE_PKL = 0x00000800 - - private final val PKL_MASK = 0x00000FFF - - - private val r2p = { - def rawFlagsToPickledAux(flags:Int) = { - var pflags=0 - if ((flags & IMPLICIT )!=0) pflags|=IMPLICIT_PKL - if ((flags & FINAL )!=0) pflags|=FINAL_PKL - if ((flags & PRIVATE )!=0) pflags|=PRIVATE_PKL - if ((flags & PROTECTED)!=0) pflags|=PROTECTED_PKL - if ((flags & SEALED )!=0) pflags|=SEALED_PKL - if ((flags & OVERRIDE )!=0) pflags|=OVERRIDE_PKL - if ((flags & CASE )!=0) pflags|=CASE_PKL - if ((flags & ABSTRACT )!=0) pflags|=ABSTRACT_PKL - if ((flags & DEFERRED )!=0) pflags|=DEFERRED_PKL - if ((flags & METHOD )!=0) pflags|=METHOD_PKL - if ((flags & MODULE )!=0) pflags|=MODULE_PKL - if ((flags & INTERFACE)!=0) pflags|=INTERFACE_PKL - pflags - } - val v=new Array[Int](PKL_MASK+1) - var i=0 - while (i<=PKL_MASK) { - v(i)=rawFlagsToPickledAux(i) - i+=1 - } - v - } - - private val p2r = { - def pickledToRawFlagsAux(pflags:Int) = { - var flags=0 - if ((pflags & IMPLICIT_PKL )!=0) flags|=IMPLICIT - if ((pflags & FINAL_PKL )!=0) flags|=FINAL - if ((pflags & PRIVATE_PKL )!=0) flags|=PRIVATE - if ((pflags & PROTECTED_PKL)!=0) flags|=PROTECTED - if ((pflags & SEALED_PKL )!=0) flags|=SEALED - if ((pflags & OVERRIDE_PKL )!=0) flags|=OVERRIDE - if ((pflags & CASE_PKL )!=0) flags|=CASE - if ((pflags & ABSTRACT_PKL )!=0) flags|=ABSTRACT - if ((pflags & DEFERRED_PKL )!=0) flags|=DEFERRED - if ((pflags & METHOD_PKL )!=0) flags|=METHOD - if ((pflags & MODULE_PKL )!=0) flags|=MODULE - if ((pflags & INTERFACE_PKL)!=0) flags|=INTERFACE - flags - } - val v=new Array[Int](PKL_MASK+1) - var i=0 - while (i<=PKL_MASK) { - v(i)=pickledToRawFlagsAux(i) - i+=1 - } - v - } - - def rawFlagsToPickled(flags:Long):Long = - (flags & ~PKL_MASK) | r2p(flags.toInt & PKL_MASK) - - def pickledToRawFlags(pflags:Long):Long = - (pflags & ~PKL_MASK) | p2r(pflags.toInt & PKL_MASK) - - // List of the raw flags, in pickled order - private val pickledListOrder = { - def findBit(m:Long):Int = { - var mask=m - var i=0 - while (i <= 62) { - if ((mask&1) == 1L) return i - mask >>= 1 - i += 1 - } - throw new FatalError("Internal error: mask is zero") - } - val v=new Array[Long](63) - v(findBit(IMPLICIT_PKL ))=IMPLICIT - v(findBit(FINAL_PKL ))=FINAL - v(findBit(PRIVATE_PKL ))=PRIVATE - v(findBit(PROTECTED_PKL))=PROTECTED - v(findBit(SEALED_PKL ))=SEALED - v(findBit(OVERRIDE_PKL ))=OVERRIDE - v(findBit(CASE_PKL ))=CASE - v(findBit(ABSTRACT_PKL ))=ABSTRACT - v(findBit(DEFERRED_PKL ))=DEFERRED - v(findBit(METHOD_PKL ))=METHOD - v(findBit(MODULE_PKL ))=MODULE - v(findBit(INTERFACE_PKL))=INTERFACE - var i=findBit(PKL_MASK+1) - while (i <= 62) { - v(i)=1L << i - i += 1 - } - v.toList - } - // masks /** This flags can be set when class or module symbol is first created. */ final val TopLevelCreationFlags: Long = @@ -244,7 +56,6 @@ object Flags { final val AccessFlags: Long = PRIVATE | PROTECTED final val VARIANCES = COVARIANT | CONTRAVARIANT final val ConstrFlags: Long = JAVA - final val PickledFlags: Long = 0xFFFFFFFFL /** Module flags inherited by their module-class */ final val ModuleToClassFlags: Long = AccessFlags | MODULE | PACKAGE | CASE | SYNTHETIC | JAVA diff --git a/src/compiler/scala/tools/nsc/symtab/Names.scala b/src/compiler/scala/tools/nsc/symtab/Names.scala index ddadc32202..3b9c1520e5 100644 --- a/src/compiler/scala/tools/nsc/symtab/Names.scala +++ b/src/compiler/scala/tools/nsc/symtab/Names.scala @@ -16,7 +16,7 @@ import java.security.MessageDigest * @author Martin Odersky * @version 1.0, 05/02/2005 */ -class Names { +trait Names extends reflect.generic.Names { // Operations ------------------------------------------------------------- @@ -164,6 +164,9 @@ class Names { def newTypeName(bs: Array[Byte], offset: Int, len: Int): Name = newTermName(bs, offset, len).toTypeName + def mkTermName(name: Name) = name.toTermName + def mkTypeName(name: Name) = name.toTypeName + def nameChars: Array[Char] = chrs implicit def view(s: String): Name = newTermName(s) diff --git a/src/compiler/scala/tools/nsc/symtab/Positions.scala b/src/compiler/scala/tools/nsc/symtab/Positions.scala index e096d3b5e3..215a6217af 100644 --- a/src/compiler/scala/tools/nsc/symtab/Positions.scala +++ b/src/compiler/scala/tools/nsc/symtab/Positions.scala @@ -33,4 +33,7 @@ self: scala.tools.nsc.symtab.SymbolTable => def ensureNonOverlapping(tree: Tree, others: List[Tree]) {} def validatePositions(tree: Tree) {} + + type Position = scala.tools.nsc.util.Position + val NoPosition = scala.tools.nsc.util.NoPosition } diff --git a/src/compiler/scala/tools/nsc/symtab/Scopes.scala b/src/compiler/scala/tools/nsc/symtab/Scopes.scala index dcd9e76b62..a66e5b6cc3 100644 --- a/src/compiler/scala/tools/nsc/symtab/Scopes.scala +++ b/src/compiler/scala/tools/nsc/symtab/Scopes.scala @@ -44,7 +44,7 @@ trait Scopes { e } - class Scope(initElems: ScopeEntry) extends Iterable[Symbol] { + class Scope(initElems: ScopeEntry) extends AbsScope { var elems: ScopeEntry = initElems @@ -275,10 +275,39 @@ trait Scopes { elemsCache } + /** Return the nesting level of this scope, i.e. the number of times this scope + * was nested in another */ + def nestingLevel = nestinglevel + /** Return all symbols as an interator in the order they were entered in this scope. */ def iterator: Iterator[Symbol] = toList.iterator +/* + /** Does this scope contain an entry for `sym`? + */ + def contains(sym: Symbol): Boolean = lookupAll(sym.name) contains sym + + /** A scope that contains all symbols of this scope and that also contains `sym`. + */ + def +(sym: Symbol): Scope = + if (contains(sym)) this + else { + val result = cloneScope + result enter sym + result + } + + /** A scope that contains all symbols of this scope except `sym`. + */ + def -(sym: Symbol): Scope = + if (!contains(sym)) this + else { + val result = cloneScope + result unlink sym + result + } +*/ override def foreach[U](p: Symbol => U): Unit = toList foreach p override def filter(p: Symbol => Boolean): Scope = @@ -287,13 +316,12 @@ trait Scopes { override def mkString(start: String, sep: String, end: String) = toList.map(_.defString).mkString(start, sep, end) - override def toString(): String = mkString("{\n ", ";\n ", "\n}") + override def toString(): String = mkString("Scope{\n ", ";\n ", "\n}") - /** Return the nesting level of this scope, i.e. the number of times this scope - * was nested in another */ - def nestingLevel = nestinglevel } + def newScope: Scope = new Scope + /** The empty scope (immutable). */ object EmptyScope extends Scope { diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala index e762448462..94bcbabaf1 100644 --- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala +++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala @@ -9,10 +9,9 @@ package symtab import scala.util.NameTransformer -trait StdNames { - self: SymbolTable => +trait StdNames extends reflect.generic.StdNames { self: SymbolTable => - object nme { + object nme extends StandardNames { // Scala keywords; enter them first to minimize scanner.maxKey val ABSTRACTkw = newTermName("abstract") @@ -73,7 +72,6 @@ trait StdNames { val LOCALDUMMY_PREFIX_STRING = "<local " val SUPER_PREFIX_STRING = "super$" - val EXPAND_SEPARATOR_STRING = "$$" val TRAIT_SETTER_SEPARATOR_STRING = "$_setter_$" val TUPLE_FIELD_PREFIX_STRING = "_" val CHECK_IF_REFUTABLE_STRING = "check$ifrefutable$" @@ -88,7 +86,7 @@ trait StdNames { def LOCAL(clazz: Symbol) = newTermName(LOCALDUMMY_PREFIX_STRING + clazz.name+">") def TUPLE_FIELD(index: Int) = newTermName(TUPLE_FIELD_PREFIX_STRING + index) - val LOCAL_SUFFIX = newTermName(" ") + val LOCAL_SUFFIX = newTermName(LOCAL_SUFFIX_STRING) val SETTER_SUFFIX = encode("_=") val IMPL_CLASS_SUFFIX = newTermName("$class") val MODULE_SUFFIX = newTermName("$module") @@ -116,9 +114,13 @@ trait StdNames { chtp == Character.MATH_SYMBOL.toInt || chtp == Character.OTHER_SYMBOL.toInt } + /** The expanded setter name of `name' relative to this class `base` + */ + def expandedSetterName(name: Name, base: Symbol): Name = + expandedName(name, base, separator = TRAIT_SETTER_SEPARATOR_STRING) + /** If `name' is an expandedName name, the original name. * Otherwise `name' itself. - * @see Symbol.expandedName */ def originalName(name: Name): Name = { var i = name.length @@ -183,19 +185,11 @@ trait StdNames { val LOCALCHILD = newTypeName("<local child>") val NOSYMBOL = newTermName("<none>") - val EMPTY = newTermName("") val ANYNAME = newTermName("<anyname>") val WILDCARD = newTermName("_") val WILDCARD_STAR = newTermName("_*") - val ANON_CLASS_NAME = newTermName("$anon") - val ANON_FUN_NAME = newTermName("$anonfun") - val REFINE_CLASS_NAME = newTermName("<refinement>") - val EMPTY_PACKAGE_NAME = newTermName("<empty>") - val IMPORT = newTermName("<import>") val STAR = newTermName("*") - val ROOT = newTermName("<root>") - val ROOTPKG = newTermName("_root_") val REPEATED_PARAM_CLASS_NAME = newTermName("<repeated>") val JAVA_REPEATED_PARAM_CLASS_NAME = newTermName("<repeated...>") val BYNAME_PARAM_CLASS_NAME = newTermName("<byname>") diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala index 51ef2fc313..23e525d8c8 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala @@ -14,7 +14,7 @@ import ch.epfl.lamp.compiler.msil.{Type => MSILType, Attribute => MSILAttribute} import scala.collection.mutable.{HashMap, HashSet} import scala.compat.Platform.currentTime import scala.tools.nsc.io.AbstractFile -import scala.tools.nsc.util.{Position, NoPosition, ClassPath, ClassRep, JavaClassPath, MsilClassPath} +import scala.tools.nsc.util.{ClassPath, ClassRep, JavaClassPath, MsilClassPath} import classfile.ClassfileParser import Flags._ @@ -110,7 +110,7 @@ abstract class SymbolLoaders { def enterClassAndModule(root: Symbol, name: String, completer: SymbolLoader) { val owner = if (root.isRoot) definitions.EmptyPackageClass else root val className = newTermName(name) - assert(owner.info.decls.lookup(name) == NoSymbol, owner.fullNameString + "." + name) + assert(owner.info.decls.lookup(name) == NoSymbol, owner.fullName + "." + name) val clazz = owner.newClass(NoPosition, name.toTypeName) val module = owner.newModule(NoPosition, name) clazz setInfo completer diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala index 2a70c55cd6..618c601b8f 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala @@ -6,22 +6,25 @@ package scala.tools.nsc package symtab -import ast.{Trees, DocComments} + +import ast.{Trees, TreePrinters, DocComments} import util._ -abstract class SymbolTable extends Names +abstract class SymbolTable extends reflect.generic.Universe + with Names with Symbols with Types with Scopes with Definitions - with Constants + with reflect.generic.Constants with BaseTypeSeqs with InfoTransformers with StdNames with AnnotationInfos with AnnotationCheckers with Trees + with TreePrinters with Positions with DocComments { diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolWalker.scala b/src/compiler/scala/tools/nsc/symtab/SymbolWalker.scala index f2e16b537a..8c111875dd 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolWalker.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolWalker.scala @@ -3,7 +3,6 @@ package symtab trait SymbolWalker { val global : Global - import scala.tools.nsc.util._ import global._ import scala.collection.mutable.LinkedHashSet trait Visitor { @@ -33,8 +32,6 @@ trait SymbolWalker { def fs(l: List[Tree]) = l foreach f def fss(l: List[List[Tree]]) = l foreach fs - if (t.isInstanceOf[StubTree]) return - val sym = (t, t.tpe) match { case (Super(_,_),SuperType(_,supertp)) if validSym(supertp) => supertp.typeSymbol case _ if validSym(t) => t.symbol diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index d6f4ef5672..1ba70a3fcf 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -17,8 +17,7 @@ import Flags._ //todo: get rid of MONOMORPHIC flag -trait Symbols { - self: SymbolTable => +trait Symbols extends reflect.generic.Symbols { self: SymbolTable => import definitions._ private var ids = 0 @@ -51,7 +50,7 @@ trait Symbols { } */ /** The class for all symbols */ - abstract class Symbol(initOwner: Symbol, initPos: Position, initName: Name) { + abstract class Symbol(initOwner: Symbol, initPos: Position, initName: Name) extends AbsSymbol { var rawowner = initOwner var rawname = initName @@ -124,8 +123,9 @@ trait Symbols { this } - def addAnnotation(annot: AnnotationInfo): this.type = + override def addAnnotation(annot: AnnotationInfo) { setAnnotations(annot :: this.rawannots) + } /** Does this symbol have an annotation of the given class? */ def hasAnnotation(cls: Symbol) = @@ -157,12 +157,16 @@ trait Symbols { * Java protected: PROTECTED flag set, privateWithin == enclosing package * Java public: no flag set, privateWithin == NoSymbol */ - var privateWithin: Symbol = _ + private[this] var _privateWithin: Symbol = _ + def privateWithin = _privateWithin + override def privateWithin_=(sym: Symbol) { _privateWithin = sym } // Creators ------------------------------------------------------------------- final def newValue(pos: Position, name: Name) = new TermSymbol(this, pos, name) + final def newValue(name: Name, pos: Position = NoPosition) = + new TermSymbol(this, pos, name) final def newVariable(pos: Position, name: Name) = newValue(pos, name).setFlag(MUTABLE) final def newValueParameter(pos: Position, name: Name) = @@ -172,6 +176,8 @@ trait Symbols { newValue(pos, nme.LOCAL(this)).setInfo(NoType) final def newMethod(pos: Position, name: Name) = new MethodSymbol(this, pos, name).setFlag(METHOD) + final def newMethod(name: Name, pos: Position = NoPosition) = + new MethodSymbol(this, pos, name).setFlag(METHOD) final def newLabel(pos: Position, name: Name) = newMethod(pos, name).setFlag(LABEL) final def newConstructor(pos: Position) = @@ -179,6 +185,9 @@ trait Symbols { final def newModule(pos: Position, name: Name, clazz: ClassSymbol) = new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL) .setModuleClass(clazz) + final def newModule(name: Name, clazz: Symbol, pos: Position = NoPosition) = + new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL) + .setModuleClass(clazz.asInstanceOf[ClassSymbol]) final def newModule(pos: Position, name: Name) = { val m = new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL) m.setModuleClass(new ModuleClassSymbol(m)) @@ -234,11 +243,15 @@ trait Symbols { */ final def newAliasType(pos: Position, name: Name) = new TypeSymbol(this, pos, name) + final def newAliasType(name: Name, pos: Position = NoPosition) = + new TypeSymbol(this, pos, name) /** Symbol of an abstract type type T >: ... <: ... */ final def newAbstractType(pos: Position, name: Name) = new TypeSymbol(this, pos, name).setFlag(DEFERRED) + final def newAbstractType(name: Name, pos: Position = NoPosition) = + new TypeSymbol(this, pos, name).setFlag(DEFERRED) /** Symbol of a type parameter */ @@ -291,9 +304,13 @@ trait Symbols { final def newClass(pos: Position, name: Name) = new ClassSymbol(this, pos, name) + final def newClass(name: Name, pos: Position = NoPosition) = + new ClassSymbol(this, pos, name) final def newModuleClass(pos: Position, name: Name) = new ModuleClassSymbol(this, pos, name) + final def newModuleClass(name: Name, pos: Position = NoPosition) = + new ModuleClassSymbol(this, pos, name) final def newAnonymousClass(pos: Position) = newClass(pos, nme.ANON_CLASS_NAME.toTypeName) @@ -362,15 +379,8 @@ trait Symbols { // Tests ---------------------------------------------------------------------- - def isTerm = false //to be overridden - def isType = false //to be overridden - def isClass = false //to be overridden - def isTypeMember = false //to be overridden todo: rename, it's something - // whose definition starts with `type', i.e. a type - // which is not a class. - def isAliasType = false //to be overridden - def isAbstractType = false //to be overridden - def isSkolem = false //to be overridden + /** Is this symbol a type but not a class? */ + def isNonClassType = false /** Term symbols with the exception of static parts of Java classes and packages */ final def isValue = isTerm && !(isModule && hasFlag(PACKAGE | JAVA)) @@ -388,29 +398,23 @@ trait Symbols { final def isValueParameter = isTerm && hasFlag(PARAM) final def isLocalDummy = isTerm && nme.isLocalDummyName(name) - final def isMethod = isTerm && hasFlag(METHOD) - final def isSourceMethod = isTerm && (flags & (METHOD | STABLE)) == METHOD.toLong // ??? final def isLabel = isMethod && !hasFlag(ACCESSOR) && hasFlag(LABEL) final def isInitializedToDefault = !isType && (getFlag(DEFAULTINIT | ACCESSOR) == (DEFAULTINIT | ACCESSOR)) final def isClassConstructor = isTerm && (name == nme.CONSTRUCTOR) final def isMixinConstructor = isTerm && (name == nme.MIXIN_CONSTRUCTOR) final def isConstructor = isTerm && (name == nme.CONSTRUCTOR) || (name == nme.MIXIN_CONSTRUCTOR) - final def isModule = isTerm && hasFlag(MODULE) final def isStaticModule = isModule && isStatic && !isMethod - final def isPackage = isModule && hasFlag(PACKAGE) final def isThisSym = isTerm && owner.thisSym == this //final def isMonomorphicType = isType && hasFlag(MONOMORPHIC) final def isError = hasFlag(IS_ERROR) final def isErroneous = isError || isInitialized && tpe.isErroneous - final def isTrait = isClass && hasFlag(TRAIT | notDEFERRED) // A virtual class becomes a trait (part of DEVIRTUALIZE) + override final def isTrait: Boolean = isClass && hasFlag(TRAIT | notDEFERRED) // A virtual class becomes a trait (part of DEVIRTUALIZE) final def isTypeParameterOrSkolem = isType && hasFlag(PARAM) final def isTypeSkolem = isSkolem && hasFlag(PARAM) - final def isTypeParameter = isTypeParameterOrSkolem && !isSkolem // a type symbol bound by an existential type, for instance the T in // List[T] forSome { type T } - final def isExistential = isType && hasFlag(EXISTENTIAL) - final def isExistentialSkolem = isSkolem && hasFlag(EXISTENTIAL) - final def isExistentialQuantified = isExistential && !isSkolem + final def isExistentialSkolem = isExistentiallyBound && isSkolem + final def isExistentialQuantified = isExistentiallyBound && !isSkolem // class C extends D( { class E { ... } ... } ). Here, E is a class local to a constructor final def isClassLocalToConstructor = isClass && hasFlag(INCONSTRUCTOR) @@ -418,17 +422,10 @@ trait Symbols { final def isAnonymousClass = isClass && (originalName startsWith nme.ANON_CLASS_NAME) // todo: find out why we can't use containsName here. final def isAnonymousFunction = hasFlag(SYNTHETIC) && (name containsName nme.ANON_FUN_NAME) - final def isRefinementClass = isClass && name == nme.REFINE_CLASS_NAME.toTypeName; // no lifting for refinement classes - final def isModuleClass = isClass && hasFlag(MODULE) final def isClassOfModule = isModuleClass || isClass && nme.isLocalName(name) - final def isPackageClass = isClass && hasFlag(PACKAGE) final def isPackageObject = isModule && name == nme.PACKAGEkw && owner.isPackageClass final def isPackageObjectClass = isModuleClass && name.toTermName == nme.PACKAGEkw && owner.isPackageClass final def definedInPackage = owner.isPackageClass || owner.isPackageObjectClass - final def isRoot = isPackageClass && name == nme.ROOT.toTypeName - final def isRootPackage = isPackage && name == nme.ROOTPKG - final def isEmptyPackage = isPackage && name == nme.EMPTY_PACKAGE_NAME - final def isEmptyPackageClass = isPackageClass && name == nme.EMPTY_PACKAGE_NAME.toTypeName final def isPredefModule = isModule && name == nme.Predef && owner.isScalaPackageClass // not printed as a prefix final def isScalaPackage = isPackage && name == nme.scala_ && owner.isRoot || // not printed as a prefix isPackageObject && owner.isScalaPackageClass @@ -476,6 +473,8 @@ trait Symbols { name.toString.startsWith(nme.INTERPRETER_LINE_PREFIX) && name.toString.endsWith(nme.INTERPRETER_WRAPPER_SUFFIX) + override def isEffectiveRoot = super.isEffectiveRoot || isInterpreterWrapper + /** Is this symbol an accessor method for outer? */ final def isOuterAccessor = { hasFlag(STABLE | SYNTHETIC) && @@ -495,9 +494,6 @@ trait Symbols { (!hasFlag(METHOD | BYNAMEPARAM) || hasFlag(STABLE)) && !(tpe.isVolatile && !hasAnnotation(uncheckedStableClass)) - def isDeferred = - hasFlag(DEFERRED) && !isClass - def isVirtualClass = hasFlag(DEFERRED) && isClass @@ -505,16 +501,6 @@ trait Symbols { hasFlag(DEFERRED) && isTrait /** Is this symbol a public */ - final def isPublic: Boolean = - !hasFlag(PRIVATE | PROTECTED) && privateWithin == NoSymbol - - /** Is this symbol a private local */ - final def isPrivateLocal = - hasFlag(PRIVATE) && hasFlag(LOCAL) - - /** Is this symbol a protected local */ - final def isProtectedLocal = - hasFlag(PROTECTED) && hasFlag(LOCAL) /** Does this symbol denote the primary constructor of its enclosing class? */ final def isPrimaryConstructor = @@ -528,11 +514,6 @@ trait Symbols { final def isCaseApplyOrUnapply = isMethod && hasFlag(CASE) && hasFlag(SYNTHETIC) - /** Is this symbol an implementation class for a mixin? */ - final def isImplClass: Boolean = isClass && hasFlag(IMPLCLASS) - - /** Is thhis symbol early initialized */ - final def isEarly: Boolean = isTerm && hasFlag(PRESUPER) /** Is this symbol a trait which needs an implementation class? */ final def needsImplClass: Boolean = @@ -560,16 +541,9 @@ trait Symbols { final def isStaticOwner: Boolean = isPackageClass || isModuleClass && isStatic - /** Is this symbol final? */ - final def isFinal: Boolean = ( - hasFlag(FINAL) || - isTerm && ( - hasFlag(PRIVATE) || isLocal || owner.isClass && owner.hasFlag(FINAL | MODULE)) - ) - - /** Is this symbol a sealed class? */ - final def isSealed: Boolean = - isClass && (hasFlag(SEALED) || isValueClass(this)) + /** Is this symbol effectively final? I.e, it cannot be overridden */ + final def isEffectivelyFinal: Boolean = isFinal || isTerm && ( + hasFlag(PRIVATE) || isLocal || owner.isClass && owner.hasFlag(FINAL | MODULE)) /** Is this symbol locally defined? I.e. not accessed from outside `this' instance */ final def isLocal: Boolean = owner.isTerm @@ -642,9 +616,6 @@ trait Symbols { isClass && (hasFlag(STABLE) || checkStable()) } - final def isCovariant: Boolean = isType && hasFlag(COVARIANT) - - final def isContravariant: Boolean = isType && hasFlag(CONTRAVARIANT) /** The variance of this symbol as an integer */ final def variance: Int = @@ -655,7 +626,7 @@ trait Symbols { // Flags, owner, and name attributes -------------------------------------------------------------- def owner: Symbol = rawowner - final def owner_=(owner: Symbol) { rawowner = owner } + override final def owner_=(owner: Symbol) { rawowner = owner } def ownerChain: List[Symbol] = this :: owner.ownerChain @@ -696,11 +667,10 @@ trait Symbols { val fs = rawflags & phase.flagMask (fs | ((fs & LateFlags) >>> LateShift)) & ~(fs >>> AntiShift) } - final def flags_=(fs: Long) = rawflags = fs + override final def flags_=(fs: Long) = rawflags = fs final def setFlag(mask: Long): this.type = { rawflags = rawflags | mask; this } final def resetFlag(mask: Long): this.type = { rawflags = rawflags & ~mask; this } final def getFlag(mask: Long): Long = flags & mask - final def hasFlag(mask: Long): Boolean = (flags & mask) != 0L final def resetFlags { rawflags = rawflags & TopLevelCreationFlags } /** The class or term up to which this symbol is accessible, @@ -735,12 +705,12 @@ trait Symbols { * to generate a type of kind * * for a term symbol, its usual type */ - def tpe: Type = info + override def tpe: Type = info /** Get type info associated with symbol at current phase, after * ensuring that symbol is initialized (i.e. type is completed). */ - def info: Type = try { + override def info: Type = try { var cnt = 0 while (validTo == NoPeriod) { //if (settings.debug.value) System.out.println("completing " + this);//DEBUG @@ -748,9 +718,14 @@ trait Symbols { assert(infos.prev eq null, this.name) val tp = infos.info //if (settings.debug.value) System.out.println("completing " + this.rawname + tp.getClass());//debug - lock { - setInfo(ErrorType) - throw CyclicReference(this, tp) + if ((rawflags & LOCKED) != 0L) { // rolled out once for performance + lock { + setInfo(ErrorType) + throw CyclicReference(this, tp) + } + } else { + rawflags |= LOCKED + activeLocks += 1 } val current = phase try { @@ -774,15 +749,16 @@ trait Symbols { throw ex } - /** Set initial info. */ - def setInfo(info: Type): this.type = { + override def info_=(info: Type) { assert(info ne null) infos = TypeHistory(currentPeriod, info, null) unlock() validTo = if (info.isComplete) currentPeriod else NoPeriod - this } + /** Set initial info. */ + def setInfo(info: Type): this.type = { info_=(info); this } + /** Set new info valid from start of this phase. */ final def updateInfo(info: Type): Symbol = { assert(phaseId(infos.validFrom) <= phase.id) @@ -1078,12 +1054,6 @@ trait Symbols { // 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 (isSourceMethod) this else owner.enclMethod - /** The primary constructor of a class */ def primaryConstructor: Symbol = { var c = info.decl( @@ -1102,10 +1072,6 @@ trait Symbols { /** The type of `this' in a class, or else the type of the symbol itself. */ 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 <code>this.type</code> in this class, * otherwise <code>NoPrefix</code>. * We always have: thisType <:< typeOfThis @@ -1320,11 +1286,6 @@ trait Symbols { result } else this - /** 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 @@ -1400,7 +1361,7 @@ trait Symbols { final def setter(base: Symbol, hasExpandedName: Boolean): Symbol = { var sname = nme.getterToSetter(nme.getterName(name)) - if (hasExpandedName) sname = base.expandedSetterName(sname) + if (hasExpandedName) sname = nme.expandedSetterName(sname, base) base.info.decl(sname) filter (_.hasFlag(ACCESSOR)) } @@ -1410,7 +1371,7 @@ trait Symbols { final def caseModule: Symbol = { var modname = name.toTermName if (privateWithin.isClass && !privateWithin.isModuleClass && !hasFlag(EXPANDEDNAME)) - modname = privateWithin.expandedName(modname) + modname = nme.expandedName(modname, privateWithin) initialize.owner.info.decl(modname).suchThat(_.isModule) } @@ -1448,20 +1409,11 @@ trait Symbols { getter(owner).expandName(base) setter(owner).expandName(base) } - name = base.expandedName(name) + name = nme.expandedName(name, base) if (isType) name = name.toTypeName } } - def expandedSetterName(simpleSetterName: Name): Name = - newTermName(fullNameString('$') + nme.TRAIT_SETTER_SEPARATOR_STRING + simpleSetterName) - - /** The expanded name of `name' relative to this class as base - */ - def expandedName(name: Name): Name = { - newTermName(fullNameString('$') + nme.EXPAND_SEPARATOR_STRING + name) - } - def sourceFile: AbstractFile = (if (isModule) moduleClass else toplevelClass).sourceFile @@ -1475,16 +1427,10 @@ trait Symbols { /** If this is a sealed class, its known direct subclasses. Otherwise Set.empty */ def children: Set[Symbol] = emptySymbolSet - /** Declare given subclass `sym' of this sealed class */ - def addChild(sym: Symbol) { - throw new Error("addChild inapplicable for " + this) - } - - // ToString ------------------------------------------------------------------- /** A tag which (in the ideal case) uniquely identifies class symbols */ - final def tag: Int = fullNameString.hashCode() + final def tag: Int = fullName.hashCode() /** The simple name of this Symbol */ final def simpleName: Name = name @@ -1527,32 +1473,11 @@ trait Symbols { * E.g. $eq => =. * If settings.uniquId adds id. */ - def nameString: String = cleanNameString + idString - - /** A nameString that never adds idString, for use in e.g. GenJVM - * where appending #uniqid breaks the bytecode. - */ - def cleanNameString: String = { - val s = simpleName.decode - if (s endsWith nme.LOCAL_SUFFIX) s.substring(0, s.length - nme.LOCAL_SUFFIX.length) - else s - } + def nameString: String = decodedName + idString - /** String representation of symbol's full name with <code>separator</code> - * between class names. - * Never translates expansions of operators back to operator symbol. - * Never adds id. + /** The name of the symbol before decoding, e.g. `$eq$eq` instead of `==`. */ - final def fullNameString(separator: Char): String = { - var str = - if (isRoot || isRootPackage || this == NoSymbol) this.toString - else if (owner.isRoot || owner.isEmptyPackageClass || owner.isInterpreterWrapper) simpleName.toString - else owner.enclClass.fullNameString(separator) + separator + simpleName - if (str.charAt(str.length - 1) == ' ') str = str.substring(0, str.length - 1) - str - } - - final def fullNameString: String = fullNameString('.') + def encodedName: String = name.toString /** If settings.uniqid is set, the symbol's id, else "" */ final def idString: String = @@ -1804,7 +1729,7 @@ trait Symbols { private var tpePeriod = NoPeriod override def isType = true - override def isTypeMember = true + override def isNonClassType = true override def isAbstractType = isDeferred override def isAliasType = !isDeferred @@ -1851,7 +1776,7 @@ trait Symbols { tyconCache } - override def setInfo(tp: Type): this.type = { + override def info_=(tp: Type) { tpePeriod = NoPeriod tyconCache = null if (tp.isComplete) @@ -1860,8 +1785,7 @@ trait Symbols { case NoType | AnnotatedType(_, _, _) => ; case _ => setFlag(MONOMORPHIC) } - super.setInfo(tp) - this + super.info_=(tp) } override def reset(completer: Type) { @@ -1954,7 +1878,7 @@ trait Symbols { private var thissym: Symbol = this override def isClass: Boolean = true - override def isTypeMember = false + override def isNonClassType = false override def isAbstractType = false override def isAliasType = false @@ -2037,22 +1961,21 @@ trait Symbols { def this(module: TermSymbol) = { this(module.owner, module.pos, module.name.toTypeName) setFlag(module.getFlag(ModuleToClassFlags) | MODULE | FINAL) - setSourceModule(module) + sourceModule = module } override def sourceModule = module lazy val implicitMembers = info.implicitMembers - def setSourceModule(module: Symbol) { this.module = module } + override def sourceModule_=(module: Symbol) { this.module = module } } /** An object repreesenting a missing symbol */ object NoSymbol extends Symbol(null, NoPosition, nme.NOSYMBOL) { setInfo(NoType) privateWithin = this - override def setInfo(info: Type): this.type = { + override def info_=(info: Type) { infos = TypeHistory(1, NoType, null) unlock() validTo = currentPeriod - this } override def defString: String = toString override def locationString: String = "" diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index f1755ed841..6a9f9a334d 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -14,7 +14,6 @@ import util.{HashSet, Position, NoPosition} import util.Statistics._ import Flags._ - /* A standard type pattern match: case ErrorType => // internal: error @@ -60,8 +59,7 @@ import Flags._ case DeBruijnIndex(level, index) */ -trait Types { - self: SymbolTable => +trait Types extends reflect.generic.Types { self: SymbolTable => import definitions._ @@ -236,7 +234,7 @@ trait Types { } /** The base class for all types */ - abstract class Type { + abstract class Type extends AbsType { /** Types for which asSeenFrom always is the identity, no matter what * prefix or owner. @@ -349,6 +347,11 @@ trait Types { def resultType(actuals: List[Type]) = this + /** If this is a TypeRef `clazz`[`T`], return the argument `T` + * otherwise return this type + */ + def remove(clazz: Symbol): Type = this + def resultApprox: Type = ApproximateDeBruijnMap(resultType) /** For a curried method or poly type its non-method result type, @@ -719,17 +722,10 @@ trait Types { typeVarToOriginMap(this) eq this } - /** Is this type completed (i.e. not a lazy type)? - */ - def isComplete: Boolean = true - /** Is this type a varargs parameter? */ def isVarargs: Boolean = typeSymbol == RepeatedParamClass - /** If this is a lazy type, assign a new type to `sym'. */ - def complete(sym: Symbol) {} - /** If this is a symbol loader type, load and assign a new type to * `sym'. */ @@ -899,24 +895,8 @@ trait Types { /** The kind of this type; used for debugging */ def kind: String = "unknown type of class "+getClass() - - override def toString: String = - if (tostringRecursions >= maxTostringRecursions) - "..." - else - try { - tostringRecursions += 1 - safeToString - } finally { - tostringRecursions -= 1 - } - - def safeToString: String = super.toString } - private final val maxTostringRecursions = 50 - private var tostringRecursions = 0 - // Subclasses ------------------------------------------------------------ trait UniqueType { @@ -1020,12 +1000,6 @@ trait Types { override def kind = "NoPrefixType" } - def ThisType(sym: Symbol) = { - if (!phase.erasedTypes) unique(new ThisType(sym) with UniqueType) - else if (sym.isImplClass) sym.typeOfThis - else sym.tpe - } - /** A class for this-types of the form <sym>.this.type */ abstract case class ThisType(sym: Symbol) extends SingletonType { @@ -1039,7 +1013,7 @@ trait Types { if (settings.debug.value) sym.nameString + ".this." else if (sym.isRoot || sym.isEmptyPackageClass || sym.isInterpreterWrapper || sym.isScalaPackageClass) "" else if (sym.isAnonymousClass || sym.isRefinementClass) "this." - else if (sym.isModuleClass) sym.fullNameString + "." + else if (sym.isModuleClass) sym.fullName + "." else sym.nameString + ".this." override def safeToString: String = if (sym.isRoot) "<root>" @@ -1049,6 +1023,13 @@ trait Types { override def kind = "ThisType" } + object ThisType extends ThisTypeExtractor { + def apply(sym: Symbol): Type = + if (!phase.erasedTypes) unique(new ThisType(sym) with UniqueType) + else if (sym.isImplClass) sym.typeOfThis + else sym.tpe + } + case class DeBruijnIndex(level: Int, paramId: Int) extends Type { override def isTrivial = true override def isStable = true @@ -1102,22 +1083,9 @@ trait Types { else pre.prefixString + sym.nameString + "." override def kind = "SingleType" } -/* - object SingleType { - def apply(pre: Type, sym: Symbol): Type = { - if (phase.erasedTypes) - sym.tpe.resultType - else if (sym.isRootPackage) - ThisType(RootClass) - else { - var sym1 = rebind(pre, sym) - val pre1 = removeSuper(pre, sym1) - if (pre1 ne pre) sym1 = rebind(pre1, sym1) - unique(new SingleType(pre1, sym1) with UniqueType) - } - } - } -*/ + + object SingleType extends SingleTypeExtractor + abstract case class SuperType(thistpe: Type, supertpe: Type) extends SingletonType { override val isTrivial: Boolean = thistpe.isTrivial && supertpe.isTrivial override def isNotNull = true; @@ -1132,9 +1100,11 @@ trait Types { override def kind = "SuperType" } - def SuperType(thistp: Type, supertp: Type): Type = - if (phase.erasedTypes) supertp - else unique(new SuperType(thistp, supertp) with UniqueType) + object SuperType extends SuperTypeExtractor { + def apply(thistp: Type, supertp: Type): Type = + if (phase.erasedTypes) supertp + else unique(new SuperType(thistp, supertp) with UniqueType) + } /** A class for the bounds of abstract types and type parameters */ @@ -1151,8 +1121,10 @@ trait Types { override def kind = "TypeBoundsType" } - def TypeBounds(lo: Type, hi: Type): TypeBounds = - unique(new TypeBounds(lo, hi) with UniqueType) + object TypeBounds extends TypeBoundsExtractor { + def apply(lo: Type, hi: Type): TypeBounds = + unique(new TypeBounds(lo, hi) with UniqueType) + } /** A common base class for intersection types and class types */ @@ -1306,13 +1278,13 @@ trait Types { if (isHigherKinded) PolyType( typeParams, - refinementOfClass( - typeSymbol, + RefinedType( parents map { case TypeRef(pre, sym, List()) => TypeRef(pre, sym, dummyArgs) case p => p }, - decls)) + decls, + typeSymbol)) else super.normalize } @@ -1346,6 +1318,11 @@ trait Types { override def kind = "RefinedType" } + object RefinedType extends RefinedTypeExtractor { + def apply(parents: List[Type], decls: Scope, clazz: Symbol) = + new RefinedType(parents, decls) { override def typeSymbol = clazz } + } + /** A class representing a class info */ case class ClassInfoType( @@ -1486,6 +1463,8 @@ trait Types { override def kind = "ClassInfoType" } + object ClassInfoType extends ClassInfoTypeExtractor + class PackageClassInfoType(decls: Scope, clazz: Symbol) extends ClassInfoType(List(), decls, clazz) @@ -1506,14 +1485,16 @@ trait Types { override def kind = "ConstantType" } - def ConstantType(value: Constant) = { - class UniqueConstantType extends ConstantType(value) with UniqueType { - /** Save the type of 'value'. For Java enums, it depends on finding the linked class, - * which might not be found after 'flatten'. */ - private lazy val _tpe: Type = value.tpe - override def underlying: Type = _tpe + object ConstantType extends ConstantTypeExtractor { + def apply(value: Constant): ConstantType = { + class UniqueConstantType extends ConstantType(value) with UniqueType { + /** Save the type of 'value'. For Java enums, it depends on finding the linked class, + * which might not be found after 'flatten'. */ + private lazy val _tpe: Type = value.tpe + override def underlying: Type = _tpe + } + unique(new UniqueConstantType) } - unique(new UniqueConstantType) } /** A class for named types of the form @@ -1526,7 +1507,7 @@ trait Types { * @param sym ... * @param args ... */ - case class TypeRef(pre: Type, sym: Symbol, args: List[Type]) extends Type { + abstract case class TypeRef(pre: Type, sym: Symbol, args: List[Type]) extends Type { // assert(!sym.isAbstractType || pre.isStable || pre.isError) // assert(!pre.isInstanceOf[ClassInfoType], this) // assert(!(sym hasFlag (PARAM | EXISTENTIAL)) || pre == NoPrefix, this) @@ -1567,10 +1548,10 @@ trait Types { def thisInfo = if (sym.isAliasType) normalize - else if (sym.isTypeMember) transformInfo(sym.info) + else if (sym.isNonClassType) transformInfo(sym.info) else sym.info - def relativeInfo = if (sym.isTypeMember) transformInfo(pre.memberInfo(sym)) else pre.memberInfo(sym) + def relativeInfo = if (sym.isNonClassType) transformInfo(pre.memberInfo(sym)) else pre.memberInfo(sym) override def typeSymbol = if (sym.isAliasType) normalize.typeSymbol else sym override def termSymbol = if (sym.isAliasType) normalize.termSymbol else super.termSymbol @@ -1632,7 +1613,7 @@ A type's typeSymbol should never be inspected directly. // (!result.isEmpty) IFF isHigherKinded override def typeParams: List[Symbol] = if (isHigherKinded) typeParamsDirect else List() - override def typeConstructor = rawTypeRef(pre, sym, List()) + override def typeConstructor = TypeRef(pre, sym, List()) // a reference (in a Scala program) to a type that has type parameters, but where the reference does not include type arguments // note that it doesn't matter whether the symbol refers to a java or scala symbol, @@ -1662,6 +1643,9 @@ A type's typeSymbol should never be inspected directly. xform.dealias } else this + override def remove(clazz: Symbol): Type = + if (sym == clazz && !args.isEmpty) args.head else this + def normalize0: Type = if (sym.isAliasType) { // beta-reduce if (sym.info.typeParams.length == args.length || !isHigherKinded) { @@ -1774,7 +1758,7 @@ A type's typeSymbol should never be inspected directly. } val monopart = if (!settings.debug.value && - (shorthands contains sym.fullNameString) && + (shorthands contains sym.fullName) && (sym.ownerChain forall (_.isClass))) // ensure that symbol is not a local copy with a name coincidence sym.name.toString else @@ -1808,7 +1792,7 @@ A type's typeSymbol should never be inspected directly. sym.isAnonymousClass || sym.isRefinementClass || sym.isScalaPackageClass) "" else if (sym.isPackageClass) - sym.fullNameString + "." + sym.fullName + "." else if (isStable && (sym.name.toString endsWith ".type")) sym.name.toString.substring(0, sym.name.length - 4) else @@ -1817,6 +1801,13 @@ A type's typeSymbol should never be inspected directly. override def kind = "TypeRef" } + object TypeRef extends TypeRefExtractor { + def apply(pre: Type, sym: Symbol, args: List[Type]): Type = { + class rawTypeRef extends TypeRef(pre, sym, args) with UniqueType + unique(new rawTypeRef) + } + } + /** A class representing a method type with parameters. */ case class MethodType(override val params: List[Symbol], @@ -1824,12 +1815,8 @@ A type's typeSymbol should never be inspected directly. override val isTrivial: Boolean = params.forall(_.tpe.isTrivial) && resultType.isTrivial - // The comment at ImplicitMethodType says the class is no longer needed, - // "a method type is implicit if the first parameter has the IMPLICIT flag". - // Should that change be pursued, then this method should be: - // def isImplicit = vparams.nonEmpty && (vparams.head hasFlag IMPLICIT) - def isImplicit = false - def isJava = false + def isImplicit = params.nonEmpty && params.head.isImplicit + def isJava = false // can we do something like for implicits? I.e. do Java methods without parameters need to be recognized? //assert(paramTypes forall (pt => !pt.typeSymbol.isImplClass))//DEBUG override def paramSectionCount: Int = resultType.paramSectionCount + 1 @@ -1873,11 +1860,7 @@ A type's typeSymbol should never be inspected directly. override def kind = "MethodType" } - // todo: this class is no longer needed, a method type is implicit if the first - // parameter has the IMPLICIT flag - class ImplicitMethodType(ps: List[Symbol], rt: Type) extends MethodType(ps, rt) { - override def isImplicit = true - } + object MethodType extends MethodTypeExtractor class JavaMethodType(ps: List[Symbol], rt: Type) extends MethodType(ps, rt) { override def isJava = true @@ -1935,6 +1918,8 @@ A type's typeSymbol should never be inspected directly. override def kind = "PolyType" } + object PolyType extends PolyTypeExtractor + case class ExistentialType(quantified: List[Symbol], override val underlying: Type) extends RewrappingTypeProxy { @@ -2029,6 +2014,8 @@ A type's typeSymbol should never be inspected directly. } } + object ExistentialType extends ExistentialTypeExtractor + /** A class containing the alternatives and type prefix of an overloaded symbol. * Not used after phase `typer'. */ @@ -2305,6 +2292,8 @@ A type's typeSymbol should never be inspected directly. override def kind = "AnnotatedType" } + object AnnotatedType extends AnnotatedTypeExtractor + /** A class representing types with a name. When an application uses * named arguments, the named argument types for calling isApplicable * are represented as NamedType. @@ -2315,10 +2304,7 @@ A type's typeSymbol should never be inspected directly. /** A class representing an as-yet unevaluated type. */ - abstract class LazyType extends Type { - override def isComplete: Boolean = false - override def complete(sym: Symbol) - override def safeToString = "<?>" + abstract class LazyType extends Type with AbsLazyType { override def kind = "LazyType" } @@ -2329,7 +2315,7 @@ A type's typeSymbol should never be inspected directly. */ private def rebind(pre: Type, sym: Symbol): Symbol = { val owner = sym.owner - if (owner.isClass && owner != pre.typeSymbol && !sym.isFinal && !sym.isClass) { + if (owner.isClass && owner != pre.typeSymbol && !sym.isEffectivelyFinal && !sym.isClass) { //Console.println("rebind "+pre+" "+sym)//DEBUG val rebind = pre.nonPrivateMember(sym.name).suchThat(sym => sym.isType || sym.isStable) if (rebind == NoSymbol) sym @@ -2345,7 +2331,7 @@ A type's typeSymbol should never be inspected directly. */ private def removeSuper(tp: Type, sym: Symbol): Type = tp match { case SuperType(thistp, _) => - if (sym.isFinal || sym.isDeferred) thistp + if (sym.isEffectivelyFinal || sym.isDeferred) thistp else tp case _ => tp @@ -2365,20 +2351,13 @@ A type's typeSymbol should never be inspected directly. } } - def refinementOfClass(clazz: Symbol, parents: List[Type], decls: Scope) = { - class RefinementOfClass extends RefinedType(parents, decls) { - override def typeSymbol: Symbol = clazz - } - new RefinementOfClass - } - /** the canonical creator for a refined type with a given scope */ def refinedType(parents: List[Type], owner: Symbol, decls: Scope, pos : Position): Type = { if (phase.erasedTypes) if (parents.isEmpty) ObjectClass.tpe else parents.head else { val clazz = owner.newRefinementClass(NoPosition) - val result = refinementOfClass(clazz, parents, decls) + val result = RefinedType(parents, decls, clazz) clazz.setInfo(result) result } @@ -2427,7 +2406,7 @@ A type's typeSymbol should never be inspected directly. transform(sym1.info) // check there are no cycles sym1.unlock() */ - rawTypeRef(pre, sym1, args) // don't expand type alias (cycles checked above) + TypeRef(pre, sym1, args) // don't expand type alias (cycles checked above) } else { val pre1 = removeSuper(pre, sym1) if (pre1 ne pre) { @@ -2438,31 +2417,20 @@ A type's typeSymbol should never be inspected directly. // sharpen prefix so that it is maximal and still contains the class. var p = pre.parents.reverse while (!p.isEmpty && p.head.member(sym1.name) != sym1) p = p.tail - if (p.isEmpty) rawTypeRef(pre, sym1, args) + if (p.isEmpty) TypeRef(pre, sym1, args) else typeRef(p.head, sym1, args) } else { - rawTypeRef(pre, sym1, args) + TypeRef(pre, sym1, args) } } } - /** create a type-ref as found, without checks or rebinds */ - def rawTypeRef(pre: Type, sym: Symbol, args: List[Type]): Type = { - class rawTypeRef extends TypeRef(pre, sym, args) with UniqueType - unique(new rawTypeRef) - } - - /** The canonical creator for implicit method types */ - def ImplicitMethodType(params: List[Symbol], resultType: Type): ImplicitMethodType = - new ImplicitMethodType(params, resultType) // don't unique this! - /** The canonical creator for implicit method types */ def JavaMethodType(params: List[Symbol], resultType: Type): JavaMethodType = new JavaMethodType(params, resultType) // don't unique this! - /** Create a new MethodType of the same class as tp, i.e. keep Java / ImplicitMethodType */ + /** Create a new MethodType of the same class as tp, i.e. keep JavaMethodType */ def copyMethodType(tp: Type, params: List[Symbol], restpe: Type): Type = tp match { - case _: ImplicitMethodType => ImplicitMethodType(params, restpe) case _: JavaMethodType => JavaMethodType(params, restpe) case _ => MethodType(params, restpe) } @@ -4480,7 +4448,7 @@ A type's typeSymbol should never be inspected directly. params1.length == params2.length && // useful pre-secreening optimization matchingParams(params1, params2, tp1.isInstanceOf[JavaMethodType], tp2.isInstanceOf[JavaMethodType]) && matchesType(res1, res2, alwaysMatchSimple) && - tp1.isInstanceOf[ImplicitMethodType] == tp2.isInstanceOf[ImplicitMethodType] + tp1.isImplicit == tp2.isImplicit case (PolyType(tparams1, res1), PolyType(tparams2, res2)) => matchesQuantified(tparams1, tparams2, res1, res2) case (PolyType(List(), rtp1), MethodType(List(), rtp2)) => diff --git a/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala b/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala index e827b28331..f1e88fe6e8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala +++ b/src/compiler/scala/tools/nsc/typechecker/ConstantFolder.scala @@ -154,7 +154,7 @@ abstract class ConstantFolder { private def foldBinop(op: Name, x: Constant, y: Constant): Constant = { val optag = if (x.tag == y.tag) x.tag - else if (isNumeric(x.tag) && isNumeric(y.tag)) math.max(x.tag, y.tag) + else if (x.isNumeric && y.isNumeric) math.max(x.tag, y.tag) else NoTag try optag match { diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index dd592bb96d..7ca4dcf885 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -8,7 +8,6 @@ package scala.tools.nsc package typechecker import symtab.Flags._ -import scala.tools.nsc.util.{Position,NoPosition} import scala.collection.mutable.ListBuffer /** This trait ... @@ -122,40 +121,6 @@ trait Contexts { self: Analyzer => var savedTypeBounds: List[(Symbol, Type)] = List() // saved type bounds // for type parameters which are narrowed in a GADT - def intern0 : Context = { - if (this eq NoContext) return this - val txt = new Context - txt.unit = unit - txt.tree = tree - txt.owner = owner - txt.scope = scope - assert(outer ne this) // stupid - txt.outer = outer // already interned - def fix(what : Context) = - if (what eq this) txt - else what - txt.enclClass = fix(enclClass) - txt.enclMethod = fix(enclMethod) - txt.implicitsEnabled = implicitsEnabled - txt.variance = variance - txt._undetparams = _undetparams - txt.depth = depth - txt.imports = imports - txt.openImplicits = openImplicits - txt.prefix = prefix - txt.inConstructorSuffix = inConstructorSuffix - txt.returnsSeen = returnsSeen - txt.reportGeneralErrors = reportGeneralErrors - txt.checking = checking - txt.retyping = retyping - txt.savedTypeBounds = savedTypeBounds - txt - } - override def equals(that: Any): Boolean = that match { - case that: AnyRef if this eq that => true - case that => super.equals(that) - } - def undetparams = _undetparams def undetparams_=(ps: List[Symbol]) = { //System.out.println("undetparams = " + ps);//debug @@ -184,11 +149,7 @@ trait Contexts { self: Analyzer => c.owner = owner c.scope = scope - c.outer = intern(this) - def internIf(txt : Context) = { - if (txt eq this) c.outer // already interned! - else txt - } + c.outer = this tree match { case Template(_, _, _) | PackageDef(_, _) => @@ -196,7 +157,7 @@ trait Contexts { self: Analyzer => c.prefix = c.owner.thisType c.inConstructorSuffix = false case _ => - c.enclClass = internIf(this.enclClass) + c.enclClass = this.enclClass c.prefix = if (c.owner != this.owner && c.owner.isTerm) NoPrefix else this.prefix @@ -206,7 +167,7 @@ trait Contexts { self: Analyzer => case DefDef(_, _, _, _, _, _) => c.enclMethod = c case _ => - c.enclMethod = internIf(this.enclMethod) + c.enclMethod = this.enclMethod } c.variance = this.variance c.depth = if (scope == this.scope) this.depth else this.depth + 1 @@ -530,30 +491,6 @@ trait Contexts { self: Analyzer => } implicitsCache } - override def hashCode = { - var hc = 0 - implicit def b2i(b : Boolean) = if (b) 1 else 0 - // assum enclClass/enclMethod/outer are all interned already. - hc += tree.hashCodeStructure - def f(txt : Context) = if (txt eq this) 0 else System.identityHashCode(txt) - hc += f(enclClass) - hc += f(enclMethod) - hc += f(outer) - hc += owner.hashCode - hc += scope.hashCode - hc += variance.hashCode - hc += _undetparams.hashCode - hc += depth - hc += imports.hashCode - hc += prefix.hashCode - hc += inConstructorSuffix - hc += checking - hc += retyping - hc += savedTypeBounds.hashCode - hc += (if (unit eq null) 0 else unit.hashCode) - hc - } - } class ImportInfo(val tree: Import, val depth: Int) { /** The prefix expression */ @@ -603,23 +540,9 @@ trait Contexts { self: Analyzer => } override def toString() = tree.toString() - - override def hashCode = tree.hashCodeStructure + depth - override def equals(that : Any) = that match { - case that : ImportInfo => - depth == that.depth && (tree equalsStructure that.tree) - case _ => false - } } case class ImportType(expr: Tree) extends Type { - override def equals(that : Any) = that match { - case ImportType(expr) => this.expr == expr - case _ => false - } - override def hashCode = expr.hashCode override def safeToString = "ImportType("+expr+")" } - protected def intern(txt : Context) = txt - } diff --git a/src/compiler/scala/tools/nsc/typechecker/DeVirtualize.scala b/src/compiler/scala/tools/nsc/typechecker/DeVirtualize.scala index 97a1d81323..304ae5cdea 100644 --- a/src/compiler/scala/tools/nsc/typechecker/DeVirtualize.scala +++ b/src/compiler/scala/tools/nsc/typechecker/DeVirtualize.scala @@ -177,7 +177,7 @@ abstract class DeVirtualize extends InfoTransform with TypingTransformers { /** The name of the field representing a constructor parameter of a virtual class */ protected def paramFieldName(clazz: Symbol, index: Int) = atPhase(ownPhase) { - clazz.expandedName(newTermName("param$"+index)) + nme.expandedName(newTermName("param$"+index), clazz) } /** The name of the field representing a constructor parameter of a virtual class */ diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala index 796d6f8134..6a94189284 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala @@ -97,7 +97,7 @@ abstract class Duplicators extends Analyzer { val tpe2: Type = (new FixInvalidSyms)(tpe1) val tpe3 = tpe2 match { case TypeRef(_, sym, _) if (sym.owner == oldClassOwner) => - log("seeing " + sym.fullNameString + " from a different angle") + log("seeing " + sym.fullName + " from a different angle") tpe2.asSeenFrom(newClassOwner.thisType, oldClassOwner) case _ => tpe2 } diff --git a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala index ee267690f1..bb9582b093 100644 --- a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala +++ b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala @@ -114,9 +114,7 @@ trait EtaExpansion { self: Analyzer => * @return ... */ def expand(tree: Tree, tpe: Type): Tree = tpe match { - case mt: ImplicitMethodType => - tree - case MethodType(paramSyms, restpe) => + case mt @ MethodType(paramSyms, restpe) if !mt.isImplicit => val params = paramSyms map (sym => ValDef(Modifiers(SYNTHETIC | PARAM), sym.name, TypeTree(sym.tpe) , EmptyTree)) diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index eb04ab984b..14190a323e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -12,7 +12,7 @@ package scala.tools.nsc package typechecker import scala.collection.mutable.{LinkedHashMap, ListBuffer} -import scala.tools.nsc.util.{ HashSet, Position, Set, NoPosition, SourceFile } +import scala.tools.nsc.util.{HashSet, Set, SourceFile} import symtab.Flags._ import util.Statistics._ @@ -798,7 +798,7 @@ self: Analyzer => (if ((pre eq NoPrefix) || pre.typeSymbol.isStaticOwner) suffix else findSubManifest(pre) :: suffix): _*) } else if (sym.isAbstractType) { - if (sym.isExistential) + if (sym.isExistentiallyBound) EmptyTree // todo: change to existential parameter manifest else if (sym.isTypeParameterOrSkolem) EmptyTree // a manifest should have been found by normal searchImplicit diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index bde84827b2..8761420778 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -6,7 +6,7 @@ package scala.tools.nsc package typechecker -import scala.tools.nsc.util.{Position, NoPosition} + import scala.collection.mutable.ListBuffer import scala.util.control.ControlException import symtab.Flags._ @@ -399,8 +399,6 @@ trait Infer { def isPlausiblyCompatible(tp: Type, pt: Type): Boolean = tp match { case PolyType(_, restpe) => isPlausiblyCompatible(restpe, pt) - case mt: ImplicitMethodType => - isPlausiblyCompatible(mt.resultType, pt) case ExistentialType(tparams, qtpe) => isPlausiblyCompatible(qtpe, pt) case mt @ MethodType(params, restpe) => @@ -565,7 +563,7 @@ trait Infer { // optimze type varianbles wrt to the implicit formals only; ignore the result type. // See test pos/jesper.scala val varianceType = restpe match { - case mt: ImplicitMethodType if isFullyDefined(pt) => + case mt: MethodType if mt.isImplicit && isFullyDefined(pt) => MethodType(mt.params, AnyClass.tpe) case _ => restpe @@ -937,7 +935,7 @@ trait Infer { case et: ExistentialType => isAsSpecific(ftpe1.skolemizeExistential, ftpe2) //et.withTypeVars(isAsSpecific(_, ftpe2)) - case mt: ImplicitMethodType => + case mt: MethodType if mt.isImplicit => isAsSpecific(ftpe1.resultType, ftpe2) case MethodType(params @ (x :: xs), _) => var argtpes = params map (_.tpe) @@ -945,7 +943,7 @@ trait Infer { argtpes = argtpes map (argtpe => if (isRepeatedParamType(argtpe)) argtpe.typeArgs.head else argtpe) isApplicable(List(), ftpe2, argtpes, WildcardType) - case PolyType(tparams, mt: ImplicitMethodType) => + case PolyType(tparams, mt: MethodType) if mt.isImplicit => isAsSpecific(PolyType(tparams, mt.resultType), ftpe2) case PolyType(_, MethodType(params @ (x :: xs), _)) => isApplicable(List(), ftpe2, params map (_.tpe), WildcardType) @@ -957,12 +955,10 @@ trait Infer { alts forall (alt => isAsSpecific(ftpe1, pre.memberType(alt))) case et: ExistentialType => et.withTypeVars(isAsSpecific(ftpe1, _)) - case mt: ImplicitMethodType => - isAsSpecific(ftpe1, mt.resultType) - case PolyType(tparams, mt: ImplicitMethodType) => - isAsSpecific(ftpe1, PolyType(tparams, mt.resultType)) - case MethodType(_, _) | PolyType(_, MethodType(_, _)) => - true + case mt: MethodType => + !mt.isImplicit || isAsSpecific(ftpe1, mt.resultType) + case PolyType(tparams, mt: MethodType) => + !mt.isImplicit || isAsSpecific(ftpe1, PolyType(tparams, mt.resultType)) case _ => isAsSpecificValueType(ftpe1, ftpe2, List(), List()) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 74c57c0fb7..e64a78e8e4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -8,7 +8,6 @@ package scala.tools.nsc package typechecker import scala.collection.mutable.HashMap -import scala.tools.nsc.util.Position import symtab.Flags import symtab.Flags._ @@ -29,7 +28,7 @@ trait Namers { self: Analyzer => case TypeRef(pre, sym, args) if (sym.isTypeSkolem && (tparams contains sym.deSkolemize)) => // println("DESKOLEMIZING "+sym+" in "+sym.owner) - mapOver(rawTypeRef(NoPrefix, sym.deSkolemize, args)) + mapOver(TypeRef(NoPrefix, sym.deSkolemize, args)) /* case PolyType(tparams1, restpe) => new DeSkolemizeMap(tparams1 ::: tparams).mapOver(tp) @@ -76,7 +75,7 @@ trait Namers { self: Analyzer => } def inConstructorFlag: Long = - if (context.owner.isConstructor && !context.inConstructorSuffix || context.owner.isEarly) INCONSTRUCTOR + if (context.owner.isConstructor && !context.inConstructorSuffix || context.owner.isEarlyInitialized) INCONSTRUCTOR else 0l def moduleClassFlags(moduleFlags: Long) = @@ -127,6 +126,7 @@ trait Namers { self: Analyzer => unsafeTypeParams foreach(sym => paramContext.scope.enter(sym)) newNamer(paramContext) } + def usePrimary = sym.isTerm && ( (sym hasFlag PARAMACCESSOR) || ((sym hasFlag PARAM) && sym.owner.isPrimaryConstructor) @@ -837,9 +837,7 @@ trait Namers { self: Analyzer => val params = vparams map (vparam => if (meth hasFlag JAVA) vparam.setInfo(objToAny(vparam.tpe)) else vparam) val restpe1 = convertToDeBruijn(vparams, 1)(restpe) // new dependent types: replace symbols in restpe with the ones in vparams - if (!vparams.isEmpty && vparams.head.hasFlag(IMPLICIT)) - ImplicitMethodType(params, restpe1) - else if (meth hasFlag JAVA) JavaMethodType(params, restpe1) + if (meth hasFlag JAVA) JavaMethodType(params, restpe1) else MethodType(params, restpe1) } @@ -946,7 +944,7 @@ trait Namers { self: Analyzer => // match empty and missing parameter list if (vparamss.isEmpty && baseParamss == List(Nil)) baseParamss = Nil if (vparamss == List(Nil) && baseParamss.isEmpty) baseParamss = List(Nil) - assert(!overrides || vparamss.length == baseParamss.length, ""+ meth.fullNameString + ", "+ overridden.fullNameString) + assert(!overrides || vparamss.length == baseParamss.length, ""+ meth.fullName + ", "+ overridden.fullName) var ownerNamer: Option[Namer] = None var moduleNamer: Option[(ClassDef, Namer)] = None @@ -957,7 +955,7 @@ trait Namers { self: Analyzer => // denotes the parameter lists which are on the left side of the current one. these get added // to the default getter. Example: "def foo(a: Int)(b: Int = a)" gives "foo$default$1(a: Int) = a" (List[List[ValDef]]() /: (vparamss))((previous: List[List[ValDef]], vparams: List[ValDef]) => { - assert(!overrides || vparams.length == baseParamss.head.length, ""+ meth.fullNameString + ", "+ overridden.fullNameString) + assert(!overrides || vparams.length == baseParamss.head.length, ""+ meth.fullName + ", "+ overridden.fullName) var baseParams = if (overrides) baseParamss.head else Nil for (vparam <- vparams) { val sym = vparam.symbol diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index b41924c3bb..273e8b1d97 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -7,7 +7,6 @@ package scala.tools.nsc package typechecker -import scala.tools.nsc.util.Position import symtab.Flags._ import scala.collection.mutable.ListBuffer diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index fcc5a3cbf4..5234bb44f1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -10,7 +10,6 @@ package typechecker import symtab.Flags._ import collection.mutable.{HashSet, HashMap} import transform.InfoTransform -import scala.tools.nsc.util.{Position, NoPosition} import scala.collection.mutable.ListBuffer /** <p> @@ -385,7 +384,7 @@ abstract class RefChecks extends InfoTransform { val opc = new overridingPairs.Cursor(clazz) while (opc.hasNext) { - //Console.println(opc.overriding/* + ":" + opc.overriding.tpe*/ + " in "+opc.overriding.fullNameString + " overrides " + opc.overridden/* + ":" + opc.overridden.tpe*/ + " in "+opc.overridden.fullNameString + "/"+ opc.overridden.hasFlag(DEFERRED));//debug + //Console.println(opc.overriding/* + ":" + opc.overriding.tpe*/ + " in "+opc.overriding.fullName + " overrides " + opc.overridden/* + ":" + opc.overridden.tpe*/ + " in "+opc.overridden.fullName + "/"+ opc.overridden.hasFlag(DEFERRED));//debug if (!opc.overridden.isClass) checkOverride(clazz, opc.overriding, opc.overridden); opc.next @@ -493,7 +492,7 @@ abstract class RefChecks extends InfoTransform { /** validate all base types of a class in reverse linear order. */ def register(tp: Type) { -// if (clazz.fullNameString.endsWith("Collection.Projection")) +// if (clazz.fullName.endsWith("Collection.Projection")) // println("validate base type "+tp) val baseClass = tp.typeSymbol if (baseClass.isClass) { diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index 257ab243b4..7012fa177a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -9,7 +9,6 @@ package typechecker import scala.collection.mutable.ListBuffer import symtab.Flags._ -import util.Position /** This phase adds super accessors for all super calls that * either appear in a trait or have as a target a member of some outer class. diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala index cc8d39fc5f..c2b6e7adf2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala @@ -8,7 +8,6 @@ package scala.tools.nsc package typechecker import scala.tools.nsc.symtab.Flags._ -import scala.tools.nsc.util.{Position, NoPosition} abstract class TreeCheckers extends Analyzer { diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index baa0f9a8be..5285322d1f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -14,7 +14,7 @@ package typechecker import scala.collection.mutable.{HashMap, ListBuffer} import scala.util.control.ControlException import scala.tools.nsc.interactive.RangePositions -import scala.tools.nsc.util.{ Position, Set, NoPosition, SourceFile, BatchSourceFile } +import scala.tools.nsc.util.{Set, SourceFile, BatchSourceFile} import symtab.Flags._ import util.Statistics @@ -334,7 +334,7 @@ trait Typers { self: Analyzer => tp match { case TypeRef(pre, sym, args) => (checkNotLocked(sym)) && ( - !sym.isTypeMember || + !sym.isNonClassType || checkNonCyclic(pos, appliedType(pre.memberInfo(sym), args), sym) // @M! info for a type ref to a type parameter now returns a polytype // @M was: checkNonCyclic(pos, pre.memberInfo(sym).subst(sym.typeParams, args), sym) ) @@ -817,7 +817,7 @@ trait Typers { self: Analyzer => TypeTree(tparam.tpeHK) setPos tree.pos.focus)) setPos tree.pos //@M/tcpolyinfer: changed tparam.tpe to tparam.tpeHK context.undetparams = context.undetparams ::: tparams1 adapt(tree1 setType restpe.substSym(tparams, tparams1), mode, pt, original) - case mt: ImplicitMethodType if ((mode & (EXPRmode | FUNmode | LHSmode)) == EXPRmode) => // (4.1) + case mt: MethodType if mt.isImplicit && ((mode & (EXPRmode | FUNmode | LHSmode)) == EXPRmode) => // (4.1) if (!context.undetparams.isEmpty/* && (mode & POLYmode) == 0 disabled to make implicits in new collection work; we should revisit this. */) { // (9) // println("adapt IMT: "+(context.undetparams, pt)) //@MDEBUG context.undetparams = inferExprInstance( @@ -1255,9 +1255,9 @@ trait Typers { self: Analyzer => /* if (settings.Xshowcls.value != "" && - settings.Xshowcls.value == context.owner.fullNameString) + settings.Xshowcls.value == context.owner.fullName) println("INFO "+context.owner+ - ", baseclasses = "+(context.owner.info.baseClasses map (_.fullNameString))+ + ", baseclasses = "+(context.owner.info.baseClasses map (_.fullName))+ ", lin = "+(context.owner.info.baseClasses map (context.owner.thisType.baseType))) */ } @@ -2676,7 +2676,7 @@ trait Typers { self: Analyzer => for (name <- names) { if (!name.annotations.contains(AnnotationInfo(AnnotationDefaultAttr.tpe, List(), List())) && !name.hasFlag(DEFAULTPARAM)) - error(ann.pos, "annotation " + annType.typeSymbol.fullNameString + " is missing argument " + name.name) + error(ann.pos, "annotation " + annType.typeSymbol.fullName + " is missing argument " + name.name) } if (hasError) annotationError @@ -3085,14 +3085,9 @@ trait Typers { self: Analyzer => } def typedAssign(lhs: Tree, rhs: Tree): Tree = { - def mayBeVarGetter(sym: Symbol) = sym.info match { - case PolyType(List(), _) => sym.owner.isClass && !sym.isStable - case _: ImplicitMethodType => sym.owner.isClass && !sym.isStable - case _ => false - } val lhs1 = typed(lhs, EXPRmode | LHSmode, WildcardType) val varsym = lhs1.symbol - if ((varsym ne null) && mayBeVarGetter(varsym)) + if ((varsym ne null) && treeInfo.mayBeVarGetter(varsym)) lhs1 match { case Select(qual, name) => return typed( @@ -3305,10 +3300,14 @@ trait Typers { self: Analyzer => case fun1: Tree => val fun2 = if (stableApplication) stabilizeFun(fun1, mode, pt) else fun1 incCounter(typedApplyCount) + def isImplicitMethod(tpe: Type) = tpe match { + case mt: MethodType => mt.isImplicit + case _ => false + } val res = if (phase.id <= currentRun.typerPhase.id && fun2.isInstanceOf[Select] && - !fun2.tpe.isInstanceOf[ImplicitMethodType] && + !isImplicitMethod(fun2.tpe) && ((fun2.symbol eq null) || !fun2.symbol.isConstructor) && (mode & (EXPRmode | SNDTRYmode)) == EXPRmode) { tryTypedApply(fun2, args) @@ -3698,7 +3697,7 @@ trait Typers { self: Analyzer => //@M! the polytype denotes the expected kind } val argtypes = args1 map (_.tpe) - val owntype = if (tpt1.symbol.isClass || tpt1.symbol.isTypeMember) + val owntype = if (tpt1.symbol.isClass || tpt1.symbol.isNonClassType) // @M! added the latter condition appliedType(tpt1.tpe, argtypes) else tpt1.tpe.instantiateTypeParams(tparams, argtypes) diff --git a/src/library/scala/reflect/Code.scala b/src/library/scala/reflect/Code.scala index 71e148db81..61138f2495 100644 --- a/src/library/scala/reflect/Code.scala +++ b/src/library/scala/reflect/Code.scala @@ -12,7 +12,7 @@ package scala.reflect /** This type is required by the compiler and <b>should not be used in client code</b>. */ -class Code[Type](val tree: Tree) +class Code[T](val tree: Tree) /** This type is required by the compiler and <b>should not be used in client code</b>. */ object Code { diff --git a/src/library/scala/reflect/NameTransformer.scala b/src/library/scala/reflect/NameTransformer.scala new file mode 100755 index 0000000000..0629c3a2f8 --- /dev/null +++ b/src/library/scala/reflect/NameTransformer.scala @@ -0,0 +1,155 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2010, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +// $Id: NameTransformer.scala 20028 2009-12-07 11:49:19Z cunei $ + + +package scala.reflect + +/** + * @author Martin Odersky + */ +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)) + } + + /* Note: decoding assumes opcodes are only ever lowercase. */ + 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") + enterOp('?', "$qmark") + enterOp('@', "$at") + + /** Replace operator symbols by corresponding "<code>$op_name</code>". + * + * @param name ... + * @return ... + */ + def encode(name: String): String = { + var buf: StringBuilder = null + val len = name.length() + var i = 0 + while (i < len) { + val c = name charAt i + if (c < nops && (op2code(c) ne null)) { + if (buf eq null) { + buf = new StringBuilder() + buf.append(name.substring(0, i)) + } + buf.append(op2code(c)) + /* Handle glyphs that are not valid Java/JVM identifiers */ + } + else if (!Character.isJavaIdentifierPart(c)) { + if (buf eq null) { + buf = new StringBuilder() + buf.append(name.substring(0, i)) + } + buf.append("$u%04X".format(c.toInt)) + } + else if (buf ne null) { + buf.append(c) + } + i += 1 + } + if (buf eq null) name else buf.toString() + } + + /** Replace <code>$op_name</code> by corresponding operator symbol. + * + * @param name0 ... + * @return ... + */ + def decode(name0: String): String = { + //System.out.println("decode: " + name);//DEBUG + val name = if (name0.endsWith("<init>")) name0.substring(0, name0.length() - ("<init>").length()) + "this" + else name0; + var buf: StringBuilder = null + val len = name.length() + var i = 0 + while (i < len) { + var ops: OpCodes = null + var unicode = false + 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 ne null) && !name.startsWith(ops.code, i)) ops = ops.next + if (ops ne null) { + if (buf eq null) { + buf = new StringBuilder() + buf.append(name.substring(0, i)) + } + buf.append(ops.op) + i += ops.code.length() + } + /* Handle the decoding of Unicode glyphs that are + * not valid Java/JVM identifiers */ + } else if ((len - i) >= 6 && // Check that there are enough characters left + ch1 == 'u' && + ((Character.isDigit(ch2)) || + ('A' <= ch2 && ch2 <= 'F'))) { + /* Skip past "$u", next four should be hexadecimal */ + val hex = name.substring(i+2, i+6) + try { + val str = Integer.parseInt(hex, 16).toChar + if (buf eq null) { + buf = new StringBuilder() + buf.append(name.substring(0, i)) + } + buf.append(str) + /* 2 for "$u", 4 for hexadecimal number */ + i += 6 + unicode = true + } catch { + case _:NumberFormatException => + /* <code>hex</code> did not decode to a hexadecimal number, so + * do nothing. */ + } + } + } + } + /* If we didn't see an opcode or encoded Unicode glyph, and the + buffer is non-empty, write the current character and advance + one */ + if ((ops eq null) && !unicode) { + if (buf ne null) + buf.append(c) + i += 1 + } + } + //System.out.println("= " + (if (buf == null) name else buf.toString()));//DEBUG + if (buf eq null) name else buf.toString() + } +} diff --git a/src/library/scala/reflect/generic/AnnotationInfos.scala b/src/library/scala/reflect/generic/AnnotationInfos.scala new file mode 100755 index 0000000000..6239ca189c --- /dev/null +++ b/src/library/scala/reflect/generic/AnnotationInfos.scala @@ -0,0 +1,42 @@ +package scala.reflect +package generic + +trait AnnotationInfos { self: Universe => + + type AnnotationInfo <: AnyRef + val AnnotationInfo: AnnotationInfoExtractor + + abstract class AnnotationInfoExtractor { + def apply(atp: Type, args: List[Tree], assocs: List[(Name, ClassfileAnnotArg)]): AnnotationInfo + def unapply(info: AnnotationInfo): Option[(Type, List[Tree], List[(Name, ClassfileAnnotArg)])] + } + + type ClassfileAnnotArg <: AnyRef + implicit def classfileAnnotArgManifest: ClassManifest[ClassfileAnnotArg] // need a precise manifest to pass to UnPickle's toArray call + + type LiteralAnnotArg <: ClassfileAnnotArg + val LiteralAnnotArg: LiteralAnnotArgExtractor + + type ArrayAnnotArg <: ClassfileAnnotArg + val ArrayAnnotArg: ArrayAnnotArgExtractor + + type NestedAnnotArg <: ClassfileAnnotArg + val NestedAnnotArg: NestedAnnotArgExtractor + + abstract class LiteralAnnotArgExtractor { + def apply(const: Constant): LiteralAnnotArg + def unapply(arg: LiteralAnnotArg): Option[Constant] + } + + abstract class ArrayAnnotArgExtractor { + def apply(const: Array[ClassfileAnnotArg]): ArrayAnnotArg + def unapply(arg: ArrayAnnotArg): Option[Array[ClassfileAnnotArg]] + } + + abstract class NestedAnnotArgExtractor { + def apply(anninfo: AnnotationInfo): NestedAnnotArg + def unapply(arg: NestedAnnotArg): Option[AnnotationInfo] + } +} + + diff --git a/src/compiler/scala/tools/nsc/symtab/Constants.scala b/src/library/scala/reflect/generic/Constants.scala index 9057c537a7..4b21823978 100644..100755 --- a/src/compiler/scala/tools/nsc/symtab/Constants.scala +++ b/src/library/scala/reflect/generic/Constants.scala @@ -2,18 +2,15 @@ * Copyright 2005-2010 LAMP/EPFL * @author Martin Odersky */ -// $Id$ - -package scala.tools.nsc -package symtab +// $Id: Constants.scala 20028 2009-12-07 11:49:19Z cunei $ +package scala.reflect +package generic import java.lang.Integer.toOctalString +import PickleFormat._ -import classfile.PickleFormat._ - -trait Constants { - self: SymbolTable => +trait Constants { self: Universe => import definitions._ @@ -33,8 +30,6 @@ trait Constants { // For supporting java enumerations inside java annotations (see ClassfileParser) final val EnumTag = LITERALenum - LITERAL - def isNumeric(tag: Int) = ByteTag <= tag && tag <= DoubleTag - case class Constant(value: Any) { val tag: Int = @@ -53,6 +48,8 @@ trait Constants { else if (value == null) NullTag else throw new Error("bad constant value: " + value) + def isNumeric: Boolean = ByteTag <= tag && tag <= DoubleTag + def tpe: Type = tag match { case UnitTag => UnitClass.tpe case BooleanTag => BooleanClass.tpe @@ -65,7 +62,7 @@ trait Constants { case DoubleTag => DoubleClass.tpe case StringTag => StringClass.tpe case NullTag => NullClass.tpe - case ClassTag => Predef_classOfType(value.asInstanceOf[Type]) + case ClassTag => ClassType(value.asInstanceOf[Type]) case EnumTag => // given (in java): "class A { enum E { VAL1 } }" // - symbolValue: the symbol of the actual enumeration value (VAL1) @@ -82,11 +79,11 @@ trait Constants { override def equals(other: Any): Boolean = other match { case that: Constant => this.tag == that.tag && - (this.value == that.value || isNaN(this.value) && isNaN(that.value)) + (this.value == that.value || this.isNaN && that.isNaN) case _ => false } - def isNaN(value: Any) = value match { + def isNaN = value match { case f: Float => f.isNaN case d: Double => d.isNaN case _ => false @@ -233,7 +230,7 @@ trait Constants { def symbolValue: Symbol = value.asInstanceOf[Symbol] - override def hashCode(): Int = + override def hashCode: Int = if (value == null) 0 else value.hashCode() * 41 + 17 } } diff --git a/src/library/scala/reflect/generic/Flags.scala b/src/library/scala/reflect/generic/Flags.scala new file mode 100755 index 0000000000..1cd9190f19 --- /dev/null +++ b/src/library/scala/reflect/generic/Flags.scala @@ -0,0 +1,198 @@ +package scala.reflect +package generic + +object Flags extends Flags + +class Flags { + + // modifiers + final val IMPLICIT = 0x00000200 + final val FINAL = 0x00000020 + final val PRIVATE = 0x00000004 + final val PROTECTED = 0x00000001 + + final val SEALED = 0x00000400 + final val OVERRIDE = 0x00000002 + final val CASE = 0x00000800 + final val ABSTRACT = 0x00000008 // abstract class, or used in conjunction + // with abstract override. + // Note difference to DEFERRED! + + final val DEFERRED = 0x00000010 // was `abstract' for members | trait is virtual + final val METHOD = 0x00000040 // a method + final val MODULE = 0x00000100 // symbol is module or class implementing a module + final val INTERFACE = 0x00000080 // symbol is an interface (i.e. a trait which defines only abstract methods) + + final val MUTABLE = 0x00001000 // symbol is a mutable variable. + final val PARAM = 0x00002000 // symbol is a (value or type) parameter to a method + final val PACKAGE = 0x00004000 // symbol is a java package + // available: 0x00008000 + + final val COVARIANT = 0x00010000 // symbol is a covariant type variable + final val CAPTURED = 0x00010000 // variable is accessed from nested function. + // Set by LambdaLift + final val BYNAMEPARAM = 0x00010000 // parameter is by name + final val CONTRAVARIANT = 0x00020000 // symbol is a contravariant type variable + final val LABEL = 0x00020000 // method symbol is a label. Set by TailCall + final val INCONSTRUCTOR = 0x00020000 // class symbol is defined in this/superclass + // constructor. + final val ABSOVERRIDE = 0x00040000 // combination of abstract & override + final val LOCAL = 0x00080000 // symbol is local to current class (i.e. private[this] or protected[this] + // pre: PRIVATE or PROTECTED are also set + final val JAVA = 0x00100000 // symbol was defined by a Java class + final val SYNTHETIC = 0x00200000 // symbol is compiler-generated + final val STABLE = 0x00400000 // functions that are assumed to be stable + // (typically, access methods for valdefs) + // or classes that do not contain abstract types. + final val STATIC = 0x00800000 // static field, method or class + + final val CASEACCESSOR = 0x01000000 // symbol is a case parameter (or its accessor) + final val TRAIT = 0x02000000 // symbol is a trait + final val DEFAULTPARAM = 0x02000000 // the parameter has a default value + final val BRIDGE = 0x04000000 // function is a bridge method. Set by Erasure + final val ACCESSOR = 0x08000000 // a value or variable accessor (getter or setter) + + final val SUPERACCESSOR = 0x10000000 // a super accessor + final val PARAMACCESSOR = 0x20000000 // for value definitions: is an access method + // for a final val parameter + // for parameters: is a val parameter + final val MODULEVAR = 0x40000000 // for variables: is the variable caching a module value + final val SYNTHETICMETH = 0x40000000 // for methods: synthetic method, but without SYNTHETIC flag + final val MONOMORPHIC = 0x40000000 // for type symbols: does not have type parameters + final val LAZY = 0x80000000L // symbol is a lazy val. can't have MUTABLE unless transformed by typer + + final val IS_ERROR = 0x100000000L // symbol is an error symbol + final val OVERLOADED = 0x200000000L // symbol is overloaded + final val LIFTED = 0x400000000L // class has been lifted out to package level + // local value has been lifted out to class level + // todo: make LIFTED = latePRIVATE? + final val MIXEDIN = 0x800000000L // term member has been mixed in + final val EXISTENTIAL = 0x800000000L // type is an existential parameter or skolem + + final val EXPANDEDNAME = 0x1000000000L // name has been expanded with class suffix + final val IMPLCLASS = 0x2000000000L // symbol is an implementation class + final val PRESUPER = 0x2000000000L // value is evaluated before super call + final val TRANS_FLAG = 0x4000000000L // transient flag guaranteed to be reset + // after each phase. + + final val LOCKED = 0x8000000000L // temporary flag to catch cyclic dependencies + final val SPECIALIZED = 0x10000000000L// symbol is a generated specialized member + final val DEFAULTINIT = 0x20000000000L// symbol is a generated specialized member + final val VBRIDGE = 0x40000000000L// symbol is a varargs bridge + + // pickling and unpickling of flags + + // The flags from 0x001 to 0x800 are different in the raw flags + // and in the pickled format. + + private final val IMPLICIT_PKL = 0x00000001 + private final val FINAL_PKL = 0x00000002 + private final val PRIVATE_PKL = 0x00000004 + private final val PROTECTED_PKL = 0x00000008 + + private final val SEALED_PKL = 0x00000010 + private final val OVERRIDE_PKL = 0x00000020 + private final val CASE_PKL = 0x00000040 + private final val ABSTRACT_PKL = 0x00000080 + + private final val DEFERRED_PKL = 0x00000100 + private final val METHOD_PKL = 0x00000200 + private final val MODULE_PKL = 0x00000400 + private final val INTERFACE_PKL = 0x00000800 + + private final val PKL_MASK = 0x00000FFF + + final val PickledFlags: Long = 0xFFFFFFFFL + + private val r2p = { + def rawFlagsToPickledAux(flags:Int) = { + var pflags=0 + if ((flags & IMPLICIT )!=0) pflags|=IMPLICIT_PKL + if ((flags & FINAL )!=0) pflags|=FINAL_PKL + if ((flags & PRIVATE )!=0) pflags|=PRIVATE_PKL + if ((flags & PROTECTED)!=0) pflags|=PROTECTED_PKL + if ((flags & SEALED )!=0) pflags|=SEALED_PKL + if ((flags & OVERRIDE )!=0) pflags|=OVERRIDE_PKL + if ((flags & CASE )!=0) pflags|=CASE_PKL + if ((flags & ABSTRACT )!=0) pflags|=ABSTRACT_PKL + if ((flags & DEFERRED )!=0) pflags|=DEFERRED_PKL + if ((flags & METHOD )!=0) pflags|=METHOD_PKL + if ((flags & MODULE )!=0) pflags|=MODULE_PKL + if ((flags & INTERFACE)!=0) pflags|=INTERFACE_PKL + pflags + } + val v=new Array[Int](PKL_MASK+1) + var i=0 + while (i<=PKL_MASK) { + v(i)=rawFlagsToPickledAux(i) + i+=1 + } + v + } + + private val p2r = { + def pickledToRawFlagsAux(pflags:Int) = { + var flags=0 + if ((pflags & IMPLICIT_PKL )!=0) flags|=IMPLICIT + if ((pflags & FINAL_PKL )!=0) flags|=FINAL + if ((pflags & PRIVATE_PKL )!=0) flags|=PRIVATE + if ((pflags & PROTECTED_PKL)!=0) flags|=PROTECTED + if ((pflags & SEALED_PKL )!=0) flags|=SEALED + if ((pflags & OVERRIDE_PKL )!=0) flags|=OVERRIDE + if ((pflags & CASE_PKL )!=0) flags|=CASE + if ((pflags & ABSTRACT_PKL )!=0) flags|=ABSTRACT + if ((pflags & DEFERRED_PKL )!=0) flags|=DEFERRED + if ((pflags & METHOD_PKL )!=0) flags|=METHOD + if ((pflags & MODULE_PKL )!=0) flags|=MODULE + if ((pflags & INTERFACE_PKL)!=0) flags|=INTERFACE + flags + } + val v=new Array[Int](PKL_MASK+1) + var i=0 + while (i<=PKL_MASK) { + v(i)=pickledToRawFlagsAux(i) + i+=1 + } + v + } + + def rawFlagsToPickled(flags:Long):Long = + (flags & ~PKL_MASK) | r2p(flags.toInt & PKL_MASK) + + def pickledToRawFlags(pflags:Long):Long = + (pflags & ~PKL_MASK) | p2r(pflags.toInt & PKL_MASK) + + // List of the raw flags, in pickled order + protected val pickledListOrder = { + def findBit(m:Long):Int = { + var mask=m + var i=0 + while (i <= 62) { + if ((mask&1) == 1L) return i + mask >>= 1 + i += 1 + } + throw new AssertionError() + } + val v=new Array[Long](63) + v(findBit(IMPLICIT_PKL ))=IMPLICIT + v(findBit(FINAL_PKL ))=FINAL + v(findBit(PRIVATE_PKL ))=PRIVATE + v(findBit(PROTECTED_PKL))=PROTECTED + v(findBit(SEALED_PKL ))=SEALED + v(findBit(OVERRIDE_PKL ))=OVERRIDE + v(findBit(CASE_PKL ))=CASE + v(findBit(ABSTRACT_PKL ))=ABSTRACT + v(findBit(DEFERRED_PKL ))=DEFERRED + v(findBit(METHOD_PKL ))=METHOD + v(findBit(MODULE_PKL ))=MODULE + v(findBit(INTERFACE_PKL))=INTERFACE + var i=findBit(PKL_MASK+1) + while (i <= 62) { + v(i)=1L << i + i += 1 + } + v.toList + } + +} diff --git a/src/library/scala/reflect/generic/Names.scala b/src/library/scala/reflect/generic/Names.scala new file mode 100755 index 0000000000..1b31726e3a --- /dev/null +++ b/src/library/scala/reflect/generic/Names.scala @@ -0,0 +1,21 @@ +package scala.reflect +package generic + +trait Names { + + type Name >: Null <: AnyRef + + def newTermName(cs: Array[Char], offset: Int, len: Int): Name + def newTermName(cs: Array[Byte], offset: Int, len: Int): Name + def newTermName(s: String): Name + + def mkTermName(name: Name): Name + + def newTypeName(cs: Array[Char], offset: Int, len: Int): Name + def newTypeName(cs: Array[Byte], offset: Int, len: Int): Name + def newTypeName(s: String): Name + + def mkTypeName(name: Name): Name +} + + diff --git a/src/library/scala/reflect/generic/PickleBuffer.scala b/src/library/scala/reflect/generic/PickleBuffer.scala new file mode 100755 index 0000000000..584b94578e --- /dev/null +++ b/src/library/scala/reflect/generic/PickleBuffer.scala @@ -0,0 +1,165 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2010 LAMP/EPFL + * @author Martin Odersky + */ +// $Id: PickleBuffer.scala 20028 2009-12-07 11:49:19Z cunei $ + +package scala.reflect +package generic + +/** Variable length byte arrays, with methods for basic pickling and unpickling. + * + * @param data The initial buffer + * @param from The first index where defined data are found + * @param to The first index where new data can be written + */ +class PickleBuffer(data: Array[Byte], from: Int, to: Int) { + + var bytes = data + var readIndex = from + var writeIndex = to + + /** Double bytes array */ + private def dble() { + val bytes1 = new Array[Byte](bytes.length * 2) + Array.copy(bytes, 0, bytes1, 0, writeIndex) + bytes = bytes1 + } + + def ensureCapacity(capacity: Int) = + while (bytes.length < writeIndex + capacity) dble() + + // -- Basic output routines -------------------------------------------- + + /** Write a byte of data */ + def writeByte(b: Int) { + if (writeIndex == bytes.length) dble() + bytes(writeIndex) = b.toByte + writeIndex += 1 + } + + /** Write a natural number in big endian format, base 128. + * All but the last digits have bit 0x80 set. + */ + def writeNat(x: Int) = + writeLongNat(x.toLong & 0x00000000FFFFFFFFL) + + /** + * Like writeNat, but for longs. This is not the same as + * writeLong, which writes in base 256. Note that the + * binary representation of LongNat is identical to Nat + * if the long value is in the range Int.MIN_VALUE to + * Int.MAX_VALUE. + */ + def writeLongNat(x: Long) { + def writeNatPrefix(x: Long) { + val y = x >>> 7 + if (y != 0L) writeNatPrefix(y) + writeByte(((x & 0x7f) | 0x80).toInt) + } + val y = x >>> 7 + if (y != 0L) writeNatPrefix(y) + writeByte((x & 0x7f).toInt) + } + + /** Write a natural number <code>x</code> at position <code>pos</code>. + * If number is more than one byte, shift rest of array to make space. + * + * @param pos ... + * @param x ... + */ + def patchNat(pos: Int, x: Int) { + def patchNatPrefix(x: Int) { + writeByte(0) + Array.copy(bytes, pos, bytes, pos+1, writeIndex - (pos+1)) + bytes(pos) = ((x & 0x7f) | 0x80).toByte + val y = x >>> 7 + if (y != 0) patchNatPrefix(y) + } + bytes(pos) = (x & 0x7f).toByte + val y = x >>> 7 + if (y != 0) patchNatPrefix(y) + } + + /** Write a long number <code>x</code> in signed big endian format, base 256. + * + * @param x The long number to be written. + */ + def writeLong(x: Long) { + val y = x >> 8 + val z = x & 0xff + if (-y != (z >> 7)) writeLong(y) + writeByte(z.toInt) + } + + // -- Basic input routines -------------------------------------------- + + /** Peek at the current byte without moving the read index */ + def peekByte(): Int = bytes(readIndex) + + /** Read a byte */ + def readByte(): Int = { + val x = bytes(readIndex); readIndex += 1; x + } + + /** Read a natural number in big endian format, base 128. + * All but the last digits have bit 0x80 set.*/ + def readNat(): Int = readLongNat().toInt + + def readLongNat(): Long = { + var b = 0L + var x = 0L + do { + b = readByte() + x = (x << 7) + (b & 0x7f) + } while ((b & 0x80) != 0L); + x + } + + /** Read a long number in signed big endian format, base 256. */ + def readLong(len: Int): Long = { + var x = 0L + var i = 0 + while (i < len) { + x = (x << 8) + (readByte() & 0xff) + i += 1 + } + val leading = 64 - (len << 3) + x << leading >> leading + } + + /** Perform operation <code>op</code> until the condition + * <code>readIndex == end</code> is satisfied. + * Concatenate results into a list. + * + * @param end ... + * @param op ... + * @return ... + */ + def until[T](end: Int, op: () => T): List[T] = + if (readIndex == end) List() else op() :: until(end, op); + + /** Perform operation <code>op</code> the number of + * times specified. Concatenate the results into a list. + */ + def times[T](n: Int, op: ()=>T): List[T] = + if (n == 0) List() else op() :: times(n-1, op) + + /** Pickle = majorVersion_Nat minorVersion_Nat nbEntries_Nat {Entry} + * Entry = type_Nat length_Nat [actual entries] + * + * Assumes that the ..Version_Nat are already consumed. + * + * @return an array mapping entry numbers to locations in + * the byte array where the entries start. + */ + def createIndex: Array[Int] = { + val index = new Array[Int](readNat()) // nbEntries_Nat + for (i <- 0 until index.length) { + index(i) = readIndex + readByte() // skip type_Nat + readIndex = readNat() + readIndex // read length_Nat, jump to next entry + } + index + } +} diff --git a/src/library/scala/reflect/generic/PickleFormat.scala b/src/library/scala/reflect/generic/PickleFormat.scala new file mode 100755 index 0000000000..d1e884f513 --- /dev/null +++ b/src/library/scala/reflect/generic/PickleFormat.scala @@ -0,0 +1,223 @@ +package scala.reflect +package generic + +/** This object provides constants for pickling attributes. + * + * If you extend the format, be sure to increase the + * version minor number. + * + * @author Martin Odersky + * @version 1.0 + */ +object PickleFormat { + +/*************************************************** + * Symbol table attribute format: + * Symtab = nentries_Nat {Entry} + * Entry = 1 TERMNAME len_Nat NameInfo + * | 2 TYPENAME len_Nat NameInfo + * | 3 NONEsym len_Nat + * | 4 TYPEsym len_Nat SymbolInfo + * | 5 ALIASsym len_Nat SymbolInfo + * | 6 CLASSsym len_Nat SymbolInfo [thistype_Ref] + * | 7 MODULEsym len_Nat SymbolInfo + * | 8 VALsym len_Nat [defaultGetter_Ref /* no longer needed*/] SymbolInfo [alias_Ref] + * | 9 EXTref len_Nat name_Ref [owner_Ref] + * | 10 EXTMODCLASSref len_Nat name_Ref [owner_Ref] + * | 11 NOtpe len_Nat + * | 12 NOPREFIXtpe len_Nat + * | 13 THIStpe len_Nat sym_Ref + * | 14 SINGLEtpe len_Nat type_Ref sym_Ref + * | 15 CONSTANTtpe len_Nat constant_Ref + * | 16 TYPEREFtpe len_Nat type_Ref sym_Ref {targ_Ref} + * | 17 TYPEBOUNDStpe len_Nat tpe_Ref tpe_Ref + * | 18 REFINEDtpe len_Nat classsym_Ref {tpe_Ref} + * | 19 CLASSINFOtpe len_Nat classsym_Ref {tpe_Ref} + * | 20 METHODtpe len_Nat tpe_Ref {sym_Ref} + * | 21 POLYTtpe len_Nat tpe_Ref {sym_Ref} + * | 22 IMPLICITMETHODtpe len_Nat tpe_Ref {sym_Ref} /* no longer needed */ + * | 52 SUPERtpe len_Nat tpe_Ref tpe_Ref + * | 24 LITERALunit len_Nat + * | 25 LITERALboolean len_Nat value_Long + * | 26 LITERALbyte len_Nat value_Long + * | 27 LITERALshort len_Nat value_Long + * | 28 LITERALchar len_Nat value_Long + * | 29 LITERALint len_Nat value_Long + * | 30 LITERALlong len_Nat value_Long + * | 31 LITERALfloat len_Nat value_Long + * | 32 LITERALdouble len_Nat value_Long + * | 33 LITERALstring len_Nat name_Ref + * | 34 LITERALnull len_Nat + * | 35 LITERALclass len_Nat tpe_Ref + * | 36 LITERALenum len_Nat sym_Ref + * | 40 SYMANNOT len_Nat sym_Ref AnnotInfoBody + * | 41 CHILDREN len_Nat sym_Ref {sym_Ref} + * | 42 ANNOTATEDtpe len_Nat [sym_Ref /* no longer needed */] tpe_Ref {annotinfo_Ref} + * | 43 ANNOTINFO len_Nat AnnotInfoBody + * | 44 ANNOTARGARRAY len_Nat {constAnnotArg_Ref} + * | 47 DEBRUIJNINDEXtpe len_Nat level_Nat index_Nat + * | 48 EXISTENTIALtpe len_Nat type_Ref {symbol_Ref} + * | 49 TREE len_Nat 1 EMPTYtree + * | 49 TREE len_Nat 2 PACKAGEtree type_Ref sym_Ref mods_Ref name_Ref {tree_Ref} + * | 49 TREE len_Nat 3 CLASStree type_Ref sym_Ref mods_Ref name_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 4 MODULEtree type_Ref sym_Ref mods_Ref name_Ref tree_Ref + * | 49 TREE len_Nat 5 VALDEFtree type_Ref sym_Ref mods_Ref name_Ref tree_Ref tree_Ref + * | 49 TREE len_Nat 6 DEFDEFtree type_Ref sym_Ref mods_Ref name_Ref numtparams_Nat {tree_Ref} numparamss_Nat {numparams_Nat {tree_Ref}} tree_Ref tree_Ref + * | 49 TREE len_Nat 7 TYPEDEFtree type_Ref sym_Ref mods_Ref name_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 8 LABELtree type_Ref sym_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 9 IMPORTtree type_Ref sym_Ref tree_Ref {name_Ref name_Ref} + * | 49 TREE len_Nat 11 DOCDEFtree type_Ref sym_Ref string_Ref tree_Ref + * | 49 TREE len_Nat 12 TEMPLATEtree type_Ref sym_Ref numparents_Nat {tree_Ref} tree_Ref {tree_Ref} + * | 49 TREE len_Nat 13 BLOCKtree type_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 14 CASEtree type_Ref tree_Ref tree_Ref tree_Ref + * | 49 TREE len_Nat 15 SEQUENCEtree type_Ref {tree_Ref} + * | 49 TREE len_Nat 16 ALTERNATIVEtree type_Ref {tree_Ref} + * | 49 TREE len_Nat 17 STARtree type_Ref {tree_Ref} + * | 49 TREE len_Nat 18 BINDtree type_Ref sym_Ref name_Ref tree_Ref + * | 49 TREE len_Nat 19 UNAPPLYtree type_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 20 ARRAYVALUEtree type_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 21 FUNCTIONtree type_Ref sym_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 22 ASSIGNtree type_Ref tree_Ref tree_Ref + * | 49 TREE len_Nat 23 IFtree type_Ref tree_Ref tree_Ref tree_Ref + * | 49 TREE len_Nat 24 MATCHtree type_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 25 RETURNtree type_Ref sym_Ref tree_Ref + * | 49 TREE len_Nat 26 TREtree type_Ref tree_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 27 THROWtree type_Ref tree_Ref + * | 49 TREE len_Nat 28 NEWtree type_Ref tree_Ref + * | 49 TREE len_Nat 29 TYPEDtree type_Ref tree_Ref tree_Ref + * | 49 TREE len_Nat 30 TYPEAPPLYtree type_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 31 APPLYtree type_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 32 APPLYDYNAMICtree type_Ref sym_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 33 SUPERtree type_Ref sym_Ref tree_Ref name_Ref + * | 49 TREE len_Nat 34 THIStree type_Ref sym_Ref name_Ref + * | 49 TREE len_Nat 35 SELECTtree type_Ref sym_Ref tree_Ref name_Ref + * | 49 TREE len_Nat 36 IDENTtree type_Ref sym_Ref name_Ref + * | 49 TREE len_Nat 37 LITERALtree type_Ref constant_Ref + * | 49 TREE len_Nat 38 TYPEtree type_Ref + * | 49 TREE len_Nat 39 ANNOTATEDtree type_Ref tree_Ref tree_Ref + * | 49 TREE len_Nat 40 SINGLETONTYPEtree type_Ref tree_Ref + * | 49 TREE len_Nat 41 SELECTFROMTYPEtree type_Ref tree_Ref name_Ref + * | 49 TREE len_Nat 42 COMPOUNDTYPEtree type_Ref tree_Ref + * | 49 TREE len_Nat 43 APPLIEDTYPEtree type_Ref tree_Ref {tree_Ref} + * | 49 TREE len_Nat 44 TYPEBOUNDStree type_Ref tree_Ref tree_Ref + * | 49 TREE len_Nat 45 EXISTENTIALTYPEtree type_Ref tree_Ref {tree_Ref} + * | 50 MODIFIERS len_Nat flags_Long privateWithin_Ref + * SymbolInfo = name_Ref owner_Ref flags_LongNat [privateWithin_Ref] info_Ref + * NameInfo = <character sequence of length len_Nat in Utf8 format> + * NumInfo = <len_Nat-byte signed number in big endian format> + * Ref = Nat + * AnnotInfoBody = info_Ref {annotArg_Ref} {name_Ref constAnnotArg_Ref} + * AnnotArg = Tree | Constant + * ConstAnnotArg = Constant | AnnotInfo | AnnotArgArray + * + * len is remaining length after `len'. + */ + val MajorVersion = 5 + val MinorVersion = 0 + + final val TERMname = 1 + final val TYPEname = 2 + final val NONEsym = 3 + final val TYPEsym = 4 + final val ALIASsym = 5 + final val CLASSsym = 6 + final val MODULEsym = 7 + final val VALsym = 8 + final val EXTref = 9 + final val EXTMODCLASSref = 10 + final val NOtpe = 11 + final val NOPREFIXtpe = 12 + final val THIStpe = 13 + final val SINGLEtpe = 14 + final val CONSTANTtpe = 15 + final val TYPEREFtpe = 16 + final val TYPEBOUNDStpe = 17 + final val REFINEDtpe = 18 + final val CLASSINFOtpe = 19 + final val METHODtpe = 20 + final val POLYtpe = 21 + final val IMPLICITMETHODtpe = 22 + + final val LITERAL = 23 // base line for literals + final val LITERALunit = 24 + final val LITERALboolean = 25 + final val LITERALbyte = 26 + final val LITERALshort = 27 + final val LITERALchar = 28 + final val LITERALint = 29 + final val LITERALlong = 30 + final val LITERALfloat = 31 + final val LITERALdouble = 32 + final val LITERALstring = 33 + final val LITERALnull = 34 + final val LITERALclass = 35 + final val LITERALenum = 36 + final val SYMANNOT = 40 + final val CHILDREN = 41 + final val ANNOTATEDtpe = 42 + final val ANNOTINFO = 43 + final val ANNOTARGARRAY = 44 + + final val SUPERtpe = 46 + final val DEBRUIJNINDEXtpe = 47 + final val EXISTENTIALtpe = 48 + + final val TREE = 49 // prefix code that means a tree is coming + final val EMPTYtree = 1 + final val PACKAGEtree = 2 + final val CLASStree = 3 + final val MODULEtree = 4 + final val VALDEFtree = 5 + final val DEFDEFtree = 6 + final val TYPEDEFtree = 7 + final val LABELtree = 8 + final val IMPORTtree = 9 + final val DOCDEFtree = 11 + final val TEMPLATEtree = 12 + final val BLOCKtree = 13 + final val CASEtree = 14 + // This node type has been removed. + // final val SEQUENCEtree = 15 + final val ALTERNATIVEtree = 16 + final val STARtree = 17 + final val BINDtree = 18 + final val UNAPPLYtree = 19 + final val ARRAYVALUEtree = 20 + final val FUNCTIONtree = 21 + final val ASSIGNtree = 22 + final val IFtree = 23 + final val MATCHtree = 24 + final val RETURNtree = 25 + final val TREtree = 26 + final val THROWtree = 27 + final val NEWtree = 28 + final val TYPEDtree = 29 + final val TYPEAPPLYtree = 30 + final val APPLYtree = 31 + final val APPLYDYNAMICtree = 32 + final val SUPERtree = 33 + final val THIStree = 34 + final val SELECTtree = 35 + final val IDENTtree = 36 + final val LITERALtree = 37 + final val TYPEtree = 38 + final val ANNOTATEDtree = 39 + final val SINGLETONTYPEtree = 40 + final val SELECTFROMTYPEtree = 41 + final val COMPOUNDTYPEtree = 42 + final val APPLIEDTYPEtree = 43 + final val TYPEBOUNDStree = 44 + final val EXISTENTIALTYPEtree = 45 + + final val MODIFIERS = 50 + + final val firstSymTag = NONEsym + final val lastSymTag = VALsym + final val lastExtSymTag = EXTMODCLASSref + + + //The following two are no longer accurate, because ANNOTATEDtpe, + //SUPERtpe, ... are not in the same range as the other types + //final val firstTypeTag = NOtpe + //final val lastTypeTag = POLYtpe +} diff --git a/src/library/scala/reflect/generic/Scopes.scala b/src/library/scala/reflect/generic/Scopes.scala new file mode 100755 index 0000000000..9f8a8ecd19 --- /dev/null +++ b/src/library/scala/reflect/generic/Scopes.scala @@ -0,0 +1,15 @@ +package scala.reflect +package generic + +trait Scopes { self: Universe => + + abstract class AbsScope extends Iterable[Symbol] { + def enter(sym: Symbol): Symbol + } + + type Scope <: AbsScope + + def newScope(): Scope +} + + diff --git a/src/library/scala/reflect/generic/StandardDefinitions.scala b/src/library/scala/reflect/generic/StandardDefinitions.scala new file mode 100755 index 0000000000..24dce7173a --- /dev/null +++ b/src/library/scala/reflect/generic/StandardDefinitions.scala @@ -0,0 +1,67 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2010 LAMP/EPFL + * @author Martin Odersky + */ +// $Id: Definitions.scala 20619 2010-01-20 10:55:56Z rytz $ + +package scala.reflect +package generic + +trait StandardDefinitions { self: Universe => + + val definitions: AbsDefinitions + + abstract class AbsDefinitions { + + // outer packages and their classes + def RootPackage: Symbol + def RootClass: Symbol + def EmptyPackage: Symbol + def EmptyPackageClass: Symbol + + def ScalaPackage: Symbol + def ScalaPackageClass: Symbol + + // top types + def AnyClass : Symbol + def AnyValClass: Symbol + def AnyRefClass: Symbol + def ObjectClass: Symbol + + // bottom types + def NullClass : Symbol + def NothingClass: Symbol + + // the scala value classes + def UnitClass : Symbol + def ByteClass : Symbol + def ShortClass : Symbol + def CharClass : Symbol + def IntClass : Symbol + def LongClass : Symbol + def FloatClass : Symbol + def DoubleClass : Symbol + def BooleanClass: Symbol + + // fundamental reference classes + def SymbolClass : Symbol + def StringClass : Symbol + def ClassClass : Symbol + + // fundamental modules + def PredefModule: Symbol + + // fundamental type constructions + def ClassType(arg: Type): Type + + /** The string representation used by the given type in the VM. + */ + def signature(tp: Type): String + + /** Is symbol one of the value classes? */ + def isValueClass(sym: Symbol): Boolean + + /** Is symbol one of the numeric value classes? */ + def isNumericValueClass(sym: Symbol): Boolean + } +} diff --git a/src/library/scala/reflect/generic/StdNames.scala b/src/library/scala/reflect/generic/StdNames.scala new file mode 100755 index 0000000000..7f48b5bf62 --- /dev/null +++ b/src/library/scala/reflect/generic/StdNames.scala @@ -0,0 +1,26 @@ +package scala.reflect +package generic + +trait StdNames { self: Universe => + + val nme: StandardNames + + class StandardNames { + val EXPAND_SEPARATOR_STRING = "$$" + val LOCAL_SUFFIX_STRING = " " + + val ANON_CLASS_NAME = newTermName("$anon") + val ANON_FUN_NAME = newTermName("$anonfun") + val EMPTY_PACKAGE_NAME = newTermName("<empty>") + val IMPORT = newTermName("<import>") + val REFINE_CLASS_NAME = newTermName("<refinement>") + val ROOT = newTermName("<root>") + val ROOTPKG = newTermName("_root_") + val EMPTY = newTermName("") + + /** The expanded name of `name' relative to this class `base` with given `seperator` + */ + def expandedName(name: Name, base: Symbol, separator: String = EXPAND_SEPARATOR_STRING): Name = + newTermName(base.fullName('$') + separator + name) + } +} diff --git a/src/library/scala/reflect/generic/Symbols.scala b/src/library/scala/reflect/generic/Symbols.scala new file mode 100755 index 0000000000..4f6e4402b9 --- /dev/null +++ b/src/library/scala/reflect/generic/Symbols.scala @@ -0,0 +1,199 @@ +package scala.reflect +package generic + +import Flags._ + +trait Symbols { self: Universe => + + type Symbol >: Null <: AbsSymbol + + abstract class AbsSymbol { this: Symbol => + + /** The owner of this symbol. + */ + def owner: Symbol + + /** The flags of this symbol */ + def flags: Long + + /** The name of the symbol as a member of the `Name` type. + */ + def name: Name + + /** The name of the symbol before decoding, e.g. `$eq$eq` instead of `==`. + */ + def encodedName: String + + /** The decoded name of the symbol, e.g. `==` instead of `$eq$eq`. + */ + def decodedName: String = stripLocalSuffix(NameTransformer.decode(encodedName)) + + /** The encoded full path name of this symbol, where outer names and inner names + * are separated by `separator` characters. + * Never translates expansions of operators back to operator symbol. + * Never adds id. + */ + final def fullName(separator: Char): String = stripLocalSuffix { + if (isRoot || isRootPackage || this == NoSymbol) this.toString + else if (owner.isEffectiveRoot) encodedName + else owner.enclClass.fullName(separator) + separator + encodedName + } + + private def stripLocalSuffix(s: String) = + if (s endsWith nme.LOCAL_SUFFIX_STRING) + s.substring(0, s.length - nme.LOCAL_SUFFIX_STRING.length) + else + s + + /** The encoded full path name of this symbol, where outer names and inner names + * are separated by periods. + */ + final def fullName: String = fullName('.') + + /** Does symbol have a flag in `mask` set? */ + final def hasFlag(mask: Long): Boolean = (flags & mask) != 0L + + /** Set when symbol has a modifier of the form private[X], NoSymbol otherwise. + */ + def privateWithin: Symbol + + /** The raw info of the type + */ + def rawInfo: Type + + /** The type of the symbol + */ + def tpe: Type = info + + /** The info of the symbol. This is like tpe, except for class symbols where the `info` + * describes the contents of the class whereas the `tpe` is a reference to the class. + */ + def info: Type = { + val tp = rawInfo + tp.complete(this) + tp + } + + /** If this symbol is a class or trait, its self type, otherwise the type of the symbol itse;lf + */ + def typeOfThis: Type + + def owner_=(sym: Symbol) { throw new UnsupportedOperationException("owner_= inapplicable for " + this) } + def flags_=(flags: Long) { throw new UnsupportedOperationException("flags_= inapplicable for " + this) } + def info_=(tp: Type) { throw new UnsupportedOperationException("info_= inapplicable for " + this) } + def typeOfThis_=(tp: Type) { throw new UnsupportedOperationException("typeOfThis_= inapplicable for " + this) } + def privateWithin_=(sym: Symbol) { throw new UnsupportedOperationException("privateWithin_= inapplicable for " + this) } + def sourceModule_=(sym: Symbol) { throw new UnsupportedOperationException("sourceModule_= inapplicable for " + this) } + def addChild(sym: Symbol) { throw new UnsupportedOperationException("addChild inapplicable for " + this) } + def addAnnotation(annot: AnnotationInfo) { throw new UnsupportedOperationException("addAnnotation inapplicable for " + this) } + + /** For a module class its linked class, for a plain class + * the module class of its linked module. + * For instance + * object Foo + * class Foo + * + * Then object Foo has a `moduleClass' (invisible to the user, the backend calls it Foo$ + * linkedClassOfClass goes from class Foo$ to class Foo, and back. + */ + def linkedClassOfClass: Symbol + + /** The module corresponding to this module class (note that this + * is not updated when a module is cloned), or NoSymbol if this is not a ModuleClass + */ + def sourceModule: Symbol = NoSymbol + + /** If symbol is an object defition, it's implied associated class, + * otherwise NoSymbol + */ + def moduleClass: Symbol + +// flags and kind tests + + def isTerm = false // to be overridden + def isType = false // to be overridden + def isClass = false // to be overridden + def isAliasType = false //to be overridden + def isAbstractType = false //to be overridden + private[scala] def isSkolem = false // to be overridden + + final def isImplicit = hasFlag(IMPLICIT) + final def isFinal = hasFlag(FINAL) + final def isPrivate = hasFlag(PRIVATE) + final def isProtected = hasFlag(PROTECTED) + + /** Is this symbol a sealed class? */ + final def isSealed = isClass && (hasFlag(SEALED) || definitions.isValueClass(this)) + final def isOverride = hasFlag(OVERRIDE) + final def isCase = hasFlag(CASE) + final def isAbstractClass = isClass && hasFlag(ABSTRACT) + final def isAbstractOverride = isTerm && hasFlag(ABSTRACT) && hasFlag(OVERRIDE) + final def isDeferred = hasFlag(DEFERRED) && !isClass + final def isMethod = isTerm && hasFlag(METHOD) + final def isSourceMethod = isTerm && (flags & (METHOD | STABLE)) == METHOD // exclude all accessors!!! + final def isModule = isTerm && hasFlag(MODULE) + final def isModuleClass = isClass && hasFlag(MODULE) + final def isInterface = hasFlag(INTERFACE) + final def isMutable = hasFlag(MUTABLE) + final def isParameter = hasFlag(PARAM) + final def isPackage = isModule && hasFlag(PACKAGE) + final def isPackageClass = isClass && hasFlag(PACKAGE) + final def isCovariant = isType && hasFlag(COVARIANT) + final def isContravariant = isType && hasFlag(CONTRAVARIANT) + final def isJavaDefined = hasFlag(JAVA) + final def isSynthetic = hasFlag(SYNTHETIC) + def isTrait: Boolean = isClass && hasFlag(TRAIT) // refined later for virtual classes. + final def hasDefault = isParameter && hasFlag(DEFAULTPARAM) + final def isBridge = hasFlag(BRIDGE) + final def isGetterOrSetter = hasFlag(ACCESSOR) + final def isSuperAccessor = hasFlag(SUPERACCESSOR) + final def isParamAccessor = hasFlag(PARAMACCESSOR) + final def isCaseAccessor = hasFlag(CASEACCESSOR) + final def isLazy = hasFlag(LAZY) + final def isExistentiallyBound = isType && hasFlag(EXISTENTIAL) + final def isTypeParameter = isType && isParameter && !isSkolem + final def isRefinementClass = isClass && name == mkTypeName(nme.REFINE_CLASS_NAME) + final def isOverloaded = hasFlag(OVERLOADED) + + /** Is this symbol an implementation class for a mixin? */ + final def isImplClass = isClass && hasFlag(IMPLCLASS) + + /** Is this symbol early initialized */ + final def isEarlyInitialized: Boolean = isTerm && hasFlag(PRESUPER) + + final def isPrivateLocal = hasFlag(PRIVATE) && hasFlag(LOCAL) + final def isProtectedLocal = hasFlag(PROTECTED) && hasFlag(LOCAL) + final def isPublic = !hasFlag(PRIVATE | PROTECTED) && privateWithin == NoSymbol + + final def isRoot = isPackageClass && owner == NoSymbol + final def isRootPackage = isPackage && owner == NoSymbol + final def isEmptyPackage = isPackage && name == nme.EMPTY_PACKAGE_NAME + final def isEmptyPackageClass = isPackageClass && name == mkTypeName(nme.EMPTY_PACKAGE_NAME) + + /** Is this symbol an effective root for fullname string? + */ + def isEffectiveRoot = isRoot || isEmptyPackageClass + + // creators + + def newValue(name: Name, pos: Position = NoPosition): Symbol + def newAbstractType(name: Name, pos: Position = NoPosition): Symbol + def newAliasType(name: Name, pos: Position = NoPosition): Symbol + def newClass(name: Name, pos: Position = NoPosition): Symbol + def newModuleClass(name: Name, pos: Position = NoPosition): Symbol + def newMethod(name: Name, pos: Position = NoPosition): Symbol + def newModule(name: Name, clazz: Symbol, pos: Position = NoPosition): 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 (isSourceMethod) this else owner.enclMethod + } + + val NoSymbol: Symbol +} + + diff --git a/src/library/scala/reflect/generic/Trees.scala b/src/library/scala/reflect/generic/Trees.scala new file mode 100755 index 0000000000..7ff3b54ab9 --- /dev/null +++ b/src/library/scala/reflect/generic/Trees.scala @@ -0,0 +1,609 @@ +package scala.reflect +package generic + +import java.io.{PrintWriter, StringWriter} +import Flags._ + +trait Trees { self: Universe => + + abstract class AbsTreePrinter(out: PrintWriter) { + def print(tree: Tree) + def flush() + } + + def newTreePrinter(out: PrintWriter): AbsTreePrinter + + private[scala] var nodeCount = 0 + + /** @param privateWithin the qualifier for a private (a type name) + * or nme.EMPTY.toTypeName, if none is given. + * @param annotations the annotations for the definition. + * <strong>Note:</strong> the typechecker drops these annotations, + * use the AnnotationInfo's (Symbol.annotations) in later phases. + */ + case class Modifiers(flags: Long, privateWithin: Name, annotations: List[Tree], positions: Map[Long, Position]) { + def isCovariant = hasFlag(COVARIANT ) // marked with `+' + def isContravariant = hasFlag(CONTRAVARIANT) // marked with `-' + def isPrivate = hasFlag(PRIVATE ) + def isProtected = hasFlag(PROTECTED) + def isVariable = hasFlag(MUTABLE ) + def isArgument = hasFlag(PARAM ) + def isAccessor = hasFlag(ACCESSOR ) + def isOverride = hasFlag(OVERRIDE ) + def isAbstract = hasFlag(ABSTRACT ) + def isDeferred = hasFlag(DEFERRED ) + def isCase = hasFlag(CASE ) + def isLazy = hasFlag(LAZY ) + def isSealed = hasFlag(SEALED ) + def isFinal = hasFlag(FINAL ) + def isTrait = hasFlag(TRAIT ) + def isImplicit = hasFlag(IMPLICIT ) + def isPublic = !isPrivate && !isProtected + def hasFlag(flag: Long) = (flag & flags) != 0L + def & (flag: Long): Modifiers = { + val flags1 = flags & flag + if (flags1 == flags) this + else Modifiers(flags1, privateWithin, annotations, positions) + } + def &~ (flag: Long): Modifiers = { + val flags1 = flags & (~flag) + if (flags1 == flags) this + else Modifiers(flags1, privateWithin, annotations, positions) + } + def | (flag: Long): Modifiers = { + val flags1 = flags | flag + if (flags1 == flags) this + else Modifiers(flags1, privateWithin, annotations, positions) + } + def withAnnotations(annots: List[Tree]) = + if (annots.isEmpty) this + else Modifiers(flags, privateWithin, annotations ::: annots, positions) + def withPosition(flag: Long, position: Position) = + Modifiers(flags, privateWithin, annotations, positions + (flag -> position)) + } + + def Modifiers(flags: Long, privateWithin: Name): Modifiers = Modifiers(flags, privateWithin, List(), new Map.EmptyMap) + def Modifiers(flags: Long): Modifiers = Modifiers(flags, mkTypeName(nme.EMPTY)) + + lazy val NoMods = Modifiers(0) + + abstract class Tree extends Product { + val id = nodeCount +// assert(id != 1223) + nodeCount += 1 + + private[this] var rawpos: Position = NoPosition + + def pos = rawpos + def pos_=(pos: Position) = rawpos = pos + def setPos(pos: Position): this.type = { rawpos = pos; this } + + private[this] var rawtpe: Type = _ + + def tpe = rawtpe + def tpe_=(t: Type) = rawtpe = t + + /** Set tpe to give `tp` and return this. + */ + def setType(tp: Type): this.type = { rawtpe = tp; this } + + /** Like `setType`, but if this is a previously empty TypeTree + * that fact is remembered so that resetType will snap back. + */ + def defineType(tp: Type): this.type = setType(tp) + + def symbol: Symbol = null + def symbol_=(sym: Symbol) { throw new UnsupportedOperationException("symbol_= inapplicable for " + this) } + def setSymbol(sym: Symbol): this.type = { symbol = sym; this } + + def hasSymbol = false + def isDef = false + def isEmpty = false + + /** The direct child trees of this tree + * EmptyTrees are always omitted. Lists are collapsed. + */ + def children: List[Tree] = { + def subtrees(x: Any): List[Tree] = x match { + case EmptyTree => List() + case t: Tree => List(t) + case xs: List[_] => xs flatMap subtrees + case _ => List() + } + productIterator.toList flatMap subtrees + } + + /** In compiler: Make a copy of this tree, keeping all attributes, + * except that all positions are focussed (so nothing + * in this tree will be found when searching by position). + * If not in compiler may also return tree unchanged. + */ + private[scala] def duplicate: this.type = + duplicateTree(this).asInstanceOf[this.type] + + private[scala] def copyAttrs(tree: Tree): this.type = { + pos = tree.pos + tpe = tree.tpe + if (hasSymbol) symbol = tree.symbol + this + } + + override def toString(): String = { + val buffer = new StringWriter() + val printer = newTreePrinter(new PrintWriter(buffer)) + printer.print(this) + printer.flush() + buffer.toString + } + + override def hashCode(): Int = super.hashCode() + + override def equals(that: Any): Boolean = that match { + case t: Tree => this eq t + case _ => false + } + } + + private[scala] def duplicateTree(tree: Tree): Tree = tree + + trait SymTree extends Tree { + override def hasSymbol = true + override var symbol: Symbol = NoSymbol + } + + trait RefTree extends SymTree { + def name: Name + } + + abstract class DefTree extends SymTree { + def name: Name + override def isDef = true + } + + trait TermTree extends Tree + + /** A tree for a type. Note that not all type trees implement + * this trait; in particular, Ident's are an exception. */ + trait TypTree extends Tree + +// ----- tree node alternatives -------------------------------------- + + /** The empty tree */ + case object EmptyTree extends TermTree { + super.tpe_=(NoType) + override def tpe_=(t: Type) = + if (t != NoType) throw new UnsupportedOperationException("tpe_=("+t+") inapplicable for <empty>") + override def isEmpty = true + } + + abstract class MemberDef extends DefTree { + def mods: Modifiers + def keyword: String = this match { + case TypeDef(_, _, _, _) => "type" + case ClassDef(mods, _, _, _) => if (mods.isTrait) "trait" else "class" + case DefDef(_, _, _, _, _, _) => "def" + case ModuleDef(_, _, _) => "object" + case PackageDef(_, _) => "package" + case ValDef(mods, _, _, _) => if (mods.isVariable) "var" else "val" + case _ => "" + } + final def hasFlag(mask: Long): Boolean = (mods.flags & mask) != 0L + } + + /** Package clause + */ + case class PackageDef(pid: RefTree, stats: List[Tree]) + extends MemberDef { + def name = pid.name + def mods = NoMods + } + + abstract class ImplDef extends MemberDef { + def impl: Template + } + + /** Class definition */ + case class ClassDef(mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template) + extends ImplDef + + /** Singleton object definition + */ + case class ModuleDef(mods: Modifiers, name: Name, impl: Template) + extends ImplDef + + abstract class ValOrDefDef extends MemberDef { + def tpt: Tree + def rhs: Tree + } + + /** Value definition + */ + case class ValDef(mods: Modifiers, name: Name, tpt: Tree, rhs: Tree) extends ValOrDefDef + + /** Method definition + */ + case class DefDef(mods: Modifiers, name: Name, tparams: List[TypeDef], + vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) extends ValOrDefDef + + /** Abstract type, type parameter, or type alias */ + case class TypeDef(mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree) + extends MemberDef + + /** <p> + * Labelled expression - the symbols in the array (must be Idents!) + * are those the label takes as argument + * </p> + * <p> + * The symbol that is given to the labeldef should have a MethodType + * (as if it were a nested function) + * </p> + * <p> + * Jumps are apply nodes attributed with label symbol, the arguments + * will get assigned to the idents. + * </p> + * <p> + * Note: on 2005-06-09 Martin, Iuli, Burak agreed to have forward + * jumps within a Block. + * </p> + */ + case class LabelDef(name: Name, params: List[Ident], rhs: Tree) + extends DefTree with TermTree + + + /** Import selector + * + * Representation of an imported name its optional rename and their optional positions + * + * @param name the imported name + * @param namePos its position or -1 if undefined + * @param rename the name the import is renamed to (== name if no renaming) + * @param renamePos the position of the rename or -1 if undefined + */ + case class ImportSelector(name: Name, namePos: Int, rename: Name, renamePos: Int) + + /** Import clause + * + * @param expr + * @param selectors + */ + case class Import(expr: Tree, selectors: List[ImportSelector]) + extends SymTree + // The symbol of an Import is an import symbol @see Symbol.newImport + // It's used primarily as a marker to check that the import has been typechecked. + + /** Instantiation template of a class or trait + * + * @param parents + * @param body + */ + case class Template(parents: List[Tree], self: ValDef, body: List[Tree]) + extends SymTree { + // the symbol of a template is a local dummy. @see Symbol.newLocalDummy + // the owner of the local dummy is the enclosing trait or class. + // the local dummy is itself the owner of any local blocks + // For example: + // + // class C { + // def foo // owner is C + // { + // def bar // owner is local dummy + // } + // System.err.println("TEMPLATE: " + parents) + } + + /** Block of expressions (semicolon separated expressions) */ + case class Block(stats: List[Tree], expr: Tree) + extends TermTree + + /** Case clause in a pattern match, eliminated by TransMatch + * (except for occurences in switch statements) + */ + case class CaseDef(pat: Tree, guard: Tree, body: Tree) + extends Tree + + /** Alternatives of patterns, eliminated by TransMatch, except for + * occurences in encoded Switch stmt (=remaining Match(CaseDef(...)) + */ + case class Alternative(trees: List[Tree]) + extends TermTree + + /** Repetition of pattern, eliminated by TransMatch */ + case class Star(elem: Tree) + extends TermTree + + /** Bind of a variable to a rhs pattern, eliminated by TransMatch + * + * @param name + * @param body + */ + case class Bind(name: Name, body: Tree) + extends DefTree + + case class UnApply(fun: Tree, args: List[Tree]) + extends TermTree + + /** Array of expressions, needs to be translated in backend, + */ + case class ArrayValue(elemtpt: Tree, elems: List[Tree]) + extends TermTree + + /** Anonymous function, eliminated by analyzer */ + case class Function(vparams: List[ValDef], body: Tree) + extends TermTree with SymTree + // The symbol of a Function is a synthetic value of name nme.ANON_FUN_NAME + // It is the owner of the function's parameters. + + /** Assignment */ + case class Assign(lhs: Tree, rhs: Tree) + extends TermTree + + /** Conditional expression */ + case class If(cond: Tree, thenp: Tree, elsep: Tree) + extends TermTree + + /** <p> + * Pattern matching expression (before <code>TransMatch</code>) + * Switch statements (after TransMatch) + * </p> + * <p> + * After <code>TransMatch</code>, cases will satisfy the following + * constraints: + * </p> + * <ul> + * <li>all guards are EmptyTree,</li> + * <li>all patterns will be either <code>Literal(Constant(x:Int))</code> + * or <code>Alternative(lit|...|lit)</code></li> + * <li>except for an "otherwise" branch, which has pattern + * <code>Ident(nme.WILDCARD)</code></li> + * </ul> + */ + case class Match(selector: Tree, cases: List[CaseDef]) + extends TermTree + + /** Return expression */ + case class Return(expr: Tree) + extends TermTree with SymTree + // The symbol of a Return node is the enclosing method. + + case class Try(block: Tree, catches: List[CaseDef], finalizer: Tree) + extends TermTree + + /** Throw expression */ + case class Throw(expr: Tree) + extends TermTree + + /** Object instantiation + * One should always use factory method below to build a user level new. + * + * @param tpt a class type + */ + case class New(tpt: Tree) extends TermTree + + /** Type annotation, eliminated by explicit outer */ + case class Typed(expr: Tree, tpt: Tree) + extends TermTree + + // Martin to Sean: Should GenericApply/TypeApply/Apply not be SymTree's? After all, + // ApplyDynamic is a SymTree. + abstract class GenericApply extends TermTree { + val fun: Tree + val args: List[Tree] + } + + /** Type application */ + case class TypeApply(fun: Tree, args: List[Tree]) + extends GenericApply { + override def symbol: Symbol = fun.symbol + override def symbol_=(sym: Symbol) { fun.symbol = sym } + } + + /** Value application */ + case class Apply(fun: Tree, args: List[Tree]) + extends GenericApply { + override def symbol: Symbol = fun.symbol + override def symbol_=(sym: Symbol) { fun.symbol = sym } + } + + /** Dynamic value application. + * In a dynamic application q.f(as) + * - q is stored in qual + * - as is stored in args + * - f is stored as the node's symbol field. + */ + case class ApplyDynamic(qual: Tree, args: List[Tree]) + extends TermTree with SymTree + // The symbol of an ApplyDynamic is the function symbol of `qual', or NoSymbol, if there is none. + + /** Super reference */ + case class Super(qual: Name, mix: Name) + extends TermTree with SymTree + // The symbol of a Super is the class _from_ which the super reference is made. + // For instance in C.super(...), it would be C. + + /** Self reference */ + case class This(qual: Name) + extends TermTree with SymTree + // The symbol of a This is the class to which the this refers. + // For instance in C.this, it would be C. + + /** Designator <qualifier> . <name> */ + case class Select(qualifier: Tree, name: Name) + extends RefTree + + /** Identifier <name> */ + case class Ident(name: Name) + extends RefTree + + class BackQuotedIdent(name: Name) extends Ident(name) + + /** Literal */ + case class Literal(value: Constant) + extends TermTree { + assert(value ne null) + } + + def Literal(value: Any): Literal = + Literal(Constant(value)) + + type TypeTree <: AbsTypeTree + val TypeTree: TypeTreeExtractor + + abstract class TypeTreeExtractor { + def apply(): TypeTree + def unapply(tree: TypeTree): Boolean + } + + /** A synthetic term holding an arbitrary type. Not to be confused with + * with TypTree, the trait for trees that are only used for type trees. + * TypeTree's are inserted in several places, but most notably in + * <code>RefCheck</code>, where the arbitrary type trees are all replaced by + * TypeTree's. */ + abstract class AbsTypeTree extends TypTree { + override def symbol = if (tpe == null) null else tpe.typeSymbol + override def isEmpty = (tpe eq null) || tpe == NoType + } + + /** A tree that has an annotation attached to it. Only used for annotated types and + * annotation ascriptions, annotations on definitions are stored in the Modifiers. + * Eliminated by typechecker (typedAnnotated), the annotations are then stored in + * an AnnotatedType. + */ + case class Annotated(annot: Tree, arg: Tree) extends Tree + + /** Singleton type, eliminated by RefCheck */ + case class SingletonTypeTree(ref: Tree) + extends TypTree + + /** Type selection <qualifier> # <name>, eliminated by RefCheck */ + case class SelectFromTypeTree(qualifier: Tree, name: Name) + extends TypTree with RefTree + + /** Intersection type <parent1> with ... with <parentN> { <decls> }, eliminated by RefCheck */ + case class CompoundTypeTree(templ: Template) + extends TypTree + + /** Applied type <tpt> [ <args> ], eliminated by RefCheck */ + case class AppliedTypeTree(tpt: Tree, args: List[Tree]) + extends TypTree { + override def symbol: Symbol = tpt.symbol + override def symbol_=(sym: Symbol) { tpt.symbol = sym } + } + + case class TypeBoundsTree(lo: Tree, hi: Tree) + extends TypTree + + case class ExistentialTypeTree(tpt: Tree, whereClauses: List[Tree]) + extends TypTree + + /** Array selection <qualifier> . <name> only used during erasure */ + case class SelectFromArray(qualifier: Tree, name: Name, erasure: Type) + extends TermTree with RefTree + +/* A standard pattern match + case EmptyTree => + case PackageDef(pid, stats) => + // package pid { stats } + case ClassDef(mods, name, tparams, impl) => + // mods class name [tparams] impl where impl = extends parents { defs } + case ModuleDef(mods, name, impl) => (eliminated by refcheck) + // mods object name impl where impl = extends parents { defs } + case ValDef(mods, name, tpt, rhs) => + // mods val name: tpt = rhs + // note missing type information is expressed by tpt = TypeTree() + case DefDef(mods, name, tparams, vparamss, tpt, rhs) => + // mods def name[tparams](vparams_1)...(vparams_n): tpt = rhs + // note missing type information is expressed by tpt = TypeTree() + case TypeDef(mods, name, tparams, rhs) => (eliminated by erasure) + // mods type name[tparams] = rhs + // mods type name[tparams] >: lo <: hi, where lo, hi are in a TypeBoundsTree, + and DEFERRED is set in mods + case LabelDef(name, params, rhs) => + // used for tailcalls and like + // while/do are desugared to label defs as follows: + // while (cond) body ==> LabelDef($L, List(), if (cond) { body; L$() } else ()) + // do body while (cond) ==> LabelDef($L, List(), body; if (cond) L$() else ()) + case Import(expr, selectors) => (eliminated by typecheck) + // import expr.{selectors} + // Selectors are a list of pairs of names (from, to). + // The last (and maybe only name) may be a nme.WILDCARD + // for instance + // import qual.{x, y => z, _} would be represented as + // Import(qual, List(("x", "x"), ("y", "z"), (WILDCARD, null))) + case Template(parents, self, body) => + // extends parents { self => body } + // if self is missing it is represented as emptyValDef + case Block(stats, expr) => + // { stats; expr } + case CaseDef(pat, guard, body) => (eliminated by transmatch/explicitouter) + // case pat if guard => body + case Alternative(trees) => (eliminated by transmatch/explicitouter) + // pat1 | ... | patn + case Star(elem) => (eliminated by transmatch/explicitouter) + // pat* + case Bind(name, body) => (eliminated by transmatch/explicitouter) + // name @ pat + case UnApply(fun: Tree, args) (introduced by typer, eliminated by transmatch/explicitouter) + // used for unapply's + case ArrayValue(elemtpt, trees) => (introduced by uncurry) + // used to pass arguments to vararg arguments + // for instance, printf("%s%d", foo, 42) is translated to after uncurry to: + // Apply( + // Ident("printf"), + // Literal("%s%d"), + // ArrayValue(<Any>, List(Ident("foo"), Literal(42)))) + case Function(vparams, body) => (eliminated by lambdaLift) + // vparams => body where vparams:List[ValDef] + case Assign(lhs, rhs) => + // lhs = rhs + case If(cond, thenp, elsep) => + // if (cond) thenp else elsep + case Match(selector, cases) => + // selector match { cases } + case Return(expr) => + // return expr + case Try(block, catches, finalizer) => + // try block catch { catches } finally finalizer where catches: List[CaseDef] + case Throw(expr) => + // throw expr + case New(tpt) => + // new tpt always in the context: (new tpt).<init>[targs](args) + case Typed(expr, tpt) => (eliminated by erasure) + // expr: tpt + case TypeApply(fun, args) => + // fun[args] + case Apply(fun, args) => + // fun(args) + // for instance fun[targs](args) is expressed as Apply(TypeApply(fun, targs), args) + case ApplyDynamic(qual, args) (introduced by erasure, eliminated by cleanup) + // fun(args) + case Super(qual, mix) => + // qual.super[mix] if qual and/or mix is empty, ther are nme.EMPTY.toTypeName + case This(qual) => + // qual.this + case Select(qualifier, selector) => + // qualifier.selector + case Ident(name) => + // name + // note: type checker converts idents that refer to enclosing fields or methods + // to selects; name ==> this.name + case Literal(value) => + // value + case TypeTree() => (introduced by refcheck) + // a type that's not written out, but given in the tpe attribute + case Annotated(annot, arg) => (eliminated by typer) + // arg @annot for types, arg: @annot for exprs + case SingletonTypeTree(ref) => (eliminated by uncurry) + // ref.type + case SelectFromTypeTree(qualifier, selector) => (eliminated by uncurry) + // qualifier # selector, a path-dependent type p.T is expressed as p.type # T + case CompoundTypeTree(templ: Template) => (eliminated by uncurry) + // parent1 with ... with parentN { refinement } + case AppliedTypeTree(tpt, args) => (eliminated by uncurry) + // tpt[args] + case TypeBoundsTree(lo, hi) => (eliminated by uncurry) + // >: lo <: hi + case ExistentialTypeTree(tpt, whereClauses) => (eliminated by uncurry) + // tpt forSome { whereClauses } + +*/ +} diff --git a/src/library/scala/reflect/generic/Types.scala b/src/library/scala/reflect/generic/Types.scala new file mode 100755 index 0000000000..a42e79a3fe --- /dev/null +++ b/src/library/scala/reflect/generic/Types.scala @@ -0,0 +1,156 @@ +package scala.reflect +package generic + +trait Types { self: Universe => + + abstract class AbsType { + def typeSymbol: Symbol + def decl(name: Name): Symbol + + /** 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) {} + + /** Convert toString avoiding infinite recursions by cutting off + * after `maxTostringRecursions` recursion levels. Uses `safeToString` + * to produce a string on each level. + */ + override def toString: String = + if (tostringRecursions >= maxTostringRecursions) + "..." + else + try { + tostringRecursions += 1 + safeToString + } finally { + tostringRecursions -= 1 + } + + /** Metod to be implemented in subclasses. + * Converts this type to a string in calling toString for its parts. + */ + def safeToString: String = super.toString + } + + type Type >: Null <: AbsType + + val NoType: Type + val NoPrefix: Type + + type ThisType <: Type + val ThisType: ThisTypeExtractor + + type TypeRef <: Type + val TypeRef: TypeRefExtractor + + type SingleType <: Type + val SingleType: SingleTypeExtractor + + type SuperType <: Type + val SuperType: SuperTypeExtractor + + type TypeBounds <: Type + val TypeBounds: TypeBoundsExtractor + + type CompoundType <: Type + + type RefinedType <: CompoundType + val RefinedType: RefinedTypeExtractor + + type ClassInfoType <: CompoundType + val ClassInfoType: ClassInfoTypeExtractor + + type ConstantType <: Type + val ConstantType: ConstantTypeExtractor + + type MethodType <: Type + val MethodType: MethodTypeExtractor + + type PolyType <: Type + val PolyType: PolyTypeExtractor + + type ExistentialType <: Type + val ExistentialType: ExistentialTypeExtractor + + type AnnotatedType <: Type + val AnnotatedType: AnnotatedTypeExtractor + + type LazyType <: Type with AbsLazyType + + trait AbsLazyType extends AbsType { + override def isComplete: Boolean = false + override def complete(sym: Symbol) + override def safeToString = "<?>" + } + + abstract class ThisTypeExtractor { + def apply(sym: Symbol): Type + def unapply(tpe: ThisType): Option[Symbol] + } + + abstract class SingleTypeExtractor { + def apply(pre: Type, sym: Symbol): Type + def unapply(tpe: SingleType): Option[(Type, Symbol)] + } + + abstract class SuperTypeExtractor { + def apply(thistpe: Type, supertpe: Type): Type + def unapply(tpe: SuperType): Option[(Type, Type)] + } + + abstract class TypeRefExtractor { + def apply(pre: Type, sym: Symbol, args: List[Type]): Type + def unapply(tpe: TypeRef): Option[(Type, Symbol, List[Type])] + } + + abstract class TypeBoundsExtractor { + def apply(lo: Type, hi: Type): TypeBounds + def unapply(tpe: TypeBounds): Option[(Type, Type)] + } + + abstract class RefinedTypeExtractor { + def apply(parents: List[Type], decls: Scope): RefinedType + def apply(parents: List[Type], decls: Scope, clazz: Symbol): RefinedType + def unapply(tpe: RefinedType): Option[(List[Type], Scope)] + } + + abstract class ClassInfoTypeExtractor { + def apply(parents: List[Type], decls: Scope, clazz: Symbol): ClassInfoType + def unapply(tpe: ClassInfoType): Option[(List[Type], Scope, Symbol)] + } + + abstract class ConstantTypeExtractor { + def apply(value: Constant): ConstantType + def unapply(tpe: ConstantType): Option[Constant] + } + + abstract class MethodTypeExtractor { + def apply(params: List[Symbol], resultType: Type): MethodType + def unapply(tpe: MethodType): Option[(List[Symbol], Type)] + } + + abstract class PolyTypeExtractor { + def apply(typeParams: List[Symbol], resultType: Type): PolyType + def unapply(tpe: PolyType): Option[(List[Symbol], Type)] + } + + abstract class ExistentialTypeExtractor { + def apply(quantified: List[Symbol], underlying: Type): ExistentialType + def unapply(tpe: ExistentialType): Option[(List[Symbol], Type)] + } + + abstract class AnnotatedTypeExtractor { + def apply(annotations: List[AnnotationInfo], underlying: Type, selfsym: Symbol): AnnotatedType + def unapply(tpe: AnnotatedType): Option[(List[AnnotationInfo], Type, Symbol)] + } + + /** The maximum number of recursions allowed in toString + */ + final val maxTostringRecursions = 50 + + private var tostringRecursions = 0 +} + diff --git a/src/library/scala/reflect/generic/UnPickler.scala b/src/library/scala/reflect/generic/UnPickler.scala new file mode 100755 index 0000000000..3f2c8800e3 --- /dev/null +++ b/src/library/scala/reflect/generic/UnPickler.scala @@ -0,0 +1,773 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2010 LAMP/EPFL + * @author Martin Odersky + */ +// $Id: UnPickler.scala 20716 2010-01-28 14:14:20Z rytz $ + +package scala.reflect +package generic + +import java.io.IOException +import java.lang.{Float, Double} + +import Flags._ +import PickleFormat._ +import collection.mutable.{HashMap, ListBuffer} +import annotation.switch + +/** @author Martin Odersky + * @version 1.0 + */ +abstract class UnPickler { + + val global: Universe + import global._ + + /** Unpickle symbol table information descending from a class and/or module root + * from an array of bytes. + * @param bytes bytearray from which we unpickle + * @param offset offset from which unpickling starts + * @param classroot the top-level class which is unpickled, or NoSymbol if unapplicable + * @param moduleroot the top-level module which is unpickled, or NoSymbol if unapplicable + * @param filename filename associated with bytearray, only used for error messages + */ + def unpickle(bytes: Array[Byte], offset: Int, classRoot: Symbol, moduleRoot: Symbol, filename: String) { + try { + scan(bytes, offset, classRoot, moduleRoot, filename) + } catch { + case ex: IOException => + throw ex + case ex: Throwable => + /*if (settings.debug.value)*/ ex.printStackTrace() + throw new RuntimeException("error reading Scala signature of "+filename+": "+ex.getMessage()) + } + } + + def scan(bytes: Array[Byte], offset: Int, classRoot: Symbol, moduleRoot: Symbol, filename: String) + + abstract class Scan(bytes: Array[Byte], offset: Int, classRoot: Symbol, moduleRoot: Symbol, filename: String) extends PickleBuffer(bytes, offset, -1) { + //println("unpickle " + classRoot + " and " + moduleRoot)//debug + + protected def debug = false + + checkVersion() + + /** A map from entry numbers to array offsets */ + private val index = createIndex + + /** A map from entry numbers to symbols, types, or annotations */ + private val entries = new Array[AnyRef](index.length) + + /** A map from symbols to their associated `decls' scopes */ + private val symScopes = new HashMap[Symbol, Scope] + + //println("unpickled " + classRoot + ":" + classRoot.rawInfo + ", " + moduleRoot + ":" + moduleRoot.rawInfo);//debug + + def run() { + for (i <- 0 until index.length) { + if (isSymbolEntry(i)) + at(i, readSymbol) + else if (isSymbolAnnotationEntry(i)) + at(i, {() => readSymbolAnnotation(); null}) + else if (isChildrenEntry(i)) + at(i, {() => readChildren(); null}) + } + } + + private def checkVersion() { + val major = readNat() + val minor = readNat() + if (major != MajorVersion || minor > MinorVersion) + throw new IOException("Scala signature " + classRoot.decodedName + + " has wrong version\n expected: " + + MajorVersion + "." + MinorVersion + + "\n found: " + major + "." + minor + + " in "+filename) + } + + /** The `decls' scope associated with given symbol */ + protected def symScope(sym: Symbol) = symScopes.get(sym) match { + case None => val s = newScope; symScopes(sym) = s; s + case Some(s) => s + } + + /** Does entry represent an (internal) symbol */ + protected def isSymbolEntry(i: Int): Boolean = { + val tag = bytes(index(i)).toInt + (firstSymTag <= tag && tag <= lastSymTag && + (tag != CLASSsym || !isRefinementSymbolEntry(i))) + } + + /** Does entry represent an (internal or external) symbol */ + protected def isSymbolRef(i: Int): Boolean = { + val tag = bytes(index(i)) + (firstSymTag <= tag && tag <= lastExtSymTag) + } + + /** Does entry represent a name? */ + protected def isNameEntry(i: Int): Boolean = { + val tag = bytes(index(i)).toInt + tag == TERMname || tag == TYPEname + } + + /** Does entry represent a symbol annotation? */ + protected def isSymbolAnnotationEntry(i: Int): Boolean = { + val tag = bytes(index(i)).toInt + tag == SYMANNOT + } + + /** Does the entry represent children of a symbol? */ + protected def isChildrenEntry(i: Int): Boolean = { + val tag = bytes(index(i)).toInt + tag == CHILDREN + } + + /** Does entry represent a refinement symbol? + * pre: Entry is a class symbol + */ + protected def isRefinementSymbolEntry(i: Int): Boolean = { + val savedIndex = readIndex + readIndex = index(i) + val tag = readByte().toInt + assert(tag == CLASSsym) + + readNat(); // read length + val result = readNameRef() == mkTypeName(nme.REFINE_CLASS_NAME) + readIndex = savedIndex + result + } + + /** If entry at <code>i</code> is undefined, define it by performing + * operation <code>op</code> with <code>readIndex at start of i'th + * entry. Restore <code>readIndex</code> afterwards. + */ + protected def at[T <: AnyRef](i: Int, op: () => T): T = { + var r = entries(i) + if (r eq null) { + val savedIndex = readIndex + readIndex = index(i) + r = op() + assert(entries(i) eq null, entries(i)) + entries(i) = r + readIndex = savedIndex + } + r.asInstanceOf[T] + } + + /** Read a name */ + protected def readName(): Name = { + val tag = readByte() + val len = readNat() + tag match { + case TERMname => newTermName(bytes, readIndex, len) + case TYPEname => newTypeName(bytes, readIndex, len) + case _ => errorBadSignature("bad name tag: " + tag) + } + } + + /** Read a symbol */ + protected def readSymbol(): Symbol = { + val tag = readByte() + val end = readNat() + readIndex + var sym: Symbol = NoSymbol + tag match { + case EXTref | EXTMODCLASSref => + val name = readNameRef() + val owner = if (readIndex == end) definitions.RootClass else readSymbolRef() + def fromName(name: Name) = + if (mkTermName(name) == nme.ROOT) definitions.RootClass + else if (name == nme.ROOTPKG) definitions.RootPackage + else if (tag == EXTref) owner.info.decl(name) + else owner.info.decl(name).moduleClass + sym = fromName(name) + // If sym not found try with expanded name. + // This can happen if references to private symbols are + // read from outside; for instance when checking the children of a class + // (see t1722) + if (sym == NoSymbol) sym = fromName(nme.expandedName(name, owner)) + + // If the owner is overloaded (i.e. a method), it's not possible to select the + // right member => return NoSymbol. This can only happen when unpickling a tree. + // the "case Apply" in readTree() takes care of selecting the correct alternative + // after parsing the arguments. + if (sym == NoSymbol && !owner.isOverloaded) errorMissingRequirement(name, owner) + + case NONEsym => + sym = NoSymbol + + case _ => // symbols that were pickled with Pickler.writeSymInfo + var defaultGetter: Symbol = NoSymbol // @deprecated, to be removed for 2.8 final + var nameref = readNat() + if (tag == VALsym && isSymbolRef(nameref)) { // @deprecated, to be removed for 2.8 final + defaultGetter = at(nameref, readSymbol) + nameref = readNat() + } + val name = at(nameref, readName) + val owner = readSymbolRef() + val flags = pickledToRawFlags(readLongNat()) + var privateWithin: Symbol = NoSymbol + var inforef = readNat() + if (isSymbolRef(inforef)) { + privateWithin = at(inforef, readSymbol) + inforef = readNat() + } + tag match { + case TYPEsym => + sym = owner.newAbstractType(name) + case ALIASsym => + sym = owner.newAliasType(name) + case CLASSsym => + sym = + if (name == classRoot.name && owner == classRoot.owner) + (if ((flags & MODULE) != 0L) moduleRoot.moduleClass + else classRoot) + else + if ((flags & MODULE) != 0L) owner.newModuleClass(name) + else owner.newClass(name) + if (readIndex != end) sym.typeOfThis = newLazyTypeRef(readNat()) + case MODULEsym => + val clazz = at(inforef, readType).typeSymbol + sym = + if (name == moduleRoot.name && owner == moduleRoot.owner) moduleRoot + else { + val m = owner.newModule(name, clazz) + clazz.sourceModule = m + m + } + case VALsym => + sym = if (name == moduleRoot.name && owner == moduleRoot.owner) { assert(false); NoSymbol } + else if ((flags & METHOD) != 0) owner.newMethod(name) + else owner.newValue(name) + case _ => + noSuchSymbolTag(tag, end, name, owner) + } + sym.flags = flags & PickledFlags + sym.privateWithin = privateWithin + if (readIndex != end) assert(sym hasFlag (SUPERACCESSOR | PARAMACCESSOR), sym) + if (sym hasFlag SUPERACCESSOR) assert(readIndex != end) + sym.info = + if (readIndex != end) newLazyTypeRefAndAlias(inforef, readNat()) + else newLazyTypeRef(inforef) + if (sym.owner.isClass && sym != classRoot && sym != moduleRoot && + !sym.isModuleClass && !sym.isRefinementClass && !sym.isTypeParameter && !sym.isExistentiallyBound) + symScope(sym.owner) enter sym + } + sym + } + + def noSuchSymbolTag(tag: Int, end: Int, name: Name, owner: Symbol) = + errorBadSignature("bad symbol tag: " + tag) + + /** Read a type */ + protected def readType(): Type = { + val tag = readByte() + val end = readNat() + readIndex + (tag: @switch) match { + case NOtpe => + NoType + case NOPREFIXtpe => + NoPrefix + case THIStpe => + ThisType(readSymbolRef()) + case SINGLEtpe => + SingleType(readTypeRef(), readSymbolRef()) // !!! was singleType + case SUPERtpe => + val thistpe = readTypeRef() + val supertpe = readTypeRef() + SuperType(thistpe, supertpe) + case CONSTANTtpe => + ConstantType(readConstantRef()) + case TYPEREFtpe => + val pre = readTypeRef() + val sym = readSymbolRef() + var args = until(end, readTypeRef) + TypeRef(pre, sym, args) + case TYPEBOUNDStpe => + TypeBounds(readTypeRef(), readTypeRef()) + case REFINEDtpe => + val clazz = readSymbolRef() + RefinedType(until(end, readTypeRef), symScope(clazz), clazz) + case CLASSINFOtpe => + val clazz = readSymbolRef() + ClassInfoType(until(end, readTypeRef), symScope(clazz), clazz) + case METHODtpe | IMPLICITMETHODtpe => + val restpe = readTypeRef() + val params = until(end, readSymbolRef) + // if the method is overloaded, the params cannot be determined (see readSymbol) => return NoType. + // Only happen for trees, "case Apply" in readTree() takes care of selecting the correct + // alternative after parsing the arguments. + if (params.contains(NoSymbol) || restpe == NoType) NoType + else MethodType(params, restpe) + case POLYtpe => + val restpe = readTypeRef() + val typeParams = until(end, readSymbolRef) + PolyType(typeParams, restpe) + case EXISTENTIALtpe => + val restpe = readTypeRef() + ExistentialType(until(end, readSymbolRef), restpe) + case ANNOTATEDtpe => + var typeRef = readNat() + val selfsym = if (isSymbolRef(typeRef)) { + val s = at(typeRef, readSymbol) + typeRef = readNat() + s + } else NoSymbol // selfsym can go. + val tp = at(typeRef, readType) + val annots = until(end, readAnnotationRef) + if (selfsym == NoSymbol) AnnotatedType(annots, tp, selfsym) + else tp + case _ => + noSuchTypeTag(tag, end) + } + } + + def noSuchTypeTag(tag: Int, end: Int): Type = + errorBadSignature("bad type tag: " + tag) + + /** Read a constant */ + protected def readConstant(): Constant = { + val tag = readByte().toInt + val len = readNat() + (tag: @switch) match { + case LITERALunit => Constant(()) + case LITERALboolean => Constant(readLong(len) != 0L) + case LITERALbyte => Constant(readLong(len).toByte) + case LITERALshort => Constant(readLong(len).toShort) + case LITERALchar => Constant(readLong(len).toChar) + case LITERALint => Constant(readLong(len).toInt) + case LITERALlong => Constant(readLong(len)) + case LITERALfloat => Constant(Float.intBitsToFloat(readLong(len).toInt)) + case LITERALdouble => Constant(Double.longBitsToDouble(readLong(len))) + case LITERALstring => Constant(readNameRef().toString()) + case LITERALnull => Constant(null) + case LITERALclass => Constant(readTypeRef()) + case LITERALenum => Constant(readSymbolRef()) + case _ => noSuchConstantTag(tag, len) + } + } + + def noSuchConstantTag(tag: Int, len: Int): Constant = + errorBadSignature("bad constant tag: " + tag) + + /** Read children and store them into the corresponding symbol. + */ + protected def readChildren() { + val tag = readByte() + assert(tag == CHILDREN) + val end = readNat() + readIndex + val target = readSymbolRef() + while (readIndex != end) target addChild readSymbolRef() + } + + /** Read an annotation argument, which is pickled either + * as a Constant or a Tree. + */ + protected def readAnnotArg(i: Int): Tree = { + if (bytes(index(i)) == TREE) { + at(i, readTree) + } else { + val const = at(i, readConstant) + global.Literal(const).setType(const.tpe) + } + } + + /** Read a ClassfileAnnotArg (argument to a classfile annotation) + */ + protected def readClassfileAnnotArg(i: Int): ClassfileAnnotArg = bytes(index(i)) match { + case ANNOTINFO => + NestedAnnotArg(at(i, readAnnotation)) + case ANNOTARGARRAY => + at(i, () => { + readByte() // skip the `annotargarray` tag + val end = readNat() + readIndex + ArrayAnnotArg(until(end, () => readClassfileAnnotArg(readNat())).toArray(classfileAnnotArgManifest)) + }) + case _ => + LiteralAnnotArg(at(i, readConstant)) + } + + /** Read an AnnotationInfo. Not to be called directly, use + * readAnnotation or readSymbolAnnotation + */ + protected def readAnnotationInfo(end: Int): AnnotationInfo = { + val atp = readTypeRef() + val args = new ListBuffer[Tree] + val assocs = new ListBuffer[(Name, ClassfileAnnotArg)] + while (readIndex != end) { + val argref = readNat() + if (isNameEntry(argref)) { + val name = at(argref, readName) + val arg = readClassfileAnnotArg(readNat()) + assocs += ((name, arg)) + } + else + args += readAnnotArg(argref) + } + AnnotationInfo(atp, args.toList, assocs.toList) + } + + /** Read an annotation and as a side effect store it into + * the symbol it requests. Called at top-level, for all + * (symbol, annotInfo) entries. */ + protected def readSymbolAnnotation() { + val tag = readByte() + if (tag != SYMANNOT) + errorBadSignature("symbol annotation expected ("+ tag +")") + val end = readNat() + readIndex + val target = readSymbolRef() + target.addAnnotation(readAnnotationInfo(end)) + } + + /** Read an annotation and return it. Used when unpickling + * an ANNOTATED(WSELF)tpe or a NestedAnnotArg */ + protected def readAnnotation(): AnnotationInfo = { + val tag = readByte() + if (tag != ANNOTINFO) + errorBadSignature("annotation expected (" + tag + ")") + val end = readNat() + readIndex + readAnnotationInfo(end) + } + + /* Read an abstract syntax tree */ + protected def readTree(): Tree = { + val outerTag = readByte() + if (outerTag != TREE) + errorBadSignature("tree expected (" + outerTag + ")") + val end = readNat() + readIndex + val tag = readByte() + val tpe = if (tag == EMPTYtree) NoType else readTypeRef() + + // Set by the three functions to follow. If symbol is non-null + // after the the new tree 't' has been created, t has its Symbol + // set to symbol; and it always has its Type set to tpe. + var symbol: Symbol = null + var mods: Modifiers = null + var name: Name = null + + /** Read a Symbol, Modifiers, and a Name */ + def setSymModsName() { + symbol = readSymbolRef() + mods = readModifiersRef() + name = readNameRef() + } + /** Read a Symbol and a Name */ + def setSymName() { + symbol = readSymbolRef() + name = readNameRef() + } + /** Read a Symbol */ + def setSym() { + symbol = readSymbolRef() + } + + val t = tag match { + case EMPTYtree => + EmptyTree + + case PACKAGEtree => + setSym() + // val discardedSymbol = readSymbolRef() // XXX is symbol intentionally not set? + val pid = readTreeRef().asInstanceOf[RefTree] + val stats = until(end, readTreeRef) + PackageDef(pid, stats) + + case CLASStree => + setSymModsName() + val impl = readTemplateRef() + val tparams = until(end, readTypeDefRef) + ClassDef(mods, name, tparams, impl) + + case MODULEtree => + setSymModsName() + ModuleDef(mods, name, readTemplateRef()) + + case VALDEFtree => + setSymModsName() + val tpt = readTreeRef() + val rhs = readTreeRef() + ValDef(mods, name, tpt, rhs) + + case DEFDEFtree => + setSymModsName() + val tparams = times(readNat(), readTypeDefRef) + val vparamss = times(readNat(), () => times(readNat(), readValDefRef)) + val tpt = readTreeRef() + val rhs = readTreeRef() + + DefDef(mods, name, tparams, vparamss, tpt, rhs) + + case TYPEDEFtree => + setSymModsName() + val rhs = readTreeRef() + val tparams = until(end, readTypeDefRef) + TypeDef(mods, name, tparams, rhs) + + case LABELtree => + setSymName() + val rhs = readTreeRef() + val params = until(end, readIdentRef) + LabelDef(name, params, rhs) + + case IMPORTtree => + setSym() + val expr = readTreeRef() + val selectors = until(end, () => { + val from = readNameRef() + val to = readNameRef() + ImportSelector(from, -1, to, -1) + }) + + Import(expr, selectors) + + case TEMPLATEtree => + setSym() + val parents = times(readNat(), readTreeRef) + val self = readValDefRef() + val body = until(end, readTreeRef) + + Template(parents, self, body) + + case BLOCKtree => + val expr = readTreeRef() + val stats = until(end, readTreeRef) + Block(stats, expr) + + case CASEtree => + val pat = readTreeRef() + val guard = readTreeRef() + val body = readTreeRef() + CaseDef(pat, guard, body) + + case ALTERNATIVEtree => + Alternative(until(end, readTreeRef)) + + case STARtree => + Star(readTreeRef()) + + case BINDtree => + setSymName() + Bind(name, readTreeRef()) + + case UNAPPLYtree => + val fun = readTreeRef() + val args = until(end, readTreeRef) + UnApply(fun, args) + + case ARRAYVALUEtree => + val elemtpt = readTreeRef() + val trees = until(end, readTreeRef) + ArrayValue(elemtpt, trees) + + case FUNCTIONtree => + setSym() + val body = readTreeRef() + val vparams = until(end, readValDefRef) + Function(vparams, body) + + case ASSIGNtree => + val lhs = readTreeRef() + val rhs = readTreeRef() + Assign(lhs, rhs) + + case IFtree => + val cond = readTreeRef() + val thenp = readTreeRef() + val elsep = readTreeRef() + If(cond, thenp, elsep) + + case MATCHtree => + val selector = readTreeRef() + val cases = until(end, readCaseDefRef) + Match(selector, cases) + + case RETURNtree => + setSym() + Return(readTreeRef()) + + case TREtree => + val block = readTreeRef() + val finalizer = readTreeRef() + val catches = until(end, readCaseDefRef) + Try(block, catches, finalizer) + + case THROWtree => + Throw(readTreeRef()) + + case NEWtree => + New(readTreeRef()) + + case TYPEDtree => + val expr = readTreeRef() + val tpt = readTreeRef() + Typed(expr, tpt) + + case TYPEAPPLYtree => + val fun = readTreeRef() + val args = until(end, readTreeRef) + TypeApply(fun, args) + + case APPLYtree => + val fun = readTreeRef() + val args = until(end, readTreeRef) + if (fun.symbol.isOverloaded) { + fun.setType(fun.symbol.info) + inferMethodAlternative(fun, args map (_.tpe), tpe) + } + Apply(fun, args) + + case APPLYDYNAMICtree => + setSym() + val qual = readTreeRef() + val args = until(end, readTreeRef) + ApplyDynamic(qual, args) + + case SUPERtree => + setSym() + val qual = readNameRef() + val mix = readNameRef() + Super(qual, mix) + + case THIStree => + setSym() + This(readNameRef()) + + case SELECTtree => + setSym() + val qualifier = readTreeRef() + val selector = readNameRef() + Select(qualifier, selector) + + case IDENTtree => + setSymName() + Ident(name) + + case LITERALtree => + global.Literal(readConstantRef()) + + case TYPEtree => + TypeTree() + + case ANNOTATEDtree => + val annot = readTreeRef() + val arg = readTreeRef() + Annotated(annot, arg) + + case SINGLETONTYPEtree => + SingletonTypeTree(readTreeRef()) + + case SELECTFROMTYPEtree => + val qualifier = readTreeRef() + val selector = readNameRef() + SelectFromTypeTree(qualifier, selector) + + case COMPOUNDTYPEtree => + CompoundTypeTree(readTemplateRef()) + + case APPLIEDTYPEtree => + val tpt = readTreeRef() + val args = until(end, readTreeRef) + AppliedTypeTree(tpt, args) + + case TYPEBOUNDStree => + val lo = readTreeRef() + val hi = readTreeRef() + TypeBoundsTree(lo, hi) + + case EXISTENTIALTYPEtree => + val tpt = readTreeRef() + val whereClauses = until(end, readTreeRef) + ExistentialTypeTree(tpt, whereClauses) + + case _ => + noSuchTreeTag(tag, end) + } + + if (symbol == null) t setType tpe + else t setSymbol symbol setType tpe + } + + def noSuchTreeTag(tag: Int, end: Int) = + errorBadSignature("unknown tree type (" + tag + ")") + + def readModifiers(): Modifiers = { + val tag = readNat() + if (tag != MODIFIERS) + errorBadSignature("expected a modifiers tag (" + tag + ")") + val end = readNat() + readIndex + val pflagsHi = readNat() + val pflagsLo = readNat() + val pflags = (pflagsHi.toLong << 32) + pflagsLo + val flags = pickledToRawFlags(pflags) + val privateWithin = readNameRef() + Modifiers(flags, privateWithin, Nil, new Map.EmptyMap) + } + + /* Read a reference to a pickled item */ + protected def readNameRef(): Name = at(readNat(), readName) + protected def readSymbolRef(): Symbol = at(readNat(), readSymbol) + protected def readTypeRef(): Type = at(readNat(), readType) + protected def readConstantRef(): Constant = at(readNat(), readConstant) + protected def readAnnotationRef(): AnnotationInfo = + at(readNat(), readAnnotation) + protected def readModifiersRef(): Modifiers = + at(readNat(), readModifiers) + protected def readTreeRef(): Tree = + at(readNat(), readTree) + + protected def readTemplateRef(): Template = + readTreeRef() match { + case templ:Template => templ + case other => + errorBadSignature("expected a template (" + other + ")") + } + protected def readCaseDefRef(): CaseDef = + readTreeRef() match { + case tree:CaseDef => tree + case other => + errorBadSignature("expected a case def (" + other + ")") + } + protected def readValDefRef(): ValDef = + readTreeRef() match { + case tree:ValDef => tree + case other => + errorBadSignature("expected a ValDef (" + other + ")") + } + protected def readIdentRef(): Ident = + readTreeRef() match { + case tree:Ident => tree + case other => + errorBadSignature("expected an Ident (" + other + ")") + } + protected def readTypeDefRef(): TypeDef = + readTreeRef() match { + case tree:TypeDef => tree + case other => + errorBadSignature("expected an TypeDef (" + other + ")") + } + + protected def errorBadSignature(msg: String) = + throw new RuntimeException("malformed Scala signature of " + classRoot.name + " at " + readIndex + "; " + msg) + + protected def errorMissingRequirement(msg: String): Nothing = + if (debug) errorBadSignature(msg) + else throw new IOException("class file needed by "+classRoot.name+" is missing.\n"+msg) + + protected def errorMissingRequirement(name: Name, owner: Symbol): Nothing = + errorMissingRequirement("reference " + NameTransformer.decode(name.toString) + " of " + owner.tpe + " refers to nonexisting symbol.") + + /** pre: `fun` points to a symbol with an overloaded type. + * Selects the overloaded alternative of `fun` which best matches given + * argument types `argtpes` and result type `restpe`. Stores this alternative as + * the symbol of `fun`. + */ + def inferMethodAlternative(fun: Tree, argtpes: List[Type], restpe: Type) + + /** Create a lazy type which when completed returns type at index `i`. */ + def newLazyTypeRef(i: Int): LazyType + + /** Create a lazy type which when completed returns type at index `i` and sets alias + * of completed symbol to symbol at index `j` + */ + def newLazyTypeRefAndAlias(i: Int, j: Int): LazyType + } +} diff --git a/src/library/scala/reflect/generic/Universe.scala b/src/library/scala/reflect/generic/Universe.scala new file mode 100755 index 0000000000..101295ae79 --- /dev/null +++ b/src/library/scala/reflect/generic/Universe.scala @@ -0,0 +1,16 @@ +package scala.reflect +package generic + +abstract class Universe extends Symbols + with Types + with Constants + with Scopes + with Names + with StdNames + with Trees + with AnnotationInfos + with StandardDefinitions { + type Position + val NoPosition: Position +} + |