diff options
author | Martin Odersky <odersky@gmail.com> | 2013-05-23 14:33:25 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2013-05-23 14:33:25 +0200 |
commit | e1be722f469c45e7546388359b5870a07f4c14b8 (patch) | |
tree | 53720d33f176dcb18cb4443867cd378bcdb62ef1 /src | |
parent | db39f1a5f5062f00e09e20a897e8f6d26e1e4193 (diff) | |
download | dotty-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.scala | 36 | ||||
-rw-r--r-- | src/dotty/tools/dotc/ast/TypedTrees.scala | 48 | ||||
-rw-r--r-- | src/dotty/tools/dotc/ast/UntypedTrees.scala | 52 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/UnPickler.scala | 2 |
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() |