aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/ast/UntypedTrees.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-05-24 16:41:52 +0200
committerMartin Odersky <odersky@gmail.com>2013-05-24 16:41:52 +0200
commit3b51d4bdcb9ca3c1f439cee7d1e09c960b3e0c6f (patch)
treea232d025080dc561c50a04873f8d641895154328 /src/dotty/tools/dotc/ast/UntypedTrees.scala
parent991860936cbbedf6087a2e13ef69a61b69b3fa86 (diff)
downloaddotty-3b51d4bdcb9ca3c1f439cee7d1e09c960b3e0c6f.tar.gz
dotty-3b51d4bdcb9ca3c1f439cee7d1e09c960b3e0c6f.tar.bz2
dotty-3b51d4bdcb9ca3c1f439cee7d1e09c960b3e0c6f.zip
Improvements to desugaring
(1) Reorganization of Typed/Untyped trees. Untyped trees now have their own copier, transformer and accumulators. (2) Better treatment of functions
Diffstat (limited to 'src/dotty/tools/dotc/ast/UntypedTrees.scala')
-rw-r--r--src/dotty/tools/dotc/ast/UntypedTrees.scala223
1 files changed, 191 insertions, 32 deletions
diff --git a/src/dotty/tools/dotc/ast/UntypedTrees.scala b/src/dotty/tools/dotc/ast/UntypedTrees.scala
index 82c99a781..ba67a0546 100644
--- a/src/dotty/tools/dotc/ast/UntypedTrees.scala
+++ b/src/dotty/tools/dotc/ast/UntypedTrees.scala
@@ -12,7 +12,7 @@ import collection.mutable.ListBuffer
object untpd extends Trees.Instance[Untyped] {
- // ----- Tree cases that exist in untyped form only ------------------
+// ----- 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: tpd.Tree) extends Tree
@@ -21,25 +21,17 @@ object untpd extends Trees.Instance[Untyped] {
case class ModuleDef(mods: Modifiers, name: TermName, impl: Template)
extends NameTree with ModDefTree {
type ThisTree[T >: Untyped] <: Trees.NameTree[T] with Trees.ModDefTree[T] with ModuleDef
- def derivedModuleDef(mods: Modifiers, name: TermName, impl: Template) =
- if ((mods eq this.mods) && (name eq this.name) && (impl eq this.impl)) this
- else ModuleDef(mods, name, impl).copyAttr(this)
- def withName(name: Name) = derivedModuleDef(mods, name.toTermName, impl)
+ def withName(name: Name) = this.derivedModuleDef(mods, name.toTermName, impl)
}
- /** (vparams) => body */
case class SymbolLit(str: String) extends Tree
case class InterpolatedString(id: TermName, strings: List[Literal], elems: List[Tree]) extends Tree
case class Function(args: List[Tree], body: Tree) extends Tree
case class InfixOp(left: Tree, op: Name, right: Tree) extends Tree
- case class PostfixOp(tree: Tree, op: Name) extends Tree
- case class PrefixOp(op: Name, tree: Tree) extends Tree
- case class Parens(tree: Tree) extends Tree {
- def derivedParens(tree: Tree) = if (this.tree eq tree) this else Parens(tree).copyAttr(this)
- }
- case class Tuple(trees: List[Tree]) extends Tree {
- def derivedTuple(trees: List[Tree]) = if (this.trees eq trees) this else Tuple(trees).copyAttr(this)
- }
+ case class PostfixOp(od: Tree, op: Name) extends Tree
+ case class PrefixOp(op: Name, od: Tree) extends Tree
+ case class Parens(t: Tree) extends Tree
+ case class Tuple(trees: List[Tree]) extends Tree
case class WhileDo(cond: Tree, body: Tree) extends TermTree
case class DoWhile(body: Tree, cond: Tree) extends TermTree
case class ForYield(enums: List[Tree], expr: Tree) extends TermTree
@@ -49,10 +41,12 @@ object untpd extends Trees.Instance[Untyped] {
case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree]) extends TypTree
case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree) extends Tree
- val unitLiteral = Literal(Constant())
+// ------ Untyped tree values and creation methods ---------------------
private type VarInfo = (NameTree, Tree)
+ val unitLiteral = Literal(Constant())
+
def ref(tp: NamedType)(implicit ctx: Context): Tree =
TypedSplice(tpd.ref(tp))
@@ -74,15 +68,13 @@ object untpd extends Trees.Instance[Untyped] {
case _ => Tuple(ts)
}
- /** new C(args) */
- def makeNew(tpt: Tree, args: List[Tree])(implicit ctx: Context): Apply =
- Apply(Select(Trees.New(tpt), nme.CONSTRUCTOR), args)
-
- def makeSyntheticParameter(pname: TermName)(implicit ctx: Context): ValDef =
- ValDef(Modifiers(SyntheticTermParam), pname, TypeTree(), EmptyTree())
+// ------ Untyped tree desugaring ------------------------------------------
def desugar(tree: Tree, mode: Mode.Value)(implicit ctx: Context): Tree = {
+ def makeSyntheticParameter(): ValDef =
+ ValDef(Modifiers(SyntheticTermParam), ctx.freshName().toTermName, TypeTree(), EmptyTree())
+
def labelDefAndCall(lname: TermName, rhs: Tree, call: Tree) = {
val ldef = DefDef(Modifiers(Label), lname, Nil, ListOfNil, TypeTree(), rhs)
Block(ldef, call)
@@ -113,6 +105,18 @@ object untpd extends Trees.Instance[Untyped] {
}
}
+ /** Make closure corresponding to function params => body */
+ def makeClosure(params: List[ValDef], body: Tree) =
+ Block(
+ DefDef(Modifiers(Synthetic), nme.ANON_FUN, Nil, params :: Nil, EmptyTree(), body),
+ Closure(Nil, Ident(nme.ANON_FUN)))
+
+ /** Make closure corresponding to partial function { cases } */
+ def makeCaseClosure(cases: List[CaseDef]) = {
+ val param = makeSyntheticParameter()
+ makeClosure(param :: Nil, Match(Ident(param.name), cases))
+ }
+
/** Create tree for for-comprehension <for (enums) do body> or
* <for (enums) yield body> where mapName and flatMapName are chosen
* corresponding to whether this is a for-do or a for-yield.
@@ -169,9 +173,9 @@ object untpd extends Trees.Instance[Untyped] {
*/
def makeLambda(pat: Tree, body: Tree): Tree = pat match {
case VarPattern(named, tpt) =>
- Function(derivedValDef(Modifiers(Param), named, tpt, EmptyTree()) :: Nil, body)
+ makeClosure(derivedValDef(Modifiers(Param), named, tpt, EmptyTree()) :: Nil, body)
case _ =>
- Match(EmptyTree(), CaseDef(pat, EmptyTree(), body) :: Nil)
+ makeCaseClosure(CaseDef(pat, EmptyTree(), body) :: Nil)
}
/** If `pat` is not yet a `Bind` wrap it in one with a fresh name
@@ -307,6 +311,8 @@ object untpd extends Trees.Instance[Untyped] {
Apply(Select(fn, nme.update), args :+ rhs)
case If(cond, thenp, EmptyTree()) =>
If(cond, thenp, unitLiteral)
+ case Match(EmptyTree(), cases) =>
+ makeCaseClosure(cases)
case _: DefDef | _: ClassDef =>
desugarContextBounds(tree)
case ModuleDef(mods, name, tmpl @ Template(constr, parents, self, body)) =>
@@ -314,13 +320,13 @@ object untpd extends Trees.Instance[Untyped] {
// <module> final class name$ extends parents { self: name.type => body }
val clsName = name.moduleClassName
val clsRef = Ident(clsName)
- val modul = ValDef(mods | ModuleCreationFlags, name, clsRef, clsRef)
+ val modul = ValDef(mods | ModuleCreationFlags, name, clsRef, New(clsRef, Nil))
val clsSelf = self.derivedValDef(self.mods, self.name, SingletonTypeTree(Ident(name)), self.rhs)
val clsTmpl = tmpl.derivedTemplate(constr, parents, clsSelf, body)
- val cls = ClassDef(mods & AccessFlags | ModuleClassCreationFlags, clsName, Nil, clsTmpl)
+ val cls = ClassDef(mods.toTypeFlags & AccessFlags | ModuleClassCreationFlags, clsName, Nil, clsTmpl)
TempTrees(List(modul, cls))
case SymbolLit(str) =>
- makeNew(ref(defn.SymbolClass.typeConstructor), Literal(Constant(str)) :: Nil)
+ New(ref(defn.SymbolClass.typeConstructor), (Literal(Constant(str)) :: Nil) :: Nil)
case InterpolatedString(id, strs, elems) =>
Apply(Select(Apply(Ident(nme.StringContext), strs), id), elems)
case Function(args, body) =>
@@ -328,12 +334,8 @@ object untpd extends Trees.Instance[Untyped] {
AppliedTypeTree(
ref(defn.FunctionClass(args.length).typeConstructor),
args :+ body)
- else { // { def $anonfun(args) = body; $anonfun }
- val params = args.asInstanceOf[List[ValDef]]
- Block(
- DefDef(Modifiers(Synthetic), nme.ANON_FUN, Nil, params :: Nil, EmptyTree(), body),
- Closure(Nil, Ident(nme.ANON_FUN)))
- }
+ else
+ makeClosure(args.asInstanceOf[List[ValDef]], body)
case InfixOp(l, op, r) =>
mode match {
case Mode.Expr => // l.op(r), or val x = r; l.op(x), plus handle named args specially
@@ -481,6 +483,8 @@ object untpd extends Trees.Instance[Untyped] {
}
}
+// ------- A decorator for producing a path to a location --------------
+
implicit class UntypedTreeDecorator(val self: Tree) extends AnyVal {
def locateEnclosing(base: List[Tree], pos: Position): List[Tree] = {
def encloses(elem: Any) = elem match {
@@ -493,4 +497,159 @@ object untpd extends Trees.Instance[Untyped] {
}
}
}
+
+// --------- Copier/Transformer/Accumulator classes for untyped trees -----
+
+ implicit class UntypedTreeCopier(val tree: Tree) extends AnyVal {
+ def derivedModuleDef(mods: Modifiers, name: TermName, impl: Template) = tree match {
+ case tree: ModuleDef if (mods eq tree.mods) && (name eq tree.name) && (impl eq tree.impl) =>tree
+ case _ => ModuleDef(mods, name, impl).copyAttr(tree)
+ }
+ def derivedSymbolLit(str: String) = tree match {
+ case tree: SymbolLit if (str == tree.str) => tree
+ case _ => SymbolLit(str).copyAttr(tree)
+ }
+ def derivedInterpolatedString(id: TermName, strings: List[Literal], elems: List[Tree]) = tree match {
+ case tree: InterpolatedString if (id eq tree.id) && (strings eq tree.strings) && (elems eq tree.elems) => tree
+ case _ => InterpolatedString(id, strings, elems).copyAttr(tree)
+ }
+ def derivedFunction(args: List[Tree], body: Tree) = tree match {
+ case tree: Function if (args eq tree.args) && (body eq tree.body) => tree
+ case _ => Function(args, body).copyAttr(tree)
+ }
+ def derivedInfixOp(left: Tree, op: Name, right: Tree) = tree match {
+ case tree: InfixOp if (left eq tree.left) && (op eq tree.op) && (right eq tree.right) => tree
+ case _ => InfixOp(left, op, right).copyAttr(tree)
+ }
+ def derivedPostfixOp(od: Tree, op: Name) = tree match {
+ case tree: PostfixOp if (od eq tree.od) && (op eq tree.op) => tree
+ case _ => PostfixOp(od, op).copyAttr(tree)
+ }
+ def derivedPrefixOp(op: Name, od: Tree) = tree match {
+ case tree: PrefixOp if (op eq tree.op) && (od eq tree.od) => tree
+ case _ => PrefixOp(op, od).copyAttr(tree)
+ }
+ def derivedParens(t: Tree) = tree match {
+ case tree: Parens if (t eq tree.t) => tree
+ case _ => Parens(t).copyAttr(tree)
+ }
+ def derivedTuple(trees: List[Tree]) = tree match {
+ case tree: Tuple if (trees eq tree.trees) => tree
+ case _ => Tuple(trees).copyAttr(tree)
+ }
+ def derivedWhileDo(cond: Tree, body: Tree) = tree match {
+ case tree: WhileDo if (cond eq tree.cond) && (body eq tree.body) => tree
+ case _ => WhileDo(cond, body).copyAttr(tree)
+ }
+ def derivedDoWhile(body: Tree, cond: Tree) = tree match {
+ case tree: DoWhile if (body eq tree.body) && (cond eq tree.cond) => tree
+ case _ => DoWhile(body, cond).copyAttr(tree)
+ }
+ def derivedForYield(enums: List[Tree], expr: Tree) = tree match {
+ case tree: ForYield if (enums eq tree.enums) && (expr eq tree.expr) => tree
+ case _ => ForYield(enums, expr).copyAttr(tree)
+ }
+ def derivedForDo(enums: List[Tree], body: Tree) = tree match {
+ case tree: ForDo if (enums eq tree.enums) && (body eq tree.body) => tree
+ case _ => ForDo(enums, body).copyAttr(tree)
+ }
+ def derivedGenFrom(pat: Tree, expr: Tree) = tree match {
+ case tree: GenFrom if (pat eq tree.pat) && (expr eq tree.expr) => tree
+ case _ => GenFrom(pat, expr).copyAttr(tree)
+ }
+ def derivedGenAlias(pat: Tree, expr: Tree) = tree match {
+ case tree: GenAlias if (pat eq tree.pat) && (expr eq tree.expr) => tree
+ case _ => GenAlias(pat, expr).copyAttr(tree)
+ }
+ def derivedContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree]) = tree match {
+ case tree: ContextBounds if (bounds eq tree.bounds) && (cxBounds eq tree.cxBounds) => tree
+ case _ => ContextBounds(bounds, cxBounds).copyAttr(tree)
+ }
+ def derivedPatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree) = tree match {
+ case tree: PatDef if (mods eq tree.mods) && (pats eq tree.pats) && (tpt eq tree.tpt) && (rhs eq tree.rhs) => tree
+ case _ => PatDef(mods, pats, tpt, rhs).copyAttr(tree)
+ }
+ }
+
+ abstract class TreeTransformer extends Trees.TreeTransformer[Untyped] {
+ override def transform(tree: Tree): Tree = tree match {
+ case ModuleDef(mods, name, impl) =>
+ tree.derivedModuleDef(mods, name, transformSub(impl))
+ case SymbolLit(str) =>
+ tree.derivedSymbolLit(str)
+ case InterpolatedString(id, strings, elems) =>
+ tree.derivedInterpolatedString(id, transformSub(strings), transform(elems))
+ case Function(args, body) =>
+ tree.derivedFunction(transform(args), transform(body))
+ case InfixOp(left, op, right) =>
+ tree.derivedInfixOp(transform(left), op, transform(right))
+ case PostfixOp(od, op) =>
+ tree.derivedPostfixOp(transform(od), op)
+ case PrefixOp(op, od) =>
+ tree.derivedPrefixOp(op, transform(od))
+ case Parens(t) =>
+ tree.derivedParens(transform(t))
+ case Tuple(trees) =>
+ tree.derivedTuple(transform(trees))
+ case WhileDo(cond, body) =>
+ tree.derivedWhileDo(transform(cond), transform(body))
+ case DoWhile(body, cond) =>
+ tree.derivedDoWhile(transform(body), transform(cond))
+ case ForYield(enums, expr) =>
+ tree.derivedForYield(transform(enums), transform(expr))
+ case ForDo(enums, body) =>
+ tree.derivedForDo(transform(enums), transform(body))
+ case GenFrom(pat, expr) =>
+ tree.derivedGenFrom(transform(pat), transform(expr))
+ case GenAlias(pat, expr) =>
+ tree.derivedGenAlias(transform(pat), transform(expr))
+ case ContextBounds(bounds, cxBounds) =>
+ tree.derivedContextBounds(transformSub(bounds), transform(cxBounds))
+ case PatDef(mods, pats, tpt, rhs) =>
+ tree.derivedPatDef(mods, transform(pats), transform(tpt), transform(rhs))
+ case _ =>
+ super.transform(tree)
+ }
+ }
+
+ abstract class TreeAccumulator[X] extends Trees.TreeAccumulator[X, Untyped] {
+ override def foldOver(x: X, tree: Tree): X = tree match {
+ case ModuleDef(mods, name, impl) =>
+ this(x, impl)
+ case SymbolLit(str) =>
+ x
+ case InterpolatedString(id, strings, elems) =>
+ this(this(x, strings), elems)
+ case Function(args, body) =>
+ this(this(x, args), body)
+ case InfixOp(left, op, right) =>
+ this(this(x, left), right)
+ case PostfixOp(od, op) =>
+ this(x, od)
+ case PrefixOp(op, od) =>
+ this(x, od)
+ case Parens(t) =>
+ this(x, t)
+ case Tuple(trees) =>
+ this(x, trees)
+ case WhileDo(cond, body) =>
+ this(this(x, cond), body)
+ case DoWhile(body, cond) =>
+ this(this(x, body), cond)
+ case ForYield(enums, expr) =>
+ this(this(x, enums), expr)
+ case ForDo(enums, body) =>
+ this(this(x, enums), body)
+ case GenFrom(pat, expr) =>
+ this(this(x, pat), expr)
+ case GenAlias(pat, expr) =>
+ this(this(x, pat), expr)
+ case ContextBounds(bounds, cxBounds) =>
+ this(this(x, bounds), cxBounds)
+ case PatDef(mods, pats, tpt, rhs) =>
+ this(this(this(x, pats), tpt), rhs)
+ case _ =>
+ super.foldOver(x, tree)
+ }
+ }
}