diff options
author | Martin Odersky <odersky@gmail.com> | 2013-02-16 14:23:05 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2013-02-16 14:23:05 +0100 |
commit | 6bd453e8f3b50e7c48b6969bd4aaf6638b0455f8 (patch) | |
tree | 024c591cf5f22c65218e0f33d053f7806b781f53 | |
parent | cf425f04b9342d15f25380e2227c6b142bd26f16 (diff) | |
download | dotty-6bd453e8f3b50e7c48b6969bd4aaf6638b0455f8.tar.gz dotty-6bd453e8f3b50e7c48b6969bd4aaf6638b0455f8.tar.bz2 dotty-6bd453e8f3b50e7c48b6969bd4aaf6638b0455f8.zip |
Fleshed out tree handling
-rw-r--r-- | src/dotty/tools/dotc/core/Contexts.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Trees.scala | 381 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypedTreeGen.scala | 43 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/UnPickler.scala | 2 |
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 = { |