diff options
author | Martin Odersky <odersky@gmail.com> | 2014-07-10 16:40:01 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-07-17 11:02:02 +0200 |
commit | 1d4c5f69de68975df3bc95e461971e1e4a779ff6 (patch) | |
tree | 8393f10006b53b1d2f8bfda778b81beff3608bab /src/dotty/tools/dotc/ast/tpd.scala | |
parent | dce9d6d3b2b60c8011c2e3362abc02bed9f26e19 (diff) | |
download | dotty-1d4c5f69de68975df3bc95e461971e1e4a779ff6.tar.gz dotty-1d4c5f69de68975df3bc95e461971e1e4a779ff6.tar.bz2 dotty-1d4c5f69de68975df3bc95e461971e1e4a779ff6.zip |
Revamped TreeTypeMap
TreeTypeMap needs to track all binding occurrences and propagate maps
to all usage occurrences.
Also, fixed `ref` for prefixless types (these mapped to a SelectFromType tree before,
now are mapped to Idents).
Diffstat (limited to 'src/dotty/tools/dotc/ast/tpd.scala')
-rw-r--r-- | src/dotty/tools/dotc/ast/tpd.scala | 84 |
1 files changed, 63 insertions, 21 deletions
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala index d9c57bd23..e296572fb 100644 --- a/src/dotty/tools/dotc/ast/tpd.scala +++ b/src/dotty/tools/dotc/ast/tpd.scala @@ -4,7 +4,7 @@ package ast import core._ import util.Positions._, Types._, Contexts._, Constants._, Names._, Flags._ -import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._ +import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._, Symbols._ import CheckTrees._, Denotations._, Decorators._ import config.Printers._ import typer.ErrorReporting._ @@ -251,7 +251,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { /** A tree representing the same reference as the given type */ def ref(tp: NamedType)(implicit ctx: Context): NameTree = - if (tp.symbol.isStatic) Ident(tp) + if (tp.symbol.isStatic || tp.prefix == NoPrefix) Ident(tp) else tp.prefix match { case pre: TermRef => ref(pre).select(tp) case pre => SelectFromTypeTree(TypeTree(pre), tp) @@ -413,26 +413,43 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { def tpes: List[Type] = xs map (_.tpe) } - class TreeTypeMap(val typeMap: Type => Type = IdentityTypeMap, val ownerMap: Symbol => Symbol = identity _)(implicit ctx: Context) extends TreeMap { + final class TreeTypeMap( + val typeMap: Type => Type = IdentityTypeMap, + val ownerMap: Symbol => Symbol = identity _, + val treeMap: Tree => Tree = identity _)(implicit ctx: Context) extends TreeMap { + override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = super.transform { - tree.withType(typeMap(tree.tpe)) match { - case bind: tpd.Bind => - val sym = bind.symbol - val newOwner = ownerMap(sym.owner) - val newInfo = typeMap(sym.info) - if ((newOwner ne sym.owner) || (newInfo ne sym.info)) - bind.withType(sym.copy(owner = newOwner, info = newInfo).namedType) - else - bind + treeMap(tree).withType(typeMap(tree.tpe)) match { + case ddef @ DefDef(mods, name, tparams, vparamss, tpt, rhs) => + val (tmap1, tparams1) = transformDefs(ddef.tparams) + val (tmap2, vparamss1) = tmap1.transformVParamss(vparamss) + cpy.DefDef(ddef, mods, name, tparams1, vparamss1, tmap2.transform(tpt), tmap2.transform(rhs)) + case blk @ Block(stats, expr) => + val (tmap1, stats1) = transformDefs(stats) + cpy.Block(blk, stats1, tmap1.transform(expr)) + case cdef @ CaseDef(pat, guard, rhs) => + val tmap = withMappedSyms(patVars(pat)) + cpy.CaseDef(cdef, tmap.transform(pat), tmap.transform(guard), tmap.transform(rhs)) case tree1 => tree1 } } - override def transformStats(trees: List[tpd.Tree])(implicit ctx: Context) = { - val locals = ta.localSyms(trees) - val mapped = ctx.mapSymbols(locals, typeMap, ownerMap) - if (locals eq mapped) super.transform(trees) - else withSubstitution(locals, mapped).transform(trees) + + override def transformStats(trees: List[tpd.Tree])(implicit ctx: Context) = + transformDefs(trees)._2 + + private def transformDefs[TT <: tpd.Tree](trees: List[TT])(implicit ctx: Context): (TreeTypeMap, List[TT]) = { + val tmap = withMappedSyms(ta.localSyms(trees)) + (tmap, tmap.transformSub(trees)) + } + + private def transformVParamss(vparamss: List[List[ValDef]]): (TreeTypeMap, List[List[ValDef]]) = vparamss match { + case vparams :: rest => + val (tmap1, vparams1) = transformDefs(vparams) + val (tmap2, vparamss2) = tmap1.transformVParamss(rest) + (tmap2, vparams1 :: vparamss2) + case nil => + (this, vparamss) } def apply[ThisTree <: tpd.Tree](tree: ThisTree): ThisTree = transform(tree).asInstanceOf[ThisTree] @@ -443,10 +460,35 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { } /** The current tree map composed with a substitution [from -> to] */ - def withSubstitution(from: List[Symbol], to: List[Symbol]) = - new TreeTypeMap( - typeMap andThen ((tp: Type) => tp.substSym(from, to)), - ownerMap andThen (from zip to).toMap) + def withSubstitution(from: List[Symbol], to: List[Symbol]): TreeTypeMap = + if (from eq to) this + else new TreeTypeMap( + typeMap andThen (_.substSym(from, to)), + ownerMap andThen { sym => + val idx = from.indexOf(sym) + if (idx >= 0) to(idx) else sym + }, + treeMap) + + /** Apply `typeMap` and `ownerMap` to given symbols `syms` + * and return a treemap that contains the substitution + * between original and mapped symbols. + */ + def withMappedSyms(syms: List[Symbol]): TreeTypeMap = { + val mapped = ctx.mapSymbols(syms, typeMap, ownerMap) + withSubstitution(syms, mapped) + } + } + + /** The variables defined by a pattern, in reverse order of their appearance. */ + def patVars(tree: Tree)(implicit ctx: Context): List[Symbol] = { + val acc = new TreeAccumulator[List[Symbol]] { + def apply(syms: List[Symbol], tree: Tree) = tree match { + case Bind(_, body) => apply(tree.symbol :: syms, body) + case _ => foldOver(syms, tree) + } + } + acc(Nil, tree) } // convert a numeric with a toXXX method |