summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/transform/LiftCode.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/transform/LiftCode.scala')
-rw-r--r--src/compiler/scala/tools/nsc/transform/LiftCode.scala147
1 files changed, 3 insertions, 144 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/LiftCode.scala b/src/compiler/scala/tools/nsc/transform/LiftCode.scala
index 91caf14b8c..e3e9d70384 100644
--- a/src/compiler/scala/tools/nsc/transform/LiftCode.scala
+++ b/src/compiler/scala/tools/nsc/transform/LiftCode.scala
@@ -19,13 +19,15 @@ import scala.tools.nsc.util.{FreshNameCreator, TreeSet}
* @author Gilles Dubochet
* @version 1.0
*/
-abstract class LiftCode extends Transform {
+abstract class LiftCode extends Transform with Reifiers {
import global._ // the global environment
import definitions._ // standard classes and methods
import typer.{typed, atOwner} // methods to type trees
import posAssigner.atPos // for filling in tree positions
+ val symbols: global.type = global
+
/** the following two members override abstract members in Transform */
val phaseName: String = "liftcode"
@@ -42,147 +44,6 @@ abstract class LiftCode extends Transform {
}
}
- case class FreeValue(tree: Tree) extends reflect.Tree
-
- class ReifyEnvironment extends HashMap[Symbol, reflect.Symbol] {
- var targets = new HashMap[String, Option[reflect.LabelSymbol]]()
- def addTarget(name: String, target: reflect.LabelSymbol): Unit =
- targets.update(name, Some(target))
- def getTarget(name: String): Option[reflect.LabelSymbol] =
- targets.get(name) match {
- case None =>
- targets.update(name, None)
- None
- //case Some(None) => None //bq:redundant
- case Some(tgt) => tgt
- }
- def hasAllTargets: Boolean =
- targets.elements.map(_._2).forall {
- case Some(_) => true
- case None => false
- }
- override def update(sym: Symbol, rsym: reflect.Symbol) =
- super.update(sym,rsym)
- }
-
-
- class Reifier(env: ReifyEnvironment, currentOwner: reflect.Symbol)
- extends SymbolReifier
- {
- val symbols: global.type = global
-
-
- def reify(tree: Tree): reflect.Tree = tree match {
- case Ident(_) =>
- val rsym = reify(tree.symbol);
- //Console.println("LiftCode: seen ident")
- if (rsym == reflect.NoSymbol) {
- //Console.println(" free = "+tree)
- FreeValue(tree)
- } else {
- //Console.println(" rsym = "+rsym)
- reflect.Ident(rsym)
- }
- case Select(qual, _) =>
- val rsym = reify(tree.symbol);
- if (rsym == reflect.NoSymbol) throw new TypeError("cannot reify symbol: " + tree.symbol)
- else reflect.Select(reify(qual), reify(tree.symbol))
-
- case _ : StubTree => reflect.Literal(0)
- case Literal(constant) =>
- reflect.Literal(constant.value)
-
- case Apply(name, args) if name.toString().startsWith("label$") =>
- env.getTarget(name.toString()) match {
- case None => throw new TypeError("cannot reify tree (no forward jumps allowed): " + tree)
- case Some(label) => reflect.Goto(label)
- }
-
- case Apply(fun, args) =>
- reflect.Apply(reify(fun), args map reify)
-
- case TypeApply(fun, args) =>
- reflect.TypeApply(reify(fun), args map (_.tpe) map reify)
-
- case Function(vparams, body) =>
- var env1 = env
- for (vparam <- vparams) {
- val local = reflect.LocalValue(
- currentOwner, vparam.symbol.name.toString(), reify(vparam.symbol.tpe));
- env1.update(vparam.symbol, local);
- }
- reflect.Function(vparams map (_.symbol) map env1,
- new Reifier(env1, currentOwner).reify(body))
- case tree@This(_) if tree.symbol.isModule =>
- // there is no reflect node for a module's this, so
- // represent it as a selection of the module
- reify(typed(
- Select(This(tree.symbol.owner), tree.symbol.name)))
- case This(_) =>
- reflect.This(reify(tree.symbol))
- case Block(stats, expr) =>
- reflect.Block(stats.map(reify), reify(expr))
- case New(clazz) =>
- val reifiedClass = reify(clazz)
- reflect.New(reifiedClass)
- case Typed(t, _) =>
- reify(t)
- case If(cond, thenp, elsep) =>
- reflect.If(reify(cond), reify(thenp), reify(elsep))
- case Assign(lhs, rhs) =>
- reflect.Assign(reify(lhs), reify(rhs))
-
- case LabelDef(name, Nil, body) =>
- val sym = new reflect.LabelSymbol(name.toString())
- env.addTarget(name.toString(), sym)
- val res = reflect.Target(sym, reify(body))
- res
-
- case vd @ ValDef(mods, name, tpt, rhs) =>
- val rtpe = reify(vd.tpe) // will return null, currently?!
- val sym = reflect.LocalValue(currentOwner, name.toString(), rtpe)
- env(vd.symbol) = sym // bq: despite Scala's scoping rules, this should work because references to vd.symbol were type checked.
- val rhs_ = reify(rhs)
- reflect.ValDef(sym, rhs_)
-
- case cd @ ClassDef(mods, name, tparams, impl) =>
- if(!tparams.isEmpty)
- throw new TypeError("cannot handle polymorphic ClassDef ("+name+"): " + tparams)
- val rsym = reify(cd.symbol)
- val rimp = reify(impl)
- val rtpe = reify(impl.self.tpt.tpe) //todo: update
- reflect.ClassDef(rsym, rtpe, rimp.asInstanceOf[reflect.Template])
-
- case tmpl @ Template(parents, self, body) =>
- val rparents = for (p <- parents) yield { reify(p.tpe) }
- //todo: add self to reified templates
- reflect.Template(rparents, body.map(reify))
-
- case dd @ DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
- if(!tparams.isEmpty)
- throw new TypeError("cannot handle polymorphic DefDef ("+name+"): " + tparams)
- val rsym = reify(dd.symbol)
- val rparss = vparamss map { x => x map (reify) }
- val rret = reify(tpt.tpe)
- val rrhs = reify(rhs)
- reflect.DefDef(rsym, rparss, rret, rrhs)
-
- case sp @ Super(qual: Name, mix: Name) =>
- val rsym = reify(sp.symbol)
- reflect.Super(rsym)
-
- case _ =>
- throw new TypeError("cannot reify tree ("+tree.getClass()+"): " + tree)
- }
-
- override def reify(sym: Symbol): reflect.Symbol =
- env.get(sym) match {
- case Some(rsym) =>
- rsym
- case None =>
- super.reify(sym)
- }
- }
type InjectEnvironment = ListMap[reflect.Symbol, Name]
@@ -247,8 +108,6 @@ abstract class LiftCode extends Transform {
}
} // Injector
- def reify(tree: Tree): reflect.Tree =
- new Reifier(new ReifyEnvironment(), reflect.NoSymbol).reify(tree)
def inject(code: reflect.Tree): Tree =
new Injector(ListMap.empty, new FreshNameCreator.Default).inject(code)