diff options
Diffstat (limited to 'src/compiler/scala/reflect/reify/package.scala')
-rw-r--r-- | src/compiler/scala/reflect/reify/package.scala | 81 |
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 + } } |