From 274ce619902b1e92ec22fcff30b965fbbece2ad3 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 25 Sep 2011 17:09:04 +0000 Subject: Getting liftCode to work. --- .../scala/reflect/internal/Importers.scala | 127 +++++----- src/compiler/scala/reflect/internal/Symbols.scala | 1 + src/compiler/scala/reflect/runtime/Mirror.scala | 34 +-- .../scala/tools/nsc/settings/ScalaSettings.scala | 1 + .../scala/tools/nsc/transform/LiftCode.scala | 282 +++++++++------------ .../scala/tools/nsc/util/SimpleTracer.scala | 19 ++ src/compiler/scala/tools/nsc/util/package.scala | 4 + src/compiler/scala/tools/nsc/util/trace.scala | 18 -- test/disabled/pos/code.scala | 20 -- test/disabled/pos/t0651.scala | 4 - test/disabled/pos/t531.scala | 10 - test/disabled/pos/t532.scala | 10 - test/files/pos/code.scala | 20 ++ test/files/pos/t0651.scala | 4 + test/files/pos/t531.scala | 10 + test/files/pos/t532.scala | 10 + 16 files changed, 257 insertions(+), 317 deletions(-) create mode 100644 src/compiler/scala/tools/nsc/util/SimpleTracer.scala delete mode 100644 src/compiler/scala/tools/nsc/util/trace.scala delete mode 100644 test/disabled/pos/code.scala delete mode 100644 test/disabled/pos/t0651.scala delete mode 100644 test/disabled/pos/t531.scala delete mode 100644 test/disabled/pos/t532.scala create mode 100644 test/files/pos/code.scala create mode 100644 test/files/pos/t0651.scala create mode 100644 test/files/pos/t531.scala create mode 100644 test/files/pos/t532.scala diff --git a/src/compiler/scala/reflect/internal/Importers.scala b/src/compiler/scala/reflect/internal/Importers.scala index 66cb990f06..32238289de 100644 --- a/src/compiler/scala/reflect/internal/Importers.scala +++ b/src/compiler/scala/reflect/internal/Importers.scala @@ -18,72 +18,81 @@ trait Importers { self: SymbolTable => def importPosition(pos: from.Position): Position = NoPosition def importSymbol(sym: from.Symbol): Symbol = { - def importOrRelink: Symbol = - if (sym == null) - null - else if (sym.getClass == NoSymbol.getClass) - NoSymbol - else if (sym.isRoot) - definitions.RootClass - else { - val myowner = importSymbol(sym.owner) - val mypos = importPosition(sym.pos) - val myname = importName(sym.name) - - def doImport: Symbol = { - val mysym = sym match { - case x: from.MethodSymbol => - val mysym = new MethodSymbol(myowner, mypos, myname) - mysym.referenced = importSymbol(x.referenced) - mysym - case x: from.ModuleSymbol => - new ModuleSymbol(myowner, mypos, myname) - case x: from.FreeVar => - new FreeVar(importName(x.name), importType(x.tpe), x.value) - case x: from.TermSymbol => - new TermSymbol(myowner, mypos, myname) - case x: from.TypeSkolem => - new TypeSkolem(myowner, mypos, myname.toTypeName, x.unpackLocation match { - case null => null - case y: from.Tree => importTree(y) - case y: from.Symbol => importSymbol(y) - }) -/* + def doImport(sym: from.Symbol): Symbol = { + val myowner = importSymbol(sym.owner) + val mypos = importPosition(sym.pos) + val myname = importName(sym.name) + def linkReferenced(mysym: TermSymbol, x: from.TermSymbol, op: from.Symbol => Symbol): Symbol = { + println("link referenced " + mysym + " " + x.referenced) + symMap(x) = mysym + mysym.referenced = op(x.referenced) + mysym + } + val mysym = sym match { + case x: from.MethodSymbol => + linkReferenced(new MethodSymbol(myowner, mypos, myname), x, importSymbol) + case x: from.ModuleSymbol => + linkReferenced(new ModuleSymbol(myowner, mypos, myname), x, doImport) + case x: from.FreeVar => + new FreeVar(importName(x.name), importType(x.tpe), x.value) + case x: from.TermSymbol => + linkReferenced(new TermSymbol(myowner, mypos, myname), x, importSymbol) + case x: from.TypeSkolem => + new TypeSkolem(myowner, mypos, myname.toTypeName, x.unpackLocation match { + case null => null + case y: from.Tree => importTree(y) + case y: from.Symbol => importSymbol(y) + }) + /* case x: from.ModuleClassSymbol => val mysym = new ModuleClassSymbol(myowner, mypos, myname.toTypeName) mysym.sourceModule = importSymbol(x.sourceModule) mysym */ - case x: from.ClassSymbol => - val mysym = new ClassSymbol(myowner, mypos, myname.toTypeName) - if (sym.thisSym != sym) { - mysym.typeOfThis = importType(sym.typeOfThis) - mysym.thisSym.name = importName(sym.thisSym.name) - } - mysym - case x: from.TypeSymbol => - new TypeSymbol(myowner, mypos, myname.toTypeName) + case x: from.ClassSymbol => + val mysym = new ClassSymbol(myowner, mypos, myname.toTypeName) + if (sym.thisSym != sym) { + mysym.typeOfThis = importType(sym.typeOfThis) + mysym.thisSym.name = importName(sym.thisSym.name) } - symMap(sym) = mysym - mysym setFlag sym.flags | Flags.LOCKED - mysym setInfo { - val mytypeParams = sym.typeParams map importSymbol - new LazyPolyType(mytypeParams) { - override def complete(s: Symbol) { - val result = sym.info match { - case from.PolyType(_, res) => res - case result => result - } - s setInfo polyType(mytypeParams, importType(result)) - s setAnnotations (sym.annotations map importAnnotationInfo) - } + mysym + case x: from.TypeSymbol => + new TypeSymbol(myowner, mypos, myname.toTypeName) + } + symMap(sym) = mysym + mysym setFlag sym.flags | Flags.LOCKED + mysym setInfo { + val mytypeParams = sym.typeParams map doImport + new LazyPolyType(mytypeParams) { + override def complete(s: Symbol) { + val result = sym.info match { + case from.PolyType(_, res) => res + case result => result } + s setInfo polyType(mytypeParams, importType(result)) + s setAnnotations (sym.annotations map importAnnotationInfo) } - mysym resetFlag Flags.LOCKED - } // end doImport + } + } + mysym resetFlag Flags.LOCKED + } // end doImport + def importOrRelink: Symbol = + if (sym == null) + null + else if (sym == from.NoSymbol) + NoSymbol + else if (sym.isRoot) + definitions.RootClass + else { + val myowner = importSymbol(sym.owner) + val myname = importName(sym.name) if (sym.isModuleClass) { - importSymbol(sym.sourceModule).moduleClass + assert(sym.sourceModule != NoSymbol, sym) + val mymodule = importSymbol(sym.sourceModule) + assert(mymodule != NoSymbol, sym) + assert(mymodule.moduleClass != NoSymbol, mymodule) + mymodule.moduleClass } else if (myowner.isClass && !myowner.isRefinementClass && !(myowner hasFlag Flags.LOCKED) && sym.owner.info.decl(sym.name).exists) { // symbol is in class scope, try to find equivalent one in local scope if (sym.isOverloaded) @@ -93,7 +102,7 @@ trait Importers { self: SymbolTable => if (existing.isOverloaded) { existing = if (sym.isMethod) { - val localCopy = doImport + val localCopy = doImport(sym) existing filter (_.tpe matches localCopy.tpe) } else { existing filter (!_.isMethod) @@ -104,7 +113,7 @@ trait Importers { self: SymbolTable => } if (existing != NoSymbol) existing else { - val mysym = doImport + val mysym = doImport(sym) assert(myowner.info.decls.lookup(myname) == NoSymbol, myname+" "+myowner.info.decl(myname)+" "+existing) myowner.info.decls enter mysym mysym @@ -118,7 +127,7 @@ trait Importers { self: SymbolTable => println(myowner.rawInfo) myowner.typeParams(sym.paramPos) } else - doImport + doImport(sym) } symMap getOrElseUpdate (sym, importOrRelink) } diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index fcf70e5825..84b54167ec 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -1794,6 +1794,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => else if (isTrait) "trait" else if (isClass) "class" else if (isType) "type" + else if (isInstanceOf[FreeVar]) "free variable" else if (isTerm && isLazy) "lazy value" else if (isVariable) "variable" else if (isClassConstructor) "constructor" diff --git a/src/compiler/scala/reflect/runtime/Mirror.scala b/src/compiler/scala/reflect/runtime/Mirror.scala index 211195c467..14604fbd52 100644 --- a/src/compiler/scala/reflect/runtime/Mirror.scala +++ b/src/compiler/scala/reflect/runtime/Mirror.scala @@ -6,7 +6,7 @@ import java.lang.reflect.Array /** The mirror for standard runtime reflection from Java. */ -class Mirror extends Universe with RuntimeTypes with ToolBoxes with api.Mirror { +class Mirror extends Universe with RuntimeTypes with TreeBuildUtil with ToolBoxes with api.Mirror { import definitions._ @@ -36,38 +36,6 @@ class Mirror extends Universe with RuntimeTypes with ToolBoxes with api.Mirror { override def classToType(jclazz: java.lang.Class[_]): Type = typeToScala(jclazz) override def classToSymbol(jclazz: java.lang.Class[_]): Symbol = classToScala(jclazz) - def staticClass(name: String): Symbol = definitions.getClass(newTypeName(name)) - def staticModule(name: String): Symbol = definitions.getModule(newTermName(name)) - - def freeVar(name: String, info: Type, value: Any) = new FreeVar(name, info, value) - - /** Selects type symbol with given name from the defined members of prefix type - */ - def selectType(owner: Symbol, name: String): Symbol = - owner.info.decl(newTypeName(name)) - - /** Selects term symbol with given name and type from the defined members of prefix type - * @pre The prefix type - * @name The name of the selected member - * @tpe The type of the selected member - */ - def selectTerm(owner: Symbol, name: String, tpe: Type): Symbol = - owner.info.decl(newTermName(name)) suchThat (_.tpe == tpe) - - def selectParam(owner: Symbol, idx: Int): Symbol = { - def selectInList(params: List[Symbol], idx: Int, fallback: Type): Symbol = { - if (params.isEmpty) selectIn(fallback, idx) - else if (idx == 0) params.head - else selectInList(params.tail, idx - 1, fallback) - } - def selectIn(tpe: Type, idx: Int): Symbol = tpe match { - case PolyType(tparams, res) => selectInList(tparams, idx, res) - case MethodType(params, res) => selectInList(params, idx, res) - case _ => NoSymbol - } - selectIn(owner.info, idx) - } - } object Mirror extends Mirror diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 1856ff3fc6..4a54dab75a 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -158,6 +158,7 @@ trait ScalaSettings extends AbsScalaSettings val Ytyperdebug = BooleanSetting ("-Ytyper-debug", "Trace all type assignments.") val Yinferdebug = BooleanSetting ("-Yinfer-debug", "Trace type inference and implicit search.") val Ypmatdebug = BooleanSetting ("-Ypmat-debug", "Trace all pattern matcher activity.") + val Yreifydebug = BooleanSetting ("-Yreify-debug", "Trace reification actions.") val Yreplsync = BooleanSetting ("-Yrepl-sync", "Do not use asynchronous code for repl startup") val Yrepldebug = BooleanSetting ("-Yrepl-debug", "Trace all repl activity.") . withPostSetHook(_ => interpreter.replProps.debug setValue true) diff --git a/src/compiler/scala/tools/nsc/transform/LiftCode.scala b/src/compiler/scala/tools/nsc/transform/LiftCode.scala index f17bdf3416..2239bfca65 100644 --- a/src/compiler/scala/tools/nsc/transform/LiftCode.scala +++ b/src/compiler/scala/tools/nsc/transform/LiftCode.scala @@ -13,10 +13,9 @@ import scala.collection.mutable.ListBuffer import scala.tools.nsc.util.FreshNameCreator /** Translate expressions of the form reflect.Code.lift(exp) - * to the lifted "reflect trees" representation of exp. + * to the reified "reflect trees" representation of exp. * Also: mutable variables that are accessed from a local function are wrapped in refs. * - * @author Gilles Dubochet * @author Martin Odersky * @version 2.10 */ @@ -32,9 +31,12 @@ abstract class LiftCode extends Transform with TypingTransformers { val phaseName: String = "liftcode" def newTransformer(unit: CompilationUnit): Transformer = - new Lifter(unit) + new Codifier(unit) - class Lifter(unit: CompilationUnit) extends TypingTransformer(unit) { + class Codifier(unit: CompilationUnit) extends TypingTransformer(unit) { + + val reifyDebug = settings.Yreifydebug.value + val debugTrace = util.trace when reifyDebug /** Set of mutable local variables that are free in some inner method. */ private val freeMutableVars: mutable.Set[Symbol] = new mutable.HashSet @@ -46,7 +48,7 @@ abstract class LiftCode extends Transform with TypingTransformers { atPhase(phase.next) { super.transformUnit(unit) } - for (v <- freeMutableVars) + for (v <- freeMutableVars) //!!! remove assert(converted contains v, "unconverted: "+v+" in "+v.owner+" in unit "+unit) } @@ -54,11 +56,13 @@ abstract class LiftCode extends Transform with TypingTransformers { val sym = tree.symbol tree match { case Apply(_, List(tree)) if sym == Code_lift => // reify Code.lift[T](expr) instances - printTypings = true //debug - val result = transform(localTyper.typedPos(tree.pos)(codify(tree))) - println("transformed = "+result) //debug - printTypings = false //debug - result + val saved = printTypings + try { + printTypings = reifyDebug + debugTrace("transformed = ") { + transform(localTyper.typedPos(tree.pos)(codify(tree))) + } + } finally printTypings = saved case ValDef(mods, name, tpt, rhs) if (freeMutableVars(sym)) => // box mutable variables that are accessed from a local closure val tpt1 = TypeTree(sym.tpe) setPos tpt.pos /* Creating a constructor argument if one isn't present. */ @@ -67,8 +71,7 @@ abstract class LiftCode extends Transform with TypingTransformers { case _ => transform(rhs) } val rhs1 = typer.typedPos(rhs.pos) { - /*util.errtrace("lifted rhs for "+tree+" in "+unit)*/ ( - Apply(Select(New(TypeTree(sym.tpe)), nme.CONSTRUCTOR), List(constructorArg))) + Apply(Select(New(TypeTree(sym.tpe)), nme.CONSTRUCTOR), List(constructorArg)) } sym resetFlag MUTABLE sym removeAnnotation VolatileAttr @@ -76,7 +79,7 @@ abstract class LiftCode extends Transform with TypingTransformers { treeCopy.ValDef(tree, mods &~ MUTABLE, name, tpt1, rhs1) case Ident(name) if freeMutableVars(sym) => localTyper.typedPos(tree.pos) { - /*util.errtrace("lifting ")*/(Select(tree setType sym.tpe, nme.elem)) + Select(tree setType sym.tpe, nme.elem) } case _ => super.transform(tree) @@ -95,11 +98,9 @@ abstract class LiftCode extends Transform with TypingTransformers { final val localPrefix = "$local" final val memoizerName = "$memo" - private val localSyms = mutable.ArrayBuffer[Symbol]() - private val symIndex = mutable.HashMap[Symbol, Int]() - private var boundSyms = Set[Symbol]() - private val typeTree = mutable.HashMap[Type, Tree]() - private val typeTreeCount = mutable.HashMap[Tree, Int]() + private val reifiableSyms = mutable.ArrayBuffer[Symbol]() // the symbols that are reified with the tree + private val symIndex = mutable.HashMap[Symbol, Int]() // the index of a reifiable symbol in `reifiableSyms` + private var boundSyms = Set[Symbol]() // set of all symbols that are bound in tree to be reified /** Generate tree of the form * @@ -124,16 +125,19 @@ abstract class LiftCode extends Transform with TypingTransformers { */ def reifyTopLevel(tree: Tree): Tree = { val rtree = reify(tree) - memoize.transform(Block(mirrorAlias :: memoizerDef :: reifySymbolTableSetup, rtree)) + Block(mirrorAlias :: reifySymbolTableSetup, rtree) } - private def registerLocalSymbol(sym: Symbol): Unit = { + private def isLocatable(sym: Symbol) = + sym.isPackageClass || sym.owner.isClass || sym.isTypeParameter && sym.paramPos >= 0 + + private def registerReifiableSymbol(sym: Symbol): Unit = { sym.owner.ownersIterator.find(!isLocatable(_)) match { - case Some(outer) => registerLocalSymbol(outer) + case Some(outer) => registerReifiableSymbol(outer) case None => } - symIndex(sym) = localSyms.length - localSyms += sym + symIndex(sym) = reifiableSyms.length + reifiableSyms += sym } // helper methods @@ -179,9 +183,6 @@ abstract class LiftCode extends Transform with TypingTransformers { private def reifyName(name: Name) = mirrorCall(if (name.isTypeName) "newTypeName" else "newTermName", Literal(Constant(name.toString))) - private def isLocatable(sym: Symbol) = - sym.isPackageClass || sym.owner.isClass || sym.isParameter && sym.paramPos >= 0 - private def isFree(sym: Symbol) = !(symIndex contains sym) @@ -192,25 +193,35 @@ abstract class LiftCode extends Transform with TypingTransformers { case Some(idx) => Ident(localName(sym)) case None => - if (sym.isStatic) - mirrorCall(if (sym.isType) "staticClass" else "staticModule", reify(sym.fullName)) + if (sym.isModuleClass) + Select(reifySymRef(sym.sourceModule), "moduleClass") + else if (sym.isStatic && sym.isClass) + mirrorCall("staticClass", reify(sym.fullName)) + else if (sym.isStatic && sym.isModule) + mirrorCall("staticModule", reify(sym.fullName)) else if (isLocatable(sym)) - if (sym.isParameter) + if (sym.isTypeParameter) mirrorCall("selectParam", reify(sym.owner), reify(sym.paramPos)) else { + if (reifyDebug) println("locatable: "+sym+" "+sym.isPackageClass+" "+sym.owner+" "+sym.isTypeParameter) val rowner = reify(sym.owner) val rname = reify(sym.name.toString) - if (sym.isType) mirrorCall("selectType", rowner, rname) - else mirrorCall("selectTerm", rowner, rname, reify(sym.tpe)) + if (sym.isType) + mirrorCall("selectType", rowner, rname) + else if (sym.isMethod && sym.owner.isClass && sym.owner.info.decl(sym.name).isOverloaded) { + val index = sym.owner.info.decl(sym.name).alternatives indexOf sym + assert(index >= 0, sym) + mirrorCall("selectOverloadedMethod", rowner, rname, reify(index)) + } else + mirrorCall("selectTerm", rowner, rname) } else { if (sym.isTerm) { - println("Free: "+sym) + if (reifyDebug) println("Free: "+sym) mirrorCall("freeVar", reify(sym.name.toString), reify(sym.tpe), Ident(sym)) } else { - println("Late local: "+sym) - assert(!sym.isParameter, sym+"/"+sym.owner+"/"+sym.owner.info+"/"+sym.paramPos) - registerLocalSymbol(sym) + if (reifyDebug) println("Late local: "+sym) + registerReifiableSymbol(sym) reifySymRef(sym) } } @@ -220,7 +231,7 @@ abstract class LiftCode extends Transform with TypingTransformers { /** reify the creation of a symbol */ private def reifySymbolDef(sym: Symbol): Tree = { - println("reify sym def "+sym) + if (reifyDebug) println("reify sym def "+sym) var rsym: Tree = New( typePath(mirrorPrefix + (if (sym.isType) "TypeSymbol" else "TermSymbol")), List(List(reify(sym.owner), reify(sym.pos), reify(sym.name)))) @@ -233,19 +244,19 @@ abstract class LiftCode extends Transform with TypingTransformers { */ private def fillInSymbol(sym: Symbol): Tree = { val rset = Apply(Select(reifySymRef(sym), "setInfo"), List(reifyType(sym.info))) - if (sym.annotations.nonEmpty) rset + if (sym.annotations.isEmpty) rset else Apply(Select(rset, "setAnnotations"), List(reify(sym.annotations))) } /** Reify a scope */ private def reifyScope(scope: Scope): Tree = { - scope foreach registerLocalSymbol + scope foreach registerReifiableSymbol mirrorCall("newScopeWith", scope.toList map reifySymRef: _*) } /** Reify a list of symbols that need to be created */ private def reifySymbols(syms: List[Symbol]): Tree = { - syms foreach registerLocalSymbol + syms foreach registerReifiableSymbol mkList(syms map reifySymRef) } @@ -254,33 +265,33 @@ abstract class LiftCode extends Transform with TypingTransformers { mirrorFactoryCall(value, reifySymbols(bound), reify(underlying)) /** Reify a type */ - private def reifyType(tpe: Type): Tree = typeTree get tpe match { - case Some(tree) => - typeTreeCount(tree) += 1 - tree - case None => - val tree = tpe match { - case NoType | NoPrefix => - reifyCaseObject(tpe.asInstanceOf[Product]) - case ThisType(_) | SuperType(_, _) | SingleType(_, _) | ConstantType(_) | - TypeRef(_, _, _) | AnnotatedType(_, _, _) | - TypeBounds(_, _) | NullaryMethodType(_) | OverloadedType(_, _) => - reifyCaseClassInstance(tpe.asInstanceOf[Product]) - case t @ RefinedType(parents, decls) => - registerLocalSymbol(tpe.typeSymbol) - mirrorFactoryCall(t, reify(parents), reify(decls), reify(t.typeSymbol)) - case t @ ExistentialType(tparams, underlying) => - reifyTypeBinder(t, tparams, underlying) - case t @ PolyType(tparams, underlying) => - reifyTypeBinder(t, tparams, underlying) - case t @ MethodType(params, restpe) => - reifyTypeBinder(t, params, restpe) - case _ => - abort("cannot reify type " + tpe + " of class " + tpe.getClass) - } - typeTree(tpe) = tree - typeTreeCount(tree) = 1 - tree + private def reifyType(tpe0: Type): Tree = { + val tpe = tpe0.normalize + val tsym = tpe.typeSymbol + if (tsym.isClass && tpe == tsym.typeConstructor && tsym.isStatic) + Select(reifySymRef(tpe.typeSymbol), "typeConstructor") + else tpe match { + case NoType | NoPrefix => + reifyCaseObject(tpe.asInstanceOf[Product]) + case tpe @ ThisType(clazz) => + if (clazz.isModuleClass && clazz.isStatic) mirrorCall("thisModuleType", reify(clazz.fullName)) + else reifyCaseClassInstance(tpe) + case SuperType(_, _) | SingleType(_, _) | ConstantType(_) | + TypeRef(_, _, _) | AnnotatedType(_, _, _) | + TypeBounds(_, _) | NullaryMethodType(_) | OverloadedType(_, _) => + reifyCaseClassInstance(tpe.asInstanceOf[Product]) + case t @ RefinedType(parents, decls) => + registerReifiableSymbol(tpe.typeSymbol) + mirrorFactoryCall(t, reify(parents), reify(decls), reify(t.typeSymbol)) + case t @ ExistentialType(tparams, underlying) => + reifyTypeBinder(t, tparams, underlying) + case t @ PolyType(tparams, underlying) => + reifyTypeBinder(t, tparams, underlying) + case t @ MethodType(params, restpe) => + reifyTypeBinder(t, params, restpe) + case _ => + abort("cannot reify type " + tpe + " of class " + tpe.getClass) + } } /** Reify a tree */ @@ -296,7 +307,7 @@ abstract class LiftCode extends Transform with TypingTransformers { reifyCaseClassInstance(tree.asInstanceOf[Product]) /* if (tree.isDef || tree.isInstanceOf[Function]) - registerLocalSymbol(tree.symbol) + registerReifiableSymbol(tree.symbol) if (tree.hasSymbol) rtree = Apply(Select(rtree, "setSymbol"), List(reifySymRef(tree.symbol))) Apply(Select(rtree, "setType"), List(reifyType(tree.tpe))) @@ -307,54 +318,50 @@ abstract class LiftCode extends Transform with TypingTransformers { * to a global value, or else a mirror Literal. */ private def reifyFree(tree: Tree): Tree = - if (tree.symbol.hasFlag(MODULE) && tree.symbol.isStatic) + if (tree.symbol.isStaticModule) reify(termPath(tree.symbol.fullName)) else // make an Ident to a freeVar mirrorCall("Ident", reifySymRef(tree.symbol)) /** Reify an arbitary value */ private def reify(value: Any): Tree = { - //println("reifing "+value) //debug - /*util.trace("reified "+value+" --> ")*/ { - value match { - case tree: Tree => - reifyTree(tree) - case sym: Symbol => - reifySymRef(sym) - case tpe: Type => - reifyType(tpe) - case xs: List[_] => - scalaFactoryCall("collection.immutable.List", xs map reify: _*) - case xs: Array[_] => - scalaFactoryCall("Array", xs map reify: _*) - case scope: Scope => - reifyScope(scope) - case x: Name => - reifyName(x) - case pos: Position => - reifyCaseObject(NoPosition) - case Constant(_) | AnnotationInfo(_, _, _) | Modifiers(_, _, _) => - reifyCaseClassInstance(value.asInstanceOf[Product]) - case arg: ClassfileAnnotArg => - reifyCaseClassInstance(arg.asInstanceOf[Product]) - case x: Product if x.getClass.getName startsWith "scala.Tuple" => - reifyCaseClassInstance(x) - 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 _ => cannotReify(value) - } + value match { + case tree: Tree => + reifyTree(tree) + case sym: Symbol => + reifySymRef(sym) + case tpe: Type => + reifyType(tpe) + case xs: List[_] => + scalaFactoryCall("collection.immutable.List", xs map reify: _*) + case xs: Array[_] => + scalaFactoryCall("Array", xs map reify: _*) + case scope: Scope => + reifyScope(scope) + case x: Name => + reifyName(x) + case pos: Position => // todo: consider whether we should also reify positions + reifyCaseObject(NoPosition) + case Constant(_) | AnnotationInfo(_, _, _) | Modifiers(_, _, _) => + reifyCaseClassInstance(value.asInstanceOf[Product]) + case arg: ClassfileAnnotArg => + reifyCaseClassInstance(arg.asInstanceOf[Product]) + case x: Product if x.getClass.getName startsWith "scala.Tuple" => + reifyCaseClassInstance(x) + 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 _ => cannotReify(value) } } - /** An (unreified) path that refers to definition with given fully qualified name * @param mkName Creator for last portion of name (either TermName or TypeName) */ @@ -378,45 +385,27 @@ abstract class LiftCode extends Transform with TypingTransformers { private def mirrorAlias = ValDef(NoMods, mirrorShortName, TypeTree(), termPath(mirrorFullName)) - private def memoizerDef = - ValDef(NoMods, memoizerName, TypeTree(), New(typePath("scala.reflect.runtime.Memoizer"), List(List()))) - - /** Generate code that generates a symbol table of all symbols registered in `localSyms` + /** Generate code that generates a symbol table of all symbols registered in `reifiableSyms` */ private def reifySymbolTableSetup: List[Tree] = { val symDefs, fillIns = new mutable.ArrayBuffer[Tree] var i = 0 - while (i < localSyms.length) { - // fillInSymbol might create new localSyms, that's why this is done iteratively - symDefs += reifySymbolDef(localSyms(i)) - fillIns += fillInSymbol(localSyms(i)) + while (i < reifiableSyms.length) { + // fillInSymbol might create new reifiableSyms, that's why this is done iteratively + symDefs += reifySymbolDef(reifiableSyms(i)) + fillIns += fillInSymbol(reifiableSyms(i)) i += 1 } symDefs.toList ++ fillIns.toList } - private object memoize extends Transformer { - var memoCount = 0 - override def transform(tree: Tree) = typeTreeCount get tree match { - case None => tree - case Some(n) => - if (n > 0) { - typeTreeCount(tree) = -memoCount - val result = call(memoizerName+".add", reify(memoCount), tree) - memoCount += 1 - result - } else - call(memoizerName+".get", reify(n)) - } - } - private def cannotReify(value: Any): Nothing = abort("don't know how to reify " + value + " of class " + value.getClass) } - def codify(tree: Tree): Tree = util.trace("codified " + tree + " -> ") { + def codify(tree: Tree): Tree = debugTrace("codified " + tree + " -> ") { val targetType = definitions.CodeClass.primaryConstructor.info.paramTypes.head val reifier = new Reifier() val arg = gen.mkAsInstanceOf(reifier.reifyTopLevel(tree), targetType, wrapInApply = false) @@ -493,36 +482,3 @@ abstract class LiftCode extends Transform with TypingTransformers { } } } - -// 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 Alternative(trees) => -// case Star(elem) => -// case Bind(name, body) => diff --git a/src/compiler/scala/tools/nsc/util/SimpleTracer.scala b/src/compiler/scala/tools/nsc/util/SimpleTracer.scala new file mode 100644 index 0000000000..b103ae9cb0 --- /dev/null +++ b/src/compiler/scala/tools/nsc/util/SimpleTracer.scala @@ -0,0 +1,19 @@ +package scala.tools.nsc +package util + +// todo: We should unify this with Tracer. I'd do it but Tracer is +// too complicated for me to understand quickly. +import java.io.PrintStream + +/** A simple tracer + * @param out: The print stream where trace info shoul be sent + * @param enabled: A condition that must be true for trace info to be produced. + */ +class SimpleTracer(out: PrintStream, enabled: Boolean = true) { + def apply[T](msg: String)(value: T): T = { + if (enabled) out.println(msg+value) + value + } + def withOutput(out: PrintStream) = new SimpleTracer(out, enabled) + def when(enabled: Boolean): SimpleTracer = new SimpleTracer(out, enabled) +} diff --git a/src/compiler/scala/tools/nsc/util/package.scala b/src/compiler/scala/tools/nsc/util/package.scala index a62dfc4c0f..c5cd51a6f0 100644 --- a/src/compiler/scala/tools/nsc/util/package.scala +++ b/src/compiler/scala/tools/nsc/util/package.scala @@ -67,4 +67,8 @@ package object util { bs.toString() } def stackTraceString(ex: Throwable): String = stringFromWriter(ex printStackTrace _) + + lazy val trace = new SimpleTracer(System.out) + lazy val errtrace = new SimpleTracer(System.err) + } diff --git a/src/compiler/scala/tools/nsc/util/trace.scala b/src/compiler/scala/tools/nsc/util/trace.scala deleted file mode 100644 index 5207d2f13c..0000000000 --- a/src/compiler/scala/tools/nsc/util/trace.scala +++ /dev/null @@ -1,18 +0,0 @@ -package scala.tools.nsc -package util - -import java.io.PrintStream - -object trace extends SimpleTracer(System.out) -object errtrace extends SimpleTracer(System.err) - -class SimpleTracer(out: PrintStream) { - def apply[T](msg: String)(value: T): T = { - out.println(msg+value) - value - } - def withFun[T, U](msg: String)(value: T)(fun: T => U): T = { - out.println(msg+fun(value)) - value - } -} diff --git a/test/disabled/pos/code.scala b/test/disabled/pos/code.scala deleted file mode 100644 index 96d49106fa..0000000000 --- a/test/disabled/pos/code.scala +++ /dev/null @@ -1,20 +0,0 @@ -import reflect.runtime.Mirror.ToolBox -import scala.tools.nsc.reporters._ -import scala.tools.nsc.Settings - -object Test extends App { - def foo(ys: List[Int]) = { - val fun: reflect.Code[Int => Int] = x => x + ys.length - fun - } - val code = foo(List(2)) - val tree = code.tree.asInstanceOf[scala.reflect.runtime.Mirror.Tree] - val targetType = code.manifest.tpe.asInstanceOf[scala.reflect.runtime.Mirror.Type] - println("testing: "+tree) - val reporter = new ConsoleReporter(new Settings) - val toolbox = new ToolBox(reporter, args mkString " ") - val ttree = toolbox.typeCheck(tree, targetType) - println("result = "+ttree) -} - - diff --git a/test/disabled/pos/t0651.scala b/test/disabled/pos/t0651.scala deleted file mode 100644 index 52bef7e02b..0000000000 --- a/test/disabled/pos/t0651.scala +++ /dev/null @@ -1,4 +0,0 @@ -object Reflection1 extends App { - case class Element(name: String) - println(reflect.Code.lift({val e = Element("someName"); e}).tree) -} diff --git a/test/disabled/pos/t531.scala b/test/disabled/pos/t531.scala deleted file mode 100644 index 02763e08f1..0000000000 --- a/test/disabled/pos/t531.scala +++ /dev/null @@ -1,10 +0,0 @@ -object Test extends App { - import scala.reflect._; - def titi = { - var truc = 0 - val tata: Code[()=>Unit] = () => { - truc = 6 - } - () - } -} diff --git a/test/disabled/pos/t532.scala b/test/disabled/pos/t532.scala deleted file mode 100644 index 32649b1629..0000000000 --- a/test/disabled/pos/t532.scala +++ /dev/null @@ -1,10 +0,0 @@ -object Test extends App { - import scala.reflect._; - def titi: Unit = { - var truc = 0 - val tata: Code[()=>Unit] = () => { - truc = truc + 6 - } - () - } -} diff --git a/test/files/pos/code.scala b/test/files/pos/code.scala new file mode 100644 index 0000000000..4def5d2f94 --- /dev/null +++ b/test/files/pos/code.scala @@ -0,0 +1,20 @@ +import reflect.runtime.Mirror.ToolBox +import scala.tools.nsc.reporters._ +import scala.tools.nsc.Settings + +object Test extends App { + def foo[T](ys: List[T]) = { + val fun: reflect.Code[Int => Int] = x => x + ys.length + fun + } + val code = foo(List(2)) + val tree = code.tree.asInstanceOf[scala.reflect.runtime.Mirror.Tree] + val targetType = code.manifest.tpe.asInstanceOf[scala.reflect.runtime.Mirror.Type] + println("testing: "+tree) + val reporter = new ConsoleReporter(new Settings) + val toolbox = new ToolBox(reporter, args mkString " ") + val ttree = toolbox.typeCheck(tree, targetType) + println("result = "+ttree) +} + + diff --git a/test/files/pos/t0651.scala b/test/files/pos/t0651.scala new file mode 100644 index 0000000000..52bef7e02b --- /dev/null +++ b/test/files/pos/t0651.scala @@ -0,0 +1,4 @@ +object Reflection1 extends App { + case class Element(name: String) + println(reflect.Code.lift({val e = Element("someName"); e}).tree) +} diff --git a/test/files/pos/t531.scala b/test/files/pos/t531.scala new file mode 100644 index 0000000000..02763e08f1 --- /dev/null +++ b/test/files/pos/t531.scala @@ -0,0 +1,10 @@ +object Test extends App { + import scala.reflect._; + def titi = { + var truc = 0 + val tata: Code[()=>Unit] = () => { + truc = 6 + } + () + } +} diff --git a/test/files/pos/t532.scala b/test/files/pos/t532.scala new file mode 100644 index 0000000000..32649b1629 --- /dev/null +++ b/test/files/pos/t532.scala @@ -0,0 +1,10 @@ +object Test extends App { + import scala.reflect._; + def titi: Unit = { + var truc = 0 + val tata: Code[()=>Unit] = () => { + truc = truc + 6 + } + () + } +} -- cgit v1.2.3