diff options
Diffstat (limited to 'src/library')
-rw-r--r-- | src/library/scala/reflect/api/Trees.scala | 270 |
1 files changed, 236 insertions, 34 deletions
diff --git a/src/library/scala/reflect/api/Trees.scala b/src/library/scala/reflect/api/Trees.scala index cf9d301e95..7185ea73e2 100644 --- a/src/library/scala/reflect/api/Trees.scala +++ b/src/library/scala/reflect/api/Trees.scala @@ -217,6 +217,25 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe => override def toString: String = show(this) override def hashCode(): Int = System.identityHashCode(this) override def equals(that: Any) = this eq that.asInstanceOf[AnyRef] + + // TODO: implementation of more aggresive caching still needs + // more testing + //protected var hasErrorTree: List[ErrorTree] = null + protected var hasErrorTree: Option[Boolean] = None + protected def initErrorCheck: Unit + + def containsError(): Boolean = { + if (hasErrorTree.isEmpty) + initErrorCheck + hasErrorTree.get + } + } + + @inline def containsErrorCheck(ts: List[Tree]): Some[Boolean] = Some(ts.exists(_.containsError())) + @inline def containsErrorCheck(t: Tree): Some[Boolean] = Some(t.containsError()) + + trait AbsErrorTree extends Tree { + def emit(): Unit } /** A tree for a term. Not all terms are TermTrees; use isTerm @@ -259,6 +278,10 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe => override def tpe_=(t: Type) = if (t != NoType) throw new UnsupportedOperationException("tpe_=("+t+") inapplicable for <empty>") override def isEmpty = true + + protected def initErrorCheck { + hasErrorTree = Some(false) + } } /** Common base class for all member definitions: types, classes, @@ -284,6 +307,10 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe => extends MemberDef { def name = pid.name def mods = Modifiers() + + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(stats) + } } /** A common base class for class and object definitions. @@ -295,13 +322,21 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe => /** A class definition. */ case class ClassDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], impl: Template) - extends ImplDef + extends ImplDef { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(tparams ++ List(impl)) + } + } /** An object definition, e.g. `object Foo`. Internally, objects are * quite frequently called modules to reduce ambiguity. */ case class ModuleDef(mods: Modifiers, name: TermName, impl: Template) - extends ImplDef + extends ImplDef { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(impl) + } + } /** A common base class for ValDefs and DefDefs. */ @@ -314,17 +349,29 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe => /** A value definition (this includes vars as well, which differ from * vals only in having the MUTABLE flag set in their Modifiers.) */ - case class ValDef(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree) extends ValOrDefDef + case class ValDef(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree) extends ValOrDefDef { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(List(tpt, rhs)) + } + } /** A method definition. */ case class DefDef(mods: Modifiers, name: TermName, tparams: List[TypeDef], - vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) extends ValOrDefDef + vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) extends ValOrDefDef { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(tparams ++ vparamss.flatten ++ List(tpt, rhs)) + } + } /** An abstract type, a type parameter, or a type alias. */ case class TypeDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], rhs: Tree) - extends MemberDef + extends MemberDef { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(tparams ++ List(rhs)) + } + } /** A labelled expression. Not expressible in language syntax, but * generated by the compiler to simulate while/do-while loops, and @@ -341,7 +388,11 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe => * Forward jumps within a block are allowed. */ case class LabelDef(name: TermName, params: List[Ident], rhs: Tree) - extends DefTree with TermTree + extends DefTree with TermTree { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(params ++ List(rhs)) + } + } /** Import selector * @@ -360,7 +411,11 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe => * @param selectors */ case class Import(expr: Tree, selectors: List[ImportSelector]) - extends SymTree + extends SymTree { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(expr) + } + } // 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. @@ -382,27 +437,46 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe => // def bar // owner is local dummy // } // System.err.println("TEMPLATE: " + parents) + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(self::parents:::body) + } } /** Block of expressions (semicolon separated expressions) */ case class Block(stats: List[Tree], expr: Tree) - extends TermTree + extends TermTree { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(stats ++ List(expr)) + } + } /** Case clause in a pattern match, eliminated during explicitouter * (except for occurrences in switch statements) */ case class CaseDef(pat: Tree, guard: Tree, body: Tree) - extends Tree + extends Tree { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(List(pat, guard, body)) + } + } /** Alternatives of patterns, eliminated by explicitouter, except for * occurrences in encoded Switch stmt (=remaining Match(CaseDef(...)) */ case class Alternative(trees: List[Tree]) - extends TermTree + extends TermTree { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(trees) + } + } /** Repetition of pattern, eliminated by explicitouter */ case class Star(elem: Tree) - extends TermTree + extends TermTree { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(elem) + } + } /** Bind of a variable to a rhs pattern, eliminated by explicitouter * @@ -410,29 +484,53 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe => * @param body */ case class Bind(name: Name, body: Tree) - extends DefTree + extends DefTree { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(body) + } + } case class UnApply(fun: Tree, args: List[Tree]) - extends TermTree + extends TermTree { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(fun::args) + } + } /** Array of expressions, needs to be translated in backend, */ case class ArrayValue(elemtpt: Tree, elems: List[Tree]) - extends TermTree + extends TermTree { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(elemtpt::elems) + } + } /** Anonymous function, eliminated by analyzer */ case class Function(vparams: List[ValDef], body: Tree) - extends TermTree with SymTree + extends TermTree with SymTree { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(vparams ++ List(body)) + } + } // 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 + extends TermTree { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(List(lhs, rhs)) + } + } /** Conditional expression */ case class If(cond: Tree, thenp: Tree, elsep: Tree) - extends TermTree + extends TermTree { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(List(cond, thenp, elsep)) + } + } /** - Pattern matching expression (before explicitouter) * - Switch statements (after explicitouter) @@ -446,30 +544,54 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe => * `Ident(nme.WILDCARD)` */ case class Match(selector: Tree, cases: List[CaseDef]) - extends TermTree + extends TermTree { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(selector::cases) + } + } /** Return expression */ case class Return(expr: Tree) - extends TermTree with SymTree + extends TermTree with SymTree { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(expr) + } + } // The symbol of a Return node is the enclosing method. case class Try(block: Tree, catches: List[CaseDef], finalizer: Tree) - extends TermTree + extends TermTree { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(block::catches ++ List(finalizer)) + } + } /** Throw expression */ case class Throw(expr: Tree) - extends TermTree + extends TermTree { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(expr) + } + } /** 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 + case class New(tpt: Tree) extends TermTree { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(tpt) + } + } /** Type annotation, eliminated by explicit outer */ case class Typed(expr: Tree, tpt: Tree) - extends TermTree + extends TermTree { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(List(expr, tpt)) + } + } /** Common base class for Apply and TypeApply. This could in principle * be a SymTree, but whether or not a Tree is a SymTree isn't used @@ -488,6 +610,10 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe => extends GenericApply { override def symbol: Symbol = fun.symbol override def symbol_=(sym: Symbol) { fun.symbol = sym } + + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(fun::args) + } } /** Value application */ @@ -495,6 +621,10 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe => extends GenericApply { override def symbol: Symbol = fun.symbol override def symbol_=(sym: Symbol) { fun.symbol = sym } + + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(fun::args) + } } class ApplyToImplicitArgs(fun: Tree, args: List[Tree]) extends Apply(fun, args) @@ -508,7 +638,11 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe => * - f is stored as the node's symbol field. */ case class ApplyDynamic(qual: Tree, args: List[Tree]) - extends TermTree with SymTree + extends TermTree with SymTree { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(qual::args) + } + } // The symbol of an ApplyDynamic is the function symbol of `qual`, or NoSymbol, if there is none. /** Super reference, qual = corresponding this reference */ @@ -517,20 +651,37 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe => // For instance in C.super(...), it would be C. override def symbol: Symbol = qual.symbol override def symbol_=(sym: Symbol) { qual.symbol = sym } + + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(qual) + } } /** Self reference */ case class This(qual: TypeName) - extends TermTree with SymTree + extends TermTree with SymTree { + protected def initErrorCheck { + // TODO should check qual name, symbol? + hasErrorTree = Some(false) + } + } // 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 + extends RefTree { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(qualifier) + } + } /** Identifier <name> */ - case class Ident(name: Name) extends RefTree { } + case class Ident(name: Name) extends RefTree { + protected def initErrorCheck { + hasErrorTree = Some(false) + } + } class BackQuotedIdent(name: Name) extends Ident(name) @@ -538,6 +689,10 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe => case class Literal(value: Constant) extends TermTree { assert(value ne null) + + protected def initErrorCheck { + hasErrorTree = Some(false) + } } // @deprecated("will be removed and then be re-introduced with changed semantics, use Literal(Constant(x)) instead") @@ -548,45 +703,81 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe => * Eliminated by typechecker (typedAnnotated), the annotations are then stored in * an AnnotatedType. */ - case class Annotated(annot: Tree, arg: Tree) extends Tree + case class Annotated(annot: Tree, arg: Tree) extends Tree { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(List(annot, arg)) + } + } /** Singleton type, eliminated by RefCheck */ case class SingletonTypeTree(ref: Tree) - extends TypTree + extends TypTree { + + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(ref) + } + } /** Type selection <qualifier> # <name>, eliminated by RefCheck */ case class SelectFromTypeTree(qualifier: Tree, name: TypeName) - extends TypTree with RefTree + extends TypTree with RefTree { + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(qualifier) + } + } /** Intersection type <parent1> with ... with <parentN> { <decls> }, eliminated by RefCheck */ case class CompoundTypeTree(templ: Template) - extends TypTree + extends TypTree { + + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(templ) + } + } /** 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 } + + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(tpt::args) + } } case class TypeBoundsTree(lo: Tree, hi: Tree) - extends TypTree + extends TypTree { + + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(List(lo, hi)) + } + } case class ExistentialTypeTree(tpt: Tree, whereClauses: List[Tree]) - extends TypTree + extends TypTree { + + protected def initErrorCheck { + hasErrorTree = containsErrorCheck(tpt::whereClauses) + } + } /** A synthetic tree 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 * `RefCheck`, where the arbitrary type trees are all replaced by - * TypeTree's. */ + * TypeTree's. + * + */ case class TypeTree() extends TypTree { private var orig: Tree = null + private var errorCause: Tree = null private[scala] var wasEmpty: Boolean = false override def symbol = if (tpe == null) null else tpe.typeSymbol override def isEmpty = (tpe eq null) || tpe == NoType + def original: Tree = orig def setOriginal(tree: Tree): this.type = { def followOriginal(t: Tree): Tree = t match { @@ -598,10 +789,20 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe => this } + def setErrorCause(tree: Tree): this.type = { + assert(tree != null) + errorCause = tree + this + } + override def defineType(tp: Type): this.type = { wasEmpty = isEmpty setType(tp) } + + protected def initErrorCheck { + hasErrorTree = Some(errorCause != null) + } } def TypeTree(tp: Type): TypeTree = TypeTree() setType tp @@ -715,6 +916,7 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe => traverse(lo); traverse(hi) case ExistentialTypeTree(tpt, whereClauses) => traverse(tpt); traverseTrees(whereClauses) + case _: AbsErrorTree => case _ => xtraverse(this, tree) } |