Skip to content
This repository has been archived by the owner on Feb 23, 2018. It is now read-only.

Commit

Permalink
Changes to Liftcode to use new reflection semantics, where a compiler…
Browse files Browse the repository at this point in the history
… uses type checking.

git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@25697 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
  • Loading branch information
odersky committed Sep 20, 2011
1 parent e0cfcf3 commit ed89775
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 32 deletions.
2 changes: 2 additions & 0 deletions src/compiler/scala/reflect/runtime/Mirror.scala
Expand Up @@ -39,6 +39,8 @@ class Mirror extends Universe with RuntimeTypes with api.Mirror {
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 =
Expand Down
14 changes: 8 additions & 6 deletions src/compiler/scala/reflect/runtime/RuntimeTypes.scala
Expand Up @@ -5,13 +5,15 @@ import collection.mutable.ListBuffer

trait RuntimeTypes extends Universe with api.RuntimeTypes {

def freeValue(x: Any): Tree = FreeValue(x)
case class FreeVar(_name: TermName, _tpe: Type, value: Any) extends TermSymbol(definitions.RootClass, NoPosition, _name) {
setInfo(_tpe)

// to do: replace with generalized
// case class Literal(x: Any),
// once calls to the deprecated factory Literal(x: Any) has been eliminated from all code.
case class FreeValue(any: Any) extends Tree {
protected def errorSubtrees = Nil
override def hashCode = value.hashCode

override def equals(other: Any): Boolean = other match {
case FreeVar(_, _, value1) => value.asInstanceOf[AnyRef] eq value1.asInstanceOf[AnyRef]
case _ => false
}
}

case class InstanceRefSymbol(value: AnyRef) extends TermSymbol(NoSymbol, NoPosition, nme.EMPTY)
Expand Down
54 changes: 37 additions & 17 deletions src/compiler/scala/tools/nsc/transform/LiftCode.scala
Expand Up @@ -97,21 +97,28 @@ abstract class LiftCode extends Transform with TypingTransformers {

private val localSyms = mutable.ArrayBuffer[Symbol]()
private val symIndex = mutable.HashMap[Symbol, Int]()
private var localClasses = Set[Symbol]()
private val typeTree = mutable.HashMap[Type, Tree]()
private val typeTreeCount = mutable.HashMap[Tree, Int]()

/** Generate tree of the form
*
* { val $localSyms = Array(sym1, ..., symN)
* localSyms(1).setInfo(tpe1)
* { val $mr = scala.reflect.runtime.Mirror
* val $memo = new scala.reflext.runtime.Memoizer
* $local1 = new TypeSymbol(owner1, NoPosition, name1)
* ...
* localSyms(N).setInfo(tpeN)
* $localN = new TermSymbol(ownerN, NoPositiion, nameN)
* $local1.setInfo(tpe1)
* ...
* $localN.setInfo(tpeN)
* $localN.setAnnotations(annotsN)
* rtree
* }
*
* where
*
* - `symI` are the symbols defined locally in `tree`
* - `$localI` are free type symbols in the environment, as well as local symbols
* of refinement types.
* - `tpeI` are the info's of `symI`
* - `rtree` is code that generates `tree` at runtime, maintaining all attributes.
*/
Expand All @@ -131,6 +138,8 @@ abstract class LiftCode extends Transform with TypingTransformers {

// helper methods

private def localName(sym: Symbol) = localPrefix + symIndex(sym)

private def call(fname: String, args: Tree*): Tree =
Apply(termPath(fname), args.toList)

Expand Down Expand Up @@ -178,7 +187,7 @@ abstract class LiftCode extends Transform with TypingTransformers {
private def reifySymRef(sym: Symbol): Tree = {
symIndex get sym match {
case Some(idx) =>
Ident(localPrefix + symIndex(sym))
Ident(localName(sym))
case None =>
if (sym.isStatic)
mirrorCall(if (sym.isType) "staticClass" else "staticModule", reify(sym.fullName))
Expand All @@ -192,10 +201,15 @@ abstract class LiftCode extends Transform with TypingTransformers {
else mirrorCall("selectTerm", rowner, rname, reify(sym.tpe))
}
else {
println("Late local: "+sym)
assert(!sym.isParameter, sym+"/"+sym.owner+"/"+sym.owner.info+"/"+sym.paramPos)
registerLocalSymbol(sym)
reifySymRef(sym)
if (sym.isTerm) {
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)
reifySymRef(sym)
}
}
}
}
Expand All @@ -209,7 +223,7 @@ abstract class LiftCode extends Transform with TypingTransformers {
List(List(reify(sym.owner), reify(sym.pos), reify(sym.name))))
if (sym.flags != 0L)
rsym = Apply(Select(rsym, "setFlag"), List(Literal(Constant(sym.flags))))
ValDef(NoMods, localPrefix + symIndex(sym), TypeTree(), rsym)
ValDef(NoMods, localName(sym), TypeTree(), rsym)
}

/** Generate code to add type and annotation info to a reified symbol
Expand Down Expand Up @@ -255,7 +269,7 @@ abstract class LiftCode extends Transform with TypingTransformers {
case t @ ExistentialType(tparams, underlying) =>
reifyTypeBinder(t, tparams, underlying)
case t @ PolyType(tparams, underlying) =>
reifyTypeBinder(t, tparams, underlying)
reifyTypeBinder(t, tparams, underlying)
case t @ MethodType(params, restpe) =>
reifyTypeBinder(t, params, restpe)
case _ =>
Expand All @@ -268,17 +282,23 @@ abstract class LiftCode extends Transform with TypingTransformers {

/** Reify a tree */
private def reifyTree(tree: Tree): Tree = tree match {
case tree @ This(_) if !(symIndex isDefinedAt tree.symbol) =>
reifyFree(tree)
case tree @ Ident(_) if !(symIndex isDefinedAt tree.symbol) =>
case EmptyTree =>
reifyCaseObject(tree)
case ClassDef(_, _, _, _) =>
localClasses += tree.symbol
reifyCaseClassInstance(tree)
case tree @ This(_) if !(localClasses contains tree.symbol) =>
reifyFree(tree)
case _ =>
var rtree = reifyCaseClassInstance(tree.asInstanceOf[Product])
// var rtree =
reifyCaseClassInstance(tree.asInstanceOf[Product])
/*
if (tree.isDef || tree.isInstanceOf[Function])
registerLocalSymbol(tree.symbol)
if (tree.hasSymbol)
rtree = Apply(Select(rtree, "setSymbol"), List(reifySymRef(tree.symbol)))
Apply(Select(rtree, "setType"), List(reifyType(tree.tpe)))
*/
}

/** Reify a free reference. The result will be either a mirror reference
Expand All @@ -287,8 +307,8 @@ abstract class LiftCode extends Transform with TypingTransformers {
private def reifyFree(tree: Tree): Tree =
if (tree.symbol.hasFlag(MODULE) && tree.symbol.isStatic)
reify(termPath(tree.symbol.fullName))
else
mirrorCall("Literal", tree)
else // make an Ident to a freeVar
mirrorCall("Ident", reifySymRef(tree.symbol))

/** Reify an arbitary value */
private def reify(value: Any): Tree = {
Expand Down
4 changes: 3 additions & 1 deletion src/library/scala/reflect/Code.scala
Expand Up @@ -11,7 +11,9 @@
package scala.reflect

/** This type is required by the compiler and <b>should not be used in client code</b>. */
class Code[T](val tree: scala.reflect.mirror.Tree)
class Code[T](val tree: scala.reflect.mirror.Tree) {

}

/** This type is required by the compiler and <b>should not be used in client code</b>. */
object Code {
Expand Down
8 changes: 6 additions & 2 deletions test/disabled/pos/code.scala
@@ -1,3 +1,7 @@
class Test {
val fun: reflect.Code[Int => Int] = x => x + 1;
object Test extends App {
def foo[T](ys: List[T]) = {
val fun: reflect.Code[Int => Int] = x => x + ys.length
fun
}
println(foo(List(2)).tree)
}
8 changes: 4 additions & 4 deletions test/files/pos/collectGenericCC.scala
@@ -1,10 +1,10 @@
import scala.collection.generic._
import scala.collection.generic.CanBuildFrom
import scala.collection._

object Test {
def collect[A, Res](r: Traversable[A])(implicit bf: CanBuild[A, Res]) = {
val b = bf()
for (a <- r) b += a
def collect[A, Res](r: Traversable[A])(implicit bf: generic.CanBuild[A, Res]) = {
val b: collection.mutable.Builder[A, Res] = bf()
r foreach ((a: A) => b += a)
b.result
}

Expand Down
4 changes: 2 additions & 2 deletions test/files/pos/spec-funs.scala
Expand Up @@ -54,10 +54,10 @@ final class ClosureTest {
}
}

object TestInt extends testing.Benchmark {
object TestInt extends scala.testing.Benchmark {
def run() = (new IntTest).run()
}

object TestClosure extends testing.Benchmark {
object TestClosure extends scala.testing.Benchmark {
def run() = (new ClosureTest).run()
}

0 comments on commit ed89775

Please sign in to comment.