summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2011-07-11 09:00:48 +0000
committerMartin Odersky <odersky@gmail.com>2011-07-11 09:00:48 +0000
commit9e1d24d64283a4caf47cb68c00298538ca0b9999 (patch)
tree368175c8b2adcc68b671b3b9d2acb8821cf04214 /src/compiler/scala/tools/nsc
parent7d4cff1dc6040d951b09f8df4af288d16ef53de2 (diff)
downloadscala-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.scala45
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreePrinters.scala24
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala282
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala2
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 {