diff options
author | Martin Odersky <odersky@gmail.com> | 2011-07-11 09:00:48 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2011-07-11 09:00:48 +0000 |
commit | 9e1d24d64283a4caf47cb68c00298538ca0b9999 (patch) | |
tree | 368175c8b2adcc68b671b3b9d2acb8821cf04214 /src/compiler/scala/tools/nsc | |
parent | 7d4cff1dc6040d951b09f8df4af288d16ef53de2 (diff) | |
download | scala-9e1d24d64283a4caf47cb68c00298538ca0b9999.tar.gz scala-9e1d24d64283a4caf47cb68c00298538ca0b9999.tar.bz2 scala-9e1d24d64283a4caf47cb68c00298538ca0b9999.zip |
Refactored reflection into reflect.api and refl...
Refactored reflection into reflect.api and reflect.internal. Severed the
last remaining dependency on reflect.generic. Review by extempore.
Diffstat (limited to 'src/compiler/scala/tools/nsc')
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/TreeInfo.scala | 45 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/TreePrinters.scala | 24 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/ast/Trees.scala | 282 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 2 |
4 files changed, 351 insertions, 2 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala new file mode 100644 index 0000000000..bc8ec07ebc --- /dev/null +++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala @@ -0,0 +1,45 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2011 LAMP/EPFL + * @author Martin Odersky + */ + +package scala.tools.nsc +package ast + +import reflect.internal.Flags._ +import symtab._ +import util.HashSet + +/** This class ... + * + * @author Martin Odersky + * @version 1.0 + */ +abstract class TreeInfo extends reflect.internal.TreeInfo { + val global: Global + import global._ + + import definitions.ThrowableClass + + /** Is tree legal as a member definition of an interface? + */ + override def isInterfaceMember(tree: Tree): Boolean = tree match { + case DocDef(_, definition) => isInterfaceMember(definition) + case _ => super.isInterfaceMember(tree) + } + + /** Is tree a pure (i.e. non-side-effecting) definition? + */ + override def isPureDef(tree: Tree): Boolean = tree match { + case DocDef(_, definition) => isPureDef(definition) + case _ => super.isPureDef(tree) + } + + /** Does list of trees start with a definition of + * a class of module with given name (ignoring imports) + */ + override def firstDefinesClassOrObject(trees: List[Tree], name: Name): Boolean = trees match { + case ClassDef(_, `name`, _, _) :: Nil => true + case _ => super.firstDefinesClassOrObject(trees, name) + } +} diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala index 1a0ddd4e1e..34f8cdc626 100644 --- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala +++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala @@ -44,6 +44,30 @@ trait TreePrinters extends reflect.internal.TreePrinters { this: Global => } } + // overflow cases missing from TreePrinter in reflect.api + override def xprintRaw(treePrinter: super.TreePrinter, tree: Tree) = tree match { + case DocDef(comment, definition) => + treePrinter.print(comment.raw) + treePrinter.println() + treePrinter.print(definition) + + case AssignOrNamedArg(lhs, rhs) => + treePrinter.print(lhs) + treePrinter.print(" = ") + treePrinter.print(rhs) + + case TypeTreeWithDeferredRefCheck() => + treePrinter.print("<tree with deferred refcheck>") + + case SelectFromArray(qualifier, name, _) => + treePrinter.print(qualifier) + treePrinter.print(".<arr>") + treePrinter.print(treePrinter.symName(tree, name)) + + case _ => + super.xprintRaw(treePrinter, tree) + } + /** A tree printer which is stingier about vertical whitespace and unnecessary * punctuation than the standard one. */ diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index 008eb8372a..42a4698793 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -6,11 +6,291 @@ package scala.tools.nsc package ast +import scala.reflect.internal.Flags.BYNAMEPARAM +import scala.reflect.internal.Flags.DEFAULTPARAM +import scala.reflect.internal.Flags.IMPLICIT +import scala.reflect.internal.Flags.PARAM +import scala.reflect.internal.Flags.PARAMACCESSOR +import scala.reflect.internal.Flags.PRESUPER +import scala.reflect.internal.Flags.TRAIT + +import util.HashSet + trait Trees extends reflect.internal.Trees { self: Global => + // --- additional cases -------------------------------------------------------- + + /** Only used during parsing */ + case class Parens(args: List[Tree]) extends Tree + + /** 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 } + override def isDef = definition.isDef + override def isTerm = definition.isTerm + override def isType = definition.isType + } + + + /** 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 + + /** Array selection <qualifier> . <name> only used during erasure */ + case class SelectFromArray(qualifier: Tree, name: Name, erasure: Type) + extends TermTree with RefTree { } + + /** emitted by typer, eliminated by refchecks */ + case class TypeTreeWithDeferredRefCheck()(val check: () => TypeTree) extends TypTree + + // --- factory methods ---------------------------------------------------------- + + /** Generates a template with constructor corresponding to + * + * constrmods (vparams1_) ... (vparams_n) preSuper { presupers } + * extends superclass(args_1) ... (args_n) with mixins { self => body } + * + * This gets translated to + * + * extends superclass with mixins { self => + * presupers' // presupers without rhs + * vparamss // abstract fields corresponding to value parameters + * def <init>(vparamss) { + * presupers + * super.<init>(args) + * } + * body + * } + */ + def Template(parents: List[Tree], self: ValDef, constrMods: Modifiers, vparamss: List[List[ValDef]], argss: List[List[Tree]], body: List[Tree], superPos: Position): Template = { + /* Add constructor to template */ + + // create parameters for <init> as synthetic trees. + var vparamss1 = + vparamss map (vps => vps.map { vd => + atPos(focusPos(vd.pos)) { + ValDef( + Modifiers(vd.mods.flags & (IMPLICIT | DEFAULTPARAM | BYNAMEPARAM) | PARAM | PARAMACCESSOR) withAnnotations vd.mods.annotations, + vd.name, vd.tpt.duplicate, vd.rhs.duplicate) + }}) + val (edefs, rest) = body span treeInfo.isEarlyDef + val (evdefs, etdefs) = edefs partition treeInfo.isEarlyValDef + val (lvdefs, gvdefs) = evdefs map { + case vdef @ ValDef(mods, name, tpt, rhs) => + val fld = treeCopy.ValDef( + vdef.duplicate, mods, name, + atPos(focusPos(vdef.pos)) { TypeTree() setOriginal tpt setPos focusPos(tpt.pos) }, // atPos in case + EmptyTree) + val local = treeCopy.ValDef(vdef, Modifiers(PRESUPER), name, tpt, rhs) + (local, fld) + } unzip + + val constrs = { + if (constrMods hasFlag TRAIT) { + if (body forall treeInfo.isInterfaceMember) List() + else List( + atPos(wrappingPos(superPos, lvdefs)) ( + DefDef(NoMods, nme.MIXIN_CONSTRUCTOR, List(), List(List()), TypeTree(), Block(lvdefs, Literal(()))))) + } else { + // convert (implicit ... ) to ()(implicit ... ) if its the only parameter section + if (vparamss1.isEmpty || !vparamss1.head.isEmpty && vparamss1.head.head.mods.isImplicit) + vparamss1 = List() :: vparamss1; + val superRef: Tree = atPos(superPos) { + Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR) + } + val superCall = (superRef /: argss) (Apply) + List( + atPos(wrappingPos(superPos, lvdefs ::: argss.flatten)) ( + DefDef(constrMods, nme.CONSTRUCTOR, List(), vparamss1, TypeTree(), Block(lvdefs ::: List(superCall), Literal(()))))) + } + } + // println("typed template, gvdefs = "+gvdefs+", parents = "+parents+", constrs = "+constrs) + constrs foreach (ensureNonOverlapping(_, parents ::: gvdefs)) + // vparamss2 are used as field definitions for the class. remove defaults + val vparamss2 = vparamss map (vps => vps map { vd => + treeCopy.ValDef(vd, vd.mods &~ DEFAULTPARAM, vd.name, vd.tpt, EmptyTree) + }) + Template(parents, self, gvdefs ::: vparamss2.flatten ::: constrs ::: etdefs ::: rest) + } + + /** Construct class definition with given class symbol, value parameters, + * supercall arguments and template body. + * + * @param sym the class symbol + * @param constrMods the modifiers for the class constructor, i.e. as in `class C private (...)` + * @param vparamss the value parameters -- if they have symbols they + * should be owned by `sym` + * @param argss the supercall arguments + * @param body the template statements without primary constructor + * and value parameter fields. + */ + def ClassDef(sym: Symbol, constrMods: Modifiers, vparamss: List[List[ValDef]], argss: List[List[Tree]], body: List[Tree], superPos: Position): ClassDef = + ClassDef(sym, + Template(sym.info.parents map TypeTree, + if (sym.thisSym == sym || phase.erasedTypes) emptyValDef else ValDef(sym.thisSym), + constrMods, vparamss, argss, body, superPos)) + + // --- subcomponents -------------------------------------------------- + + object treeInfo extends { + val global: Trees.this.type = self + } with TreeInfo + lazy val treePrinter = newTreePrinter() + // --- additional cases in operations ---------------------------------- + + override protected def xtraverse(traverser: Traverser, tree: Tree): Unit = tree match { + case Parens(ts) => + traverser.traverseTrees(ts) + case DocDef(comment, definition) => + traverser.traverse(definition) + case AssignOrNamedArg(lhs, rhs) => + traverser.traverse(lhs); traverser.traverse(rhs) + case SelectFromArray(qualifier, selector, erasure) => + traverser.traverse(qualifier) + case TypeTreeWithDeferredRefCheck() => // TODO: should we traverse the wrapped tree? + // (and rewrap the result? how to update the deferred check? would need to store wrapped tree instead of returning it from check) + case _ => super.xtraverse(traverser, tree) + } + + trait TreeCopier extends super.TreeCopierOps { + def DocDef(tree: Tree, comment: DocComment, definition: Tree): DocDef + def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree): AssignOrNamedArg + def SelectFromArray(tree: Tree, qualifier: Tree, selector: Name, erasure: Type): SelectFromArray + def TypeTreeWithDeferredRefCheck(tree: Tree): TypeTreeWithDeferredRefCheck + } + + def newStrictTreeCopier: TreeCopier = new StrictTreeCopier + def newLazyTreeCopier: TreeCopier = new LazyTreeCopier + + class StrictTreeCopier extends super.StrictTreeCopier with TreeCopier { + def DocDef(tree: Tree, comment: DocComment, definition: Tree) = + new DocDef(comment, definition).copyAttrs(tree) + def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree) = + new AssignOrNamedArg(lhs, rhs).copyAttrs(tree) + def SelectFromArray(tree: Tree, qualifier: Tree, selector: Name, erasure: Type) = + new SelectFromArray(qualifier, selector, erasure).copyAttrs(tree) + def TypeTreeWithDeferredRefCheck(tree: Tree) = tree match { + case dc@TypeTreeWithDeferredRefCheck() => new TypeTreeWithDeferredRefCheck()(dc.check).copyAttrs(tree) + } + } + + class LazyTreeCopier extends super.LazyTreeCopier with TreeCopier { + def DocDef(tree: Tree, comment: DocComment, definition: Tree) = tree match { + case t @ DocDef(comment0, definition0) + if (comment0 == comment) && (definition0 == definition) => t + case _ => this.treeCopy.DocDef(tree, comment, definition) + } + def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree) = tree match { + case t @ AssignOrNamedArg(lhs0, rhs0) + if (lhs0 == lhs) && (rhs0 == rhs) => t + case _ => this.treeCopy.AssignOrNamedArg(tree, lhs, rhs) + } + def SelectFromArray(tree: Tree, qualifier: Tree, selector: Name, erasure: Type) = tree match { + case t @ SelectFromArray(qualifier0, selector0, _) + if (qualifier0 == qualifier) && (selector0 == selector) => t + case _ => this.treeCopy.SelectFromArray(tree, qualifier, selector, erasure) + } + def TypeTreeWithDeferredRefCheck(tree: Tree) = tree match { + case t @ TypeTreeWithDeferredRefCheck() => t + case _ => this.treeCopy.TypeTreeWithDeferredRefCheck(tree) + } + } + class Transformer extends super.Transformer { def transformUnit(unit: CompilationUnit) { unit.body = transform(unit.body) } } -}
\ No newline at end of file + + override protected def xtransform(transformer: super.Transformer, tree: Tree): Tree = tree match { + case DocDef(comment, definition) => + transformer.treeCopy.DocDef(tree, comment, transformer.transform(definition)) + case AssignOrNamedArg(lhs, rhs) => + transformer.treeCopy.AssignOrNamedArg(tree, transformer.transform(lhs), transformer.transform(rhs)) + case SelectFromArray(qualifier, selector, erasure) => + transformer.treeCopy.SelectFromArray( + tree, transformer.transform(qualifier), selector, erasure) + case TypeTreeWithDeferredRefCheck() => + transformer.treeCopy.TypeTreeWithDeferredRefCheck(tree) + } + + object resetPos extends Traverser { + override def traverse(t: Tree) { + if (t != EmptyTree) t.setPos(NoPosition) + super.traverse(t) + } + } + + /** resets symbol and tpe fields in a tree, @see ResetAttrsTraverse + */ + def resetAllAttrs[A<:Tree](x:A): A = { new ResetAttrsTraverser().traverse(x); x } + def resetLocalAttrs[A<:Tree](x:A): A = { new ResetLocalAttrsTraverser().traverse(x); x } + + /** A traverser which resets symbol and tpe fields of all nodes in a given tree + * except for (1) TypeTree nodes, whose <code>.tpe</code> field is kept, and + * (2) This(pkg) nodes, where pkg refers to a package symbol -- their attributes are kept, and + * (3) if a <code>.symbol</code> field refers to a symbol which is defined + * outside the tree, it is also kept. + * + * (2) is necessary because some This(pkg) are generated where pkg is not + * an enclosing package.n In that case, resetting the symbol would cause the + * next type checking run to fail. See #3152. + * + * (bq:) This traverser has mutable state and should be discarded after use + */ + private class ResetAttrsTraverser extends Traverser { + protected def isLocal(sym: Symbol): Boolean = true + protected def resetDef(tree: Tree) { + tree.symbol = NoSymbol + } + override def traverse(tree: Tree): Unit = { + tree match { + case _: DefTree | Function(_, _) | Template(_, _, _) => + resetDef(tree) + tree.tpe = null + case tpt: TypeTree => + if (tpt.wasEmpty) tree.tpe = null + case This(_) if tree.symbol != null && tree.symbol.isPackageClass => + ; + case EmptyTree => + ; + case _ => + if (tree.hasSymbol && isLocal(tree.symbol)) tree.symbol = NoSymbol + tree.tpe = null + } + super.traverse(tree) + } + } + + private class ResetLocalAttrsTraverser extends ResetAttrsTraverser { + private val erasedSyms = HashSet[Symbol](8) + override protected def isLocal(sym: Symbol) = erasedSyms(sym) + override protected def resetDef(tree: Tree) { + erasedSyms addEntry tree.symbol + super.resetDef(tree) + } + override def traverse(tree: Tree): Unit = tree match { + case Template(parents, self, body) => + for (stat <- body) + if (stat.isDef) erasedSyms.addEntry(stat.symbol) + super.traverse(tree) + case _ => + super.traverse(tree) + } + } + + /* New pattern matching cases: + + case Parens(expr) (only used during parsing) + case DocDef(comment, defn) => (eliminated by typer) + case AssignOrNamedArg(lhs, rhs) => (eliminated by typer) + case TypeTreeWithDeferredRefCheck() => (created and eliminated by typer) + case SelectFromArray(_, _, _) => (created and eliminated by erasure) + + */ + + }
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index a390d0fc7b..023f170c4b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -2086,7 +2086,7 @@ trait Typers extends Modes { tree.pos.isRange && context.unit != null && (tree.pos includes context.unit.targetPos) val localTarget = stats exists includesTargetPos def typedStat(stat: Tree): Tree = { - if (context.owner.isRefinementClass && !treeInfo.isDeclaration(stat)) + if (context.owner.isRefinementClass && !treeInfo.isDeclarationOrTypeDef(stat)) errorTree(stat, "only declarations allowed here") else stat match { |