summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2011-09-25 17:09:04 +0000
committerMartin Odersky <odersky@gmail.com>2011-09-25 17:09:04 +0000
commit274ce619902b1e92ec22fcff30b965fbbece2ad3 (patch)
treebec90e01d3dbbcd47dcabb487ba0cb43d7f1b81a
parent5d5826812ae66b748342d86c5185e9bf7612fe7f (diff)
downloadscala-274ce619902b1e92ec22fcff30b965fbbece2ad3.tar.gz
scala-274ce619902b1e92ec22fcff30b965fbbece2ad3.tar.bz2
scala-274ce619902b1e92ec22fcff30b965fbbece2ad3.zip
Getting liftCode to work.
-rw-r--r--src/compiler/scala/reflect/internal/Importers.scala127
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala1
-rw-r--r--src/compiler/scala/reflect/runtime/Mirror.scala34
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala1
-rw-r--r--src/compiler/scala/tools/nsc/transform/LiftCode.scala282
-rw-r--r--src/compiler/scala/tools/nsc/util/SimpleTracer.scala19
-rw-r--r--src/compiler/scala/tools/nsc/util/package.scala4
-rw-r--r--src/compiler/scala/tools/nsc/util/trace.scala18
-rw-r--r--test/files/pos/code.scala (renamed from test/disabled/pos/code.scala)2
-rw-r--r--test/files/pos/t0651.scala (renamed from test/disabled/pos/t0651.scala)0
-rw-r--r--test/files/pos/t531.scala (renamed from test/disabled/pos/t531.scala)0
-rw-r--r--test/files/pos/t532.scala (renamed from test/disabled/pos/t532.scala)0
12 files changed, 214 insertions, 274 deletions
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/files/pos/code.scala
index 96d49106fa..4def5d2f94 100644
--- a/test/disabled/pos/code.scala
+++ b/test/files/pos/code.scala
@@ -3,7 +3,7 @@ import scala.tools.nsc.reporters._
import scala.tools.nsc.Settings
object Test extends App {
- def foo(ys: List[Int]) = {
+ def foo[T](ys: List[T]) = {
val fun: reflect.Code[Int => Int] = x => x + ys.length
fun
}
diff --git a/test/disabled/pos/t0651.scala b/test/files/pos/t0651.scala
index 52bef7e02b..52bef7e02b 100644
--- a/test/disabled/pos/t0651.scala
+++ b/test/files/pos/t0651.scala
diff --git a/test/disabled/pos/t531.scala b/test/files/pos/t531.scala
index 02763e08f1..02763e08f1 100644
--- a/test/disabled/pos/t531.scala
+++ b/test/files/pos/t531.scala
diff --git a/test/disabled/pos/t532.scala b/test/files/pos/t532.scala
index 32649b1629..32649b1629 100644
--- a/test/disabled/pos/t532.scala
+++ b/test/files/pos/t532.scala