aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-05-23 14:33:25 +0200
committerMartin Odersky <odersky@gmail.com>2013-05-23 14:33:25 +0200
commite1be722f469c45e7546388359b5870a07f4c14b8 (patch)
tree53720d33f176dcb18cb4443867cd378bcdb62ef1 /src
parentdb39f1a5f5062f00e09e20a897e8f6d26e1e4193 (diff)
downloaddotty-e1be722f469c45e7546388359b5870a07f4c14b8.tar.gz
dotty-e1be722f469c45e7546388359b5870a07f4c14b8.tar.bz2
dotty-e1be722f469c45e7546388359b5870a07f4c14b8.zip
More tweaks to desugaring
(1) Made desugaring reaching a fixed point. (2) Systematic encoding of names. (3) Introduced Closure nodes which represent anonymous functions
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/ast/Trees.scala36
-rw-r--r--src/dotty/tools/dotc/ast/TypedTrees.scala48
-rw-r--r--src/dotty/tools/dotc/ast/UntypedTrees.scala52
-rw-r--r--src/dotty/tools/dotc/core/pickling/UnPickler.scala2
4 files changed, 92 insertions, 46 deletions
diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala
index 5e3509441..153e14495 100644
--- a/src/dotty/tools/dotc/ast/Trees.scala
+++ b/src/dotty/tools/dotc/ast/Trees.scala
@@ -46,7 +46,7 @@ object Trees {
* destructively and the item itself is returned.
*/
def withPos(pos: Position): this.type = {
- val newpd = (if (pos != curPos && curPos.isSynthetic) this else clone).asInstanceOf[Positioned]
+ val newpd = (if (pos == curPos || curPos.isSynthetic) this else clone).asInstanceOf[Positioned]
newpd.curPos = pos
newpd.asInstanceOf[this.type]
}
@@ -272,6 +272,7 @@ object Trees {
abstract class NameTree[T >: Untyped] extends DenotingTree[T] {
type ThisTree[T >: Untyped] <: NameTree[T]
def name: Name
+ def withName(name1: Name): NameTree[T]
}
/** Tree refers by name to a denotation */
@@ -305,6 +306,7 @@ object Trees {
case class Ident[T >: Untyped](name: Name)
extends RefTree[T] {
type ThisTree[T >: Untyped] = Ident[T]
+ def withName(name: Name) = this.derivedIdent(name)
def qualifier: Tree[T] = EmptyTree[T]
}
@@ -315,6 +317,7 @@ object Trees {
case class Select[T >: Untyped](qualifier: Tree[T], name: Name)
extends RefTree[T] {
type ThisTree[T >: Untyped] = Select[T]
+ def withName(name: Name) = this.derivedSelect(qualifier, name)
}
/** qual.this */
@@ -406,6 +409,12 @@ object Trees {
type ThisTree[T >: Untyped] = If[T]
}
+ /** A closure with an environment and a reference to a method */
+ case class Closure[T >: Untyped](env: List[Tree[T]], meth: RefTree[T])
+ extends TermTree[T] {
+ type ThisTree[T >: Untyped] = Closure[T]
+ }
+
/** selector match { cases } */
case class Match[T >: Untyped](selector: Tree[T], cases: List[CaseDef[T]])
extends TermTree[T] {
@@ -464,6 +473,7 @@ object Trees {
case class SelectFromTypeTree[T >: Untyped](qualifier: Tree[T], name: Name)
extends RefTree[T] {
type ThisTree[T >: Untyped] = SelectFromTypeTree[T]
+ def withName(name: Name) = this.derivedSelectFromTypeTree(qualifier, name)
}
/** left & right */
@@ -506,6 +516,7 @@ object Trees {
extends NameTree[T] with DefTree[T] with PatternTree[T] {
type ThisTree[T >: Untyped] = Bind[T]
override def envelope: Position = pos union initialPos
+ def withName(name: Name) = this.derivedBind(name, body)
}
/** tree_1 | ... | tree_n */
@@ -524,12 +535,14 @@ object Trees {
case class ValDef[T >: Untyped](mods: Modifiers[T], name: TermName, tpt: Tree[T], rhs: Tree[T])
extends NameTree[T] with ModDefTree[T] {
type ThisTree[T >: Untyped] = ValDef[T]
+ def withName(name: Name) = this.derivedValDef(mods, name.toTermName, tpt, rhs)
}
/** mods def name[tparams](vparams_1)...(vparams_n): tpt = rhs */
case class DefDef[T >: Untyped](mods: Modifiers[T], name: TermName, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], tpt: Tree[T], rhs: Tree[T])
extends NameTree[T] with ModDefTree[T] {
type ThisTree[T >: Untyped] = DefDef[T]
+ def withName(name: Name) = this.derivedDefDef(mods, name.toTermName, tparams, vparamss, tpt, rhs)
}
/** mods type name = rhs or
@@ -538,6 +551,7 @@ object Trees {
case class TypeDef[T >: Untyped](mods: Modifiers[T], name: TypeName, tparams: List[TypeDef[T]], rhs: Tree[T])
extends NameTree[T] with ModDefTree[T] {
type ThisTree[T >: Untyped] = TypeDef[T]
+ def withName(name: Name) = this.derivedTypeDef(mods, name.toTypeName, tparams, rhs)
}
/** extends parents { self => body } */
@@ -550,6 +564,7 @@ object Trees {
case class ClassDef[T >: Untyped](mods: Modifiers[T], name: TypeName, tparams: List[TypeDef[T]], impl: Template[T])
extends NameTree[T] with ModDefTree[T] {
type ThisTree[T >: Untyped] = ClassDef[T]
+ def withName(name: Name) = this.derivedClassDef(mods, name.toTypeName, tparams, impl)
}
/** import expr.selectors
@@ -618,6 +633,7 @@ object Trees {
* a `transform(List[Tree])` call.
*/
case class TempTrees[T >: Untyped](trees: List[Tree[T]]) extends Tree[T] {
+ type ThisTree[T >: Untyped] = TempTrees[T]
override def tpe: T = unsupported("tpe")
}
@@ -679,6 +695,7 @@ object Trees {
type Assign = Trees.Assign[T]
type Block = Trees.Block[T]
type If = Trees.If[T]
+ type Closure = Trees.Closure[T]
type Match = Trees.Match[T]
type CaseDef = Trees.CaseDef[T]
type Return = Trees.Return[T]
@@ -778,6 +795,10 @@ object Trees {
case tree: If[_] if (cond eq tree.cond) && (thenp eq tree.thenp) && (elsep eq tree.elsep) => tree
case _ => If(cond, thenp, elsep).copyAttr(tree)
}
+ def derivedClosure(env: List[Tree[T]], meth: RefTree[T]): Closure[T] = tree match {
+ case tree: Closure[_] if (env eq tree.env) && (meth eq tree.meth) => tree
+ case _ => Closure(env, meth).copyAttr(tree)
+ }
def derivedMatch(selector: Tree[T], cases: List[CaseDef[T]]): Match[T] = tree match {
case tree: Match[_] if (selector eq tree.selector) && (cases eq tree.cases) => tree
case _ => Match(selector, cases).copyAttr(tree)
@@ -878,6 +899,10 @@ object Trees {
case tree: SharedTree[_] if (shared eq tree.shared) => tree
case _ => SharedTree(shared).copyAttr(tree)
}
+ def derivedTempTrees(trees: List[Tree[T]]): TempTrees[T] = tree match {
+ case tree: TempTrees[_] if (trees eq tree.trees) => tree
+ case _ => TempTrees(trees).copyAttr(tree)
+ }
}
abstract class FullTreeTransformer[T >: Untyped, C] {
@@ -912,6 +937,8 @@ object Trees {
finishBlock(tree.derivedBlock(transform(stats, c), transform(expr, c)), tree, c, plugins)
case If(cond, thenp, elsep) =>
finishIf(tree.derivedIf(transform(cond, c), transform(thenp, c), transform(elsep, c)), tree, c, plugins)
+ case Closure(env, meth) =>
+ finishClosure(tree.derivedClosure(transform(env, c), transformSub(meth, c)), tree, c, plugins)
case Match(selector, cases) =>
finishMatch(tree.derivedMatch(transform(selector, c), transformSub(cases, c)), tree, c, plugins)
case CaseDef(pat, guard, body) =>
@@ -1000,6 +1027,7 @@ object Trees {
def finishFunction(tree: Tree[T], old: Tree[T], c: C, plugins: Plugins) = tree
def finishBlock(tree: Tree[T], old: Tree[T], c: C, plugins: Plugins) = tree
def finishIf(tree: Tree[T], old: Tree[T], c: C, plugins: Plugins) = tree
+ def finishClosure(tree: Tree[T], old: Tree[T], c: C, plugins: Plugins) = tree
def finishMatch(tree: Tree[T], old: Tree[T], c: C, plugins: Plugins) = tree
def finishCaseDef(tree: Tree[T], old: Tree[T], c: C, plugins: Plugins) = tree
def finishReturn(tree: Tree[T], old: Tree[T], c: C, plugins: Plugins) = tree
@@ -1061,6 +1089,8 @@ object Trees {
tree.derivedBlock(transform(stats), transform(expr))
case If(cond, thenp, elsep) =>
tree.derivedIf(transform(cond), transform(thenp), transform(elsep))
+ case Closure(env, meth) =>
+ tree.derivedClosure(transform(env), transformSub(meth))
case Match(selector, cases) =>
tree.derivedMatch(transform(selector), transformSub(cases))
case CaseDef(pat, guard, body) =>
@@ -1121,6 +1151,8 @@ object Trees {
sharedMemo = sharedMemo.updated(tree, tree1)
tree1
}
+ case TempTrees(trees) =>
+ tree.derivedTempTrees(transform(trees))
}
def transform(trees: List[Tree[T]]): List[Tree[T]] =
flatten(trees mapConserve (transform(_)))
@@ -1163,6 +1195,8 @@ object Trees {
this(this(x, stats), expr)
case If(cond, thenp, elsep) =>
this(this(this(x, cond), thenp), elsep)
+ case Closure(env, meth) =>
+ this(this(x, env), meth)
case Match(selector, cases) =>
this(this(x, selector), cases)
case CaseDef(pat, guard, body) =>
diff --git a/src/dotty/tools/dotc/ast/TypedTrees.scala b/src/dotty/tools/dotc/ast/TypedTrees.scala
index e5e0c99fd..93b83bdb0 100644
--- a/src/dotty/tools/dotc/ast/TypedTrees.scala
+++ b/src/dotty/tools/dotc/ast/TypedTrees.scala
@@ -90,6 +90,30 @@ object tpd extends Trees.Instance[Type] {
def If(cond: Tree, thenp: Tree, elsep: Tree)(implicit ctx: Context): If =
Trees.If(cond, thenp, elsep).withType(thenp.tpe | elsep.tpe).checked
+ /** A function def
+ *
+ * vparams => expr
+ *
+ * gets expanded to
+ *
+ * { def $anonfun(vparams) = expr; Closure($anonfun) }
+ *
+ * where the closure's type is the target type of the expression (FunctionN, unless
+ * otherwise specified).
+ */
+ def Closure(meth: TermSymbol, body: Tree, target: Type = NoType)(implicit ctx: Context): Block = {
+ val funtpe =
+ if (target.exists) target
+ else meth.info match {
+ case mt @ MethodType(_, formals) =>
+ assert(!mt.isDependent)
+ defn.FunctionType(formals, mt.resultType)
+ }
+ Block(
+ DefDef(meth, body) :: Nil,
+ Trees.Closure(Nil, Ident(TermRef.withSym(NoPrefix, meth)))).withType(funtpe).checked
+ }
+
def Match(selector: Tree, cases: List[CaseDef])(implicit ctx: Context): Match =
Trees.Match(selector, cases).withType(ctx.lub(cases map (_.body.tpe))).checked
@@ -284,30 +308,6 @@ object tpd extends Trees.Instance[Type] {
TempTrees(valdef :: clsdef :: Nil)
}
- /** A function def
- *
- * vparams => expr
- *
- * gets expanded to
- *
- * { def $anonfun(vparams) = expr; $anonfun: pt }
- *
- * where pt is the target type of the expression (FunctionN) unless
- * otherwise specified.
- */
- def Function(meth: TermSymbol, body: Tree, target: Type = NoType)(implicit ctx: Context): Block = {
- val funtpe =
- if (target.exists) target
- else meth.info match {
- case mt @ MethodType(_, formals) =>
- assert(!mt.isDependent)
- defn.FunctionType(formals, mt.resultType)
- }
- Block(
- DefDef(meth, body) :: Nil,
- Typed(Ident(TermRef.withSym(NoPrefix, meth)), TypeTree(funtpe)))
- }
-
private class FindLocalDummyAccumulator(cls: ClassSymbol)(implicit ctx: Context) extends TreeAccumulator[Symbol] {
def apply(sym: Symbol, tree: Tree) =
if (sym.exists) sym
diff --git a/src/dotty/tools/dotc/ast/UntypedTrees.scala b/src/dotty/tools/dotc/ast/UntypedTrees.scala
index f733734a7..82c99a781 100644
--- a/src/dotty/tools/dotc/ast/UntypedTrees.scala
+++ b/src/dotty/tools/dotc/ast/UntypedTrees.scala
@@ -21,6 +21,10 @@ 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)
}
/** (vparams) => body */
@@ -100,12 +104,12 @@ object untpd extends Trees.Instance[Untyped] {
case Tuple(args) => args mapConserve assignToNamedArg
case _ => right :: Nil
}
- Apply(Select(left, op.encode), args)
+ Apply(Select(left, op), args)
} else {
val x = ctx.freshName().toTermName
Block(
ValDef(Modifiers(Synthetic), x, TypeTree(), left),
- Apply(Select(right, op.encode), Ident(x)))
+ Apply(Select(right, op), Ident(x)))
}
}
@@ -292,7 +296,7 @@ object untpd extends Trees.Instance[Untyped] {
mode == Mode.Pattern && isVarPattern(id) && id.name != nme.WILDCARD
// begin desugar
- tree match { // todo: move general tree desugaring to typer, and keep only untyped trees here?
+ val tree1 = tree match { // todo: move general tree desugaring to typer, and keep only untyped trees here?
case id @ Ident(_) if isPatternVar(id) =>
Bind(id.name, Ident(nme.WILDCARD))
case Typed(id @ Ident(_), tpt) if isPatternVar(id) =>
@@ -328,16 +332,16 @@ object untpd extends Trees.Instance[Untyped] {
val params = args.asInstanceOf[List[ValDef]]
Block(
DefDef(Modifiers(Synthetic), nme.ANON_FUN, Nil, params :: Nil, EmptyTree(), body),
- Ident(nme.ANON_FUN))
+ Closure(Nil, Ident(nme.ANON_FUN)))
}
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
+ case Mode.Expr => // l.op(r), or val x = r; l.op(x), plus handle named args specially
makeBinop(l, op, r)
- case Mode.Pattern => // op'(l, r)
- Apply(Ident(op.encode), l :: r :: Nil)
- case Mode.Type => // op'[l, r]
- AppliedTypeTree(Ident(op.encode), l :: r :: Nil)
+ case Mode.Pattern => // op(l, r)
+ Apply(Ident(op), l :: r :: Nil)
+ case Mode.Type => // op[l, r]
+ AppliedTypeTree(Ident(op), l :: r :: Nil)
}
case PostfixOp(t, op) =>
if (mode == Mode.Type && op == nme.raw.STAR)
@@ -345,13 +349,13 @@ object untpd extends Trees.Instance[Untyped] {
else {
assert(mode == Mode.Expr)
if (op == nme.WILDCARD) tree // desugar later by eta expansion
- else Select(t, op.encode)
+ else Select(t, op)
}
case PrefixOp(op, t) =>
if (mode == Mode.Type && op == nme.ARROWkw)
AppliedTypeTree(ref(defn.ByNameParamClass.typeConstructor), t)
else
- Select(t, nme.UNARY_PREFIX ++ op.encode)
+ Select(t, nme.UNARY_PREFIX ++ op)
case Parens(t) =>
t
case Tuple(ts) =>
@@ -380,12 +384,16 @@ object untpd extends Trees.Instance[Untyped] {
case _ =>
tree
}
+ tree1 match {
+ case tree1: NameTree => tree1.withName(tree1.name.encode)
+ case _ => tree1
+ }
}.withPos(tree.pos)
def desugarContextBounds(tparams: List[TypeDef], vparamss: List[List[ValDef]], ofClass: Boolean): (List[TypeDef], List[List[ValDef]]) = {
val epbuf = new ListBuffer[ValDef]
def makeEvidenceParam(cxBound: Tree): ValDef = ???
- val tparams1 = tparams map {
+ val tparams1 = tparams mapConserve {
case tparam @ TypeDef(mods, name, ttparams, ContextBounds(tbounds, cxbounds)) =>
for (cxbound <- cxbounds) {
val accessMods = if (ofClass) PrivateOrLocal else EmptyFlags
@@ -397,21 +405,25 @@ object untpd extends Trees.Instance[Untyped] {
case tparam =>
tparam
}
- val evidenceParams = epbuf.toList
- val vparamss1 = vparamss.reverse match {
- case (vparams @ (vparam :: _)) :: rvparamss if vparam.mods is Implicit =>
- ((vparams ++ evidenceParams) :: rvparamss).reverse
- case _ =>
- vparamss :+ evidenceParams
+ epbuf.toList match {
+ case Nil =>
+ (tparams, vparamss)
+ case evidenceParams =>
+ val vparamss1 = vparamss.reverse match {
+ case (vparams @ (vparam :: _)) :: rvparamss if vparam.mods is Implicit =>
+ ((vparams ++ evidenceParams) :: rvparamss).reverse
+ case _ =>
+ vparamss :+ evidenceParams
+ }
+ (tparams1, vparamss1)
}
- (tparams1, vparamss1)
}
def desugarContextBounds(tree: Tree): Tree = tree match {
case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
val (tparams1, vparamss1) =
desugarContextBounds(tparams, vparamss, ofClass = false)
- tree.derivedDefDef(mods, name, tparams1, vparamss, tpt, rhs)
+ tree.derivedDefDef(mods, name, tparams1, vparamss1, tpt, rhs)
case ClassDef(
mods, name, tparams, templ @ Template(constr, parents, self, body)) =>
val (tparams1, vparamss1) =
diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
index 51816b971..f96115f95 100644
--- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
@@ -999,7 +999,7 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot:
val vparams = until(end, readValDefRef)
val applyType = MethodType(vparams map (_.name), vparams map (_.tpt.tpe), body.tpe)
val applyMeth = cctx.newSymbol(symbol.owner, nme.apply, Method, applyType)
- Function(applyMeth, body.changeOwner(symbol, applyMeth), tpe)
+ Closure(applyMeth, body.changeOwner(symbol, applyMeth), tpe)
case ASSIGNtree =>
val lhs = readTreeRef()