summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
Diffstat (limited to 'src/library')
-rw-r--r--src/library/scala/reflect/api/Trees.scala270
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)
}