aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core
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
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')
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala6
-rw-r--r--src/dotty/tools/dotc/core/Trees.scala381
-rw-r--r--src/dotty/tools/dotc/core/TypedTreeGen.scala43
-rw-r--r--src/dotty/tools/dotc/core/pickling/UnPickler.scala2
4 files changed, 401 insertions, 31 deletions
diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala
index b07319f06..9ca111dc0 100644
--- a/src/dotty/tools/dotc/core/Contexts.scala
+++ b/src/dotty/tools/dotc/core/Contexts.scala
@@ -7,7 +7,7 @@ import Names._
import Phases._
import Types._
import Symbols._
-import TypeComparers._, Printers._, NameOps._, SymDenotations._
+import TypeComparers._, Printers._, NameOps._, SymDenotations._, Positions._
import config.Settings._
import config.ScalaSettings
import collection.mutable
@@ -67,6 +67,10 @@ object Contexts {
_typeComparer
}
+ private[this] var _position: Position = _
+ protected def position_=(position: Position) = _position = position
+ def position: Position = _position
+
private[this] var _plainPrinter: Context => Printer = _
protected def plainPrinter_=(plainPrinter: Context => Printer) = _plainPrinter = plainPrinter
def plainPrinter: Context => Printer = _plainPrinter
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 {
diff --git a/src/dotty/tools/dotc/core/TypedTreeGen.scala b/src/dotty/tools/dotc/core/TypedTreeGen.scala
new file mode 100644
index 000000000..0b47c4489
--- /dev/null
+++ b/src/dotty/tools/dotc/core/TypedTreeGen.scala
@@ -0,0 +1,43 @@
+package dotty.tools.dotc
+package core
+
+import Trees._, Positions._, Types._, Contexts._, Constants._, Names._
+import SymDenotations._, Symbols._
+
+object TypedTrees {
+
+ class TypeTreeGen {
+ implicit def pos(implicit ctx: Context): Position = ctx.position
+ def Ident(tp: NamedType)(implicit ctx: Context): Ident[Type] =
+ Trees.Ident(tp.name).withType(tp)
+ def Select(pre: TypedTree, tp: NamedType)(implicit ctx: Context): Select[Type] =
+ Trees.Select(pre, tp.name).withType(tp)
+ def Apply(fn: TypedTree, args: List[TypedTree])(implicit ctx: Context): Apply[Type] = {
+ val fntpe @ MethodType(pnames, ptypes) = fn.tpe
+ assert(sameLength(ptypes, args))
+ Trees.Apply(fn, args).withType(fntpe.instantiate(args map (_.tpe)))
+ }
+ def TypeTree(tp: Type)(implicit ctx: Context):TypeTree[Type] =
+ Trees.TypeTree().withType(tp)
+ def New(tp: Type)(implicit ctx: Context): New[Type] =
+ Trees.New(TypeTree(tp))
+ def Literal(const: Constant)(implicit ctx: Context): Literal[Type] =
+ Trees.Literal(const).withType(const.tpe)
+ def ArrayValue(elemtpt: TypedTree, elems: List[TypedTree])(implicit ctx: Context) =
+ Trees.ArrayValue(elemtpt, elems).withType(defn.ArrayType.appliedTo(elemtpt.tpe))
+ def NamedArg[T](name: Name, arg: TypedTree)(implicit ctx: Context) =
+ Trees.NamedArg(name, arg).withType(arg.tpe)
+
+ // ----------------------------------------------------------
+
+ def New(tp: Type, args: List[TypedTree])(implicit ctx: Context): Apply[Type] =
+ Apply(
+ Select(
+ New(tp),
+ TermRef(tp.normalizedPrefix, tp.typeSymbol.primaryConstructor.asTerm)),
+ args)
+ }
+
+ object tpd extends TypeTreeGen
+}
+
diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
index 9822ac222..ee60f89ad 100644
--- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
@@ -272,7 +272,7 @@ class UnPickler(bytes: Array[Byte], classRoot: LazyClassDenotation, moduleRoot:
protected def readTypeName(): TypeName = readName().toTypeName
/** Read a symbol */
- protected def readSymbol(): Symbol = readDisambiguatedSymbol(Function.const(true))()
+ protected def readSymbol(): Symbol = readDisambiguatedSymbol(scala.Function.const(true))()
/** Read a symbol, with possible disambiguation */
protected def readDisambiguatedSymbol(p: Symbol => Boolean)(): Symbol = {