diff options
30 files changed, 293 insertions, 119 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index b3a651563e..3b32d475ce 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -477,6 +477,7 @@ trait Definitions extends api.StandardDefinitions { lazy val MacroContextClass = getClassIfDefined("scala.reflect.makro.Context") // defined in scala-reflect.jar, so we need to be careful def MacroContextPrefix = if (MacroContextClass != NoSymbol) getMemberMethod(MacroContextClass, nme.prefix) else NoSymbol def MacroContextPrefixType = if (MacroContextClass != NoSymbol) getMemberType(MacroContextClass, tpnme.PrefixType) else NoSymbol + def MacroContextUniverse = if (MacroContextClass != NoSymbol) getMemberMethod(MacroContextClass, nme.universe) else NoSymbol def MacroContextMirror = if (MacroContextClass != NoSymbol) getMemberMethod(MacroContextClass, nme.mirror) else NoSymbol def MacroContextReify = if (MacroContextClass != NoSymbol) getMemberMethod(MacroContextClass, nme.reify) else NoSymbol lazy val MacroImplAnnotation = requiredClass[scala.reflect.makro.internal.macroImpl] diff --git a/src/compiler/scala/reflect/makro/runtime/Aliases.scala b/src/compiler/scala/reflect/makro/runtime/Aliases.scala index 30b015b201..76c2834102 100644 --- a/src/compiler/scala/reflect/makro/runtime/Aliases.scala +++ b/src/compiler/scala/reflect/makro/runtime/Aliases.scala @@ -4,20 +4,24 @@ package runtime trait Aliases { self: Context => - /** Aliases of mirror types */ - override type Symbol = mirror.Symbol - override type Type = mirror.Type - override type Name = mirror.Name - override type Tree = mirror.Tree - // override type Position = mirror.Position - override type Scope = mirror.Scope - override type Modifiers = mirror.Modifiers - override type Expr[+T] = mirror.Expr[T] - override type TypeTag[T] = mirror.TypeTag[T] - override type ConcreteTypeTag[T] = mirror.ConcreteTypeTag[T] + override type Symbol = universe.Symbol + override type Type = universe.Type + override type Name = universe.Name + override type TermName = universe.TermName + override type TypeName = universe.TypeName + override type Tree = universe.Tree + // override type Position = universe.Position + override type Scope = universe.Scope + override type Modifiers = universe.Modifiers - /** Creator/extractor objects for Expr and TypeTag values */ - override val TypeTag = mirror.TypeTag - override val ConcreteTypeTag = mirror.ConcreteTypeTag - override val Expr = mirror.Expr + override type Expr[+T] = universe.Expr[T] + override val Expr = universe.Expr + + override type TypeTag[T] = universe.TypeTag[T] + override type ConcreteTypeTag[T] = universe.ConcreteTypeTag[T] + override val TypeTag = universe.TypeTag + override val ConcreteTypeTag = universe.ConcreteTypeTag + override def typeTag[T](implicit ttag: TypeTag[T]) = ttag + override def concreteTypeTag[T](implicit cttag: ConcreteTypeTag[T]) = cttag + override def typeOf[T](implicit ttag: TypeTag[T]): Type = ttag.tpe }
\ No newline at end of file diff --git a/src/compiler/scala/reflect/makro/runtime/CapturedVariables.scala b/src/compiler/scala/reflect/makro/runtime/CapturedVariables.scala index 4e93d4e06d..021b93ceee 100644 --- a/src/compiler/scala/reflect/makro/runtime/CapturedVariables.scala +++ b/src/compiler/scala/reflect/makro/runtime/CapturedVariables.scala @@ -5,10 +5,11 @@ trait CapturedVariables { self: Context => import mirror._ + import universe._ - def captureVariable(vble: Symbol): Unit = mirror.captureVariable(vble) + def captureVariable(vble: Symbol): Unit = universe.captureVariable(vble) - def referenceCapturedVariable(vble: Symbol): Tree = mirror.referenceCapturedVariable(vble) + def referenceCapturedVariable(vble: Symbol): Tree = universe.referenceCapturedVariable(vble) - def capturedVariableType(vble: Symbol): Type = mirror.capturedVariableType(vble) + def capturedVariableType(vble: Symbol): Type = universe.capturedVariableType(vble) }
\ No newline at end of file diff --git a/src/compiler/scala/reflect/makro/runtime/Context.scala b/src/compiler/scala/reflect/makro/runtime/Context.scala index 6faf045d75..7fd7a358b8 100644 --- a/src/compiler/scala/reflect/makro/runtime/Context.scala +++ b/src/compiler/scala/reflect/makro/runtime/Context.scala @@ -8,21 +8,26 @@ abstract class Context extends scala.reflect.makro.Context with CapturedVariables with Infrastructure with Enclosures + with Mirrors with Names with Reifiers with FrontEnds with Settings with Typers + with Parsers with Exprs with TypeTags + with Evals with Util with Traces { - val mirror: Global + val universe: Global - val callsiteTyper: mirror.analyzer.Typer + val mirror: MirrorOf[universe.type] = new ContextMirror + + val callsiteTyper: universe.analyzer.Typer val prefix: Expr[PrefixType] val expandee: Tree -}
\ No newline at end of file +} diff --git a/src/compiler/scala/reflect/makro/runtime/Enclosures.scala b/src/compiler/scala/reflect/makro/runtime/Enclosures.scala index ab38fc024d..80c35d22ff 100644 --- a/src/compiler/scala/reflect/makro/runtime/Enclosures.scala +++ b/src/compiler/scala/reflect/makro/runtime/Enclosures.scala @@ -4,6 +4,7 @@ package runtime trait Enclosures { self: Context => + import universe._ import mirror._ private def site = callsiteTyper.context @@ -16,7 +17,7 @@ trait Enclosures { val enclosingApplication: Tree = enclTrees collectFirst { case t: Apply => t } getOrElse EmptyTree val enclosingClass: Tree = site.enclClass.tree val enclosingImplicits: List[(Type, Tree)] = site.openImplicits - val enclosingMacros: List[Context] = this :: mirror.analyzer.openMacros // include self + val enclosingMacros: List[Context] = this :: universe.analyzer.openMacros // include self val enclosingMethod: Tree = site.enclMethod.tree val enclosingPosition: Position = if (enclPoses.isEmpty) NoPosition else enclPoses.head.pos val enclosingUnit: CompilationUnit = currentRun.currentUnit diff --git a/src/compiler/scala/reflect/makro/runtime/Evals.scala b/src/compiler/scala/reflect/makro/runtime/Evals.scala new file mode 100644 index 0000000000..0574359a19 --- /dev/null +++ b/src/compiler/scala/reflect/makro/runtime/Evals.scala @@ -0,0 +1,18 @@ +package scala.reflect.makro +package runtime + +import scala.reflect.runtime.{universe => ru} +import scala.tools.reflect.ToolBox + +trait Evals { + self: Context => + + private lazy val evalMirror = ru.runtimeMirror(libraryClassLoader) + private lazy val evalToolBox = evalMirror.mkToolBox() + private lazy val evalImporter = ru.mkImporter(universe).asInstanceOf[ru.Importer { val from: universe.type }] + + def eval[T](expr: Expr[T]): T = { + val imported = evalImporter.importTree(expr.tree) + evalToolBox.runExpr(imported).asInstanceOf[T] + } +}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/makro/runtime/Exprs.scala b/src/compiler/scala/reflect/makro/runtime/Exprs.scala index d47ff4e450..df2ea0c3ea 100644 --- a/src/compiler/scala/reflect/makro/runtime/Exprs.scala +++ b/src/compiler/scala/reflect/makro/runtime/Exprs.scala @@ -4,5 +4,5 @@ package runtime trait Exprs { self: Context => - def Expr[T: TypeTag](tree: Tree): Expr[T] = mirror.Expr[T](mirror.rootMirror, mirror.FixedMirrorTreeCreator(mirror.rootMirror, tree)) + def Expr[T: TypeTag](tree: Tree): Expr[T] = universe.Expr[T](mirror, universe.FixedMirrorTreeCreator(mirror, tree)) } diff --git a/src/compiler/scala/reflect/makro/runtime/FrontEnds.scala b/src/compiler/scala/reflect/makro/runtime/FrontEnds.scala index a21c8f90c9..6644c579ac 100644 --- a/src/compiler/scala/reflect/makro/runtime/FrontEnds.scala +++ b/src/compiler/scala/reflect/makro/runtime/FrontEnds.scala @@ -4,31 +4,32 @@ package runtime trait FrontEnds extends scala.tools.reflect.FrontEnds { self: Context => + import universe._ import mirror._ - override type Position = mirror.Position + override type Position = universe.Position - def frontEnd: FrontEnd = wrapReporter(mirror.reporter) + def frontEnd: FrontEnd = wrapReporter(universe.reporter) def setFrontEnd(frontEnd: FrontEnd): this.type = { - mirror.reporter = wrapFrontEnd(frontEnd) + universe.reporter = wrapFrontEnd(frontEnd) this } def withFrontEnd[T](frontEnd: FrontEnd)(op: => T): T = { - val old = mirror.reporter + val old = universe.reporter setFrontEnd(frontEnd) try op - finally mirror.reporter = old + finally universe.reporter = old } - def echo(pos: Position, msg: String): Unit = mirror.reporter.echo(pos, msg) + def echo(pos: Position, msg: String): Unit = universe.reporter.echo(pos, msg) - def info(pos: Position, msg: String, force: Boolean): Unit = mirror.reporter.info(pos, msg, force) + def info(pos: Position, msg: String, force: Boolean): Unit = universe.reporter.info(pos, msg, force) - def hasWarnings: Boolean = mirror.reporter.hasErrors + def hasWarnings: Boolean = universe.reporter.hasErrors - def hasErrors: Boolean = mirror.reporter.hasErrors + def hasErrors: Boolean = universe.reporter.hasErrors def warning(pos: Position, msg: String): Unit = callsiteTyper.context.warning(pos, msg) @@ -39,7 +40,7 @@ trait FrontEnds extends scala.tools.reflect.FrontEnds { throw new AbortMacroException(pos, msg) } - def interactive(): Unit = mirror.reporter match { + def interactive(): Unit = universe.reporter match { case reporter: tools.nsc.reporters.AbstractReporter => reporter.displayPrompt() case _ => () } diff --git a/src/compiler/scala/reflect/makro/runtime/Infrastructure.scala b/src/compiler/scala/reflect/makro/runtime/Infrastructure.scala index 6d8e55cc35..76c4b21731 100644 --- a/src/compiler/scala/reflect/makro/runtime/Infrastructure.scala +++ b/src/compiler/scala/reflect/makro/runtime/Infrastructure.scala @@ -1,26 +1,44 @@ package scala.reflect.makro package runtime +import scala.tools.nsc.util.ScalaClassLoader + trait Infrastructure { self: Context => - val forJVM: Boolean = mirror.forJVM + val forJVM: Boolean = universe.forJVM + + val forMSIL: Boolean = universe.forMSIL + + val forInteractive: Boolean = universe.forInteractive - val forMSIL: Boolean = mirror.forMSIL + val forScaladoc: Boolean = universe.forScaladoc - val forInteractive: Boolean = mirror.forInteractive + val currentRun: Run = universe.currentRun - val forScaladoc: Boolean = mirror.forScaladoc + val libraryClassPath: List[java.net.URL] = universe.classPath.asURLs - val currentRun: Run = mirror.currentRun + lazy val libraryClassLoader: ClassLoader = { + val classpath = libraryClassPath + var loader: ClassLoader = ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader) + + // [Eugene] a heuristic to detect REPL + if (universe.settings.exposeEmptyPackage.value) { + import scala.tools.nsc.interpreter._ + val virtualDirectory = universe.settings.outputDirs.getSingleOutput.get + loader = new AbstractFileClassLoader(virtualDirectory, loader) {} + } + + loader + } - type Run = mirror.Run + type Run = universe.Run object Run extends RunExtractor { def unapply(run: Run): Option[(CompilationUnit, List[CompilationUnit])] = Some(run.currentUnit, run.units.toList) } - type CompilationUnit = mirror.CompilationUnit + type CompilationUnit = universe.CompilationUnit object CompilationUnit extends CompilationUnitExtractor { def unapply(compilationUnit: CompilationUnit): Option[(java.io.File, Array[Char], Tree)] = Some(compilationUnit.source.file.file, compilationUnit.source.content, compilationUnit.body) @@ -28,7 +46,7 @@ trait Infrastructure { val currentMacro: Symbol = expandee.symbol - val globalCache: collection.mutable.Map[Any, Any] = mirror.analyzer.globalMacroCache + val globalCache: collection.mutable.Map[Any, Any] = universe.analyzer.globalMacroCache - val cache: collection.mutable.Map[Any, Any] = mirror.analyzer.perRunMacroCache.getOrElseUpdate(currentMacro, collection.mutable.Map[Any, Any]()) + val cache: collection.mutable.Map[Any, Any] = universe.analyzer.perRunMacroCache.getOrElseUpdate(currentMacro, collection.mutable.Map[Any, Any]()) }
\ No newline at end of file diff --git a/src/compiler/scala/reflect/makro/runtime/Mirrors.scala b/src/compiler/scala/reflect/makro/runtime/Mirrors.scala new file mode 100644 index 0000000000..79fa07fdb4 --- /dev/null +++ b/src/compiler/scala/reflect/makro/runtime/Mirrors.scala @@ -0,0 +1,40 @@ +package scala.reflect.makro +package runtime + +import scala.tools.nsc.util.ScalaClassLoader + +trait Mirrors { + self: Context => + + import universe._ + import definitions._ + + class ContextMirror extends RootsBase(NoSymbol) { + val universe: self.universe.type = self.universe + def rootLoader: LazyType = rootMirror.rootLoader + + val RootPackage = rootMirror.RootPackage + val RootClass = rootMirror.RootClass + val EmptyPackage = rootMirror.EmptyPackage + val EmptyPackageClass = rootMirror.EmptyPackageClass + + // [Eugene++] this still doesn't solve the problem of invoking `c.typeCheck` on the code that refers to packageless symbols + override protected def mirrorMissingHook(owner: Symbol, name: Name): Symbol = { + if (owner.isRoot && isJavaClass(name.toString)) EmptyPackageClass.info decl name + else NoSymbol + } + + private def isJavaClass(path: String): Boolean = + try { + val classpath = platform.classPath.asURLs + var classLoader = ScalaClassLoader.fromURLs(classpath) + Class.forName(path, true, classLoader) + true + } catch { + case (_: ClassNotFoundException) | (_: NoClassDefFoundError) | (_: IncompatibleClassChangeError) => + false + } + + override def toString = "macro context mirror" + } +}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/makro/runtime/Names.scala b/src/compiler/scala/reflect/makro/runtime/Names.scala index d8ecc2b89e..5b1a41a13d 100644 --- a/src/compiler/scala/reflect/makro/runtime/Names.scala +++ b/src/compiler/scala/reflect/makro/runtime/Names.scala @@ -14,7 +14,7 @@ trait Names { freshNameCreator.newName(name) } - def fresh(name: Name): Name = { - name.mapName(freshNameCreator.newName(_)) + def fresh[NameType <: Name](name: NameType): NameType = { + name.mapName(freshNameCreator.newName(_)).asInstanceOf[NameType] } }
\ No newline at end of file diff --git a/src/compiler/scala/reflect/makro/runtime/Parsers.scala b/src/compiler/scala/reflect/makro/runtime/Parsers.scala new file mode 100644 index 0000000000..ac8d09f592 --- /dev/null +++ b/src/compiler/scala/reflect/makro/runtime/Parsers.scala @@ -0,0 +1,25 @@ +package scala.reflect.makro +package runtime + +import language.existentials +import scala.tools.reflect.ToolBox +import scala.tools.reflect.ToolBoxError + +trait Parsers { + self: Context => + + def parse(code: String): Tree = + // todo. provide decent implementation + try { + import scala.reflect.runtime.{universe => ru} + val parsed = ru.rootMirror.mkToolBox().parseExpr(code) + val importer = universe.mkImporter(ru) + importer.importTree(parsed) + } catch { + case ToolBoxError(msg, cause) => + throw new ParseError(universe.NoPosition, msg) + } + + case class ParseError(val pos: Position, val msg: String) extends Throwable(msg) + object ParseError extends ParseErrorExtractor +}
\ No newline at end of file diff --git a/src/compiler/scala/reflect/makro/runtime/Reifiers.scala b/src/compiler/scala/reflect/makro/runtime/Reifiers.scala index 95e031ebc8..7d404128fb 100644 --- a/src/compiler/scala/reflect/makro/runtime/Reifiers.scala +++ b/src/compiler/scala/reflect/makro/runtime/Reifiers.scala @@ -9,19 +9,19 @@ package runtime trait Reifiers { self: Context => - import mirror._ + import universe._ import definitions._ lazy val reflectMirrorPrefix: Tree = ??? def reifyTree(prefix: Tree, tree: Tree): Tree = - scala.reflect.reify.`package`.reifyTree(mirror)(callsiteTyper, prefix, tree) + scala.reflect.reify.`package`.reifyTree(universe)(callsiteTyper, prefix, tree) def reifyType(prefix: Tree, tpe: Type, dontSpliceAtTopLevel: Boolean = false, concrete: Boolean = false): Tree = - scala.reflect.reify.`package`.reifyType(mirror)(callsiteTyper, prefix, tpe, dontSpliceAtTopLevel, concrete) + scala.reflect.reify.`package`.reifyType(universe)(callsiteTyper, prefix, tpe, dontSpliceAtTopLevel, concrete) def reifyRuntimeClass(tpe: Type, concrete: Boolean = true): Tree = - scala.reflect.reify.`package`.reifyRuntimeClass(mirror)(callsiteTyper, tpe, concrete) + scala.reflect.reify.`package`.reifyRuntimeClass(universe)(callsiteTyper, tpe, concrete) def unreifyTree(tree: Tree): Tree = Select(tree, definitions.ExprSplice) diff --git a/src/compiler/scala/reflect/makro/runtime/Settings.scala b/src/compiler/scala/reflect/makro/runtime/Settings.scala index 32f7115db8..8288180b8d 100644 --- a/src/compiler/scala/reflect/makro/runtime/Settings.scala +++ b/src/compiler/scala/reflect/makro/runtime/Settings.scala @@ -5,12 +5,12 @@ trait Settings { self: Context => def settings: List[String] = { - val optionName = mirror.settings.XmacroSettings.name + val optionName = universe.settings.XmacroSettings.name val settings = compilerSettings.find(opt => opt.startsWith(optionName)).map(opt => opt.substring(optionName.length + 1)).getOrElse("") settings.split(",").toList } - def compilerSettings: List[String] = mirror.settings.recreateArgs + def compilerSettings: List[String] = universe.settings.recreateArgs def setCompilerSettings(options: String): this.type = // todo. is not going to work with quoted arguments with embedded whitespaces @@ -19,7 +19,7 @@ trait Settings { def setCompilerSettings(options: List[String]): this.type = { val settings = new tools.nsc.Settings(_ => ()) // [Eugene] what settings should we exclude? - settings.copyInto(mirror.settings) + settings.copyInto(universe.settings) this } diff --git a/src/compiler/scala/reflect/makro/runtime/Traces.scala b/src/compiler/scala/reflect/makro/runtime/Traces.scala index 6b61842316..225ee1f62b 100644 --- a/src/compiler/scala/reflect/makro/runtime/Traces.scala +++ b/src/compiler/scala/reflect/makro/runtime/Traces.scala @@ -4,5 +4,5 @@ package runtime trait Traces extends util.Traces { self: Context => - def globalSettings = mirror.settings + def globalSettings = universe.settings } diff --git a/src/compiler/scala/reflect/makro/runtime/TypeTags.scala b/src/compiler/scala/reflect/makro/runtime/TypeTags.scala index a8e67da56a..b4ac01eedf 100644 --- a/src/compiler/scala/reflect/makro/runtime/TypeTags.scala +++ b/src/compiler/scala/reflect/makro/runtime/TypeTags.scala @@ -4,6 +4,6 @@ package runtime trait TypeTags { self: Context => - def TypeTag[T](tpe: Type): TypeTag[T] = mirror.TypeTag[T](mirror.rootMirror, mirror.FixedMirrorTypeCreator(mirror.rootMirror, tpe)) - def ConcreteTypeTag[T](tpe: Type): ConcreteTypeTag[T] = mirror.ConcreteTypeTag[T](mirror.rootMirror, mirror.FixedMirrorTypeCreator(mirror.rootMirror, tpe)) + def TypeTag[T](tpe: Type): TypeTag[T] = universe.TypeTag[T](mirror, universe.FixedMirrorTypeCreator(mirror, tpe)) + def ConcreteTypeTag[T](tpe: Type): ConcreteTypeTag[T] = universe.ConcreteTypeTag[T](mirror, universe.FixedMirrorTypeCreator(mirror, tpe)) } diff --git a/src/compiler/scala/reflect/makro/runtime/Typers.scala b/src/compiler/scala/reflect/makro/runtime/Typers.scala index 704d3d7ac2..18c1714d15 100644 --- a/src/compiler/scala/reflect/makro/runtime/Typers.scala +++ b/src/compiler/scala/reflect/makro/runtime/Typers.scala @@ -4,11 +4,11 @@ package runtime trait Typers { self: Context => - def openMacros: List[Context] = this :: mirror.analyzer.openMacros + def openMacros: List[Context] = this :: universe.analyzer.openMacros def openImplicits: List[(Type, Tree)] = callsiteTyper.context.openImplicits - def typeCheck(tree: Tree, pt: Type = mirror.WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree = { + def typeCheck(tree: Tree, pt: Type = universe.WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree = { macroLogVerbose("typechecking %s with expected type %s, implicit views = %s, macros = %s".format(tree, pt, !withImplicitViewsDisabled, !withMacrosDisabled)) val wrapper1 = if (!withImplicitViewsDisabled) (callsiteTyper.context.withImplicitsEnabled[Tree] _) else (callsiteTyper.context.withImplicitsDisabled[Tree] _) val wrapper2 = if (!withMacrosDisabled) (callsiteTyper.context.withMacrosEnabled[Tree] _) else (callsiteTyper.context.withMacrosDisabled[Tree] _) @@ -18,28 +18,28 @@ trait Typers { // typechecking uses silent anyways (e.g. in typedSelect), so you'll only waste your time // I'd advise fixing the root cause: finding why the context is not set to report errors // (also see reflect.runtime.ToolBoxes.typeCheckExpr for a workaround that might work for you) - wrapper(callsiteTyper.silent(_.typed(tree, mirror.analyzer.EXPRmode, pt)) match { - case mirror.analyzer.SilentResultValue(result) => + wrapper(callsiteTyper.silent(_.typed(tree, universe.analyzer.EXPRmode, pt)) match { + case universe.analyzer.SilentResultValue(result) => macroLogVerbose(result) result - case error @ mirror.analyzer.SilentTypeError(_) => + case error @ universe.analyzer.SilentTypeError(_) => macroLogVerbose(error.err.errMsg) - if (!silent) throw new mirror.TypeError(error.err.errPos, error.err.errMsg) - mirror.EmptyTree + if (!silent) throw new universe.TypeError(error.err.errPos, error.err.errMsg) + universe.EmptyTree }) } def inferImplicitValue(pt: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: Position = enclosingPosition): Tree = { macroLogVerbose("inferring implicit value of type %s, macros = %s".format(pt, !withMacrosDisabled)) - import mirror.analyzer.SearchResult + import universe.analyzer.SearchResult val context = callsiteTyper.context val wrapper1 = if (!withMacrosDisabled) (context.withMacrosEnabled[SearchResult] _) else (context.withMacrosDisabled[SearchResult] _) def wrapper (inference: => SearchResult) = wrapper1(inference) - wrapper(mirror.analyzer.inferImplicit(mirror.EmptyTree, pt, true, false, context, !silent, pos)) match { + wrapper(universe.analyzer.inferImplicit(universe.EmptyTree, pt, true, false, context, !silent, pos)) match { case failure if failure.tree.isEmpty => macroLogVerbose("implicit search has failed. to find out the reason, turn on -Xlog-implicits") - if (context.hasErrors) throw new mirror.TypeError(context.errBuffer.head.errPos, context.errBuffer.head.errMsg) - mirror.EmptyTree + if (context.hasErrors) throw new universe.TypeError(context.errBuffer.head.errPos, context.errBuffer.head.errMsg) + universe.EmptyTree case success => success.tree } @@ -47,29 +47,29 @@ trait Typers { def inferImplicitView(tree: Tree, from: Type, to: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, reportAmbiguous: Boolean = true, pos: Position = enclosingPosition): Tree = { macroLogVerbose("inferring implicit view from %s to %s for %s, macros = %s, reportAmbiguous = %s".format(from, to, tree, !withMacrosDisabled, reportAmbiguous)) - import mirror.analyzer.SearchResult + import universe.analyzer.SearchResult val context = callsiteTyper.context val wrapper1 = if (!withMacrosDisabled) (context.withMacrosEnabled[SearchResult] _) else (context.withMacrosDisabled[SearchResult] _) def wrapper (inference: => SearchResult) = wrapper1(inference) - val fun1 = mirror.definitions.FunctionClass(1) - val viewTpe = mirror.TypeRef(fun1.typeConstructor.prefix, fun1, List(from, to)) - wrapper(mirror.analyzer.inferImplicit(tree, viewTpe, reportAmbiguous, true, context, !silent, pos)) match { + val fun1 = universe.definitions.FunctionClass(1) + val viewTpe = universe.TypeRef(fun1.typeConstructor.prefix, fun1, List(from, to)) + wrapper(universe.analyzer.inferImplicit(tree, viewTpe, reportAmbiguous, true, context, !silent, pos)) match { case failure if failure.tree.isEmpty => macroLogVerbose("implicit search has failed. to find out the reason, turn on -Xlog-implicits") - if (context.hasErrors) throw new mirror.TypeError(context.errBuffer.head.errPos, context.errBuffer.head.errMsg) - mirror.EmptyTree + if (context.hasErrors) throw new universe.TypeError(context.errBuffer.head.errPos, context.errBuffer.head.errMsg) + universe.EmptyTree case success => success.tree } } - type TypeError = mirror.TypeError + type TypeError = universe.TypeError object TypeError extends TypeErrorExtractor { def unapply(error: TypeError): Option[(Position, String)] = Some((error.pos, error.msg)) } - def resetAllAttrs(tree: Tree): Tree = mirror.resetAllAttrs(tree) + def resetAllAttrs(tree: Tree): Tree = universe.resetAllAttrs(tree) - def resetLocalAttrs(tree: Tree): Tree = mirror.resetLocalAttrs(tree) + def resetLocalAttrs(tree: Tree): Tree = universe.resetLocalAttrs(tree) }
\ No newline at end of file diff --git a/src/compiler/scala/reflect/makro/runtime/Util.scala b/src/compiler/scala/reflect/makro/runtime/Util.scala index 2671155721..09ed47efdd 100644 --- a/src/compiler/scala/reflect/makro/runtime/Util.scala +++ b/src/compiler/scala/reflect/makro/runtime/Util.scala @@ -4,7 +4,7 @@ package runtime trait Util { self: Context => - import mirror._ + import universe._ def literalNull = Expr[Null](Literal(Constant(null)))(TypeTag.Null) diff --git a/src/compiler/scala/reflect/reify/Taggers.scala b/src/compiler/scala/reflect/reify/Taggers.scala index 26b8b1efde..d8da7e74ff 100644 --- a/src/compiler/scala/reflect/reify/Taggers.scala +++ b/src/compiler/scala/reflect/reify/Taggers.scala @@ -6,7 +6,7 @@ import scala.reflect.makro.runtime.Context abstract class Taggers { val c: Context - import c.mirror._ + import c.universe._ import definitions._ val coreTags = Map( diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index ed3f372cb2..96fcdd793e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -26,7 +26,7 @@ import java.lang.reflect.{Array => jArray, Method => jMethod} * def fooBar[T: c.TypeTag] * (c: scala.reflect.makro.Context) * (xs: c.Expr[List[T]]) - * : c.mirror.Tree = { + * : c.Tree = { * ... * } * @@ -200,8 +200,8 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { implicit class AugmentedString(s: String) { def abbreviateCoreAliases: String = { // hack! var result = s - result = result.replace("c.mirror.TypeTag", "c.TypeTag") - result = result.replace("c.mirror.Expr", "c.Expr") + result = result.replace("c.universe.TypeTag", "c.TypeTag") + result = result.replace("c.universe.Expr", "c.Expr") result } } @@ -770,8 +770,8 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { private def macroContext(typer: Typer, prefixTree: Tree, expandeeTree: Tree): MacroContext = new { - val mirror: self.global.type = self.global - val callsiteTyper: mirror.analyzer.Typer = typer.asInstanceOf[global.analyzer.Typer] + val universe: self.global.type = self.global + val callsiteTyper: universe.analyzer.Typer = typer.asInstanceOf[global.analyzer.Typer] val expandee = expandeeTree } with UnaffiliatedMacroContext { // todo. infer precise typetag for this Expr, namely the PrefixType member of the Context refinement @@ -787,26 +787,23 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { * @return list of runtime objects to pass to the implementation obtained by ``macroRuntime'' */ private def macroArgs(typer: Typer, expandee: Tree): Option[List[Any]] = { - val macroDef = expandee.symbol - val runtime = macroRuntime(macroDef) orElse { return None } - var prefixTree: Tree = EmptyTree - var typeArgs = List[Tree]() - val exprArgs = ListBuffer[List[Expr[_]]]() - + val macroDef = expandee.symbol + val runtime = macroRuntime(macroDef) orElse { return None } + val prefixTree = expandee.collect{ case Select(qual, name) => qual }.headOption.getOrElse(EmptyTree) + val context = expandee.attachments.get[MacroRuntimeAttachment].flatMap(_.macroContext).getOrElse(macroContext(typer, prefixTree, expandee)) + var typeArgs = List[Tree]() + val exprArgs = ListBuffer[List[Expr[_]]]() def collectMacroArgs(tree: Tree): Unit = tree match { case Apply(fn, args) => // todo. infer precise typetag for this Expr, namely the declared type of the corresponding macro impl argument - exprArgs.prepend(args map (arg => Expr(rootMirror, FixedMirrorTreeCreator(rootMirror, arg))(TypeTag.Nothing))) + exprArgs.prepend(args map (arg => context.Expr[Nothing](arg)(TypeTag.Nothing))) collectMacroArgs(fn) case TypeApply(fn, args) => typeArgs = args collectMacroArgs(fn) - case Select(qual, name) => - prefixTree = qual case _ => } collectMacroArgs(expandee) - val context = expandee.attachments.get[MacroAttachment].flatMap(_.macroContext).getOrElse(macroContext(typer, prefixTree, expandee)) var argss: List[List[Any]] = List(context) :: exprArgs.toList macroTraceVerbose("argss: ")(argss) val rawArgss = @@ -1115,7 +1112,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { delayed += expandee -> undetparams // need to save typer context for `macroExpandAll` // need to save macro context to preserve enclosures - expandee addAttachment MacroAttachment(delayed = true, typerContext = typer.context, macroContext = Some(context.asInstanceOf[MacroContext])) + expandee addAttachment MacroRuntimeAttachment(delayed = true, typerContext = typer.context, macroContext = Some(context.asInstanceOf[MacroContext])) Delay(expandee) } else { @@ -1130,7 +1127,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { case x => x } finally { - expandee.removeAttachment[MacroAttachment] + expandee.removeAttachment[MacroRuntimeAttachment] if (!isSuccess) openMacros = openMacros.tail } } @@ -1281,7 +1278,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces { override def transform(tree: Tree) = super.transform(tree match { // todo. expansion should work from the inside out case wannabe if (delayed contains wannabe) && calculateUndetparams(wannabe).isEmpty => - val context = wannabe.attachments.get[MacroAttachment].get.typerContext + val context = wannabe.attachments.get[MacroRuntimeAttachment].get.typerContext delayed -= wannabe context.implicitsEnabled = typer.context.implicitsEnabled context.enrichmentEnabled = typer.context.enrichmentEnabled diff --git a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala index 3033230603..190b18711c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala +++ b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala @@ -5,6 +5,6 @@ trait StdAttachments { self: Analyzer => type UnaffiliatedMacroContext = scala.reflect.makro.runtime.Context - type MacroContext = UnaffiliatedMacroContext { val mirror: self.global.type } - case class MacroAttachment(delayed: Boolean, typerContext: Context, macroContext: Option[MacroContext]) + type MacroContext = UnaffiliatedMacroContext { val universe: self.global.type } + case class MacroRuntimeAttachment(delayed: Boolean, typerContext: Context, macroContext: Option[MacroContext]) }
\ No newline at end of file diff --git a/src/library/scala/reflect/makro/Aliases.scala b/src/library/scala/reflect/makro/Aliases.scala index d7dd111f22..5e9ebdb263 100644 --- a/src/library/scala/reflect/makro/Aliases.scala +++ b/src/library/scala/reflect/makro/Aliases.scala @@ -3,26 +3,24 @@ package scala.reflect.makro trait Aliases { self: Context => - /** Aliases of mirror types */ - type Symbol = mirror.Symbol - type Type = mirror.Type - type Name = mirror.Name - type Tree = mirror.Tree - // type Position = mirror.Position - type Scope = mirror.Scope - type Modifiers = mirror.Modifiers - type Expr[+T] = mirror.Expr[T] - type TypeTag[T] = mirror.TypeTag[T] - type ConcreteTypeTag[T] = mirror.ConcreteTypeTag[T] + type Symbol = universe.Symbol + type Type = universe.Type + type Name = universe.Name + type TermName = universe.TermName + type TypeName = universe.TypeName + type Tree = universe.Tree + // type Position = universe.Position + type Scope = universe.Scope + type Modifiers = universe.Modifiers - /** Creator/extractor objects for Expr and TypeTag values */ - val TypeTag = mirror.TypeTag - val ConcreteTypeTag = mirror.ConcreteTypeTag - val Expr = mirror.Expr + type Expr[+T] = universe.Expr[T] + val Expr = universe.Expr - /** incantations for summoning tags */ - def tag[T](implicit ttag: TypeTag[T]) = ttag + type TypeTag[T] = universe.TypeTag[T] + type ConcreteTypeTag[T] = universe.ConcreteTypeTag[T] + val TypeTag = universe.TypeTag + val ConcreteTypeTag = universe.ConcreteTypeTag def typeTag[T](implicit ttag: TypeTag[T]) = ttag - def concreteTag[T](implicit cttag: ConcreteTypeTag[T]) = cttag def concreteTypeTag[T](implicit cttag: ConcreteTypeTag[T]) = cttag + def typeOf[T](implicit ttag: TypeTag[T]): Type = ttag.tpe } diff --git a/src/library/scala/reflect/makro/Context.scala b/src/library/scala/reflect/makro/Context.scala index fb77405d37..58fd0d3df3 100644 --- a/src/library/scala/reflect/makro/Context.scala +++ b/src/library/scala/reflect/makro/Context.scala @@ -15,12 +15,17 @@ trait Context extends Aliases with FrontEnds with Settings with Typers + with Parsers with Exprs with TypeTags + with Evals with Util { - /** The mirror that corresponds to the compile-time universe */ - val mirror: Universe + /** The compile-time universe */ + val universe: Universe + + /** The mirror of the compile-time universe */ + val mirror: MirrorOf[universe.type] /** The type of the prefix tree from which the macro is selected */ type PrefixType diff --git a/src/library/scala/reflect/makro/Evals.scala b/src/library/scala/reflect/makro/Evals.scala new file mode 100644 index 0000000000..e34f74ca1b --- /dev/null +++ b/src/library/scala/reflect/makro/Evals.scala @@ -0,0 +1,8 @@ +package scala.reflect.makro + +trait Evals { + self: Context => + + /** .. */ + def eval[T](expr: Expr[T]): T +}
\ No newline at end of file diff --git a/src/library/scala/reflect/makro/FrontEnds.scala b/src/library/scala/reflect/makro/FrontEnds.scala index d76907cdc8..7e47701ffa 100644 --- a/src/library/scala/reflect/makro/FrontEnds.scala +++ b/src/library/scala/reflect/makro/FrontEnds.scala @@ -5,7 +5,7 @@ trait FrontEnds extends scala.reflect.api.FrontEnds { import mirror._ - type Position = mirror.Position + type Position = universe.Position /** Exposes means to control the compiler UI */ def frontEnd: FrontEnd diff --git a/src/library/scala/reflect/makro/Infrastructure.scala b/src/library/scala/reflect/makro/Infrastructure.scala index 2bf49dca77..69394a27ea 100644 --- a/src/library/scala/reflect/makro/Infrastructure.scala +++ b/src/library/scala/reflect/makro/Infrastructure.scala @@ -23,6 +23,35 @@ trait Infrastructure { */ val currentRun: Run + /** Exposes library classpath. + */ + val libraryClassPath: List[java.net.URL] + + /** Exposes a classloader that corresponds to the library classpath. + * + * With this classloader you can perform on-the-fly evaluation of macro arguments. + * For example, consider this code snippet: + * + * def staticEval[T](x: T) = macro staticEval[T] + * + * def staticEval[T: c.TypeTag](c: Context)(x: c.Expr[T]) = { + * import scala.reflect.runtime.{universe => ru} + * val mirror = ru.runtimeMirror(c.libraryClassLoader) + * import scala.tools.reflect.ToolBox + * val toolBox = mirror.mkToolBox() + * val importer = ru.mkImporter(c.universe).asInstanceOf[ru.Importer { val from: c.universe.type }] + * val tree = c.resetAllAttrs(x.tree.duplicate) + * val imported = importer.importTree(tree) + * val valueOfX = toolBox.runExpr(imported).asInstanceOf[T] + * ... + * } + * + * // [Eugene++] using this guy will tremendously slow down the compilation + * // https://twitter.com/xeno_by/status/201248317831774208 + * // todo. we need to address this somehow + */ + def libraryClassLoader: ClassLoader + /** As seen by macro API, compilation run is an opaque type that can be deconstructed into: * 1) Current compilation unit * 2) List of all compilation units that comprise the run diff --git a/src/library/scala/reflect/makro/Names.scala b/src/library/scala/reflect/makro/Names.scala index 8a823d19cb..c842c48e52 100644 --- a/src/library/scala/reflect/makro/Names.scala +++ b/src/library/scala/reflect/makro/Names.scala @@ -10,5 +10,5 @@ trait Names { def fresh(name: String): String /** Creates a fresh name from the provided name */ - def fresh(name: Name): Name + def fresh[NameType <: Name](name: NameType): NameType } diff --git a/src/library/scala/reflect/makro/Parsers.scala b/src/library/scala/reflect/makro/Parsers.scala new file mode 100644 index 0000000000..737d387434 --- /dev/null +++ b/src/library/scala/reflect/makro/Parsers.scala @@ -0,0 +1,17 @@ +package scala.reflect.makro + +trait Parsers { + self: Context => + + /** .. */ + // todo. distinguish between `parseExpr` and `parse` + def parse(code: String): Tree + + /** Represents an error during parsing + */ + type ParseError <: Throwable + val ParseError: ParseErrorExtractor + abstract class ParseErrorExtractor { + def unapply(error: ParseError): Option[(Position, String)] + } +}
\ No newline at end of file diff --git a/src/library/scala/reflect/makro/Typers.scala b/src/library/scala/reflect/makro/Typers.scala index 90024a4f7a..2087309520 100644 --- a/src/library/scala/reflect/makro/Typers.scala +++ b/src/library/scala/reflect/makro/Typers.scala @@ -3,7 +3,7 @@ package scala.reflect.makro trait Typers { self: Context => - import mirror._ + import universe._ /** Contexts that represent macros in-flight, including the current one. Very much like a stack trace, but for macros only. * Can be useful for interoperating with other macros and for imposing compiler-friendly limits on macro expansion. diff --git a/src/library/scala/reflect/makro/package.scala b/src/library/scala/reflect/makro/package.scala new file mode 100644 index 0000000000..3c0e51030e --- /dev/null +++ b/src/library/scala/reflect/makro/package.scala @@ -0,0 +1,6 @@ +package scala.reflect + +package object makro { + + type MirrorOf[U <: base.Universe with Singleton] = base.MirrorOf[U] +} |