aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/Trees.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-02-16 14:23:05 +0100
committerMartin Odersky <odersky@gmail.com>2013-02-16 14:23:05 +0100
commit6bd453e8f3b50e7c48b6969bd4aaf6638b0455f8 (patch)
tree024c591cf5f22c65218e0f33d053f7806b781f53 /src/dotty/tools/dotc/core/Trees.scala
parentcf425f04b9342d15f25380e2227c6b142bd26f16 (diff)
downloaddotty-6bd453e8f3b50e7c48b6969bd4aaf6638b0455f8.tar.gz
dotty-6bd453e8f3b50e7c48b6969bd4aaf6638b0455f8.tar.bz2
dotty-6bd453e8f3b50e7c48b6969bd4aaf6638b0455f8.zip
Fleshed out tree handling
Diffstat (limited to 'src/dotty/tools/dotc/core/Trees.scala')
-rw-r--r--src/dotty/tools/dotc/core/Trees.scala381
1 files changed, 352 insertions, 29 deletions
diff --git a/src/dotty/tools/dotc/core/Trees.scala b/src/dotty/tools/dotc/core/Trees.scala
index 3a0c4efad..ccc20ab97 100644
--- a/src/dotty/tools/dotc/core/Trees.scala
+++ b/src/dotty/tools/dotc/core/Trees.scala
@@ -1,11 +1,14 @@
package dotty.tools.dotc.core
import Types._, Names._, Flags._, Positions._, Contexts._, Constants._, SymDenotations._, Symbols._
+import Denotations._
object Trees {
- abstract class Modifiers {
+ abstract class Modifiers[T] {
val flags: FlagSet
+ val privateWithin: Name
+ val annotations: List[Tree[T]]
}
/** Trees take a parameter indicating what the type of their `tpe` field
@@ -27,74 +30,394 @@ object Trees {
* - Type checking an untyped tree will remove all embedded `TypedSplice`
* nodes.
*/
- abstract class Tree[T] {
+ abstract class Tree[T] extends DotClass {
def pos: Position
- private var _tpe: T = _
+ type ThisTree[T] <: Tree[T]
+
+ protected var _tpe: T = _
def tpe: T = {
if (_tpe == null) throw new UnAssignedTypeException(this)
_tpe
}
- def withType(tpe: Type): Tree[Type] = {
+ def withType(tpe: Type): ThisTree[Type] = {
val tree =
(if (_tpe == null ||
(_tpe.asInstanceOf[AnyRef] eq tpe.asInstanceOf[AnyRef])) this
- else clone).asInstanceOf[Tree[Type]]
+ else clone).asInstanceOf[TypedTree]
tree._tpe = tpe
- tree
+ tree.asInstanceOf[ThisTree[Type]]
}
+ def denot(implicit ctx: Context): Denotation = NoDenotation
+ def symbol(implicit ctx: Context): Symbol = NoSymbol
+
+ def isType: Boolean = false
+ def isTerm: Boolean = false
+ def isDef: Boolean = false
+
def withPosition(pos: Position) = ???
}
- case class Ident[T] (name: Name)(implicit val pos: Position) extends Tree[T]
+ class UnAssignedTypeException[T](tree: Tree[T]) extends RuntimeException {
+ override def getMessage: String = s"type of $tree is not assigned"
+ }
- case class Select[T](qualifier: Tree[T], name: Name)(implicit val pos: Position) extends Tree[T]
+ type TypedTree = Tree[Type]
+ type UntypedTree = Tree[Nothing]
- case class Apply[T](fun: Tree[T], args: List[Tree[T]])(implicit val pos: Position) extends Tree[T]
+// ------ Categories of trees -----------------------------------
- case class Pair[T](left: Tree[T], right: Tree[T])(implicit val pos: Position) extends Tree[T]
+ /** Tree is definitely a type. 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
+ }
- case class ValDef[T](mods: Modifiers, name: Name, rtpe: Tree[T], rhs: Tree[T])(implicit val pos: Position) extends Tree[T]
+ /** Tree is definitely a term. Note that some trees
+ * have isType = true without being TypTrees (e.g. Ident, AnnotatedTree)
+ */
+ trait TermTree[T] extends Tree[T] {
+ type ThisTree[T] <: TermTree[T]
+ override def isTerm = true
+ }
- case class TypeDef[T](mods: Modifiers, name: Name, rhs: Tree[T])(implicit val pos: Position) extends Tree[T]
+ /** Tree's symbol can be derived from its type */
+ abstract class SymTree[T] extends Tree[T] {
+ type ThisTree[T] <: SymTree[T]
+ override def denot(implicit ctx: Context) = tpe match {
+ case tpe: NamedType => tpe.denot
+ case _ => NoDenotation
+ }
+ override def symbol(implicit ctx: Context): Symbol = tpe match {
+ case tpe: Type => if (isType) tpe.typeSymbol else tpe.termSymbol
+ case _ => NoSymbol
+ }
+ }
- case class DefDef[T](mods: Modifiers, name: Name, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], rtpe: Tree[T], rhs: Tree[T])(implicit val pos: Position) extends Tree[T]
+ /** Tree's symbol/isType/isTerm properties come from a subtree identifier
+ * by `forwardTo`.
+ */
+ abstract class ProxyTree[T] extends Tree[T] {
+ type ThisTree[T] <: ProxyTree[T]
+ def forwardTo: Tree[T]
+ override def denot(implicit ctx: Context): Denotation = forwardTo.denot
+ override def symbol(implicit ctx: Context): Symbol = forwardTo.symbol
+ override def isTerm = forwardTo.isTerm
+ override def isType = forwardTo.isType
+ }
- case class TypeTree[T](original: Tree[T] = EmptyTree[T])(implicit val pos: Position) extends Tree[T]
+ /** Tree has a name */
+ abstract class NameTree[T] extends SymTree[T] {
+ type ThisTree[T] <: NameTree[T]
+ def name: Name
+ }
- case class EmptyTree[T]() extends Tree[T] {
- val pos = NoPosition
+ /** Tree refers by name to a denotation */
+ abstract class RefTree[T] extends NameTree[T] {
+ type ThisTree[T] <: RefTree[T]
+ def qualifier: Tree[T]
+ override def isType = name.isTypeName
+ override def isTerm = name.isTermName
+ }
+
+ abstract class DefTree[T] extends NameTree[T] {
+ type ThisTree[T] <: DefTree[T]
+ override def isDef = true
+ }
+
+// ----------- Tree case classes ------------------------------------
+
+ /** name */
+ case class Ident[T] (name: Name)(implicit val pos: Position)
+ extends RefTree[T] {
+ type ThisTree[T] = Ident[T]
+ def qualifier: Tree[T] = EmptyTree[T]
+ }
+
+ /** qualifier.name */
+ case class Select[T](qualifier: Tree[T], name: Name)(implicit val pos: Position)
+ extends RefTree[T] {
+ type ThisTree[T] = Select[T]
+ }
+
+ /** qual.this */
+ case class This[T](qual: TypeName)(implicit val pos: Position)
+ extends SymTree[T] with TermTree[T] {
+ type ThisTree[T] = This[T]
+ }
+
+ /** C.super[mix], where qual = C.this */
+ case class Super[T](qual: Tree[T], mix: TypeName)(implicit val pos: Position)
+ extends ProxyTree[T] with TermTree[T] {
+ type ThisTree[T] = Super[T]
+ def forwardTo = qual
+ }
+
+ abstract class GenericApply[T] extends ProxyTree[T] with TermTree[T] {
+ type ThisTree[T] <: GenericApply[T]
+ val fun: Tree[T]
+ val args: List[Tree[T]]
+ def forwardTo = fun
+ }
+
+ /** fun(args) */
+ case class Apply[T](fun: Tree[T], args: List[Tree[T]])(implicit val pos: Position)
+ extends GenericApply[T] {
+ type ThisTree[T] = Apply[T]
+ }
+
+ /** fun[args] */
+ case class TypeApply[T](fun: Tree[T], args: List[Tree[T]])(implicit val pos: Position)
+ extends GenericApply[T] {
+ type ThisTree[T] = TypeApply[T]
+ }
+
+ /** const */
+ case class Literal[T](const: Constant)(implicit val pos: Position)
+ extends TermTree[T] {
+ type ThisTree[T] = Literal[T]
+ }
+
+ /** new tpt, but no constructor call */
+ case class New[T](tpt: Tree[T])(implicit val pos: Position)
+ extends TermTree[T] {
+ type ThisTree[T] = New[T]
+ }
+
+ /** (left, right) */
+ case class Pair[T](left: Tree[T], right: Tree[T])(implicit val pos: Position)
+ extends TermTree[T] {
+ type ThisTree[T] = Pair[T]
+ }
+
+ /** expr : tpt */
+ case class Typed[T](expr: Tree[T], tpt: Tree[T])(implicit val pos: Position)
+ extends ProxyTree[T] with TermTree[T] {
+ type ThisTree[T] = Typed[T]
+ def forwardTo = expr
+ }
+
+ /** name = arg, in a parameter list */
+ case class NamedArg[T](name: Name, arg: Tree[T])(implicit val pos: Position)
+ extends TermTree[T] {
+ type ThisTree[T] = NamedArg[T]
+ }
+
+ /** name = arg, outside a parameter list */
+ case class Assign[T](name: Name, arg: Tree[T])(implicit val pos: Position)
+ extends TermTree[T] {
+ type ThisTree[T] = Assign[T]
+ }
+
+ /** (vparams) => body */
+ case class Function[T](vparams: List[ValDef[T]], body: Tree[T])(implicit val pos: Position)
+ extends SymTree[T] with TermTree[T] {
+ type ThisTree[T] = Function[T]
+ }
+
+ /** { stats; expr } */
+ case class Block[T](stats: List[Tree[T]], expr: Tree[T])(implicit val pos: Position)
+ extends TermTree[T] {
+ type ThisTree[T] = Block[T]
+ }
+
+ /** if cond then thenp else elsep */
+ case class If[T](cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit val pos: Position)
+ extends TermTree[T] {
+ type ThisTree[T] = If[T]
+ }
+
+ /** selector match { cases } */
+ case class Match[T](selector: Tree[T], cases: List[CaseDef[T]])(implicit val pos: Position)
+ extends TermTree[T] {
+ type ThisTree[T] = Match[T]
+ }
+
+ /** return expr
+ * where `from` refers to the method from which the return takes place
+ * 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)
+ extends TermTree[T] {
+ type ThisTree[T] = Return[T]
+ }
+
+ /** try block catch { catches } */
+ case class Try[T](block: Tree[T], catches: List[CaseDef[T]], finalizer: Tree[T])(implicit val pos: Position)
+ extends TermTree[T] {
+ type ThisTree[T] = Try[T]
+ }
+
+ /** throw expr */
+ case class Throw[T](expr: Tree[T])(implicit val pos: Position)
+ extends TermTree[T] {
+ type ThisTree[T] = Throw[T]
+ }
+
+ /** Array[elemtpt](elems) */
+ case class ArrayValue[T](elemtpt: Tree[T], elems: List[Tree[T]])(implicit val pos: Position)
+ extends TermTree[T] {
+ type ThisTree[T] = ArrayValue[T]
+ }
+
+ /** A type tree that represents an existing or inferred type */
+ case class TypeTree[T](original: Tree[T] = EmptyTree[T])(implicit val pos: Position)
+ extends SymTree[T] with TypTree[T] {
+ type ThisTree[T] = TypeTree[T]
+ }
+
+ /** ref.type */
+ case class SingletonTypeTree[T](ref: Tree[T])(implicit val pos: Position)
+ extends SymTree[T] with TypTree[T] {
+ type ThisTree[T] = SingletonTypeTree[T]
+ }
+
+ /** qualifier # name */
+ case class SelectFromTypeTree[T](qualifier: Tree[T], name: TypeName)(implicit val pos: Position)
+ extends RefTree[T] with TypTree[T] {
+ type ThisTree[T] = SelectFromTypeTree[T]
+ }
+
+ /** left & right */
+ case class AndTypeTree[T](left: Tree[T], right: Tree[T])(implicit val pos: Position)
+ extends TypTree[T] {
+ type ThisTree[T] = AndTypeTree[T]
+ }
+
+ /** left | right */
+ case class OrTypeTree[T](left: Tree[T], right: Tree[T])(implicit val pos: Position)
+ extends TypTree[T] {
+ type ThisTree[T] = OrTypeTree[T]
+ }
+
+ /** tpt { refinements } */
+ case class RefineTypeTree[T](tpt: Tree[T], refinements: List[DefTree[T]])(implicit val pos: Position)
+ extends ProxyTree[T] with TypTree[T] {
+ type ThisTree[T] = RefineTypeTree[T]
+ def forwardTo = tpt
+ }
+
+ /** tpt[args] */
+ case class AppliedTypeTree[T](tpt: Tree[T], args: List[Tree[T]])(implicit val pos: Position)
+ extends ProxyTree[T] with TypTree[T] {
+ type ThisTree[T] = AppliedTypeTree[T]
+ def forwardTo = tpt
+ }
+
+ /** >: lo <: hi */
+ case class TypeBoundsTree[T](lo: Tree[T], hi: Tree[T])(implicit val pos: Position)
+ extends Tree[T] {
+ type ThisTree[T] = TypeBoundsTree[T]
+ }
+
+ /** name @ body */
+ case class Bind[T](name: Name, body: Tree[T])(implicit val pos: Position)
+ extends DefTree[T] {
+ type ThisTree[T] = Bind[T]
}
- case class Literal[T](const: Constant)(implicit val pos: Position) extends Tree[T]
+ /** case pat if guard => body */
+ case class CaseDef[T](pat: Tree[T], guard: Tree[T], body: Tree[T])(implicit val pos: Position)
+ extends Tree[T] {
+ type ThisTree[T] = CaseDef[T]
+ }
- case class New[T](tpt: Tree[T])(implicit val pos: Position) extends Tree[T]
+ /** tree_1 | ... | tree_n */
+ case class Alternative[T](trees: List[Tree[T]])(implicit val pos: Position)
+ extends Tree[T] {
+ type ThisTree[T] = Alternative[T]
+ }
- case class ArrayValue[T](elemtpt: Tree[T], elems: List[Tree[T]])(implicit val pos: Position) extends Tree[T]
+ /** 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)
+ extends Tree[T] {
+ type ThisTree[T] = UnApply[T]
+ }
- case class NamedArg[T](name: Name, arg: Tree[T])(implicit val pos: Position) extends Tree[T]
+ /** mods val name: rtpe = rhs */
+ case class ValDef[T](mods: Modifiers[T], name: Name, rtpe: Tree[T], rhs: Tree[T])(implicit val pos: Position)
+ extends DefTree[T] {
+ type ThisTree[T] = ValDef[T]
+ }
+
+ /** mods def name[tparams](vparams_1)...(vparams_n): rtpe = rhs */
+ case class DefDef[T](mods: Modifiers[T], name: Name, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], rtpe: Tree[T], rhs: Tree[T])(implicit val pos: Position)
+ extends DefTree[T] {
+ type ThisTree[T] = DefDef[T]
+ }
- class ImplicitDefDef[T](mods: Modifiers, name: Name, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], rtpe: Tree[T], rhs: Tree[T])
+ class ImplicitDefDef[T](mods: Modifiers[T], name: Name, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], rtpe: Tree[T], rhs: Tree[T])
(implicit pos: Position) extends DefDef[T](mods, name, tparams, vparamss, rtpe, rhs) {
- override def copy[T](mods: Modifiers, name: Name, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], rtpe: Tree[T], rhs: Tree[T])(implicit pos: Position) =
+ override def copy[T](mods: Modifiers[T], name: Name, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], rtpe: Tree[T], rhs: Tree[T])(implicit pos: Position) =
new ImplicitDefDef[T](mods, name, tparams, vparamss, rtpe, rhs)
}
- case class TypedSplice(tree: Tree[Type]) extends Tree[Nothing] {
- def pos = tree.pos
+ /** 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)
+ extends DefTree[T] {
+ type ThisTree[T] = TypeDef[T]
}
- implicit def embedTyped(tree: Tree[Type]): Tree[Nothing] = TypedSplice(tree)
+ /** extends parents { self => body } */
+ case class Template[T](parents: List[Tree[T]], self: ValDef[T], body: List[Tree[T]])(implicit val pos: Position)
+ extends SymTree[T] {
+ type ThisTree[T] = Template[T]
+ }
- class UnAssignedTypeException[T](tree: Tree[T]) extends Exception {
- override def getMessage: String = s"type of $tree is not assigned"
+ /** 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)
+ extends DefTree[T] {
+ type ThisTree[T] = ClassDef[T]
}
- type TypedTree = Tree[Type]
- type UntypedTree = Tree[Nothing]
+ /** 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)
+ extends SymTree[T] {
+ type ThisTree[T] = Import[T]
+ }
+
+ /** package pid { stats } */
+ case class PackageDef[T](pid: RefTree[T], stats: List[Tree[T]])(implicit val pos: Position)
+ extends DefTree[T] {
+ type ThisTree[T] = PackageDef[T]
+ override def name = pid.name
+ }
+
+ /** arg @annot */
+ case class Annotated[T](annot: Tree[T], arg: Tree[T])(implicit val pos: Position)
+ extends ProxyTree[T] {
+ type ThisTree[T] = Annotated[T]
+ def forwardTo = arg
+ }
+
+ /** A missing tree */
+ case class EmptyTree[T]()
+ extends Tree[T] {
+ type ThisTree[T] = EmptyTree[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
+ }
+
+ /** mods object name impl */
+ case class ModuleDef(mods: Modifiers[Nothing], name: TermName, impl: Template[Nothing])(implicit val pos: Position)
+ extends DefTree[Nothing] {
+ }
// this will probably to its own file at some point.
class MakeTypedTree(implicit val ctx: Context) extends AnyVal {