summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2011-11-15 18:33:07 +0000
committerMartin Odersky <odersky@gmail.com>2011-11-15 18:33:07 +0000
commit8a64ed85b9a63fd08c13f6730f038ba233d27fb6 (patch)
tree02770db6dbae39192acd196205b9c45bb0df017a
parent7abc466d64681ea7f2610068702019fee66b0579 (diff)
downloadscala-8a64ed85b9a63fd08c13f6730f038ba233d27fb6.tar.gz
scala-8a64ed85b9a63fd08c13f6730f038ba233d27fb6.tar.bz2
scala-8a64ed85b9a63fd08c13f6730f038ba233d27fb6.zip
Towards better reflection APIs.
-rw-r--r--src/compiler/scala/reflect/internal/Scopes.scala3
-rw-r--r--src/compiler/scala/reflect/internal/SymbolTable.scala1
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala17
-rw-r--r--src/compiler/scala/reflect/internal/Trees.scala6
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala15
-rw-r--r--src/compiler/scala/reflect/internal/transform/Transforms.scala29
-rw-r--r--src/compiler/scala/reflect/internal/transform/UnCurry.scala2
-rw-r--r--src/compiler/scala/reflect/runtime/Mirror.scala3
-rw-r--r--src/compiler/scala/reflect/runtime/TreeBuildUtil.scala17
-rw-r--r--src/compiler/scala/reflect/runtime/Universe.scala2
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala6
-rw-r--r--src/compiler/scala/tools/nsc/transform/LiftCode.scala707
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala11
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala4
-rw-r--r--src/library/scala/reflect/Code.scala2
-rw-r--r--src/library/scala/reflect/Manifest.scala20
-rw-r--r--src/library/scala/reflect/api/Mirror.scala20
-rwxr-xr-xsrc/library/scala/reflect/api/Symbols.scala47
-rw-r--r--src/library/scala/reflect/api/Trees.scala6
-rwxr-xr-xsrc/library/scala/reflect/api/Types.scala396
-rw-r--r--test/files/run/t4875.check2
21 files changed, 886 insertions, 430 deletions
diff --git a/src/compiler/scala/reflect/internal/Scopes.scala b/src/compiler/scala/reflect/internal/Scopes.scala
index 3ea43c22f2..fb3012adff 100644
--- a/src/compiler/scala/reflect/internal/Scopes.scala
+++ b/src/compiler/scala/reflect/internal/Scopes.scala
@@ -331,13 +331,12 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
*/
def scopeTransform(owner: Symbol)(op: => Scope): Scope = op
- def newScopeWith(elems: Symbol*) = {
+ def newScopeWith(elems: Symbol*): Scope = {
val scope = newScope
elems foreach scope.enter
scope
}
-
/** The empty scope (immutable).
*/
object EmptyScope extends Scope {
diff --git a/src/compiler/scala/reflect/internal/SymbolTable.scala b/src/compiler/scala/reflect/internal/SymbolTable.scala
index 4b9b9d5959..0e9210f1f7 100644
--- a/src/compiler/scala/reflect/internal/SymbolTable.scala
+++ b/src/compiler/scala/reflect/internal/SymbolTable.scala
@@ -18,6 +18,7 @@ abstract class SymbolTable extends api.Universe
with Constants
with BaseTypeSeqs
with InfoTransformers
+ with transform.Transforms
with StdNames
with AnnotationInfos
with AnnotationCheckers
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala
index a49a5ebd1e..89183b99c7 100644
--- a/src/compiler/scala/reflect/internal/Symbols.scala
+++ b/src/compiler/scala/reflect/internal/Symbols.scala
@@ -41,9 +41,24 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*/
val originalOwner = perRunCaches.newMap[Symbol, Symbol]()
+ abstract class AbsSymbolImpl extends AbsSymbol { this: Symbol =>
+ def newNestedSymbol(pos: Position, name: Name) = name match {
+ case n: TermName => newValue(pos, n)
+ case n: TypeName => newAliasType(pos, n)
+ }
+ def typeSig: Type = info
+ def typeSigIn(site: Type): Type = site.memberInfo(this)
+ def asType: Type = tpe
+ def asTypeIn(site: Type): Type = site.memberType(this)
+ def asTypeConstructor: Type = typeConstructor
+ def setInternalFlags(flag: Long): this.type = { setFlag(flag); this }
+ def setTypeSig(tpe: Type): this.type = { setInfo(tpe); this }
+ def setAnnotations(annots: AnnotationInfo*): this.type = { setAnnotations(annots.toList); this }
+ }
+
/** The class for all symbols */
abstract class Symbol(initOwner: Symbol, initPos: Position, initName: Name)
- extends AbsSymbol
+ extends AbsSymbolImpl
with HasFlags
with Annotatable[Symbol] {
diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala
index 3adba8b66d..1ccd668fd6 100644
--- a/src/compiler/scala/reflect/internal/Trees.scala
+++ b/src/compiler/scala/reflect/internal/Trees.scala
@@ -248,12 +248,6 @@ trait Trees extends api.Trees { self: SymbolTable =>
def This(sym: Symbol): Tree = This(sym.name.toTypeName) setSymbol sym
- def Select(qualifier: Tree, sym: Symbol): Select =
- Select(qualifier, sym.name) setSymbol sym
-
- def Ident(sym: Symbol): Ident =
- Ident(sym.name) setSymbol sym
-
/** Block factory that flattens directly nested blocks.
*/
def Block(stats: Tree*): Block = stats match {
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index 91cc0a6215..c8d7cb3a1e 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -235,8 +235,17 @@ trait Types extends api.Types { self: SymbolTable =>
override def tpe_=(t: Type) = if (t != NoType) throw new UnsupportedOperationException("tpe_=("+t+") inapplicable for <empty>")
}
+ abstract class AbsTypeImpl extends AbsType { this: Type =>
+ def declaration(name: Name): Symbol = decl(name)
+ def nonPrivateDeclaration(name: Name): Symbol = nonPrivateDecl(name)
+ def allDeclarations = decls
+ def allMembers = members
+ def typeArguments = typeArgs
+ def erasedType = transformedType(this)
+ }
+
/** The base class for all types */
- abstract class Type extends AbsType with Annotatable[Type] {
+ abstract class Type extends AbsTypeImpl with Annotatable[Type] {
/** Types for which asSeenFrom always is the identity, no matter what
* prefix or owner.
*/
@@ -1063,7 +1072,7 @@ trait Types extends api.Types { self: SymbolTable =>
/** A base class for types that represent a single value
* (single-types and this-types).
*/
- abstract class SingletonType extends SubType with SimpleTypeProxy {
+ abstract class SingletonType extends SubType with SimpleTypeProxy with AbsSingletonType {
def supertype = underlying
override def isTrivial = false
override def isStable = true
@@ -1435,7 +1444,7 @@ trait Types extends api.Types { self: SymbolTable =>
override def isHigherKinded = (
parents.nonEmpty &&
(parents forall (_.isHigherKinded)) &&
- !phase.erasedTypes // @MO to AM: please check this class!
+ !phase.erasedTypes
)
override def typeParams =
diff --git a/src/compiler/scala/reflect/internal/transform/Transforms.scala b/src/compiler/scala/reflect/internal/transform/Transforms.scala
index c2f3dc6092..a7cc99ba3b 100644
--- a/src/compiler/scala/reflect/internal/transform/Transforms.scala
+++ b/src/compiler/scala/reflect/internal/transform/Transforms.scala
@@ -4,13 +4,36 @@ package transform
trait Transforms { self: SymbolTable =>
- object refChecks extends { val global: Transforms.this.type = self } with RefChecks
- object uncurry extends { val global: Transforms.this.type = self } with UnCurry
- object erasure extends { val global: Transforms.this.type = self } with Erasure
+ /** We need to encode laziness by hand here because the three components refChecks, uncurry and erasure
+ * are overwritten by objects in Global.
+ * It would be best of objects could override lazy values. See SI-5187.
+ * In the absence of this, the Lazy functionality should probably be somewhere
+ * in the standard library. Or is it already?
+ */
+ private class Lazy[T](op: => T) {
+ private var value: T = _
+ private var _isDefined = false
+ def isDefined = _isDefined
+ def force: T = {
+ if (!isDefined) { value = op; _isDefined = true }
+ value
+ }
+ }
+
+ private val refChecksLazy = new Lazy(new { val global: Transforms.this.type = self } with RefChecks)
+ private val uncurryLazy = new Lazy(new { val global: Transforms.this.type = self } with UnCurry)
+ private val erasureLazy = new Lazy(new { val global: Transforms.this.type = self } with Erasure)
+
+ def refChecks = refChecksLazy.force
+ def uncurry = uncurryLazy.force
+ def erasure = erasureLazy.force
def transformedType(sym: Symbol) =
erasure.transformInfo(sym,
uncurry.transformInfo(sym,
refChecks.transformInfo(sym, sym.info)))
+ def transformedType(tpe: Type) =
+ erasure.scalaErasure(uncurry.uncurry(tpe))
+
} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/internal/transform/UnCurry.scala b/src/compiler/scala/reflect/internal/transform/UnCurry.scala
index 1d63aa4582..fd6d4e177d 100644
--- a/src/compiler/scala/reflect/internal/transform/UnCurry.scala
+++ b/src/compiler/scala/reflect/internal/transform/UnCurry.scala
@@ -17,7 +17,7 @@ trait UnCurry {
case _ => false
}
- protected val uncurry: TypeMap = new TypeMap {
+ val uncurry: TypeMap = new TypeMap {
def apply(tp0: Type): Type = {
// tp0.typeSymbolDirect.initialize
val tp = expandAlias(tp0)
diff --git a/src/compiler/scala/reflect/runtime/Mirror.scala b/src/compiler/scala/reflect/runtime/Mirror.scala
index faec0a7783..9490dc4ad7 100644
--- a/src/compiler/scala/reflect/runtime/Mirror.scala
+++ b/src/compiler/scala/reflect/runtime/Mirror.scala
@@ -38,6 +38,9 @@ class Mirror extends Universe with RuntimeTypes with TreeBuildUtil with ToolBoxe
override def classToType(jclazz: java.lang.Class[_]): Type = typeToScala(jclazz)
override def classToSymbol(jclazz: java.lang.Class[_]): Symbol = classToScala(jclazz)
+ override def typeToClass(tpe: Type): java.lang.Class[_] = typeToJavaClass(tpe)
+ override def symbolToClass(sym: Symbol): java.lang.Class[_] = classToJava(sym)
+
}
object Mirror extends Mirror
diff --git a/src/compiler/scala/reflect/runtime/TreeBuildUtil.scala b/src/compiler/scala/reflect/runtime/TreeBuildUtil.scala
index 090862c759..8c9e6a2565 100644
--- a/src/compiler/scala/reflect/runtime/TreeBuildUtil.scala
+++ b/src/compiler/scala/reflect/runtime/TreeBuildUtil.scala
@@ -1,12 +1,13 @@
-package scala.reflect.runtime
+package scala.reflect
+package runtime
-trait TreeBuildUtil extends Universe {
+trait TreeBuildUtil extends Universe with api.TreeBuildUtil {
- def staticClass(name: String): Symbol = definitions.getClass(newTypeName(name))
- def staticModule(name: String): Symbol = definitions.getModule(newTermName(name))
+ def staticClass(fullname: String): Symbol = definitions.getClass(newTypeName(fullname))
+ def staticModule(fullname: String): Symbol = definitions.getModule(newTermName(fullname))
- def thisModuleType(name: String) =
- definitions.getModule(name).moduleClass.thisType
+ def thisModuleType(fullname: String) =
+ definitions.getModule(fullname).moduleClass.thisType
/** Selects type symbol with given name from the defined members of prefix type
*/
@@ -40,9 +41,9 @@ trait TreeBuildUtil extends Universe {
selectIn(owner.info, idx)
}
-
def freeVar(name: String, info: Type, value: Any) = new FreeVar(name, info, value)
- def newScopeWith(decls: List[Symbol]) = new Scope(decls)
+ def modifiersFromInternalFlags(flags: Long, privateWithin: Name, annotations: List[Tree]): Modifiers =
+ Modifiers(flags, privateWithin, annotations)
} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/runtime/Universe.scala b/src/compiler/scala/reflect/runtime/Universe.scala
index a2c48b4c3f..c786bb86c5 100644
--- a/src/compiler/scala/reflect/runtime/Universe.scala
+++ b/src/compiler/scala/reflect/runtime/Universe.scala
@@ -8,7 +8,7 @@ import internal.{SomePhase, NoPhase, Phase, TreeGen}
* It also provides methods to go from Java members to Scala members,
* using the code in JavaConversions.
*/
-class Universe extends SymbolTable with internal.transform.Transforms {
+class Universe extends SymbolTable {
type AbstractFileType = AbstractFile
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 11c0911337..fcbcb94e94 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -417,7 +417,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
} with Pickler
// phaseName = "refchecks"
- object refChecks extends {
+ override object refChecks extends {
val global: Global.this.type = Global.this
val runsAfter = List[String]("pickler")
val runsRightAfter = None
@@ -431,7 +431,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
} with LiftCode
// phaseName = "uncurry"
- object uncurry extends {
+ override object uncurry extends {
val global: Global.this.type = Global.this
val runsAfter = List[String]("refchecks", "liftcode")
val runsRightAfter = None
@@ -459,7 +459,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
} with SpecializeTypes
// phaseName = "erasure"
- object erasure extends {
+ override object erasure extends {
val global: Global.this.type = Global.this
val runsAfter = List[String]("explicitouter")
val runsRightAfter = Some("explicitouter")
diff --git a/src/compiler/scala/tools/nsc/transform/LiftCode.scala b/src/compiler/scala/tools/nsc/transform/LiftCode.scala
index 82df75067d..ac2788b8ef 100644
--- a/src/compiler/scala/tools/nsc/transform/LiftCode.scala
+++ b/src/compiler/scala/tools/nsc/transform/LiftCode.scala
@@ -12,7 +12,8 @@ import scala.collection.{ mutable, immutable }
import scala.collection.mutable.ListBuffer
import scala.tools.nsc.util.FreshNameCreator
-/** Translate expressions of the form reflect.Code.lift(exp)
+/**
+ * Translate expressions of the form reflect.Code.lift(exp)
* to the reified "reflect trees" representation of exp.
* Also: mutable variables that are accessed from a local function are wrapped in refs.
*
@@ -21,9 +22,9 @@ import scala.tools.nsc.util.FreshNameCreator
*/
abstract class LiftCode extends Transform with TypingTransformers {
- import global._ // the global environment
- import definitions._ // standard classes and methods
- import typer.{typed, atOwner} // methods to type trees
+ import global._ // the global environment
+ import definitions._ // standard classes and methods
+ import typer.{ typed, atOwner } // methods to type trees
val symbols: global.type = global
@@ -49,7 +50,7 @@ abstract class LiftCode extends Transform with TypingTransformers {
super.transformUnit(unit)
}
for (v <- freeMutableVars) //!!! remove
- assert(converted contains v, "unconverted: "+v+" in "+v.owner+" in unit "+unit)
+ assert(converted contains v, "unconverted: " + v + " in " + v.owner + " in unit " + unit)
}
override def transform(tree: Tree): Tree = {
@@ -75,7 +76,7 @@ abstract class LiftCode extends Transform with TypingTransformers {
}
sym resetFlag MUTABLE
sym removeAnnotation VolatileAttr
- converted += sym// dereference boxed variables
+ converted += sym // dereference boxed variables
treeCopy.ValDef(tree, mods &~ MUTABLE, name, tpt1, rhs1)
case Ident(name) if freeMutableVars(sym) =>
localTyper.typedPos(tree.pos) {
@@ -86,348 +87,14 @@ abstract class LiftCode extends Transform with TypingTransformers {
}
}
- /**
- * Given a tree, generate a tree that when exeuted ar tuntime produces the original tree.
- * For instance: Given
- *
- * var x = 1; Code(x + 1)
- *
- * The `x + 1` expression is reified to
- *
- * $mr.Apply($mr.Select($mr.Ident($mr.freeVar("x". <Int>, x), "+"), List($mr.Literal($mr.Constant(1))))))
- *
- * Or, the term name 'abc' is reified to:
- *
- * $mr.Apply($mr.Select($mr.Ident("newTermName")), List(Literal(Constant("abc")))))
- *
- * todo: Treat embedded Code blocks by merging them into containing block
- *
- */
- class Reifier() {
-
- final val mirrorFullName = "scala.reflect.runtime.Mirror"
- final val mirrorShortName = "$mr"
- final val mirrorPrefix = mirrorShortName + "."
- final val scalaPrefix = "scala."
- final val localPrefix = "$local"
- final val memoizerName = "$memo"
-
- 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
- *
- * { val $mr = scala.reflect.runtime.Mirror
- * $local1 = new TypeSymbol(owner1, NoPosition, name1)
- * ...
- * $localN = new TermSymbol(ownerN, NoPositiion, nameN)
- * $local1.setInfo(tpe1)
- * ...
- * $localN.setInfo(tpeN)
- * $localN.setAnnotations(annotsN)
- * rtree
- * }
- *
- * where
- *
- * - `$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.
- */
- def reifyTopLevel(tree: Tree): Tree = {
- val rtree = reify(tree)
- Block(mirrorAlias :: reifySymbolTableSetup, rtree)
- }
-
- private def isLocatable(sym: Symbol) =
- sym.isPackageClass || sym.owner.isClass || sym.isTypeParameter && sym.paramPos >= 0
-
- private def registerReifiableSymbol(sym: Symbol): Unit =
- if (!(symIndex contains sym)) {
- sym.owner.ownersIterator.find(!isLocatable(_)) match {
- case Some(outer) => registerReifiableSymbol(outer)
- case None =>
- }
- symIndex(sym) = reifiableSyms.length
- reifiableSyms += sym
- }
-
- // helper methods
-
- private def localName(sym: Symbol) = localPrefix + symIndex(sym)
-
- private def call(fname: String, args: Tree*): Tree =
- Apply(termPath(fname), args.toList)
-
- private def mirrorSelect(name: String): Tree =
- termPath(mirrorPrefix + name)
-
- private def mirrorCall(name: String, args: Tree*): Tree =
- call(mirrorPrefix + name, args: _*)
-
- private def mirrorFactoryCall(value: Product, args: Tree*): Tree =
- mirrorCall(value.productPrefix, args: _*)
-
- private def scalaFactoryCall(name: String, args: Tree*): Tree =
- call(scalaPrefix + name + ".apply", args: _*)
-
- private def mkList(args: List[Tree]): Tree =
- scalaFactoryCall("collection.immutable.List", args: _*)
-
- /** Reify a case object defined in Mirror
- */
- private def reifyCaseObject(value: Product) = mirrorSelect(value.productPrefix)
-
- /** Reify an instance of a case class defined in Mirror
- */
- private def reifyCaseClassInstance(value: Product) =
- mirrorFactoryCall(value, (value.productIterator map reify).toList: _*)
-
- private def reifyAggregate(name: String, args: Any*) =
- scalaFactoryCall(name, (args map reify).toList: _*)
-
- /** Reify a list
- */
- private def reifyList(xs: List[Any]): Tree =
- mkList(xs map reify)
-
- /** Reify a name */
- private def reifyName(name: Name) =
- mirrorCall(if (name.isTypeName) "newTypeName" else "newTermName", Literal(Constant(name.toString)))
-
- private def isFree(sym: Symbol) =
- !(symIndex contains sym)
-
- /** Reify a reference to a symbol
- */
- private def reifySymRef(sym: Symbol): Tree = {
- symIndex get sym match {
- case Some(idx) =>
- Ident(localName(sym))
- case None =>
- if (sym == NoSymbol)
- mirrorSelect("NoSymbol")
- else 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.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 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) {
- if (reifyDebug) println("Free: "+sym)
- mirrorCall("freeVar", reify(sym.name.toString), reify(sym.tpe), Ident(sym))
- } else {
- if (reifyDebug) println("Late local: "+sym)
- registerReifiableSymbol(sym)
- reifySymRef(sym)
- }
- }
- }
- }
-
- /** reify the creation of a symbol
- */
- private def reifySymbolDef(sym: Symbol): Tree = {
- 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))))
- if (sym.flags != 0L)
- rsym = Apply(Select(rsym, "setFlag"), List(Literal(Constant(sym.flags))))
- ValDef(NoMods, localName(sym), TypeTree(), rsym)
- }
-
- /** Generate code to add type and annotation info to a reified symbol
- */
- private def fillInSymbol(sym: Symbol): Tree = {
- val rset = Apply(Select(reifySymRef(sym), "setInfo"), List(reifyType(sym.info)))
- 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 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 registerReifiableSymbol
- mkList(syms map reifySymRef)
- }
-
- /** Reify a type that defines some symbols */
- private def reifyTypeBinder(value: Product, bound: List[Symbol], underlying: Type): Tree =
- mirrorFactoryCall(value, reifySymbols(bound), reify(underlying))
-
- /** Reify a type */
- 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 @ ClassInfoType(parents, decls, clazz) =>
- registerReifiableSymbol(clazz)
- 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 */
- private def reifyTree(tree: Tree): Tree = tree match {
- case EmptyTree =>
- reifyCaseObject(tree)
- case This(_) if !(boundSyms contains tree.symbol) =>
- reifyFree(tree)
- case Ident(_) if !(boundSyms contains tree.symbol) =>
- reifyFree(tree)
- case TypeTree() if (tree.tpe != null) =>
- mirrorCall("TypeTree", reifyType(tree.tpe))
- case _ =>
- if (tree.isDef) boundSyms += tree.symbol
- reifyCaseClassInstance(tree.asInstanceOf[Product])
-/*
- if (tree.isDef || tree.isInstanceOf[Function])
- registerReifiableSymbol(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
- * to a global value, or else a mirror Literal.
- */
- private def reifyFree(tree: Tree): Tree =
- mirrorCall("Ident", reifySymRef(tree.symbol))
-
- /** Reify an arbitary value */
- private def reify(value: Any): Tree = {
- 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)
- */
- private def path(fullname: String, mkName: String => Name): Tree = {
- val parts = fullname split "\\."
- val prefixParts = parts.init
- val lastName = mkName(parts.last)
- if (prefixParts.isEmpty) Ident(lastName)
- else {
- val prefixTree = ((Ident(prefixParts.head): Tree) /: prefixParts.tail)(Select(_, _))
- Select(prefixTree, lastName)
- }
- }
-
- /** An (unreified) path that refers to term definition with given fully qualified name */
- private def termPath(fullname: String): Tree = path(fullname, newTermName)
-
- /** An (unreified) path that refers to type definition with given fully qualified name */
- private def typePath(fullname: String): Tree = path(fullname, newTypeName)
-
- private def mirrorAlias =
- ValDef(NoMods, mirrorShortName, TypeTree(), termPath(mirrorFullName))
-
- /** 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 < 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 def cannotReify(value: Any): Nothing =
- abort("don't know how to reify " + value + " of class " + value.getClass)
-
- }
-
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)
- New(TypeTree(appliedType(definitions.CodeClass.typeConstructor, List(tree.tpe))),
+ val treetpe =
+ if (tree.tpe.typeSymbol.isAnonymousClass) tree.tpe.typeSymbol.classBound
+ else tree.tpe
+ New(TypeTree(appliedType(definitions.CodeClass.typeConstructor, List(treetpe))),
List(List(arg)))
}
@@ -499,4 +166,356 @@ abstract class LiftCode extends Transform with TypingTransformers {
}
}
}
+
+ /**
+ * Given a tree or type, generate a tree that when executed at runtime produces the original tree or type.
+ * For instance: Given
+ *
+ * var x = 1; Code(x + 1)
+ *
+ * The `x + 1` expression is reified to
+ *
+ * $mr.Apply($mr.Select($mr.Ident($mr.freeVar("x". <Int>, x), "+"), List($mr.Literal($mr.Constant(1))))))
+ *
+ * Or, the term name 'abc' is reified to:
+ *
+ * $mr.Apply($mr.Select($mr.Ident("newTermName")), List(Literal(Constant("abc")))))
+ *
+ * todo: Treat embedded Code blocks by merging them into containing block
+ *
+ */
+ class Reifier() {
+
+ final val mirrorFullName = "scala.reflect.mirror"
+ final val mirrorShortName = "$mr"
+ final val mirrorPrefix = mirrorShortName + "."
+ final val scalaPrefix = "scala."
+ final val localPrefix = "$local"
+ final val memoizerName = "$memo"
+
+ val reifyDebug = settings.Yreifydebug.value
+
+ 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
+ *
+ * { val $mr = scala.reflect.runtime.Mirror
+ * $local1 = new TypeSymbol(owner1, NoPosition, name1)
+ * ...
+ * $localN = new TermSymbol(ownerN, NoPositiion, nameN)
+ * $local1.setInfo(tpe1)
+ * ...
+ * $localN.setInfo(tpeN)
+ * $localN.setAnnotations(annotsN)
+ * rtree
+ * }
+ *
+ * where
+ *
+ * - `$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 `data` at runtime, maintaining all attributes.
+ * - `data` is typically a tree or a type.
+ */
+ def reifyTopLevel(data: Any): Tree = {
+ val rtree = reify(data)
+ Block(mirrorAlias :: reifySymbolTableSetup, rtree)
+ }
+
+ private def isLocatable(sym: Symbol) =
+ sym.isPackageClass || sym.owner.isClass || sym.isTypeParameter && sym.paramPos >= 0
+
+ private def registerReifiableSymbol(sym: Symbol): Unit =
+ if (!(symIndex contains sym)) {
+ sym.owner.ownersIterator.find(!isLocatable(_)) match {
+ case Some(outer) => registerReifiableSymbol(outer)
+ case None =>
+ }
+ symIndex(sym) = reifiableSyms.length
+ reifiableSyms += sym
+ }
+
+ // helper methods
+
+ private def localName(sym: Symbol) = localPrefix + symIndex(sym)
+
+ private def call(fname: String, args: Tree*): Tree =
+ Apply(termPath(fname), args.toList)
+
+ private def mirrorSelect(name: String): Tree =
+ termPath(mirrorPrefix + name)
+
+ private def mirrorCall(name: String, args: Tree*): Tree =
+ call(mirrorPrefix + name, args: _*)
+
+ private def mirrorFactoryCall(value: Product, args: Tree*): Tree =
+ mirrorCall(value.productPrefix, args: _*)
+
+ private def scalaFactoryCall(name: String, args: Tree*): Tree =
+ call(scalaPrefix + name + ".apply", args: _*)
+
+ private def mkList(args: List[Tree]): Tree =
+ scalaFactoryCall("collection.immutable.List", args: _*)
+
+ /**
+ * Reify a case object defined in Mirror
+ */
+ private def reifyCaseObject(value: Product) = mirrorSelect(value.productPrefix)
+
+ /**
+ * Reify an instance of a case class defined in Mirror
+ */
+ private def reifyCaseClassInstance(value: Product) =
+ mirrorFactoryCall(value, (value.productIterator map reify).toList: _*)
+
+ private def reifyAggregate(name: String, args: Any*) =
+ scalaFactoryCall(name, (args map reify).toList: _*)
+
+ /**
+ * Reify a list
+ */
+ private def reifyList(xs: List[Any]): Tree =
+ mkList(xs map reify)
+
+ /** Reify a name */
+ private def reifyName(name: Name) =
+ mirrorCall(if (name.isTypeName) "newTypeName" else "newTermName", Literal(Constant(name.toString)))
+
+ private def isFree(sym: Symbol) =
+ !(symIndex contains sym)
+
+ /**
+ * Reify a reference to a symbol
+ */
+ private def reifySymRef(sym: Symbol): Tree = {
+ symIndex get sym match {
+ case Some(idx) =>
+ Ident(localName(sym))
+ case None =>
+ if (sym == NoSymbol)
+ mirrorSelect("NoSymbol")
+ else 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.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 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) {
+ if (reifyDebug) println("Free: " + sym)
+ mirrorCall("freeVar", reify(sym.name.toString), reify(sym.tpe), Ident(sym))
+ } else {
+ if (reifyDebug) println("Late local: " + sym)
+ registerReifiableSymbol(sym)
+ reifySymRef(sym)
+ }
+ }
+ }
+ }
+
+ /**
+ * reify the creation of a symbol
+ */
+ private def reifySymbolDef(sym: Symbol): Tree = {
+ if (reifyDebug) println("reify sym def " + sym)
+ var rsym: Tree =
+ Apply(
+ Select(reify(sym.owner), "newNestedSymbol"),
+ List(reify(sym.pos), reify(sym.name)))
+ if (sym.flags != 0L)
+ rsym = Apply(Select(rsym, "setInternalFlags"), List(Literal(Constant(sym.flags))))
+ ValDef(NoMods, localName(sym), TypeTree(), rsym)
+ }
+
+ /**
+ * Generate code to add type and annotation info to a reified symbol
+ */
+ private def fillInSymbol(sym: Symbol): Tree = {
+ val rset = Apply(Select(reifySymRef(sym), "setTypeSig"), List(reifyType(sym.info)))
+ 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 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 registerReifiableSymbol
+ mkList(syms map reifySymRef)
+ }
+
+ /** Reify a type that defines some symbols */
+ private def reifyTypeBinder(value: Product, bound: List[Symbol], underlying: Type): Tree =
+ mirrorFactoryCall(value, reifySymbols(bound), reify(underlying))
+
+ /** Reify a type */
+ 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), "asTypeConstructor")
+ 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 @ ClassInfoType(parents, decls, clazz) =>
+ registerReifiableSymbol(clazz)
+ 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 _ =>
+ cannotReify(tpe)
+ }
+ }
+
+ /** Reify a tree */
+ private def reifyTree(tree: Tree): Tree = tree match {
+ case EmptyTree =>
+ reifyCaseObject(tree)
+ case This(_) if !(boundSyms contains tree.symbol) =>
+ reifyFree(tree)
+ case Ident(_) if !(boundSyms contains tree.symbol) =>
+ reifyFree(tree)
+ case TypeTree() if (tree.tpe != null) =>
+ mirrorCall("TypeTree", reifyType(tree.tpe))
+ case _ =>
+ if (tree.isDef) boundSyms += tree.symbol
+ reifyCaseClassInstance(tree.asInstanceOf[Product])
+ /*
+ if (tree.isDef || tree.isInstanceOf[Function])
+ registerReifiableSymbol(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
+ * to a global value, or else a mirror Literal.
+ */
+ private def reifyFree(tree: Tree): Tree =
+ mirrorCall("Ident", reifySymRef(tree.symbol))
+
+ /** Reify an arbitary value */
+ private def reify(value: Any): Tree = {
+ 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(_, _, _) =>
+ reifyCaseClassInstance(value.asInstanceOf[Product])
+ case Modifiers(flags, qual, annots) =>
+ mirrorCall("modifiersFromInternalFlags", reify(flags), reify(qual), reify(annots))
+ 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)
+ */
+ private def path(fullname: String, mkName: String => Name): Tree = {
+ val parts = fullname split "\\."
+ val prefixParts = parts.init
+ val lastName = mkName(parts.last)
+ if (prefixParts.isEmpty) Ident(lastName)
+ else {
+ val prefixTree = ((Ident(prefixParts.head): Tree) /: prefixParts.tail)(Select(_, _))
+ Select(prefixTree, lastName)
+ }
+ }
+
+ /** An (unreified) path that refers to term definition with given fully qualified name */
+ private def termPath(fullname: String): Tree = path(fullname, newTermName)
+
+ /** An (unreified) path that refers to type definition with given fully qualified name */
+ private def typePath(fullname: String): Tree = path(fullname, newTypeName)
+
+ private def mirrorAlias =
+ ValDef(NoMods, mirrorShortName, TypeTree(), termPath(mirrorFullName))
+
+ /**
+ * 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 < 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 def cannotReify(value: Any): Nothing =
+ abort("don't know how to reify " + value + " of class " + value.getClass)
+ }
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index d58df50451..2c32d22081 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -1110,7 +1110,7 @@ trait Implicits {
// a manifest should have been found by normal searchImplicit
EmptyTree
}
- case RefinedType(parents, decls) =>
+ case RefinedType(parents, decls) => // !!! not yet: if !full || decls.isEmpty =>
// refinement is not generated yet
if (hasLength(parents, 1)) findManifest(parents.head)
else if (full) manifestFactoryCall("intersectionType", tp, parents map findSubManifest: _*)
@@ -1119,7 +1119,14 @@ trait Implicits {
mot(tp1.skolemizeExistential, from, to)
case _ =>
EmptyTree
- }
+/* !!! the following is almost right, but we have to splice nested manifest
+ * !!! types into this type. This requires a substantial extension of
+ * !!! reifiers.
+ val reifier = new liftcode.Reifier()
+ val rtree = reifier.reifyTopLevel(tp1)
+ manifestFactoryCall("apply", tp, rtree)
+*/
+ }
}
mot(tp, Nil, Nil)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index e758c8960a..fd75b03297 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -368,8 +368,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val tp1 = apply(tree.tpe)
if (hiddenSymbols.isEmpty) tree setType tp1
else if (hiddenSymbols exists (_.isErroneous)) setError(tree)
- else if (isFullyDefined(pt)) tree setType pt //todo: eliminate
- else if (tp1.typeSymbol.isAnonymousClass) // todo: eliminate
+ else if (isFullyDefined(pt)) tree setType pt
+ else if (tp1.typeSymbol.isAnonymousClass)
check(owner, scope, pt, tree setType tp1.typeSymbol.classBound)
else if (owner == NoSymbol)
tree setType packSymbols(hiddenSymbols.reverse, tp1)
diff --git a/src/library/scala/reflect/Code.scala b/src/library/scala/reflect/Code.scala
index 65954c7970..52705d302c 100644
--- a/src/library/scala/reflect/Code.scala
+++ b/src/library/scala/reflect/Code.scala
@@ -13,7 +13,7 @@ package scala.reflect
/** This type is required by the compiler and <b>should not be used in client code</b>. */
class Code[T: Manifest](val tree: scala.reflect.mirror.Tree) {
val manifest = implicitly[Manifest[T]]
- override def toString = "Code(manifest = " + manifest + ")"
+ override def toString = "Code(tree = "+tree+", manifest = "+manifest+")"
}
/** This type is required by the compiler and <b>should not be used in client code</b>. */
diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala
index 9151b0c2a7..df5f64cdf6 100644
--- a/src/library/scala/reflect/Manifest.scala
+++ b/src/library/scala/reflect/Manifest.scala
@@ -284,4 +284,24 @@ object Manifest {
override lazy val tpe = mirror.RefinedType((parents map (_.tpe)).toList, newScope)
override def toString = parents.mkString(" with ")
}
+
+ /** A generic manifest factory from a reflect.Type. Except where
+ * mandated by performance considerations, we should replace most
+ * other manifest factories by this one. There's just one thing
+ * that needs to be done first: A Manifest's type can refer
+ * to type variables that are controlled by manifests. In that
+ * case the reified type needs to contain the type passed in the manifest
+ * instead of the reference to the manifest. Note that splicing manifests
+ * into manfifests is completely analogous to splicing code blocks into
+ * code blocks. Manifest[T] and Code[T] are really the same thing, only one
+ * works for types, the other for trees.
+ * Another complication is that once we generate manifests from types, we really
+ * should have reflection as a standard component shipped with the standard library,
+ * instead of in scala-compiler.jar.
+ */
+ def apply[T](_tpe: mirror.Type): Manifest[T] = new Manifest[T] {
+ override lazy val tpe = _tpe
+ override def erasure = mirror.typeToClass(_tpe.erasedType)
+ override def toString = _tpe.toString
+ }
}
diff --git a/src/library/scala/reflect/api/Mirror.scala b/src/library/scala/reflect/api/Mirror.scala
index 9dc861464a..53ac84f8cb 100644
--- a/src/library/scala/reflect/api/Mirror.scala
+++ b/src/library/scala/reflect/api/Mirror.scala
@@ -5,7 +5,7 @@ package api
* runtime entities such as class names and object instances
* with a refexive universe.
*/
-trait Mirror extends Universe with RuntimeTypes {
+trait Mirror extends Universe with RuntimeTypes with TreeBuildUtil {
/** The Scala class symbol that has given fully qualified name
* @param name The fully qualified name of the class to be returned
@@ -65,17 +65,15 @@ trait Mirror extends Universe with RuntimeTypes {
*/
def classToSymbol(clazz: java.lang.Class[_]): Symbol
-/*
- /** 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
+ /** Maps a Scala type to the corresponding Java class object
*/
- def selectTerm(pre: Type, name: String, tpe: Type) : Symbol
+ def typeToClass(tpe: Type): java.lang.Class[_]
- /** Selects type symbol with given name from the defined members of prefix type
+ /** Maps a Scala symbol to the corresponding Java class object
+ * @throws ClassNotFoundException if there is no Java class
+ * corresponding to the given Scala symbol.
+ * Note: If the Scala symbol is ArrayClass, a ClassNotFound exception is thrown
+ * because there is no unique Java class corresponding to a Scala generic array
*/
- def selectType(pre: Type, name: String): Symbol
-
-*/
+ def symbolToClass(sym: Symbol): java.lang.Class[_]
}
diff --git a/src/library/scala/reflect/api/Symbols.scala b/src/library/scala/reflect/api/Symbols.scala
index 0f0fdf06af..3c4408aacd 100755
--- a/src/library/scala/reflect/api/Symbols.scala
+++ b/src/library/scala/reflect/api/Symbols.scala
@@ -103,10 +103,10 @@ trait Symbols { self: Universe =>
*/
def sourceModule: Symbol
- /** If symbol is an object definition, it's implied associated class,
+ /** If symbol is an object definition, its implied associated class,
* otherwise NoSymbol
*/
- def moduleClass: Symbol
+ def moduleClass: Symbol // needed for LiftCode
/** The top-level class containing this symbol. */
def toplevelClass: Symbol
@@ -122,6 +122,49 @@ trait Symbols { self: Universe =>
def isClass : Boolean
def isAliasType : Boolean
def isAbstractType : Boolean
+
+ /** The type signature of this symbol.
+ * Note if symbol is a member of a class, one almost always is interested
+ * in `typeSigIn` with a site type instead.
+ */
+ def typeSig: Type
+
+ /** The type signature of this symbol seen as a member of given type `site`.
+ */
+ def typeSigIn(site: Type): Type
+
+ /** The type constructor corresponding to this type symbol.
+ */
+ def asTypeConstructor: Type // needed by LiftCode
+
+ /** A type reference that refers to this type symbol
+ * Note if symbol is a member of a class, one almost always is interested
+ * in `asTypeIn` with a site type instead.
+ */
+ def asType: Type
+
+ /** A type reference that refers to this type symbol seen as a member of given type `site`.
+ */
+ def asTypeIn(site: Type): Type
+
+ /** A fresh symbol with given position `pos` and name `name` that has
+ * the current symbol as its owner.
+ */
+ def newNestedSymbol(pos: Position, name: Name): Symbol // needed by LiftCode
+
+ /** Low-level operation to set the symbol's flags
+ * @return the symbol itself
+ */
+ def setInternalFlags(flags: Long): this.type // needed by LiftCode
+
+ /** Set symbol's type signature to given type
+ * @return the symbol itself
+ */
+ def setTypeSig(tpe: Type): this.type // needed by LiftCode
+
+ /** Set symbol's annotations to given annotations `annots`.
+ */
+ def setAnnotations(annots: AnnotationInfo*): this.type // needed by LiftCode
}
val NoSymbol: Symbol
diff --git a/src/library/scala/reflect/api/Trees.scala b/src/library/scala/reflect/api/Trees.scala
index de01c0b862..3e5dae739d 100644
--- a/src/library/scala/reflect/api/Trees.scala
+++ b/src/library/scala/reflect/api/Trees.scala
@@ -542,9 +542,15 @@ trait Trees /*extends reflect.generic.Trees*/ { self: Universe =>
case class Select(qualifier: Tree, name: Name)
extends RefTree
+ def Select(qualifier: Tree, sym: Symbol): Select =
+ Select(qualifier, sym.name) setSymbol sym
+
/** Identifier <name> */
case class Ident(name: Name) extends RefTree { }
+ def Ident(sym: Symbol): Ident =
+ Ident(sym.name) setSymbol sym
+
class BackQuotedIdent(name: Name) extends Ident(name)
/** Literal */
diff --git a/src/library/scala/reflect/api/Types.scala b/src/library/scala/reflect/api/Types.scala
index 0f6cdcd2e9..75189d51cb 100755
--- a/src/library/scala/reflect/api/Types.scala
+++ b/src/library/scala/reflect/api/Types.scala
@@ -3,46 +3,324 @@ package api
trait Types { self: Universe =>
+ /** This class declares operations that are visible in a Type.
+ */
abstract class AbsType {
+
+ /** The type symbol associated with the type, or `NoSymbol` for types
+ * that do not refer to a type symbol.
+ */
def typeSymbol: Symbol
- def decl(name: Name): Symbol
+
+ /** The defined or declared members with name `name` in this type;
+ * an OverloadedSymbol if several exist, NoSymbol if none exist.
+ * Alternatives of overloaded symbol appear in the order they are declared.
+ */
+ def declaration(name: Name): Symbol
+
+ /** The member with given name, either directly declared or inherited,
+ * an OverloadedSymbol if several exist, NoSymbol if none exist.
+ */
def member(name: Name): Symbol
+
+ /** The non-private member with given name, either directly declared or inherited,
+ * an OverloadedSymbol if several exist, NoSymbol if none exist.
+ */
+ def nonPrivateMember(name: Name): Symbol
+
+ /** An iterable containing all members of this type (directly declared or inherited)
+ * Members appear in the linearization order of their owners.
+ * Members with the same owner appear in reverse order of their declarations.
+ */
+ def allMembers: Iterable[Symbol]
+
+ /** An iterable containing all non-private members of this type (directly declared or inherited)
+ * Members appear in the linearization order of their owners.
+ * Members with the same owner appear in reverse order of their declarations.
+ */
+ def nonPrivateMembers: Iterable[Symbol]
+
+ /** Substitute types in `to` for corresponding occurrences of references to
+ * symbols `from` in this type.
+ */
+ def subst(from: List[Symbol], to: List[Type]): Type
+
+ /** If this is a parameterized types, the type arguments.
+ * Otherwise the empty list
+ */
+ def typeArguments: List[Type]
+
+ /** Is this type a type constructor that is missing its type arguments?
+ */
+ def isHigherKinded: Boolean
+
+ /**
+ * Expands type aliases and converts higher-kinded TypeRefs to PolyTypes.
+ * Functions on types are also implemented as PolyTypes.
+ *
+ * Example: (in the below, <List> is the type constructor of List)
+ * TypeRef(pre, <List>, List()) is replaced by
+ * PolyType(X, TypeRef(pre, <List>, List(X)))
+ */
+ def normalize: Type
+
+ /** Does this type conform to given type argument `that`? */
+ def <:< (that: Type): Boolean
+
+ /** Is this type equivalent to given type argument `that`? */
+ def =:= (that: Type): Boolean
+
+ /** The list of all baseclasses of this type (including its own typeSymbol)
+ * in reverse linearization order, starting with the class itself and ending
+ * in class Any.
+ */
+ def baseClasses: List[Symbol]
+
+ /** The least type instance of given class which is a supertype
+ * of this type. Example:
+ * {{{
+ * class D[T]
+ * class C extends p.D[Int]
+ * ThisType(C).baseType(D) = p.D[Int]
+ * }}}
+ */
+ def baseType(clazz: Symbol): Type
+
+ /** This type as seen from prefix `pre` and class `clazz`. This means:
+ * Replace all thistypes of `clazz` or one of its subclasses
+ * by `pre` and instantiate all parameters by arguments of `pre`.
+ * Proceed analogously for thistypes referring to outer classes.
+ *
+ * Example:
+ * class D[T] { def m: T }
+ * class C extends p.D[Int]
+ * T.asSeenFrom(ThisType(C), D) (where D is owner of m)
+ * = Int
+ */
+ def asSeenFrom(pre: Type, clazz: Symbol): Type
+
+ /** The erased type corresponding to this type after
+ * all transcformations from Scala to Java have been performed.
+ */
+ def erasedType: Type
+
+ /** Apply `f` to each part of this type, returning
+ * a new type. children get mapped before their parents */
+ def map(f: Type => Type): Type
+
+ /** Apply `f` to each part of this type, for side effects only */
+ def foreach(f: Type => Unit)
+
+ /** Returns optionally first type (in a preorder traversal) which satisfies predicate `p`,
+ * or None if none exists.
+ */
+ def find(p: Type => Boolean): Option[Type]
+
+ /** Is there part of this type which satisfies predicate `p`? */
+ def exists(p: Type => Boolean): Boolean
+
+ /** Does this type contain a reference to given symbol? */
+ def contains(sym: Symbol): Boolean
}
+ /** This class declares methods that are visible in a `SingleType`.
+ */
+ trait AbsSingletonType extends AbsType {
+
+ /** The type underlying a singleton type */
+ def underlying: Type
+
+ /** Widen from singleton type to its underlying non-singleton
+ * base type by applying one or more `underlying` dereferences,
+ * identity for all other types.
+ *
+ * class Outer { class C ; val x: C }
+ * val o: Outer
+ * <o.x.type>.widen = o.C
+ */
+ def widen: Type
+ }
+
+ /** This class declares methods that are visible in a `CompoundType` (i.e.
+ * a class/trait/object template or refined type of the form
+ * {{{
+ * P_1 with ... with P_m { D_1; ...; D_n }
+ * }}}
+ * P_n
+ */
+ trait AbsCompoundType extends AbsType {
+
+ /** The list of parent types of this compound type */
+ def parents: List[Type]
+
+ /** The collection of declarations in this compound type
+ */
+ def allDeclarations: Iterable[Symbol]
+ }
+
+ /** The type of Scala types, and also Scala type signatures.
+ * (No difference is internally made between the two).
+ */
type Type >: Null <: AbsType
+
+ /** The type of Scala singleton types, i.e. types that are inhabited
+ * by only one nun-null value. These include types of the forms
+ * {{{
+ * C.this.type
+ * C.super.type
+ * x.type
+ * }}}
+ * as well as constant types.
+ */
type SingletonType >: Null <: Type
+ /** This constant is used as a special value that indicates that no meaningful type exists.
+ */
val NoType: Type
+
+ /** This constant is used as a special value denoting the empty prefix in a path dependent type.
+ * For instance `x.type` is represented as `SingleType(NoPrefix, <x>)`, where `<x>` stands for
+ * the symbol for `x`.
+ */
val NoPrefix: Type
+ /** The `ThisType` type describes types of the form on the left with the
+ * correspnding ThisType representations to the right.
+ * {{{
+ * C.this.type ThisType(C)
+ * }}}
+ */
type ThisType <: SingletonType
+
+ /** The constructor/deconstructor for `ThisType` instances. */
val ThisType: ThisTypeExtractor
+ /** An extractor class to create and pattern match with syntax `ThisType(sym)`
+ * where `sym` is the class prefix of the this type.
+ */
+ abstract class ThisTypeExtractor {
+ def apply(sym: Symbol): Type
+ def unapply(tpe: ThisType): Option[Symbol]
+ }
+
+ /** The `TypeRef` type describes types of any of the forms on the left,
+ * with their TypeRef representations to the right.
+ * {{{
+ * T # C[T_1, ..., T_n] TypeRef(T, C, List(T_1, ..., T_n))
+ * p.C[T_1, ..., T_n] TypeRef(p.type, C, List(T_1, ..., T_n))
+ * C[T_1, ..., T_n] TypeRef(NoPrefix, C, List(T_1, ..., T_n))
+ * T # C TypeRef(T, C, Nil)
+ * p.C TypeRef(p.type, C, Nil)
+ * C TypeRef(NoPrefix, C, Nil)
+ * }}}
+ */
type TypeRef <: Type
+
+ /** The constructor/deconstructor for `TypeRef` instances. */
val TypeRef: TypeRefExtractor
+ /** An extractor class to create and pattern match with syntax `TypeRef(pre, sym, args)`
+ * Here, `pre` is the prefix of the type reference, `sym` is the symbol
+ * referred to by the type reference, and `args` is a possible empty list of
+ * type argumenrts.
+ */
+ abstract class TypeRefExtractor {
+ def apply(pre: Type, sym: Symbol, args: List[Type]): Type
+ def unapply(tpe: TypeRef): Option[(Type, Symbol, List[Type])]
+ }
+
+ /** The `SingleType` type describes types of any of the forms on the left,
+ * with their TypeRef representations to the right.
+ * {{{
+ * (T # x).type SingleType(T, x)
+ * p.x.type SingleType(p.type, x)
+ * x.type SingleType(NoPrefix, x)
+ */
type SingleType <: SingletonType
+
+ /** The constructor/deconstructor for `SingleType` instances. */
val SingleType: SingleTypeExtractor
+ /** An extractor class to create and pattern match with syntax `SingleType(pre, sym)`
+ * Here, `pre` is the prefix of the single-type, and `sym` is the stable value symbol
+ * referred to by the single-type.
+ */
+ abstract class SingleTypeExtractor {
+ def apply(pre: Type, sym: Symbol): Type
+ def unapply(tpe: SingleType): Option[(Type, Symbol)]
+ }
+
+ /** The `SuperType` type is not directly written, but arises when `C.super` is used
+ * as a prefix in a `TypeRef` or `SingleType`. It's internal presentation is
+ * {{{
+ * SuperType(thistpe, supertpe)
+ * }}}
+ * Here, `thistpe` is the type of the corresponding this-type. For instance,
+ * in the type arising from C.super, the `thistpe` part would be `ThisType(C)`.
+ * `supertpe` is the type of the super class referred to by the `super`.
+ */
type SuperType <: SingletonType
+
+ /** The constructor/deconstructor for `SuperType` instances. */
val SuperType: SuperTypeExtractor
- type TypeBounds <: Type
- val TypeBounds: TypeBoundsExtractor
+ /** An extractor class to create and pattern match with syntax `SingleType(thistpe, supertpe)`
+ */
+ abstract class SuperTypeExtractor {
+ def apply(thistpe: Type, supertpe: Type): Type
+ def unapply(tpe: SuperType): Option[(Type, Type)]
+ }
+
+ /** The `ConstantType` type is not directly written in user programs, but arises as the type of a constant.
+ * The REPL expresses constant types like Int(11). Here are some constants with their types.
+ * {{{
+ * 1 ConstantType(Constant(1))
+ * "abc" ConstantType(Constant("abc"))
+ * }}}
+ */
+ type ConstantType <: SingletonType
+
+ /** The constructor/deconstructor for `ConstantType` instances. */
+ val ConstantType: ConstantTypeExtractor
- type CompoundType <: Type
+ /** An extractor class to create and pattern match with syntax `ConstantType(constant)`
+ * Here, `constant` is the constant value represented by the type.
+ */
+ abstract class ConstantTypeExtractor {
+ def apply(value: Constant): ConstantType
+ def unapply(tpe: ConstantType): Option[Constant]
+ }
+ /** A subtype of Type representing refined types as well as `ClassInfo` signatures.
+ */
+ type CompoundType <: /*AbsCompoundType with*/ Type
+
+ /** The `RefinedType` type defines types of any of the forms on the left,
+ * with their RefinedType representations to the right.
+ * {{{
+ * P_1 with ... with P_m { D_1; ...; D_n} RefinedType(List(P_1, ..., P_m), Scope(D_1, ..., D_n))
+ * P_1 with ... with P_m RefinedType(List(P_1, ..., P_m), Scope())
+ * { D_1; ...; D_n} RefinedType(List(AnyRef), Scope(D_1, ..., D_n))
+ * }}}
+ */
type RefinedType <: CompoundType
- val RefinedType: RefinedTypeExtractor
- type ClassInfoType <: CompoundType
- val ClassInfoType: ClassInfoTypeExtractor
+ /** The constructor/deconstructor for `RefinedType` instances. */
+ val RefinedType: RefinedTypeExtractor
- type ConstantType <: Type
- val ConstantType: ConstantTypeExtractor
+ /** An extractor class to create and pattern match with syntax `RefinedType(parents, decls)`
+ * Here, `parents` is the list of parent types of the class, and `decls` is the scope
+ * containing all declarations in the class.
+ */
+ abstract class RefinedTypeExtractor {
+ def apply(parents: List[Type], decls: Scope): RefinedType
- type MethodType <: Type
- val MethodType: MethodTypeExtractor
+ /** An alternative constructor that passes in the synthetic classs symbol
+ * that backs the refined type. (Normally, a fresh class symbol is created automatically).
+ */
+ def apply(parents: List[Type], decls: Scope, clazz: Symbol): RefinedType
+ def unapply(tpe: RefinedType): Option[(List[Type], Scope)]
+ }
type NullaryMethodType <: Type
val NullaryMethodType: NullaryMethodTypeExtractor
@@ -56,51 +334,85 @@ trait Types { self: Universe =>
type AnnotatedType <: Type
val AnnotatedType: AnnotatedTypeExtractor
- abstract class ThisTypeExtractor {
- def apply(sym: Symbol): Type
- def unapply(tpe: ThisType): Option[Symbol]
- }
+ /** The `MethodType` type signature is used to indicate parameters and result type of a method
+ */
+ type MethodType <: Type
- abstract class SingleTypeExtractor {
- def apply(pre: Type, sym: Symbol): Type
- def unapply(tpe: SingleType): Option[(Type, Symbol)]
- }
+ /** The constructor/deconstructor for `MethodType` instances. */
+ val MethodType: MethodTypeExtractor
- abstract class SuperTypeExtractor {
- def apply(thistpe: Type, supertpe: Type): Type
- def unapply(tpe: SuperType): Option[(Type, Type)]
+ /** An extractor class to create and pattern match with syntax `MethodType(params, respte)`
+ * Here, `params` is a potentially empty list of parameter symbols of the method,
+ * and `restpe` is the result type of the method. If the method is curried, `restpe` would
+ * be another `MethodType`.
+ * Note: `MethodType(Nil, Int)` would be the type of a method defined with an empty parameter list.
+ * {{{
+ * def f(): Int
+ * }}}
+ * If the method is completely parameterless, as in
+ * {{{
+ * def f: Int
+ * }}}
+ * its type is a `NullaryMethodType`.
+ */
+ abstract class MethodTypeExtractor {
+ def apply(params: List[Symbol], resultType: Type): MethodType
+ def unapply(tpe: MethodType): Option[(List[Symbol], Type)]
}
- abstract class TypeRefExtractor {
- def apply(pre: Type, sym: Symbol, args: List[Type]): Type
- def unapply(tpe: TypeRef): Option[(Type, Symbol, List[Type])]
- }
+ /** The `TypeBounds` type signature is used to indicate lower and upper type bounds
+ * of type parameters and abstract types. It is not a first-class type.
+ * If an abstract type or type parameter is declared with any of the forms
+ * on the left, its type signature is the TypeBounds type on the right.
+ * {{{
+ * T >: L <: U TypeBounds(L, U)
+ * T >: L TypeBounds(L, Any)
+ * T <: U TypeBounds(Nothing, U)
+ * }}}
+ */
+ type TypeBounds <: Type
+
+ /** The constructor/deconstructor for `TypeBounds` instances. */
+ val TypeBounds: TypeBoundsExtractor
+ /** An extractor class to create and pattern match with syntax `TypeBound(lower, upper)`
+ * Here, `lower` is the lower bound of the `TypeBounds` pair, and `upper` is
+ * the upper bound.
+ */
abstract class TypeBoundsExtractor {
def apply(lo: Type, hi: Type): TypeBounds
def unapply(tpe: TypeBounds): Option[(Type, Type)]
}
- abstract class RefinedTypeExtractor {
- def apply(parents: List[Type], decls: Scope): RefinedType
- def apply(parents: List[Type], decls: Scope, clazz: Symbol): RefinedType
- def unapply(tpe: RefinedType): Option[(List[Type], Scope)]
- }
+ /** The `ClassInfo` type signature is used to define parents and declarations
+ * of classes, traits, and objects. If a class, trait, or object C is declared like this
+ * {{{
+ * C extends P_1 with ... with P_m { D_1; ...; D_n}
+ * }}}
+ * its `ClassInfo` type has the following form:
+ * {{{
+ * ClassInfo(List(P_1, ..., P_m), Scope(D_1, ..., D_n), C)
+ * }}}
+ */
+ type ClassInfoType <: CompoundType
+ /** The constructor/deconstructor for `ClassInfoType` instances. */
+ val ClassInfoType: ClassInfoTypeExtractor
+
+ /** An extractor class to create and pattern match with syntax `ClassInfo(parents, decls, clazz)`
+ * Here, `parents` is the list of parent types of the class, `decls` is the scope
+ * containing all declarations in the class, and `clazz` is the symbol of the class
+ * itself.
+ */
abstract class ClassInfoTypeExtractor {
def apply(parents: List[Type], decls: Scope, clazz: Symbol): ClassInfoType
def unapply(tpe: ClassInfoType): Option[(List[Type], Scope, Symbol)]
}
- abstract class ConstantTypeExtractor {
- def apply(value: Constant): ConstantType
- def unapply(tpe: ConstantType): Option[Constant]
- }
- abstract class MethodTypeExtractor {
- def apply(params: List[Symbol], resultType: Type): MethodType
- def unapply(tpe: MethodType): Option[(List[Symbol], Type)]
- }
+
+
+
abstract class NullaryMethodTypeExtractor {
def apply(resultType: Type): NullaryMethodType
@@ -121,5 +433,11 @@ trait Types { self: Universe =>
def apply(annotations: List[AnnotationInfo], underlying: Type, selfsym: Symbol): AnnotatedType
def unapply(tpe: AnnotatedType): Option[(List[AnnotationInfo], Type, Symbol)]
}
+
+ /** The least upper bound wrt <:< of a list of types */
+ def lub(xs: List[Type]): Type
+
+ /** The greatest lower bound wrt <:< of a list of types */
+ def glb(ts: List[Type]): Type
}
diff --git a/test/files/run/t4875.check b/test/files/run/t4875.check
index 05a398593c..f7609d5ca5 100644
--- a/test/files/run/t4875.check
+++ b/test/files/run/t4875.check
@@ -10,7 +10,7 @@ scala> def codeOf[A](code: Code[A]) = code
codeOf: [A](code: scala.reflect.Code[A])scala.reflect.Code[A]
scala> codeOf((x: Iterable[_]) => throw new Exception)
-res0: scala.reflect.Code[Iterable[_] => Nothing] = Code(manifest = scala.Function1[scala.collection.Iterable[Any], Nothing])
+res0: scala.reflect.Code[Iterable[_] => Nothing] = Code(tree = ((x: Iterable[Any]) => throw new scala.`package`.Exception()), manifest = scala.Function1[scala.collection.Iterable[Any], Nothing])
scala>