diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2014-01-14 00:34:24 -0800 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2014-01-14 00:34:24 -0800 |
commit | ef4c5d2f43e912b5562c1372228e9c6ec9f25bb0 (patch) | |
tree | bb7385f1971d1b7869eed8678fb0bfef24082e60 /src/compiler | |
parent | 4065b5136f2d0d1b6b9bb03f6669c1fd8a2b4e64 (diff) | |
parent | b2f67b5730adccc4cbb24e5b542dc66452869489 (diff) | |
download | scala-ef4c5d2f43e912b5562c1372228e9c6ec9f25bb0.tar.gz scala-ef4c5d2f43e912b5562c1372228e9c6ec9f25bb0.tar.bz2 scala-ef4c5d2f43e912b5562c1372228e9c6ec9f25bb0.zip |
Merge pull request #3355 from xeno-by/topic/saturday-night
reshuffles names for blackbox/whitebox contexts, changes bundle notation
Diffstat (limited to 'src/compiler')
10 files changed, 40 insertions, 108 deletions
diff --git a/src/compiler/scala/reflect/macros/compiler/Errors.scala b/src/compiler/scala/reflect/macros/compiler/Errors.scala index 4c30a9a85c..280baa2a42 100644 --- a/src/compiler/scala/reflect/macros/compiler/Errors.scala +++ b/src/compiler/scala/reflect/macros/compiler/Errors.scala @@ -51,7 +51,7 @@ trait Errors extends Traces { def MacroBundleNonStaticError() = bundleRefError("macro bundles must be static") - def MacroBundleWrongShapeError() = bundleRefError("macro bundles must be monomorphic traits extending either BlackboxMacro or WhiteboxMacro and not implementing their `val c: BlackboxContext/WhiteboxContext` member") + def MacroBundleWrongShapeError() = bundleRefError("macro bundles must be concrete classes having a single constructor with a `val c: Context` parameter") // compatibility errors diff --git a/src/compiler/scala/reflect/macros/compiler/Resolvers.scala b/src/compiler/scala/reflect/macros/compiler/Resolvers.scala index e4851632a5..d35f1c32a9 100644 --- a/src/compiler/scala/reflect/macros/compiler/Resolvers.scala +++ b/src/compiler/scala/reflect/macros/compiler/Resolvers.scala @@ -40,36 +40,11 @@ trait Resolvers { } val untypedImplRef = typer.silent(_.typedTypeConstructor(maybeBundleRef)) match { - case SilentResultValue(result) if mightBeMacroBundleType(result.tpe) => - val bundleProto = result.tpe.typeSymbol - val bundlePkg = bundleProto.enclosingPackageClass - if (!isMacroBundleProtoType(bundleProto.tpe)) MacroBundleWrongShapeError() - if (!bundleProto.owner.isStaticOwner) MacroBundleNonStaticError() - - // synthesize the bundle, i.e. given a static `trait Foo extends Macro { def expand = ... } ` - // create a top-level definition `class Foo$Bundle(val c: BlackboxContext/WhiteboxContext) extends Foo` in a package next to `Foo` - val bundlePid = gen.mkUnattributedRef(bundlePkg) - val bundlePrefix = - if (bundlePkg == EmptyPackageClass) bundleProto.fullName('$') - else bundleProto.fullName('$').substring(bundlePkg.fullName('$').length + 1) - val bundleName = TypeName(bundlePrefix + tpnme.MACRO_BUNDLE_SUFFIX) - val existingBundle = bundleProto.enclosingPackageClass.info.decl(bundleName) - if (!currentRun.compiles(existingBundle)) { - val contextType = if (isBlackboxMacroBundleType(bundleProto.tpe)) BlackboxContextClass.tpe else WhiteboxContextClass.tpe - def mkContextValDef(flags: Long) = ValDef(Modifiers(flags), nme.c, TypeTree(contextType), EmptyTree) - val contextField = mkContextValDef(PARAMACCESSOR) - val contextParam = mkContextValDef(PARAM | PARAMACCESSOR) - val bundleCtor = DefDef(Modifiers(), nme.CONSTRUCTOR, Nil, List(List(contextParam)), TypeTree(), Block(List(pendingSuperCall), Literal(Constant(())))) - val bundleParent = gen.mkAppliedTypeTree(Ident(bundleProto), bundleProto.typeParams.map(sym => Ident(sym.name))) - val bundleTemplate = Template(List(bundleParent), noSelfType, List(contextField, bundleCtor)) - val bundle = atPos(bundleProto.pos)(ClassDef(NoMods, bundleName, bundleProto.typeParams.map(TypeDef(_)), bundleTemplate)) - currentRun.compileLate(bundleName + ".scala", PackageDef(bundlePid, List(bundle))) - } - - // synthesize the macro impl reference, which is going to look like: - // `new FooBundle(???).macroName` plus the optional type arguments - val bundleInstance = New(Select(bundlePid, bundleName), List(List(Ident(Predef_???)))) - atPos(macroDdef.rhs.pos)(gen.mkTypeApply(Select(bundleInstance, methName), targs)) + case SilentResultValue(result) if looksLikeMacroBundleType(result.tpe) => + val bundle = result.tpe.typeSymbol + if (!isMacroBundleType(bundle.tpe)) MacroBundleWrongShapeError() + if (!bundle.owner.isStaticOwner) MacroBundleNonStaticError() + atPos(macroDdef.rhs.pos)(gen.mkTypeApply(Select(New(bundle, Ident(Predef_???)), methName), targs)) case _ => macroDdef.rhs } diff --git a/src/compiler/scala/reflect/macros/compiler/Validators.scala b/src/compiler/scala/reflect/macros/compiler/Validators.scala index 5936b52890..02c1f7c431 100644 --- a/src/compiler/scala/reflect/macros/compiler/Validators.scala +++ b/src/compiler/scala/reflect/macros/compiler/Validators.scala @@ -26,9 +26,9 @@ trait Validators { if (macroImpl.isOverloaded) MacroImplOverloadedError() val implicitParams = aparamss.flatten filter (_.isImplicit) if (implicitParams.nonEmpty) MacroImplNonTagImplicitParameters(implicitParams) - val declaredInStaticObject = isImplMethod && (macroImplOwner.isStaticOwner || macroImplOwner.moduleClass.isStaticOwner) - val declaredInTopLevelClass = isImplBundle && macroImplOwner.owner.isPackageClass - if (!declaredInStaticObject && !declaredInTopLevelClass) MacroImplReferenceWrongShapeError() + val effectiveOwner = if (isImplMethod) macroImplOwner else macroImplOwner.owner + val declaredInStaticObject = effectiveOwner.isStaticOwner || effectiveOwner.moduleClass.isStaticOwner + if (!declaredInStaticObject) MacroImplReferenceWrongShapeError() } private def checkMacroDefMacroImplCorrespondence() = { @@ -93,20 +93,20 @@ trait Validators { * * For the following macro impl: * def fooBar[T: c.WeakTypeTag] - * (c: scala.reflect.macros.BlackboxContext) + * (c: scala.reflect.macros.blackbox.Context) * (xs: c.Expr[List[T]]) * : c.Expr[T] = ... * * This function will return: - * (c: scala.reflect.macros.BlackboxContext)(xs: c.Expr[List[T]])c.Expr[T] + * (c: scala.reflect.macros.blackbox.Context)(xs: c.Expr[List[T]])c.Expr[T] * * Note that type tag evidence parameters are not included into the result. * Type tag context bounds for macro impl tparams are optional. * Therefore compatibility checks ignore such parameters, and we don't need to bother about them here. * * This method cannot be reduced to just macroImpl.info, because macro implementations might - * come in different shapes. If the implementation is an apply method of a BlackboxMacro/WhiteboxMacro-compatible object, - * then it won't have (c: BlackboxContext/WhiteboxContext) in its parameters, but will rather refer to BlackboxMacro/WhiteboxMacro.c. + * come in different shapes. If the implementation is an apply method of a *box.Macro-compatible object, + * then it won't have (c: *box.Context) in its parameters, but will rather refer to *boxMacro.c. * * @param macroImpl The macro implementation symbol */ @@ -123,8 +123,8 @@ trait Validators { * def foo[T](xs: List[T]): T = macro fooBar * * This function will return: - * (c: scala.reflect.macros.BlackboxContext)(xs: c.Expr[List[T]])c.Expr[T] or - * (c: scala.reflect.macros.WhiteboxContext)(xs: c.Expr[List[T]])c.Expr[T] + * (c: scala.reflect.macros.blackbox.Context)(xs: c.Expr[List[T]])c.Expr[T] or + * (c: scala.reflect.macros.whitebox.Context)(xs: c.Expr[List[T]])c.Expr[T] * * Note that type tag evidence parameters are not included into the result. * Type tag context bounds for macro impl tparams are optional. diff --git a/src/compiler/scala/reflect/macros/contexts/Context.scala b/src/compiler/scala/reflect/macros/contexts/Context.scala index 7b79b52a18..87dac18849 100644 --- a/src/compiler/scala/reflect/macros/contexts/Context.scala +++ b/src/compiler/scala/reflect/macros/contexts/Context.scala @@ -3,8 +3,8 @@ package contexts import scala.tools.nsc.Global -abstract class Context extends scala.reflect.macros.BlackboxContext - with scala.reflect.macros.WhiteboxContext +abstract class Context extends scala.reflect.macros.blackbox.Context + with scala.reflect.macros.whitebox.Context with Aliases with Enclosures with Names diff --git a/src/compiler/scala/reflect/macros/runtime/JavaReflectionRuntimes.scala b/src/compiler/scala/reflect/macros/runtime/JavaReflectionRuntimes.scala index 450cb4d9ea..ecdd48db22 100644 --- a/src/compiler/scala/reflect/macros/runtime/JavaReflectionRuntimes.scala +++ b/src/compiler/scala/reflect/macros/runtime/JavaReflectionRuntimes.scala @@ -2,7 +2,9 @@ package scala.reflect.macros package runtime import scala.reflect.runtime.ReflectionUtils -import scala.reflect.macros.{Context => ApiContext} +import scala.reflect.macros.blackbox.{Context => BlackboxContext} +import scala.reflect.macros.whitebox.{Context => WhiteboxContext} +import java.lang.reflect.{Constructor => jConstructor} trait JavaReflectionRuntimes { self: scala.tools.nsc.typechecker.Analyzer => @@ -19,8 +21,15 @@ trait JavaReflectionRuntimes { macroLogVerbose(s"successfully loaded macro impl as ($implClass, $implMeth)") args => { val implObj = - if (isBundle) implClass.getConstructor(classOf[ApiContext]).newInstance(args.c) - else ReflectionUtils.staticSingletonInstance(implClass) + if (isBundle) { + def isMacroContext(clazz: Class[_]) = clazz == classOf[BlackboxContext] || clazz == classOf[WhiteboxContext] + def isBundleCtor(ctor: jConstructor[_]) = ctor.getParameterTypes match { + case Array(param) if isMacroContext(param) => true + case _ => false + } + val Array(bundleCtor) = implClass.getConstructors.filter(isBundleCtor) + bundleCtor.newInstance(args.c) + } else ReflectionUtils.staticSingletonInstance(implClass) val implArgs = if (isBundle) args.others else args.c +: args.others implMeth.invoke(implObj, implArgs.asInstanceOf[Seq[AnyRef]]: _*) } diff --git a/src/compiler/scala/reflect/macros/runtime/MacroRuntimes.scala b/src/compiler/scala/reflect/macros/runtime/MacroRuntimes.scala index 14b0c6baba..5fd9c0db34 100644 --- a/src/compiler/scala/reflect/macros/runtime/MacroRuntimes.scala +++ b/src/compiler/scala/reflect/macros/runtime/MacroRuntimes.scala @@ -4,7 +4,7 @@ package runtime import scala.reflect.internal.Flags._ import scala.reflect.runtime.ReflectionUtils -trait MacroRuntimes extends JavaReflectionRuntimes with ScalaReflectionRuntimes { +trait MacroRuntimes extends JavaReflectionRuntimes { self: scala.tools.nsc.typechecker.Analyzer => import global._ @@ -49,8 +49,7 @@ trait MacroRuntimes extends JavaReflectionRuntimes with ScalaReflectionRuntimes /** Abstracts away resolution of macro runtimes. */ type MacroRuntime = MacroArgs => Any - class MacroRuntimeResolver(val macroDef: Symbol) extends JavaReflectionResolvers - with ScalaReflectionResolvers { + class MacroRuntimeResolver(val macroDef: Symbol) extends JavaReflectionResolvers { val binding = loadMacroImplBinding(macroDef).get val isBundle = binding.isBundle val className = binding.className @@ -63,7 +62,6 @@ trait MacroRuntimes extends JavaReflectionRuntimes with ScalaReflectionRuntimes try { macroLogVerbose(s"resolving macro implementation as $className.$methName (isBundle = $isBundle)") macroLogVerbose(s"classloader is: ${ReflectionUtils.show(defaultMacroClassloader)}") - // resolveScalaReflectionRuntime(defaultMacroClassloader) resolveJavaReflectionRuntime(defaultMacroClassloader) } catch { case ex: Exception => diff --git a/src/compiler/scala/reflect/macros/runtime/ScalaReflectionRuntimes.scala b/src/compiler/scala/reflect/macros/runtime/ScalaReflectionRuntimes.scala deleted file mode 100644 index 50f64310f8..0000000000 --- a/src/compiler/scala/reflect/macros/runtime/ScalaReflectionRuntimes.scala +++ /dev/null @@ -1,31 +0,0 @@ -package scala.reflect.macros -package runtime - -import scala.reflect.runtime.{universe => ru} - -trait ScalaReflectionRuntimes { - self: scala.tools.nsc.typechecker.Analyzer => - - trait ScalaReflectionResolvers { - self: MacroRuntimeResolver => - - def resolveScalaReflectionRuntime(classLoader: ClassLoader): MacroRuntime = { - val macroMirror: ru.JavaMirror = ru.runtimeMirror(classLoader) - val implContainerSym = macroMirror.classSymbol(Class.forName(className, true, classLoader)) - val implMethSym = implContainerSym.typeSignature.member(ru.TermName(methName)).asMethod - macroLogVerbose(s"successfully loaded macro impl as ($implContainerSym, $implMethSym)") - args => { - val implContainer = - if (isBundle) { - val implCtorSym = implContainerSym.typeSignature.member(ru.nme.CONSTRUCTOR).asMethod - macroMirror.reflectClass(implContainerSym).reflectConstructor(implCtorSym)(args.c) - } else { - macroMirror.reflectModule(implContainerSym.module.asModule).instance - } - val implMeth = macroMirror.reflect(implContainer).reflectMethod(implMethSym) - val implArgs = if (isBundle) args.others else args.c +: args.others - implMeth(implArgs: _*) - } - } - } -} diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 5f079a428b..5492e563dd 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -1710,25 +1710,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) } } - /** Create and compile a synthetic compilation unit from the provided tree. - * - * This needs to create a virtual file underlying the compilation unit in order to appease SBT. - * However this file cannot have a randomly generated name, because then SBT 0.13 goes into a vicious loop - * as described on the mailing list: https://groups.google.com/forum/#!msg/scala-user/r1SgSoVfs0U/Wv4av0LOKukJ - * Therefore I have introduced an additional parameter that makes everyone specify meaningful file names. - */ - def compileLate(virtualFileName: String, code: PackageDef) { - // compatibility with SBT - // on the one hand, we need to specify some jfile here, otherwise sbt crashes with an NPE (SI-6870) - // on the other hand, we can't specify the obvious enclosingUnit, because then sbt somehow fails to run tests using type macros - val fakeJfile = new java.io.File(virtualFileName) - val virtualFile = new VirtualFile(virtualFileName) { override def file = fakeJfile } - val sourceFile = new BatchSourceFile(virtualFile, code.toString) - val unit = new CompilationUnit(sourceFile) - unit.body = code - compileLate(unit) - } - /** Reset package class to state at typer (not sure what this * is needed for?) */ diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index fdec1edcc0..19fba639e3 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -1145,7 +1145,7 @@ trait Implicits { gen.mkAttributedThis(thisSym) case _ => // if `pre` is not a PDT, e.g. if someone wrote - // implicitly[scala.reflect.macros.BlackboxContext#TypeTag[Int]] + // implicitly[scala.reflect.macros.blackbox.Context#TypeTag[Int]] // then we need to fail, because we don't know the prefix to use during type reification // upd. we also need to fail silently, because this is a very common situation // e.g. quite often we're searching for BaseUniverse#TypeTag, e.g. for a type tag in any universe diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index a1e77515a8..cf82d6baac 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -29,7 +29,7 @@ import Fingerprint._ * Then fooBar needs to point to a static method of the following form: * * def fooBar[T: c.WeakTypeTag] // type tag annotation is optional - * (c: scala.reflect.macros.BlackboxContext) + * (c: scala.reflect.macros.blackbox.Context) * (xs: c.Expr[List[T]]) * : c.Expr[T] = { * ... @@ -67,7 +67,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { * * This solution is very simple, but unfortunately it's also lacking. If we use it, then * signatures of macro defs become transitively dependent on scala-reflect.jar - * (because they refer to macro impls, and macro impls refer to scala.reflect.macros.BlackboxContext/WhiteboxContext defined in scala-reflect.jar). + * (because they refer to macro impls, and macro impls refer to *box.Context defined in scala-reflect.jar). * More details can be found in comments to https://issues.scala-lang.org/browse/SI-5940. * * Therefore we have to avoid putting macro impls into binding pickles and come up with our own serialization format. @@ -81,9 +81,9 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { * and various accounting information necessary when composing an argument list for the reflective invocation. */ case class MacroImplBinding( - // Is this macro impl a bundle (a trait extending BlackboxMacro or WhiteboxMacro) or a vanilla def? + // Is this macro impl a bundle (a trait extending *box.Macro) or a vanilla def? val isBundle: Boolean, - // Is this macro impl blackbox (i.e. having BlackboxContext in its signature)? + // Is this macro impl blackbox (i.e. having blackbox.Context in its signature)? val isBlackbox: Boolean, // Java class name of the class that contains the macro implementation // is used to load the corresponding object with Java reflection @@ -97,8 +97,8 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { // * c.Expr[T] => LiftedTyped // * c.Tree => LiftedUntyped // * c.WeakTypeTag[T] => Tagged(index of the type parameter corresponding to that type tag) - // * everything else (e.g. scala.reflect.macros.BlackboxContext/WhiteboxContext) => Other - // f.ex. for: def impl[T: WeakTypeTag, U, V: WeakTypeTag](c: BlackboxContext)(x: c.Expr[T], y: c.Tree): (U, V) = ??? + // * everything else (e.g. *box.Context) => Other + // f.ex. for: def impl[T: WeakTypeTag, U, V: WeakTypeTag](c: blackbox.Context)(x: c.Expr[T], y: c.Tree): (U, V) = ??? // `signature` will be equal to List(List(Other), List(LiftedTyped, LiftedUntyped), List(Tagged(0), Tagged(2))) signature: List[List[Fingerprint]], // type arguments part of a macro impl ref (the right-hand side of a macro definition) @@ -116,7 +116,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { * with synthetic content that carries the payload described in `MacroImplBinding`. * * For example, for a pair of macro definition and macro implementation: - * def impl(c: scala.reflect.macros.BlackboxContext): c.Expr[Unit] = ??? + * def impl(c: scala.reflect.macros.blackbox.Context): c.Expr[Unit] = ??? * def foo: Unit = macro impl * * We will have the following annotation added on the macro definition `foo`: @@ -478,7 +478,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers { } /** Keeps track of macros in-flight. - * See more informations in comments to `openMacros` in `scala.reflect.macros.WhiteboxContext`. + * See more informations in comments to `openMacros` in `scala.reflect.macros.whitebox.Context`. */ var _openMacros = List[MacroContext]() def openMacros = _openMacros |