summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-06-06 14:29:05 +0200
committerEugene Burmako <xeno.by@gmail.com>2012-06-08 15:31:58 +0200
commitce67870e64afabf75363679bcee597812ad223e9 (patch)
treece84ef7673977b0dde4ed13ca1276e25517d6b9c /src
parentbdff66e2730518f449634375b1f3d19689d72b1e (diff)
downloadscala-ce67870e64afabf75363679bcee597812ad223e9.tar.gz
scala-ce67870e64afabf75363679bcee597812ad223e9.tar.bz2
scala-ce67870e64afabf75363679bcee597812ad223e9.zip
brings macros up to speed
Before reflection refactoring, macro contexts only exposed a mirror. Now it's time to expose both a universe (the compiler instance) and a mirror (a macro-specific symbol resolver). By the way, speaking of mirrors. Macro contexts have their own mirror, which is different from compiler's rootMirror. This is done because macros need to be able to resolve stuff from empty package. Reflection refactoring brought major changes to runtime evaluation, which got dropped from universes and now requires scala-compiler.jar. However there are macro users, who would like to do eval inside macros. To help them we expose `libraryClassLoader` to manually build toolboxes, and also a simple-to-use `c.eval` method. I've also sneakily introduced `c.parse`, because it's something that has also been frequently requested. Moreover, it might help Scaladoc. So I decided that it might be worth it to add this new functionality.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala1
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Aliases.scala34
-rw-r--r--src/compiler/scala/reflect/makro/runtime/CapturedVariables.scala7
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Context.scala11
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Enclosures.scala3
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Evals.scala18
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Exprs.scala2
-rw-r--r--src/compiler/scala/reflect/makro/runtime/FrontEnds.scala21
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Infrastructure.scala36
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Mirrors.scala40
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Names.scala4
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Parsers.scala25
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Reifiers.scala8
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Settings.scala6
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Traces.scala2
-rw-r--r--src/compiler/scala/reflect/makro/runtime/TypeTags.scala4
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Typers.scala40
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Util.scala2
-rw-r--r--src/compiler/scala/reflect/reify/Taggers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala33
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala4
-rw-r--r--src/library/scala/reflect/makro/Aliases.scala34
-rw-r--r--src/library/scala/reflect/makro/Context.scala9
-rw-r--r--src/library/scala/reflect/makro/Evals.scala8
-rw-r--r--src/library/scala/reflect/makro/FrontEnds.scala2
-rw-r--r--src/library/scala/reflect/makro/Infrastructure.scala29
-rw-r--r--src/library/scala/reflect/makro/Names.scala2
-rw-r--r--src/library/scala/reflect/makro/Parsers.scala17
-rw-r--r--src/library/scala/reflect/makro/Typers.scala2
-rw-r--r--src/library/scala/reflect/makro/package.scala6
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]
+}