aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/Trees.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/core/Trees.scala')
-rw-r--r--src/dotty/tools/dotc/core/Trees.scala176
1 files changed, 127 insertions, 49 deletions
diff --git a/src/dotty/tools/dotc/core/Trees.scala b/src/dotty/tools/dotc/core/Trees.scala
index 25226c660..1245119f2 100644
--- a/src/dotty/tools/dotc/core/Trees.scala
+++ b/src/dotty/tools/dotc/core/Trees.scala
@@ -2,6 +2,7 @@ package dotty.tools.dotc.core
import Types._, Names._, Flags._, Positions._, Contexts._, Constants._, SymDenotations._, Symbols._
import Denotations._, StdNames._
+import annotation.tailrec
object Trees {
@@ -30,17 +31,29 @@ object Trees {
* nodes.
*/
abstract class Tree[T] extends DotClass {
+
+ /** The tree's position. Except
+ * for Shared nodes, it is always ensured that a tree's position
+ * contains the positions of all its subtrees.
+ */
def pos: Position
+ /** The typeconstructor at the root of the tree */
type ThisTree[T] <: Tree[T]
protected var _tpe: T = _
+ /** The type of the tree. In case of an untyped tree,
+ * an UnAssignedTypeException is thrown.
+ */
def tpe: T = {
if (_tpe == null) throw new UnAssignedTypeException(this)
_tpe
}
+ /** Return a typed tree that's isomorphic to this tree, but has given
+ * type.
+ */
def withType(tpe: Type): ThisTree[Type] = {
val tree =
(if (_tpe == null ||
@@ -50,12 +63,22 @@ object Trees {
tree.asInstanceOf[ThisTree[Type]]
}
+ /** The denotation referred to by this tree, NoDenotation where not applicable */
def denot(implicit ctx: Context): Denotation = NoDenotation
+
+ /** The symbol defined by ot referred to by this tree, NoSymbol where not applicable */
def symbol(implicit ctx: Context): Symbol = NoSymbol
+ /** Does this tree represent a type? */
def isType: Boolean = false
+
+ /** Does this tree represent a term? */
def isTerm: Boolean = false
+
+ /** Does this tree represent a definition or declaration? */
def isDef: Boolean = false
+
+ /** Is this tree either the empty tree or the empty ValDef? */
def isEmpty: Boolean = false
}
@@ -68,16 +91,16 @@ object Trees {
// ------ Categories of trees -----------------------------------
- /** Tree is definitely a type. Note that some trees
- * have isType = true without being TypTrees (e.g. Ident, AnnotatedTree)
+ /** Instances of this class are trees for which isType is definitely true.
+ * Note that some trees have isType = true without being TypTrees (e.g. Ident, AnnotatedTree)
*/
trait TypTree[T] extends Tree[T] {
type ThisTree[T] <: TypTree[T]
override def isType = true
}
- /** Tree is definitely a term. Note that some trees
- * have isType = true without being TypTrees (e.g. Ident, AnnotatedTree)
+ /** Instances of this class are trees for which isTerm is definitely true.
+ * Note that some trees have isTerm = true without being TermTrees (e.g. Ident, AnnotatedTree)
*/
trait TermTree[T] extends Tree[T] {
type ThisTree[T] <: TermTree[T]
@@ -97,7 +120,7 @@ object Trees {
}
}
- /** Tree's symbol/isType/isTerm properties come from a subtree identifier
+ /** Tree's symbol/isType/isTerm properties come from a subtree identified
* by `forwardTo`.
*/
abstract class ProxyTree[T] extends Tree[T] {
@@ -123,6 +146,7 @@ object Trees {
override def isTerm = name.isTermName
}
+ /** Tree represents a definition */
abstract class DefTree[T] extends NameTree[T] {
type ThisTree[T] <: DefTree[T]
override def isDef = true
@@ -131,28 +155,32 @@ object Trees {
// ----------- Tree case classes ------------------------------------
/** name */
- case class Ident[T] (name: Name)(implicit val pos: Position)
+ case class Ident[T] (name: Name)(implicit cpos: Position)
extends RefTree[T] {
type ThisTree[T] = Ident[T]
+ val pos = cpos
def qualifier: Tree[T] = EmptyTree[T]
}
/** qualifier.name */
- case class Select[T](qualifier: Tree[T], name: Name)(implicit val pos: Position)
+ case class Select[T](qualifier: Tree[T], name: Name)(implicit cpos: Position)
extends RefTree[T] {
type ThisTree[T] = Select[T]
+ val pos = cpos union qualifier.pos
}
/** qual.this */
- case class This[T](qual: TypeName)(implicit val pos: Position)
+ case class This[T](qual: TypeName)(implicit cpos: Position)
extends SymTree[T] with TermTree[T] {
type ThisTree[T] = This[T]
+ val pos = cpos
}
/** C.super[mix], where qual = C.this */
- case class Super[T](qual: Tree[T], mix: TypeName)(implicit val pos: Position)
+ case class Super[T](qual: Tree[T], mix: TypeName)(implicit cpos: Position)
extends ProxyTree[T] with TermTree[T] {
type ThisTree[T] = Super[T]
+ val pos = cpos union qual.pos
def forwardTo = qual
}
@@ -164,82 +192,95 @@ object Trees {
}
/** fun(args) */
- case class Apply[T](fun: Tree[T], args: List[Tree[T]])(implicit val pos: Position)
+ case class Apply[T](fun: Tree[T], args: List[Tree[T]])(implicit cpos: Position)
extends GenericApply[T] {
type ThisTree[T] = Apply[T]
+ val pos = unionPos(cpos union fun.pos, args)
}
/** fun[args] */
- case class TypeApply[T](fun: Tree[T], args: List[Tree[T]])(implicit val pos: Position)
+ case class TypeApply[T](fun: Tree[T], args: List[Tree[T]])(implicit cpos: Position)
extends GenericApply[T] {
type ThisTree[T] = TypeApply[T]
+ val pos = unionPos(cpos union fun.pos, args)
}
/** const */
- case class Literal[T](const: Constant)(implicit val pos: Position)
+ case class Literal[T](const: Constant)(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = Literal[T]
+ val pos = cpos
}
/** new tpt, but no constructor call */
- case class New[T](tpt: Tree[T])(implicit val pos: Position)
+ case class New[T](tpt: Tree[T])(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = New[T]
+ val pos = cpos union tpt.pos
}
/** (left, right) */
- case class Pair[T](left: Tree[T], right: Tree[T])(implicit val pos: Position)
+ case class Pair[T](left: Tree[T], right: Tree[T])(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = Pair[T]
+ val pos = cpos union left.pos union right.pos
}
/** expr : tpt */
- case class Typed[T](expr: Tree[T], tpt: Tree[T])(implicit val pos: Position)
+ case class Typed[T](expr: Tree[T], tpt: Tree[T])(implicit cpos: Position)
extends ProxyTree[T] with TermTree[T] {
type ThisTree[T] = Typed[T]
+ val pos = cpos union expr.pos union tpt.pos
def forwardTo = expr
}
/** name = arg, in a parameter list */
- case class NamedArg[T](name: Name, arg: Tree[T])(implicit val pos: Position)
+ case class NamedArg[T](name: Name, arg: Tree[T])(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = NamedArg[T]
+ val pos = cpos union arg.pos
}
/** name = arg, outside a parameter list */
- case class Assign[T](lhs: Tree[T], rhs: Tree[T])(implicit val pos: Position)
+ case class Assign[T](lhs: Tree[T], rhs: Tree[T])(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = Assign[T]
+ val pos = cpos union lhs.pos union rhs.pos
}
/** (vparams) => body */
- case class Function[T](vparams: List[ValDef[T]], body: Tree[T])(implicit val pos: Position)
+ case class Function[T](vparams: List[ValDef[T]], body: Tree[T])(implicit cpos: Position)
extends SymTree[T] with TermTree[T] {
type ThisTree[T] = Function[T]
+ val pos = unionPos(cpos union body.pos, vparams)
}
/** { stats; expr } */
- case class Block[T](stats: List[Tree[T]], expr: Tree[T])(implicit val pos: Position)
+ case class Block[T](stats: List[Tree[T]], expr: Tree[T])(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = Block[T]
+ val pos = unionPos(cpos union expr.pos, stats)
}
/** if cond then thenp else elsep */
- case class If[T](cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit val pos: Position)
+ case class If[T](cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = If[T]
+ val pos = cpos union cond.pos union thenp.pos union elsep.pos
}
/** selector match { cases } */
- case class Match[T](selector: Tree[T], cases: List[CaseDef[T]])(implicit val pos: Position)
+ case class Match[T](selector: Tree[T], cases: List[CaseDef[T]])(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = Match[T]
+ val pos = unionPos(cpos union selector.pos, cases)
}
/** case pat if guard => body */
- case class CaseDef[T](pat: Tree[T], guard: Tree[T], body: Tree[T])(implicit val pos: Position)
+ case class CaseDef[T](pat: Tree[T], guard: Tree[T], body: Tree[T])(implicit cpos: Position)
extends Tree[T] {
type ThisTree[T] = CaseDef[T]
+ val pos = cpos union pat.pos union guard.pos union body.pos
}
/** return expr
@@ -247,107 +288,124 @@ object Trees {
* After program transformations this is not necessarily the enclosing method, because
* closures can intervene.
*/
- case class Return[T](expr: Tree[T], from: Ident[T])(implicit val pos: Position)
+ case class Return[T](expr: Tree[T], from: Ident[T])(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = Return[T]
+ val pos = cpos union expr.pos // from is synthetic, does not influence pos
}
/** try block catch { catches } */
- case class Try[T](block: Tree[T], catches: List[CaseDef[T]], finalizer: Tree[T])(implicit val pos: Position)
+ case class Try[T](block: Tree[T], catches: List[CaseDef[T]], finalizer: Tree[T])(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = Try[T]
+ val pos = unionPos(cpos union block.pos union finalizer.pos, catches)
}
/** throw expr */
- case class Throw[T](expr: Tree[T])(implicit val pos: Position)
+ case class Throw[T](expr: Tree[T])(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = Throw[T]
+ val pos = cpos union expr.pos
}
/** Array[elemtpt](elems) */
- case class ArrayValue[T](elemtpt: Tree[T], elems: List[Tree[T]])(implicit val pos: Position)
+ case class ArrayValue[T](elemtpt: Tree[T], elems: List[Tree[T]])(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = ArrayValue[T]
+ val pos = unionPos(cpos union elemtpt.pos, elems)
}
/** A type tree that represents an existing or inferred type */
- case class TypeTree[T](original: Tree[T] = EmptyTree[T])(implicit val pos: Position)
+ case class TypeTree[T](original: Tree[T] = EmptyTree[T])(implicit cpos: Position)
extends SymTree[T] with TypTree[T] {
type ThisTree[T] = TypeTree[T]
+ val pos = cpos union original.pos
}
/** ref.type */
- case class SingletonTypeTree[T](ref: Tree[T])(implicit val pos: Position)
+ case class SingletonTypeTree[T](ref: Tree[T])(implicit cpos: Position)
extends SymTree[T] with TypTree[T] {
type ThisTree[T] = SingletonTypeTree[T]
+ val pos = cpos union ref.pos
}
/** qualifier # name */
- case class SelectFromTypeTree[T](qualifier: Tree[T], name: TypeName)(implicit val pos: Position)
+ case class SelectFromTypeTree[T](qualifier: Tree[T], name: TypeName)(implicit cpos: Position)
extends RefTree[T] with TypTree[T] {
type ThisTree[T] = SelectFromTypeTree[T]
+ val pos = cpos union qualifier.pos
}
/** left & right */
- case class AndTypeTree[T](left: Tree[T], right: Tree[T])(implicit val pos: Position)
+ case class AndTypeTree[T](left: Tree[T], right: Tree[T])(implicit cpos: Position)
extends TypTree[T] {
type ThisTree[T] = AndTypeTree[T]
+ val pos = cpos union left.pos union right.pos
}
/** left | right */
- case class OrTypeTree[T](left: Tree[T], right: Tree[T])(implicit val pos: Position)
+ case class OrTypeTree[T](left: Tree[T], right: Tree[T])(implicit cpos: Position)
extends TypTree[T] {
type ThisTree[T] = OrTypeTree[T]
+ val pos = cpos union left.pos union right.pos
}
/** tpt { refinements } */
- case class RefineTypeTree[T](tpt: Tree[T], refinements: List[DefTree[T]])(implicit val pos: Position)
+ case class RefineTypeTree[T](tpt: Tree[T], refinements: List[DefTree[T]])(implicit cpos: Position)
extends ProxyTree[T] with TypTree[T] {
type ThisTree[T] = RefineTypeTree[T]
+ val pos = unionPos(cpos union tpt.pos, refinements)
def forwardTo = tpt
}
/** tpt[args] */
- case class AppliedTypeTree[T](tpt: Tree[T], args: List[Tree[T]])(implicit val pos: Position)
+ case class AppliedTypeTree[T](tpt: Tree[T], args: List[Tree[T]])(implicit cpos: Position)
extends ProxyTree[T] with TypTree[T] {
type ThisTree[T] = AppliedTypeTree[T]
+ val pos = unionPos(cpos union tpt.pos, args)
def forwardTo = tpt
}
/** >: lo <: hi */
- case class TypeBoundsTree[T](lo: Tree[T], hi: Tree[T])(implicit val pos: Position)
+ case class TypeBoundsTree[T](lo: Tree[T], hi: Tree[T])(implicit cpos: Position)
extends Tree[T] {
type ThisTree[T] = TypeBoundsTree[T]
+ val pos = cpos union lo.pos union hi.pos
}
/** name @ body */
- case class Bind[T](name: Name, body: Tree[T])(implicit val pos: Position)
+ case class Bind[T](name: Name, body: Tree[T])(implicit cpos: Position)
extends DefTree[T] {
type ThisTree[T] = Bind[T]
+ val pos = cpos union body.pos
}
/** tree_1 | ... | tree_n */
- case class Alternative[T](trees: List[Tree[T]])(implicit val pos: Position)
+ case class Alternative[T](trees: List[Tree[T]])(implicit cpos: Position)
extends Tree[T] {
type ThisTree[T] = Alternative[T]
+ val pos = unionPos(cpos, trees)
}
/** fun(args) in a pattern, if fun is an extractor */
- case class UnApply[T](fun: Tree[T], args: List[Tree[T]])(implicit val pos: Position)
+ case class UnApply[T](fun: Tree[T], args: List[Tree[T]])(implicit cpos: Position)
extends Tree[T] {
type ThisTree[T] = UnApply[T]
+ val pos = unionPos(cpos union fun.pos, args)
}
/** mods val name: tpt = rhs */
- case class ValDef[T](mods: Modifiers[T], name: Name, tpt: Tree[T], rhs: Tree[T])(implicit val pos: Position)
+ case class ValDef[T](mods: Modifiers[T], name: Name, tpt: Tree[T], rhs: Tree[T])(implicit cpos: Position)
extends DefTree[T] {
type ThisTree[T] = ValDef[T]
+ val pos = cpos union tpt.pos union rhs.pos
}
/** mods def name[tparams](vparams_1)...(vparams_n): tpt = rhs */
- case class DefDef[T](mods: Modifiers[T], name: Name, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], tpt: Tree[T], rhs: Tree[T])(implicit val pos: Position)
+ case class DefDef[T](mods: Modifiers[T], name: Name, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], tpt: Tree[T], rhs: Tree[T])(implicit cpos: Position)
extends DefTree[T] {
type ThisTree[T] = DefDef[T]
+ val pos = (unionPos(cpos union tpt.pos union rhs.pos, tparams) /: vparamss)(unionPos)
}
class ImplicitDefDef[T](mods: Modifiers[T], name: Name, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], tpt: Tree[T], rhs: Tree[T])
@@ -358,43 +416,49 @@ object Trees {
/** mods type name = rhs or
* mods type name >: lo <: hi, if rhs = TypeBoundsTree(lo, hi) */
- case class TypeDef[T](mods: Modifiers[T], name: Name, rhs: Tree[T])(implicit val pos: Position)
+ case class TypeDef[T](mods: Modifiers[T], name: Name, rhs: Tree[T])(implicit cpos: Position)
extends DefTree[T] {
type ThisTree[T] = TypeDef[T]
+ val pos = cpos union rhs.pos
}
/** extends parents { self => body } */
- case class Template[T](parents: List[Tree[T]], self: ValDef[T], body: List[Tree[T]])(implicit val pos: Position)
+ case class Template[T](parents: List[Tree[T]], self: ValDef[T], body: List[Tree[T]])(implicit cpos: Position)
extends SymTree[T] {
type ThisTree[T] = Template[T]
+ val pos = unionPos(unionPos(cpos union self.pos, parents), body)
}
/** mods class name[tparams] impl */
- case class ClassDef[T](mods: Modifiers[T], name: TypeName, tparams: List[TypeDef[T]], impl: Template[T])(implicit val pos: Position)
+ case class ClassDef[T](mods: Modifiers[T], name: TypeName, tparams: List[TypeDef[T]], impl: Template[T])(implicit cpos: Position)
extends DefTree[T] {
type ThisTree[T] = ClassDef[T]
+ val pos = unionPos(cpos union impl.pos, tparams)
}
/** import expr.selectors
* where a selector is either an untyped `Ident`, `name` or
* an untyped `Pair` `name => rename`
*/
- case class Import[T](expr: Tree[T], selectors: List[UntypedTree])(implicit val pos: Position)
+ case class Import[T](expr: Tree[T], selectors: List[UntypedTree])(implicit cpos: Position)
extends SymTree[T] {
type ThisTree[T] = Import[T]
+ val pos = unionPos(cpos union expr.pos, selectors)
}
/** package pid { stats } */
- case class PackageDef[T](pid: RefTree[T], stats: List[Tree[T]])(implicit val pos: Position)
+ case class PackageDef[T](pid: RefTree[T], stats: List[Tree[T]])(implicit cpos: Position)
extends DefTree[T] {
type ThisTree[T] = PackageDef[T]
+ val pos = unionPos(cpos union pid.pos, stats)
override def name = pid.name
}
/** arg @annot */
- case class Annotated[T](annot: Tree[T], arg: Tree[T])(implicit val pos: Position)
+ case class Annotated[T](annot: Tree[T], arg: Tree[T])(implicit cpos: Position)
extends ProxyTree[T] {
type ThisTree[T] = Annotated[T]
+ val pos = cpos union annot.pos union arg.pos
def forwardTo = arg
}
@@ -426,20 +490,34 @@ object Trees {
def apply[T]: EmptyValDef[T] = theEmptyValDef.asInstanceOf
}
-// ----- Tree cases that exist in untyped form only ------------------
+ /** A tree that can be shared without its position polluting containing trees */
+ case class Shared[T](tree: Tree[T]) extends Tree[T] {
+ type ThisTree[T] = Shared[T]
+ val pos = NoPosition
+ }
+
+ // ----- Tree cases that exist in untyped form only ------------------
/** A typed subtree of an untyped tree needs to be wrapped in a TypedSlice */
- case class TypedSplice(tree: TypedTree) extends UntypedTree {
- def pos = tree.pos
+ class TypedSplice(tree: TypedTree) extends UntypedTree {
+ val pos = tree.pos
}
/** mods object name impl */
- case class ModuleDef(mods: Modifiers[Nothing], name: TermName, impl: Template[Nothing])(implicit val pos: Position)
+ case class ModuleDef(mods: Modifiers[Nothing], name: TermName, impl: Template[Nothing])(implicit cpos: Position)
extends DefTree[Nothing] {
+ val pos = cpos union impl.pos
}
abstract class TreeAccumulator[T, U] extends ((T, Tree[U]) => T) {
def apply(x: T, tree: Tree[U]): T
def foldOver(x: T, tree: Tree[U]): T = ???
}
+
+// ----- Helper functions ---------------------------------------------
+
+ @tailrec final def unionPos(base: Position, trees: List[Tree[_]]): Position = trees match {
+ case t :: ts => unionPos(base union t.pos, ts)
+ case nil => base
+ }
} \ No newline at end of file