diff options
Diffstat (limited to 'src/dotty/tools/dotc/core/Trees.scala')
-rw-r--r-- | src/dotty/tools/dotc/core/Trees.scala | 176 |
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 |