summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-04-26 10:03:56 +0300
committerEugene Burmako <xeno.by@gmail.com>2012-04-26 10:03:56 +0300
commit99388a81d42cde0cb0e8ecd57f290f6df25b9bdd (patch)
tree37eb4cab4c3ae68a024f3e810ce18d8140aa7128 /src
parent8fc543b5dd7e6a8fa1827cc9e9d65e721cae140e (diff)
downloadscala-99388a81d42cde0cb0e8ecd57f290f6df25b9bdd.tar.gz
scala-99388a81d42cde0cb0e8ecd57f290f6df25b9bdd.tar.bz2
scala-99388a81d42cde0cb0e8ecd57f290f6df25b9bdd.zip
cleaning up macros, one step at a time
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Context.scala3
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Traces.scala8
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Typers.scala17
-rw-r--r--src/compiler/scala/reflect/makro/util/Traces.scala18
-rw-r--r--src/compiler/scala/reflect/reify/Errors.scala3
-rw-r--r--src/compiler/scala/reflect/reify/codegen/Types.scala2
-rw-r--r--src/compiler/scala/reflect/reify/codegen/Util.scala2
-rw-r--r--src/compiler/scala/reflect/reify/package.scala10
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala201
-rw-r--r--src/library/scala/reflect/makro/Typers.scala2
11 files changed, 135 insertions, 137 deletions
diff --git a/src/compiler/scala/reflect/makro/runtime/Context.scala b/src/compiler/scala/reflect/makro/runtime/Context.scala
index 15a4118b85..ca02822788 100644
--- a/src/compiler/scala/reflect/makro/runtime/Context.scala
+++ b/src/compiler/scala/reflect/makro/runtime/Context.scala
@@ -14,7 +14,8 @@ abstract class Context extends scala.reflect.makro.Context
with Settings
with Symbols
with Typers
- with Util {
+ with Util
+ with Traces {
val mirror: Global
diff --git a/src/compiler/scala/reflect/makro/runtime/Traces.scala b/src/compiler/scala/reflect/makro/runtime/Traces.scala
new file mode 100644
index 0000000000..6b61842316
--- /dev/null
+++ b/src/compiler/scala/reflect/makro/runtime/Traces.scala
@@ -0,0 +1,8 @@
+package scala.reflect.makro
+package runtime
+
+trait Traces extends util.Traces {
+ self: Context =>
+
+ def globalSettings = mirror.settings
+}
diff --git a/src/compiler/scala/reflect/makro/runtime/Typers.scala b/src/compiler/scala/reflect/makro/runtime/Typers.scala
index 98dbd65b72..c61e492250 100644
--- a/src/compiler/scala/reflect/makro/runtime/Typers.scala
+++ b/src/compiler/scala/reflect/makro/runtime/Typers.scala
@@ -9,8 +9,7 @@ trait Typers {
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 trace(msg: Any) = if (mirror.settings.Ymacrodebug.value) println(msg)
- trace("typechecking %s with expected type %s, implicit views = %s, macros = %s".format(tree, pt, !withImplicitViewsDisabled, !withMacrosDisabled))
+ 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] _)
def wrapper (tree: => Tree) = wrapper1(wrapper2(tree))
@@ -21,25 +20,24 @@ trait Typers {
// (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) =>
- trace(result)
+ macroLogVerbose(result)
result
case error @ mirror.analyzer.SilentTypeError(_) =>
- trace(error.err.errMsg)
+ macroLogVerbose(error.err.errMsg)
if (!silent) throw new mirror.TypeError(error.err.errPos, error.err.errMsg)
mirror.EmptyTree
})
}
def inferImplicitValue(pt: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: Position = enclosingPosition): Tree = {
- def trace(msg: Any) = if (mirror.settings.Ymacrodebug.value) println(msg)
- trace("inferring implicit value of type %s, macros = %s".format(pt, !withMacrosDisabled))
+ macroLogVerbose("inferring implicit value of type %s, macros = %s".format(pt, !withMacrosDisabled))
import mirror.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 {
case failure if failure.tree.isEmpty =>
- trace("implicit search has failed. to find out the reason, turn on -Xlog-implicits")
+ 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
case success =>
@@ -48,8 +46,7 @@ trait Typers {
}
def inferImplicitView(tree: Tree, from: Type, to: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, reportAmbiguous: Boolean = true, pos: Position = enclosingPosition): Tree = {
- def trace(msg: Any) = if (mirror.settings.Ymacrodebug.value) println(msg)
- trace("inferring implicit view from %s to %s for %s, macros = %s, reportAmbiguous = %s".format(from, to, tree, !withMacrosDisabled, reportAmbiguous))
+ macroLogVerbose("inferring implicit view from %s to %s for %s, macros = %s, reportAmbiguous = %s".format(from, to, tree, !withMacrosDisabled, reportAmbiguous))
import mirror.analyzer.SearchResult
val context = callsiteTyper.context
val wrapper1 = if (!withMacrosDisabled) (context.withMacrosEnabled[SearchResult] _) else (context.withMacrosDisabled[SearchResult] _)
@@ -58,7 +55,7 @@ trait Typers {
val viewTpe = mirror.TypeRef(fun1.typeConstructor.prefix, fun1, List(from, to))
wrapper(mirror.analyzer.inferImplicit(tree, viewTpe, reportAmbiguous, true, context, !silent, pos)) match {
case failure if failure.tree.isEmpty =>
- trace("implicit search has failed. to find out the reason, turn on -Xlog-implicits")
+ 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
case success =>
diff --git a/src/compiler/scala/reflect/makro/util/Traces.scala b/src/compiler/scala/reflect/makro/util/Traces.scala
new file mode 100644
index 0000000000..2363cc4bac
--- /dev/null
+++ b/src/compiler/scala/reflect/makro/util/Traces.scala
@@ -0,0 +1,18 @@
+package scala.reflect.makro
+package util
+
+trait Traces {
+ def globalSettings: tools.nsc.Settings
+
+ // [Eugene] lots of ways to log:
+ // 1) trace(...)
+ // 2) log(...)
+ // 3) if (foo) { doStuff(); includingSomeLogs(); }
+ // what is the conventional way of unifying this?
+ val macroDebugLite = globalSettings.YmacrodebugLite.value
+ val macroDebugVerbose = globalSettings.YmacrodebugVerbose.value
+ val macroTraceLite = scala.tools.nsc.util.trace when (macroDebugLite || macroDebugVerbose)
+ val macroTraceVerbose = scala.tools.nsc.util.trace when macroDebugVerbose
+ @inline final def macroLogLite(msg: => Any) { if (macroDebugLite || macroDebugVerbose) println(msg) }
+ @inline final def macroLogVerbose(msg: => Any) { if (macroDebugVerbose) println(msg) }
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/reify/Errors.scala b/src/compiler/scala/reflect/reify/Errors.scala
index 1a881455f2..4466f281b8 100644
--- a/src/compiler/scala/reflect/reify/Errors.scala
+++ b/src/compiler/scala/reflect/reify/Errors.scala
@@ -10,8 +10,7 @@ trait Errors {
import mirror._
import definitions._
- lazy val defaultErrorPosition: Position =
- mirror.analyzer.openMacros.find(c => c.macroApplication.pos != NoPosition).map(_.macroApplication.pos).getOrElse(NoPosition)
+ def defaultErrorPosition = analyzer.enclosingMacroPosition
// expected errors: these can happen if the user casually writes whatever.reify(...)
// hence we don't crash here, but nicely report a typechecking error and bail out asap
diff --git a/src/compiler/scala/reflect/reify/codegen/Types.scala b/src/compiler/scala/reflect/reify/codegen/Types.scala
index 8fa24c5b00..1f336f4b0f 100644
--- a/src/compiler/scala/reflect/reify/codegen/Types.scala
+++ b/src/compiler/scala/reflect/reify/codegen/Types.scala
@@ -99,7 +99,7 @@ trait Types {
// if this fails, it might produce the dreaded "erroneous or inaccessible type" error
// to find out the whereabouts of the error run scalac with -Ydebug
if (reifyDebug) println("launching implicit search for %s.%s[%s]".format(prefix, tagClass.name, tpe))
- typer.resolveTypeTag(positionBearer.pos, prefix.tpe, tpe, concrete) match {
+ typer.resolveTypeTag(defaultErrorPosition, prefix.tpe, tpe, concrete) match {
case failure if failure.isEmpty =>
if (reifyDebug) println("implicit search was fruitless")
EmptyTree
diff --git a/src/compiler/scala/reflect/reify/codegen/Util.scala b/src/compiler/scala/reflect/reify/codegen/Util.scala
index 8d7cf39ff7..bb369a1adb 100644
--- a/src/compiler/scala/reflect/reify/codegen/Util.scala
+++ b/src/compiler/scala/reflect/reify/codegen/Util.scala
@@ -14,8 +14,6 @@ trait Util {
object reifiedNodePrinters extends { val global: mirror.type = mirror } with tools.nsc.ast.NodePrinters with NodePrinters
val reifiedNodeToString = reifiedNodePrinters.reifiedNodeToString
- val positionBearer = mirror.analyzer.openMacros.find(c => c.macroApplication.pos != NoPosition).map(_.macroApplication).getOrElse(EmptyTree).asInstanceOf[Tree]
-
def reifyList(xs: List[Any]): Tree =
mkList(xs map reify)
diff --git a/src/compiler/scala/reflect/reify/package.scala b/src/compiler/scala/reflect/reify/package.scala
index fa11c6313d..3f9d6200cd 100644
--- a/src/compiler/scala/reflect/reify/package.scala
+++ b/src/compiler/scala/reflect/reify/package.scala
@@ -31,8 +31,12 @@ package object reify {
def reifyErasure(global: Global)(typer0: global.analyzer.Typer, tpe: global.Type, concrete: Boolean = true): global.Tree = {
import global._
import definitions._
- val positionBearer = analyzer.openMacros.find(_.macroApplication.pos != NoPosition).map(_.macroApplication).getOrElse(EmptyTree).asInstanceOf[Tree]
- val inScope = typer0.context.withMacrosDisabled(typer0.resolveErasureTag(positionBearer.pos, tpe, concrete = concrete), typer0.resolveArrayTag(positionBearer.pos, tpe))
+ import analyzer.enclosingMacroPosition
+
+ def erasureTagInScope = typer0.context.withMacrosDisabled(typer0.resolveErasureTag(enclosingMacroPosition, tpe, concrete = concrete))
+ def arrayTagInScope = typer0.context.withMacrosDisabled(typer0.resolveArrayTag(enclosingMacroPosition, tpe))
+ val inScope = (erasureTagInScope, arrayTagInScope)
+
inScope match {
case (success, _) if !success.isEmpty =>
Select(success, nme.erasure)
@@ -44,7 +48,7 @@ package object reify {
val componentErasure = reifyErasure(global)(typer0, componentTpe, concrete)
gen.mkMethodCall(arrayClassMethod, List(componentErasure))
} else {
- if (tpe.isSpliceable && concrete) throw new ReificationError(positionBearer.pos, "tpe %s is an unresolved spliceable type".format(tpe))
+ if (tpe.isSpliceable && concrete) throw new ReificationError(enclosingMacroPosition, "tpe %s is an unresolved spliceable type".format(tpe))
var erasure = tpe.erasure
if (tpe.typeSymbol.isDerivedValueClass && global.phase.id < global.currentRun.erasurePhase.id) erasure = tpe
gen.mkNullaryCall(Predef_classOf, List(erasure))
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index 6a5c4c92bc..91e31cae97 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -138,7 +138,7 @@ trait ScalaSettings extends AbsScalaSettings
val termConflict = ChoiceSetting ("-Yresolve-term-conflict", "strategy", "Resolve term conflicts", List("package", "object", "error"), "error")
val inline = BooleanSetting ("-Yinline", "Perform inlining when possible.")
val inlineHandlers = BooleanSetting ("-Yinline-handlers", "Perform exception handler inlining when possible.")
- val YinlinerWarnings= BooleanSetting ("-Yinline-warnings", "Emit inlining warnings. (Normally surpressed due to high volume)")
+ val YinlinerWarnings= BooleanSetting ("-Yinline-warnings", "Emit inlining warnings. (Normally surpressed due to high volume)")
val Xlinearizer = ChoiceSetting ("-Ylinearizer", "which", "Linearizer to use", List("normal", "dfs", "rpo", "dump"), "rpo")
val log = PhasesSetting ("-Ylog", "Log operations during")
val Ylogcp = BooleanSetting ("-Ylog-classpath", "Output information about what classpath is being applied.")
@@ -172,7 +172,6 @@ trait ScalaSettings extends AbsScalaSettings
val YrichExes = BooleanSetting ("-Yrich-exceptions", "Fancier exceptions. Set source search path with -D" + sys.SystemProperties.traceSourcePath.key)
val Ybuilderdebug = ChoiceSetting ("-Ybuilder-debug", "manager", "Compile using the specified build manager.", List("none", "refined", "simple"), "none")
val Yreifycopypaste = BooleanSetting ("-Yreify-copypaste", "Dump the reified trees in copypasteable representation.")
- val Ymacrocopypaste = BooleanSetting ("-Ymacro-copypaste", "Dump macro expansions in copypasteable representation.")
val Yreplsync = BooleanSetting ("-Yrepl-sync", "Do not use asynchronous code for repl startup")
val Ynotnull = BooleanSetting ("-Ynotnull", "Enable (experimental and incomplete) scala.NotNull.")
val YmethodInfer = BooleanSetting ("-Yinfer-argument-types", "Infer types for arguments of overriden methods.")
@@ -193,7 +192,8 @@ trait ScalaSettings extends AbsScalaSettings
val Yidedebug = BooleanSetting("-Yide-debug", "Generate, validate and output trees using the interactive compiler.")
val Yinferdebug = BooleanSetting("-Yinfer-debug", "Trace type inference and implicit search.")
val Yissuedebug = BooleanSetting("-Yissue-debug", "Print stack traces when a context issues an error.")
- val Ymacrodebug = BooleanSetting("-Ymacro-debug", "Trace macro-related activities: compilation, generation of synthetics, classloading, expansion, exceptions.")
+ val YmacrodebugLite = BooleanSetting("-Ymacro-debug-lite", "Trace essential macro-related activities.")
+ val YmacrodebugVerbose = BooleanSetting("-Ymacro-debug-verbose", "Trace all macro-related activities: compilation, generation of synthetics, classloading, expansion, exceptions.")
val Ypmatdebug = BooleanSetting("-Ypmat-debug", "Trace all pattern matcher activity.")
val Yposdebug = BooleanSetting("-Ypos-debug", "Trace position validation.")
val Yreifydebug = BooleanSetting("-Yreify-debug", "Trace reification.")
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index 14f09d9dc9..1b8a43bf27 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -10,6 +10,7 @@ import scala.compat.Platform.EOL
import scala.reflect.makro.runtime.{Context => MacroContext}
import scala.reflect.runtime.Mirror
import util.Statistics._
+import scala.reflect.makro.util._
/**
* Code to deal with macros, namely with:
@@ -36,13 +37,12 @@ import util.Statistics._
* (Expr(elems))
* (TypeTag(Int))
*/
-trait Macros { self: Analyzer =>
+trait Macros extends Traces {
+ self: Analyzer =>
+
import global._
import definitions._
-
- val macroDebug = settings.Ymacrodebug.value
- val macroCopypaste = settings.Ymacrocopypaste.value
- val macroTrace = scala.tools.nsc.util.trace when macroDebug
+ def globalSettings = global.settings
val globalMacroCache = collection.mutable.Map[Any, Any]()
val perRunMacroCache = perRunCaches.newMap[Symbol, collection.mutable.Map[Any, Any]]
@@ -136,11 +136,11 @@ trait Macros { self: Analyzer =>
}
import SigGenerator._
- macroTrace("generating macroImplSigs for: ")(macroDef)
- macroTrace("tparams are: ")(tparams)
- macroTrace("vparamss are: ")(vparamss)
- macroTrace("retTpe is: ")(retTpe)
- macroTrace("macroImplSigs are: ")(paramsss, implRetTpe)
+ macroTraceVerbose("generating macroImplSigs for: ")(macroDef)
+ macroTraceVerbose("tparams are: ")(tparams)
+ macroTraceVerbose("vparamss are: ")(vparamss)
+ macroTraceVerbose("retTpe is: ")(retTpe)
+ macroTraceVerbose("macroImplSigs are: ")(paramsss, implRetTpe)
}
private def transformTypeTagEvidenceParams(paramss: List[List[Symbol]], transform: (Symbol, Symbol) => Option[Symbol]): List[List[Symbol]] = {
@@ -183,7 +183,7 @@ trait Macros { self: Analyzer =>
*/
def typedMacroBody(typer: Typer, ddef: DefDef): Tree = {
import typer.context
- if (macroDebug) println("typechecking macro def %s at %s".format(ddef.symbol, ddef.pos))
+ macroLogVerbose("typechecking macro def %s at %s".format(ddef.symbol, ddef.pos))
if (!typer.checkFeature(ddef.pos, MacrosFeature, immediate = true)) {
ddef.symbol setFlag IS_ERROR
@@ -267,7 +267,7 @@ trait Macros { self: Analyzer =>
val rhs = ddef.rhs
validatePreTyper(rhs)
- if (hasErrors) macroTrace("macro def failed to satisfy trivial preconditions: ")(macroDef)
+ if (hasErrors) macroTraceVerbose("macro def failed to satisfy trivial preconditions: ")(macroDef)
// we use typed1 instead of typed, because otherwise adapt is going to mess us up
// if adapt sees <qualifier>.<method>, it will want to perform eta-expansion and will fail
@@ -284,12 +284,7 @@ trait Macros { self: Analyzer =>
case Success(expanded) =>
try {
val typechecked = typer.typed1(expanded, EXPRmode, WildcardType)
- if (macroDebug) {
- println("typechecked1:")
- println(typechecked)
- println(showRaw(typechecked))
- }
-
+ macroLogVerbose("typechecked1:%n%s%n%s".format(typechecked, showRaw(typechecked)))
typechecked
} finally {
openMacros = openMacros.tail
@@ -312,7 +307,7 @@ trait Macros { self: Analyzer =>
var rhs1 = typecheckRhs(rhs)
def typecheckedWithErrors = (rhs1 exists (_.isErroneous)) || reporter.ERROR.count != prevNumErrors
hasErrors = hasErrors || typecheckedWithErrors
- if (typecheckedWithErrors) macroTrace("body of a macro def failed to typecheck: ")(ddef)
+ if (typecheckedWithErrors) macroTraceVerbose("body of a macro def failed to typecheck: ")(ddef)
val macroImpl = rhs1.symbol
macroDef withAnnotation AnnotationInfo(MacroImplAnnotation.tpe, List(rhs1), Nil)
@@ -330,7 +325,7 @@ trait Macros { self: Analyzer =>
validatePostTyper(rhs1)
}
if (hasErrors)
- macroTrace("macro def failed to satisfy trivial preconditions: ")(macroDef)
+ macroTraceVerbose("macro def failed to satisfy trivial preconditions: ")(macroDef)
}
if (!hasErrors) {
@@ -352,7 +347,7 @@ trait Macros { self: Analyzer =>
compatibilityError("number of parameter sections differ")
def checkSubType(slot: String, reqtpe: Type, acttpe: Type): Unit = {
- val ok = if (macroDebug) {
+ val ok = if (macroDebugVerbose) {
if (reqtpe eq acttpe) println(reqtpe + " <: " + acttpe + "?" + EOL + "true")
withTypesExplained(reqtpe <:< acttpe)
} else reqtpe <:< acttpe
@@ -437,7 +432,7 @@ trait Macros { self: Analyzer =>
val implicitParams = actparamss.flatten filter (_.isImplicit)
if (implicitParams.length > 0) {
reportError(implicitParams.head.pos, "macro implementations cannot have implicit parameters other than TypeTag evidences")
- macroTrace("macro def failed to satisfy trivial preconditions: ")(macroDef)
+ macroTraceVerbose("macro def failed to satisfy trivial preconditions: ")(macroDef)
}
if (!hasErrors) {
@@ -458,9 +453,9 @@ trait Macros { self: Analyzer =>
"\n found : "+showMeth(actparamss, actres, false)+
"\n"+addendum)
- macroTrace("considering " + reqparamsss.length + " possibilities of compatible macro impl signatures for macro def: ")(ddef.name)
+ macroTraceVerbose("considering " + reqparamsss.length + " possibilities of compatible macro impl signatures for macro def: ")(ddef.name)
val results = reqparamsss map (checkCompatibility(_, actparamss, reqres, actres))
- if (macroDebug) (reqparamsss zip results) foreach { case (reqparamss, result) =>
+ if (macroDebugVerbose) (reqparamsss zip results) foreach { case (reqparamss, result) =>
println("%s %s".format(if (result.isEmpty) "[ OK ]" else "[FAILED]", reqparamss))
result foreach (errorMsg => println(" " + errorMsg))
}
@@ -472,7 +467,7 @@ trait Macros { self: Analyzer =>
compatibilityError(mostRelevantMessage)
} else {
assert((results filter (_.isEmpty)).length == 1, results)
- if (macroDebug) (reqparamsss zip results) filter (_._2.isEmpty) foreach { case (reqparamss, result) =>
+ if (macroDebugVerbose) (reqparamsss zip results) filter (_._2.isEmpty) foreach { case (reqparamss, result) =>
println("typechecked macro impl as: " + reqparamss)
}
}
@@ -596,11 +591,11 @@ trait Macros { self: Analyzer =>
val libraryClassLoader = {
if (settings.XmacroPrimaryClasspath.value != "") {
- if (macroDebug) println("primary macro mirror: initializing from -Xmacro-primary-classpath: %s".format(settings.XmacroPrimaryClasspath.value))
+ macroLogVerbose("primary macro mirror: initializing from -Xmacro-primary-classpath: %s".format(settings.XmacroPrimaryClasspath.value))
val classpath = toURLs(settings.XmacroFallbackClasspath.value)
ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader)
} else {
- if (macroDebug) println("primary macro mirror: initializing from -cp: %s".format(global.classPath.asURLs))
+ macroLogVerbose("primary macro mirror: initializing from -cp: %s".format(global.classPath.asURLs))
val classpath = global.classPath.asURLs
var loader: ClassLoader = ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader)
@@ -626,7 +621,7 @@ trait Macros { self: Analyzer =>
throw new UnsupportedOperationException("Scala reflection not available on this platform")
val fallbackClassLoader = {
- if (macroDebug) println("fallback macro mirror: initializing from -Xmacro-fallback-classpath: %s".format(settings.XmacroFallbackClasspath.value))
+ macroLogVerbose("fallback macro mirror: initializing from -Xmacro-fallback-classpath: %s".format(settings.XmacroFallbackClasspath.value))
val classpath = toURLs(settings.XmacroFallbackClasspath.value)
ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader)
}
@@ -649,24 +644,24 @@ trait Macros { self: Analyzer =>
private def macroRuntime(macroDef: Symbol): Option[MacroRuntime] =
macroRuntimesCache.getOrElseUpdate(macroDef, {
val runtime = {
- macroTrace("looking for macro implementation: ")(macroDef)
- macroTrace("macroDef is annotated with: ")(macroDef.annotations)
+ macroTraceVerbose("looking for macro implementation: ")(macroDef)
+ macroTraceVerbose("macroDef is annotated with: ")(macroDef.annotations)
val ann = macroDef.getAnnotation(MacroImplAnnotation)
if (ann == None) {
- macroTrace("@macroImpl annotation is missing (this means that macro definition failed to typecheck)")(macroDef)
+ macroTraceVerbose("@macroImpl annotation is missing (this means that macro definition failed to typecheck)")(macroDef)
return None
}
val macroImpl = ann.get.args(0).symbol
if (macroImpl == NoSymbol) {
- macroTrace("@macroImpl annotation is malformed (this means that macro definition failed to typecheck)")(macroDef)
+ macroTraceVerbose("@macroImpl annotation is malformed (this means that macro definition failed to typecheck)")(macroDef)
return None
}
- if (macroDebug) println("resolved implementation %s at %s".format(macroImpl, macroImpl.pos))
+ macroLogVerbose("resolved implementation %s at %s".format(macroImpl, macroImpl.pos))
if (macroImpl.isErroneous) {
- macroTrace("macro implementation is erroneous (this means that either macro body or macro implementation signature failed to typecheck)")(macroDef)
+ macroTraceVerbose("macro implementation is erroneous (this means that either macro body or macro implementation signature failed to typecheck)")(macroDef)
return None
}
@@ -680,14 +675,14 @@ trait Macros { self: Analyzer =>
// however, the code below doesn't account for these guys, because it'd take a look of time to get it right
// for now I leave it as a todo and move along to more the important stuff
- macroTrace("loading implementation class from %s: ".format(macroMirror))(macroImpl.owner.fullName)
- macroTrace("classloader is: ")("%s of type %s".format(macroMirror.classLoader, if (macroMirror.classLoader != null) macroMirror.classLoader.getClass.toString else "primordial classloader"))
+ macroTraceVerbose("loading implementation class from %s: ".format(macroMirror))(macroImpl.owner.fullName)
+ macroTraceVerbose("classloader is: ")("%s of type %s".format(macroMirror.classLoader, if (macroMirror.classLoader != null) macroMirror.classLoader.getClass.toString else "primordial classloader"))
def inferClasspath(cl: ClassLoader) = cl match {
case cl: java.net.URLClassLoader => "[" + (cl.getURLs mkString ",") + "]"
case null => "[" + scala.tools.util.PathResolver.Environment.javaBootClassPath + "]"
case _ => "<unknown>"
}
- macroTrace("classpath is: ")(inferClasspath(macroMirror.classLoader))
+ macroTraceVerbose("classpath is: ")(inferClasspath(macroMirror.classLoader))
// [Eugene] relies on the fact that macro implementations can only be defined in static classes
// [Martin to Eugene] There's similar logic buried in Symbol#flatname. Maybe we can refactor?
@@ -711,7 +706,7 @@ trait Macros { self: Analyzer =>
val implClassName = classfile(macroImpl.owner)
val implClassSymbol: macroMirror.Symbol = macroMirror.symbolForName(implClassName)
- if (macroDebug) {
+ if (macroDebugVerbose) {
println("implClassSymbol is: " + implClassSymbol.fullNameString)
if (implClassSymbol != macroMirror.NoSymbol) {
@@ -723,7 +718,7 @@ trait Macros { self: Analyzer =>
}
val implObjSymbol = implClassSymbol.companionModule
- macroTrace("implObjSymbol is: ")(implObjSymbol.fullNameString)
+ macroTraceVerbose("implObjSymbol is: ")(implObjSymbol.fullNameString)
if (implObjSymbol == macroMirror.NoSymbol) None
else {
@@ -733,29 +728,27 @@ trait Macros { self: Analyzer =>
val implObjClass = java.lang.Class.forName(implClassName, true, macroMirror.classLoader)
implObjClass getField "MODULE$" get null
} catch {
- case ex: NoSuchFieldException => macroTrace("exception when loading implObj: ")(ex); null
- case ex: NoClassDefFoundError => macroTrace("exception when loading implObj: ")(ex); null
- case ex: ClassNotFoundException => macroTrace("exception when loading implObj: ")(ex); null
+ case ex: NoSuchFieldException => macroTraceVerbose("exception when loading implObj: ")(ex); null
+ case ex: NoClassDefFoundError => macroTraceVerbose("exception when loading implObj: ")(ex); null
+ case ex: ClassNotFoundException => macroTraceVerbose("exception when loading implObj: ")(ex); null
}
if (implObj == null) None
else {
val implMethSymbol = implObjSymbol.info.member(macroMirror.newTermName(macroImpl.name.toString))
- if (macroDebug) {
- println("implMethSymbol is: " + implMethSymbol.fullNameString)
- println("jimplMethSymbol is: " + macroMirror.methodToJava(implMethSymbol))
- }
+ macroLogVerbose("implMethSymbol is: " + implMethSymbol.fullNameString)
+ macroLogVerbose("jimplMethSymbol is: " + macroMirror.methodToJava(implMethSymbol))
if (implMethSymbol == macroMirror.NoSymbol) None
else {
- if (macroDebug) println("successfully loaded macro impl as (%s, %s)".format(implObj, implMethSymbol))
+ macroLogVerbose("successfully loaded macro impl as (%s, %s)".format(implObj, implMethSymbol))
Some((implObj, implMethSymbol))
}
}
}
} catch {
case ex: ClassNotFoundException =>
- macroTrace("implementation class failed to load: ")(ex.toString)
+ macroTraceVerbose("implementation class failed to load: ")(ex.toString)
None
}
}
@@ -767,7 +760,7 @@ trait Macros { self: Analyzer =>
Some(runtime _)
case None =>
if (settings.XmacroFallbackClasspath.value != "") {
- if (macroDebug) println("trying to load macro implementation from the fallback mirror: %s".format(settings.XmacroFallbackClasspath.value))
+ macroLogVerbose("trying to load macro implementation from the fallback mirror: %s".format(settings.XmacroFallbackClasspath.value))
val fallback = loadMacroImpl(fallbackMirror)
fallback match {
case Some((implObj, implMethSymbol)) =>
@@ -827,13 +820,13 @@ trait Macros { self: Analyzer =>
collectMacroArgs(expandee)
val context = expandee.attachmentOpt[MacroAttachment].flatMap(_.macroContext).getOrElse(macroContext(typer, prefixTree, expandee))
var argss: List[List[Any]] = List(context) :: exprArgs.toList
- macroTrace("argss: ")(argss)
+ macroTraceVerbose("argss: ")(argss)
val ann = macroDef.getAnnotation(MacroImplAnnotation).getOrElse(throw new Error("assertion failed. %s: %s".format(macroDef, macroDef.annotations)))
val macroImpl = ann.args(0).symbol
var paramss = macroImpl.paramss
val tparams = macroImpl.typeParams
- macroTrace("paramss: ")(paramss)
+ macroTraceVerbose("paramss: ")(paramss)
// we need to take care of all possible combos of nullary/empty-paramlist macro defs vs nullary/empty-arglist invocations
// nullary def + nullary invocation => paramss and argss match, everything is okay
@@ -845,7 +838,7 @@ trait Macros { self: Analyzer =>
val isEmptyParamlistDef = paramss_without_evidences.nonEmpty && paramss_without_evidences.last.isEmpty
val isEmptyArglistInvocation = argss.nonEmpty && argss.last.isEmpty
if (isEmptyParamlistDef && !isEmptyArglistInvocation) {
- if (macroDebug) println("isEmptyParamlistDef && !isEmptyArglistInvocation: appending a List() to argss")
+ macroLogVerbose("isEmptyParamlistDef && !isEmptyArglistInvocation: appending a List() to argss")
argss = argss :+ Nil
}
@@ -890,7 +883,7 @@ trait Macros { self: Analyzer =>
macroDef.owner)
} else
implRefTarg.tpe
- if (macroDebug) println("resolved tparam %s as %s".format(tparam, tpe))
+ macroLogVerbose("resolved tparam %s as %s".format(tparam, tpe))
resolved(tparam) = tpe
param.tpe.typeSymbol match {
case definitions.TypeTagClass =>
@@ -919,7 +912,7 @@ trait Macros { self: Analyzer =>
else as
}
val rawArgs = rawArgss.flatten
- macroTrace("rawArgs: ")(rawArgs)
+ macroTraceVerbose("rawArgs: ")(rawArgs)
Some(rawArgs)
}
@@ -927,16 +920,7 @@ trait Macros { self: Analyzer =>
* See more informations in comments to ``openMacros'' in ``scala.reflect.makro.Context''.
*/
var openMacros = List[MacroContext]()
- private def openMacroPos = openMacros map (_.expandee.pos) find (_ ne NoPosition) getOrElse NoPosition
-
- // !!! YOu should use a method like this which manages the stack.
- // That you presently need to spread this logic out is a major
- // design flaw.
- private def pushMacroContext[T](mc: MacroContext)(body: => T): T = {
- openMacros ::= mc
- try body
- finally openMacros = openMacros.tail
- }
+ def enclosingMacroPosition = openMacros map (_.macroApplication.pos) find (_ ne NoPosition) getOrElse NoPosition
/** Performs macro expansion:
* 1) Checks whether the expansion needs to be delayed (see ``mustDelayMacroExpansion'')
@@ -945,13 +929,13 @@ trait Macros { self: Analyzer =>
* 4) Checks that the result is a tree bound to this universe
* 5) Typechecks the result against the return type of the macro definition
*
- * If -Ymacro-debug is enabled, you will get detailed log of how exactly this function
+ * If -Ymacro-debug-lite is enabled, you will get basic notifications about macro expansion
+ * along with macro expansions logged in the form that can be copy/pasted verbatim into REPL.
+ *
+ * If -Ymacro-debug-verbose is enabled, you will get detailed log of how exactly this function
* performs class loading and method resolution in order to load the macro implementation.
* The log will also include other non-trivial steps of macro expansion.
*
- * If -Ymacro-copypaste is enabled along with -Ymacro-debug, you will get macro expansions
- * logged in the form that can be copy/pasted verbatim into REPL (useful for debugging!).
- *
* @return
* the expansion result if the expansion has been successful,
* the fallback method invocation if the expansion has been unsuccessful, but there is a fallback,
@@ -963,7 +947,7 @@ trait Macros { self: Analyzer =>
def macroExpand(typer: Typer, expandee: Tree, mode: Int = EXPRmode, pt: Type = WildcardType): Tree = {
def fail(what: String, tree: Tree): Tree = {
val err = typer.context.errBuffer.head
- this.fail(typer, tree, "failed to perform %s: %s at %s".format(what, err.errMsg, err.errPos))
+ this.fail(typer, tree, "failed to %s: %s at %s".format(what, err.errMsg, err.errPos))
return expandee
}
val start = startTimer(macroExpandNanos)
@@ -984,31 +968,23 @@ trait Macros { self: Analyzer =>
}
if (isNullaryInvocation) expectedTpe match {
case NullaryMethodType(restpe) =>
- macroTrace("nullary invocation of a nullary method. unwrapping expectedTpe from " + expectedTpe + " to: ")(restpe)
+ macroTraceVerbose("nullary invocation of a nullary method. unwrapping expectedTpe from " + expectedTpe + " to: ")(restpe)
expectedTpe = restpe
case MethodType(Nil, restpe) =>
- macroTrace("nullary invocation of a method with an empty parameter list. unwrapping expectedTpe from " + expectedTpe + " to: ")(restpe)
+ macroTraceVerbose("nullary invocation of a method with an empty parameter list. unwrapping expectedTpe from " + expectedTpe + " to: ")(restpe)
expectedTpe = restpe
case _ => ;
}
- if (macroDebug) println("typechecking1 against %s: %s".format(expectedTpe, expanded))
+ macroLogVerbose("typechecking1 against %s: %s".format(expectedTpe, expanded))
var typechecked = typer.context.withImplicitsEnabled(typer.typed(expanded, EXPRmode, expectedTpe))
- if (typer.context.hasErrors) fail("typecheck1", expanded)
- if (macroDebug) {
- println("typechecked1:")
- println(typechecked)
- println(showRaw(typechecked))
- }
+ if (typer.context.hasErrors) fail("typecheck against macro def return type", expanded)
+ macroLogVerbose("typechecked1:%n%s%n%s".format(typechecked, showRaw(typechecked)))
- if (macroDebug) println("typechecking2 against %s: %s".format(pt, expanded))
+ macroLogVerbose("typechecking2 against %s: %s".format(pt, expanded))
typechecked = typer.context.withImplicitsEnabled(typer.typed(typechecked, EXPRmode, pt))
- if (typer.context.hasErrors) fail("typecheck2", expanded)
- if (macroDebug) {
- println("typechecked2:")
- println(typechecked)
- println(showRaw(typechecked))
- }
+ if (typer.context.hasErrors) fail("typecheck against expected type", expanded)
+ macroLogVerbose("typechecked2:%n%s%n%s".format(typechecked, showRaw(typechecked)))
typechecked
} finally {
@@ -1033,11 +1009,9 @@ trait Macros { self: Analyzer =>
private def Cancel(expandee: Tree) = Other(expandee)
private def Failure(expandee: Tree) = Other(expandee)
private def fail(typer: Typer, expandee: Tree, msg: String = null) = {
- if (macroDebug || macroCopypaste) {
- var msg1 = if (msg != null && (msg contains "exception during macro expansion")) msg.split(EOL).drop(1).headOption.getOrElse("?") else msg
- if (macroDebug) println("macro expansion has failed: %s".format(msg1))
- }
- val pos = if (expandee.pos != NoPosition) expandee.pos else openMacros.find(c => c.expandee.pos != NoPosition).map(_.expandee.pos).getOrElse(NoPosition)
+ def msgForLog = if (msg != null && (msg contains "exception during macro expansion")) msg.split(EOL).drop(1).headOption.getOrElse("?") else msg
+ macroLogVerbose("macro expansion has failed: %s".format(msgForLog))
+ val pos = if (expandee.pos != NoPosition) expandee.pos else enclosingMacroPosition
if (msg != null) typer.context.error(pos, msg)
typer.infer.setError(expandee)
Failure(expandee)
@@ -1058,7 +1032,7 @@ trait Macros { self: Analyzer =>
// there is no sense to expand the macro itself => it will only make matters worse
if (expandee.symbol.isErroneous || (expandee exists (_.isErroneous))) {
val reason = if (expandee.symbol.isErroneous) "incompatible macro implementation" else "erroneous arguments"
- macroTrace("cancelled macro expansion because of %s: ".format(reason))(expandee)
+ macroTraceVerbose("cancelled macro expansion because of %s: ".format(reason))(expandee)
return Cancel(typer.infer.setError(expandee))
}
@@ -1092,7 +1066,7 @@ trait Macros { self: Analyzer =>
val wasDelayed = isDelayed(expandee)
val undetparams = calculateUndetparams(expandee)
val nowDelayed = !typer.context.macrosEnabled || undetparams.nonEmpty
-
+
def failExpansion(msg: String = null) = fail(typer, expandee, msg)
def performExpansion(args: List[Any]): MacroExpansionResult = {
val numErrors = reporter.ERROR.count
@@ -1104,17 +1078,18 @@ trait Macros { self: Analyzer =>
failExpansion() // errors have been reported by the macro itself
else expanded match {
case expanded: Expr[_] =>
- if (macroDebug) println("original:")
- macroDebugLog("" + expanded.tree + "\n" + showRaw(expanded.tree))
+ macroLogVerbose("original:")
+ macroLogVerbose("" + expanded.tree + "\n" + showRaw(expanded.tree))
freeTerms(expanded.tree) foreach issueFreeError
freeTypes(expanded.tree) foreach issueFreeError
+ if (hasNewErrors) failExpansion()
+
// inherit the position from the first position-ful expandee in macro callstack
// this is essential for sane error messages
// now macro expansion gets typechecked against the macro definition return type
// however, this happens in macroExpand, not here in macroExpand1
- if (hasNewErrors) failExpansion()
- else Success(atPos(openMacroPos.focus)(expanded.tree))
+ else Success(atPos(enclosingMacroPosition.focus)(expanded.tree))
case _ =>
failExpansion(
"macro must return a compiler-specific expr; returned value is " + (
@@ -1130,11 +1105,11 @@ trait Macros { self: Analyzer =>
else Skip(macroExpandAll(typer, expandee))
}
else {
- macroDebugLog("typechecking macro expansion %s at %s".format(expandee, expandee.pos))
+ macroLogVerbose("typechecking macro expansion %s at %s".format(expandee, expandee.pos))
macroArgs(typer, expandee).fold(failExpansion(): MacroExpansionResult) {
case args @ ((context: MacroContext) :: _) =>
if (nowDelayed) {
- macroDebugLog("macro expansion is delayed: %s".format(expandee))
+ macroLogVerbose("macro expansion is delayed: %s".format(expandee))
delayed += expandee -> undetparams
// need to save typer context for `macroExpandAll`
// need to save macro context to preserve enclosures
@@ -1144,7 +1119,9 @@ trait Macros { self: Analyzer =>
else {
// adding stuff to openMacros is easy, but removing it is a nightmare
// it needs to be sprinkled over several different code locations
- openMacros ::= args.head.asInstanceOf[MacroContext]
+ // why? https://github.com/scala/scala/commit/bd3eacbae21f39b1ac7fe8ade4ed71fa98e1a28d#L2R1137
+ // todo. will be improved
+ openMacros ::= context
var isSuccess = false
try performExpansion(args) match {
case x: Success => isSuccess = true ; x
@@ -1158,7 +1135,7 @@ trait Macros { self: Analyzer =>
}
}
}
-
+
try macroExpandInternal
catch { case ex => handleMacroExpansionException(typer, expandee, ex) }
}
@@ -1179,7 +1156,7 @@ trait Macros { self: Analyzer =>
case first :: _ =>
Some(Select(qual, name) setPos tree.pos setSymbol first)
case _ =>
- macroTrace("macro is not overridden: ")(tree)
+ macroTraceVerbose("macro is not overridden: ")(tree)
notFound()
}
case Apply(fn, args) =>
@@ -1193,33 +1170,29 @@ trait Macros { self: Analyzer =>
case _ => None
}
case _ =>
- macroTrace("unexpected tree in fallback: ")(tree)
+ macroTraceVerbose("unexpected tree in fallback: ")(tree)
notFound()
}
}
fallBackToOverridden(expandee) match {
case Some(tree1) =>
- macroTrace("falling back to: ")(tree1)
+ macroTraceVerbose("falling back to: ")(tree1)
currentRun.macroExpansionFailed = true
Fallback(tree1)
case None =>
fail(typer, expandee)
}
}
-
- @inline final def macroDebugLog(msg: => String) {
- if (macroDebug || macroCopypaste) println(msg)
- }
- private def handleMacroExpansionException(typer: Typer, expandee: Tree, ex: Throwable): MacroExpansionResult = {
+ private def handleMacroExpansionException(typer: Typer, expandee: Tree, ex: Throwable): MacroExpansionResult = {
// [Eugene] any ideas about how to improve this one?
val realex = ReflectionUtils.unwrapThrowable(ex)
realex match {
case realex: reflect.makro.runtime.AbortMacroException =>
- macroDebugLog("macro expansion has failed: %s".format(realex.msg))
+ macroLogVerbose("macro expansion has failed: %s".format(realex.msg))
fail(typer, expandee) // error has been reported by abort
case err: TypeError =>
- macroDebugLog("macro expansion has failed: %s at %s".format(err.msg, err.pos))
+ macroLogVerbose("macro expansion has failed: %s at %s".format(err.msg, err.pos))
throw err // error should be propagated, don't report
case _ =>
val message = {
@@ -1271,24 +1244,24 @@ trait Macros { self: Analyzer =>
if (sub.symbol != null) traverse(sub.symbol)
if (sub.tpe != null) sub.tpe foreach (sub => traverse(sub.typeSymbol))
})
- if (macroDebug) println("calculateUndetparams: %s".format(calculated))
+ macroLogVerbose("calculateUndetparams: %s".format(calculated))
calculated map (_.id)
}
private val undetparams = perRunCaches.newSet[Int]
def notifyUndetparamsAdded(newUndets: List[Symbol]): Unit = {
undetparams ++= newUndets map (_.id)
- if (macroDebug) newUndets foreach (sym => println("undetParam added: %s".format(sym)))
+ if (macroDebugVerbose) newUndets foreach (sym => println("undetParam added: %s".format(sym)))
}
def notifyUndetparamsInferred(undetNoMore: List[Symbol], inferreds: List[Type]): Unit = {
undetparams --= undetNoMore map (_.id)
- if (macroDebug) (undetNoMore zip inferreds) foreach {case (sym, tpe) => println("undetParam inferred: %s as %s".format(sym, tpe))}
+ if (macroDebugVerbose) (undetNoMore zip inferreds) foreach { case (sym, tpe) => println("undetParam inferred: %s as %s".format(sym, tpe))}
if (!delayed.isEmpty)
delayed.toList foreach {
case (expandee, undetparams) if !undetparams.isEmpty =>
undetparams --= undetNoMore map (_.id)
if (undetparams.isEmpty) {
hasPendingMacroExpansions = true
- macroTrace("macro expansion is pending: ")(expandee)
+ macroTraceVerbose("macro expansion is pending: ")(expandee)
}
case _ =>
// do nothing
diff --git a/src/library/scala/reflect/makro/Typers.scala b/src/library/scala/reflect/makro/Typers.scala
index 1ced2daccd..c62c5f254c 100644
--- a/src/library/scala/reflect/makro/Typers.scala
+++ b/src/library/scala/reflect/makro/Typers.scala
@@ -29,7 +29,7 @@ trait Typers {
*
* If ``silent'' is false, ``TypeError'' will be thrown in case of a typecheck error.
* If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs.
- * Such errors don't vanish and can be inspected by turning on -Ymacro-debug.
+ * Such errors don't vanish and can be inspected by turning on -Ymacro-debug-verbose.
* Unlike in ``inferImplicitValue'' and ``inferImplicitView'', ``silent'' is false by default.
*
* Typechecking can be steered with the following optional parameters: