summaryrefslogtreecommitdiff
path: root/src/compiler/scala/reflect/reify/package.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/reflect/reify/package.scala')
-rw-r--r--src/compiler/scala/reflect/reify/package.scala81
1 files changed, 50 insertions, 31 deletions
diff --git a/src/compiler/scala/reflect/reify/package.scala b/src/compiler/scala/reflect/reify/package.scala
index 35b3d9bf38..342b49dee7 100644
--- a/src/compiler/scala/reflect/reify/package.scala
+++ b/src/compiler/scala/reflect/reify/package.scala
@@ -1,59 +1,78 @@
package scala.reflect
+import language.implicitConversions
+import language.experimental.macros
+import scala.reflect.base.{Universe => BaseUniverse}
+import scala.reflect.makro.{Context, ReificationError, UnexpectedReificationError}
import scala.tools.nsc.Global
-import scala.reflect.makro.ReificationError
-import scala.reflect.makro.UnexpectedReificationError
package object reify {
- private def mkReifier(global: Global)(typer: global.analyzer.Typer, prefix: global.Tree, reifee: Any, dontSpliceAtTopLevel: Boolean = false, concrete: Boolean = false): Reifier { val mirror: global.type } = {
+ private def mkReifier(global1: Global)(typer: global1.analyzer.Typer, universe: global1.Tree, mirror: global1.Tree, reifee: Any, concrete: Boolean = false): Reifier { val global: global1.type } = {
val typer1: typer.type = typer
- val prefix1: prefix.type = prefix
+ val universe1: universe.type = universe
+ val mirror1: mirror.type = mirror
val reifee1 = reifee
- val dontSpliceAtTopLevel1 = dontSpliceAtTopLevel
val concrete1 = concrete
new {
- val mirror: global.type = global
+ val global: global1.type = global1
val typer = typer1
- val prefix = prefix1
+ val universe = universe1
+ val mirror = mirror1
val reifee = reifee1
- val dontSpliceAtTopLevel = dontSpliceAtTopLevel1
val concrete = concrete1
} with Reifier
}
- def reifyTree(global: Global)(typer: global.analyzer.Typer, prefix: global.Tree, tree: global.Tree): global.Tree =
- mkReifier(global)(typer, prefix, tree, false, false).reified.asInstanceOf[global.Tree]
+ private[reify] def mkDefaultMirrorRef(global: Global)(universe: global.Tree, typer0: global.analyzer.Typer): global.Tree = {
+ import global._
+ import definitions._
+ val enclosingErasure = reifyEnclosingRuntimeClass(global)(typer0)
+ // JavaUniverse is defined in scala-reflect.jar, so we must be very careful in case someone reifies stuff having only scala-library.jar on the classpath
+ val isJavaUniverse = JavaUniverseClass != NoSymbol && universe.tpe <:< JavaUniverseClass.asTypeConstructor
+ if (isJavaUniverse && !enclosingErasure.isEmpty) Apply(Select(universe, nme.runtimeMirror), List(Select(enclosingErasure, sn.GetClassLoader)))
+ else Select(universe, nme.rootMirror)
+ }
- def reifyType(global: Global)(typer: global.analyzer.Typer, prefix: global.Tree, tpe: global.Type, dontSpliceAtTopLevel: Boolean = false, concrete: Boolean = false): global.Tree =
- mkReifier(global)(typer, prefix, tpe, dontSpliceAtTopLevel, concrete).reified.asInstanceOf[global.Tree]
+ def reifyTree(global: Global)(typer: global.analyzer.Typer, universe: global.Tree, mirror: global.Tree, tree: global.Tree): global.Tree =
+ mkReifier(global)(typer, universe, mirror, tree, concrete = false).reification.asInstanceOf[global.Tree]
+
+ def reifyType(global: Global)(typer: global.analyzer.Typer,universe: global.Tree, mirror: global.Tree, tpe: global.Type, concrete: Boolean = false): global.Tree =
+ mkReifier(global)(typer, universe, mirror, tpe, concrete = concrete).reification.asInstanceOf[global.Tree]
def reifyRuntimeClass(global: Global)(typer0: global.analyzer.Typer, tpe: global.Type, concrete: Boolean = true): global.Tree = {
import global._
import definitions._
import analyzer.enclosingMacroPosition
- def erasureTagInScope = typer0.context.withMacrosDisabled(typer0.resolveErasureTag(tpe, enclosingMacroPosition, concrete = concrete))
- def arrayTagInScope = typer0.context.withMacrosDisabled(typer0.resolveArrayTag(tpe, enclosingMacroPosition))
- val inScope = (erasureTagInScope, arrayTagInScope)
+ if (tpe.isSpliceable) {
+ val classTagInScope = typer0.resolveClassTag(enclosingMacroPosition, tpe, allowMaterialization = false)
+ if (!classTagInScope.isEmpty) return Select(classTagInScope, nme.runtimeClass)
+ val arrayTagInScope = typer0.resolveArrayTag(enclosingMacroPosition, tpe, allowMaterialization = false)
+ if (!arrayTagInScope.isEmpty) return gen.mkMethodCall(arrayElementClassMethod, List(arrayTagInScope))
+ if (concrete) throw new ReificationError(enclosingMacroPosition, "tpe %s is an unresolved spliceable type".format(tpe))
+ }
- inScope match {
- case (success, _) if !success.isEmpty =>
- Select(success, nme.runtimeClass)
- case (_, success) if !success.isEmpty =>
- gen.mkMethodCall(arrayElementClassMethod, List(success))
+ tpe.normalize match {
+ case TypeRef(_, ArrayClass, componentTpe :: Nil) =>
+ val componentErasure = reifyRuntimeClass(global)(typer0, componentTpe, concrete)
+ gen.mkMethodCall(arrayClassMethod, List(componentErasure))
case _ =>
- tpe.normalize match {
- case TypeRef(_, ArrayClass, componentTpe :: Nil) =>
- val componentRuntimeClass = reifyRuntimeClass(global)(typer0, componentTpe, concrete)
- gen.mkMethodCall(arrayClassMethod, List(componentRuntimeClass))
- case _ =>
- if (tpe.isSpliceable && concrete)
- throw new ReificationError(enclosingMacroPosition, "tpe %s is an unresolved spliceable type".format(tpe))
- var erasure = tpe.erasure
- if (tpe.typeSymbol.isDerivedValueClass && global.phase.id < global.currentRun.erasurePhase.id) erasure = tpe
- gen.mkNullaryCall(Predef_classOf, List(erasure))
- }
+ var erasure = tpe.erasure
+ if (tpe.typeSymbol.isDerivedValueClass && global.phase.id < global.currentRun.erasurePhase.id) erasure = tpe
+ gen.mkNullaryCall(Predef_classOf, List(erasure))
}
}
+
+ def reifyEnclosingRuntimeClass(global: Global)(typer0: global.analyzer.Typer): global.Tree = {
+ import global._
+ import definitions._
+ def isThisInScope = typer0.context.enclosingContextChain exists (_.tree.isInstanceOf[Template])
+ if (isThisInScope) {
+ val enclosingClasses = typer0.context.enclosingContextChain map (_.tree) collect { case classDef: ClassDef => classDef }
+ val classInScope = enclosingClasses.headOption getOrElse EmptyTree
+ if (!classInScope.isEmpty) reifyRuntimeClass(global)(typer0, classInScope.symbol.asTypeConstructor, concrete = true)
+ else Select(This(tpnme.EMPTY), sn.GetClass)
+ } else EmptyTree
+ }
}