/* NSC -- new Scala compiler * Copyright 2005-2009 LAMP/EPFL * @author Gilles Dubochet */ // $Id: LiftCode.scala 18387 2009-07-24 15:28:37Z odersky $ package scala.tools.nsc package transform import symtab._ import Flags._ import symtab.Flags._ import scala.collection.immutable.ListMap import scala.collection.mutable.{HashMap, ListBuffer} import scala.tools.nsc.util.{FreshNameCreator, TreeSet} /** Translate expressions of the form reflect.Code.lift(exp) * to the lifted "reflect trees" representation of exp. * * @author Gilles Dubochet * @version 1.0 */ 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 val symbols: global.type = global /** the following two members override abstract members in Transform */ 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 = ListMap[reflect.Symbol, Name] class Injector(env: InjectEnvironment, fresh: FreshNameCreator) { // todo replace className by caseName in CaseClass once we have switched to nsc. def className(value: AnyRef): String = value match { case _ :: _ => "scala.$colon$colon" case reflect.MethodType(_, _) => if (value.isInstanceOf[reflect.ImplicitMethodType]) "scala.reflect.ImplicitMethodType" else "scala.reflect.MethodType" case x:Product => "scala.reflect."+x.productPrefix //caseName //case _ => // bq:unreachable code // "" } 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) throw new Error("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 _ => throw new Error("don't know how to inject " + value) } } } // Injector def inject(code: reflect.Tree): Tree = new Injector(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))))) } // case EmptyTree => // case LiftPoint(tree) => // case PackageDef(pid, stats) => // case ClassDef(mods, name, tparams, impl) => // case ValDef(mods, name, tpt, rhs) => // case DefDef(mods, name, tparams, vparamss, tpt, rhs) => // case TypeDef(mods, name, tparams, rhs) => // case LabelDef(name, params, rhs) => // case Template(parents, self, body) => // case Block(stats, expr) => // case ArrayValue(elemtpt, trees) => // case Assign(lhs, rhs) => // case If(cond, thenp, elsep) => // case Match(selector, cases) => // case Return(expr) => // case Try(block, catches, finalizer) => // case Throw(expr) => // case New(tpt) => // case Typed(expr, tpt) => // case TypeApply(fun, args) => // case Apply(fun, args) => // case Super(qual, mix) => // case This(qual) => // case Select(qualifier, selector) => // case Ident(name) => // case Literal(value) => // case TypeTree() => // /* Pattern matching */ // case CaseDef(pat, guard, body) => // case Sequence(trees) => // case Alternative(trees) => // case Star(elem) => // case Bind(name, body) =>