package scala.tools.nsc
package transform
import symtab._
import Flags._
import scala.collection.{ mutable, immutable }
import scala.collection.mutable.ListBuffer
import scala.tools.nsc.util.FreshNameCreator
abstract class LiftCode extends Transform with Reifiers {
import global._
import definitions._
import typer.{typed, atOwner}
val symbols: global.type = global
val phaseName: String = "liftcode"
def newTransformer(unit: CompilationUnit): Transformer =
new AddRefFields(unit)
class AddRefFields(unit: CompilationUnit) extends Transformer {
override def transform(tree: Tree): Tree = tree match {
case Apply(lift, List(tree))
if lift.symbol == Code_lift =>
typed(atPos(tree.pos)(codify(tree)))
case _ =>
super.transform(tree)
}
}
type InjectEnvironment = immutable.ListMap[reflect.Symbol, Name]
class Injector(env: InjectEnvironment, fresh: FreshNameCreator) {
def className(value: AnyRef): String = value match {
case _ :: _ => "scala.$colon$colon"
case reflect.MethodType(_, _) =>
"scala.reflect.MethodType"
case x:Product =>
"scala.reflect."+x.productPrefix
}
def objectName(value: Any): String = value match {
case Nil => "scala.collection.immutable.Nil"
case reflect.NoSymbol => "scala.reflect.NoSymbol"
case reflect.RootSymbol => "scala.reflect.RootSymbol"
case reflect.NoPrefix => "scala.reflect.NoPrefix"
case reflect.NoType => "scala.reflect.NoType"
case _ => ""
}
def inject(value: Any): Tree = {
def treatProduct(c: Product) = {
val name = objectName(c)
if (name.length() != 0)
gen.mkAttributedRef(definitions.getModule(name))
else {
val name = className(c)
if (name.length() == 0) abort("don't know how to inject " + value)
val injectedArgs = new ListBuffer[Tree]
for (i <- 0 until c.productArity)
injectedArgs += inject(c.productElement(i))
New(Ident(definitions.getClass(name)), List(injectedArgs.toList))
}
}
value match {
case FreeValue(tree) =>
New(Ident(definitions.getClass("scala.reflect.Literal")), List(List(tree)))
case () => Literal(Constant(()))
case x: String => Literal(Constant(x))
case x: Boolean => Literal(Constant(x))
case x: Byte => Literal(Constant(x))
case x: Short => Literal(Constant(x))
case x: Char => Literal(Constant(x))
case x: Int => Literal(Constant(x))
case x: Long => Literal(Constant(x))
case x: Float => Literal(Constant(x))
case x: Double => Literal(Constant(x))
case c: Product => treatProduct(c)
case null =>
gen.mkAttributedRef(definitions.getModule("scala.reflect.NoType"))
case _ =>
abort("don't know how to inject " + value)
}
}
}
def inject(code: reflect.Tree): Tree =
new Injector(immutable.ListMap.empty, new FreshNameCreator.Default).inject(code)
def codify (tree: Tree): Tree =
New(TypeTree(appliedType(definitions.CodeClass.typeConstructor,
List(tree.tpe))),
List(List(inject(reify(tree)))))
}