summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2012-08-18 18:51:58 +0200
committerEugene Burmako <xeno.by@gmail.com>2012-08-19 09:36:54 +0200
commita3735fdbbf93128874d93da5c69af0f777220313 (patch)
treeb4f3684e98da1391c6d2ba38c308e75fad684c89
parentac430ac8ba554d1b976d44598400d95ce5cf3816 (diff)
downloadscala-a3735fdbbf93128874d93da5c69af0f777220313.tar.gz
scala-a3735fdbbf93128874d93da5c69af0f777220313.tar.bz2
scala-a3735fdbbf93128874d93da5c69af0f777220313.zip
pull request feedback
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala5
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala11
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala147
-rw-r--r--src/compiler/scala/tools/reflect/FastTrack.scala11
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala8
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala6
6 files changed, 87 insertions, 101 deletions
diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala b/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala
index 2c16a754cb..4a4a900e2b 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala
@@ -8,6 +8,7 @@ package interpreter
import scala.reflect.internal.util.Position
import scala.util.control.Exception.ignoring
+import scala.tools.nsc.util.stackTraceString
/**
* Machinery for the asynchronous initialization of the repl.
@@ -94,9 +95,7 @@ trait ILoopInit {
runThunks()
} catch {
case ex: Throwable =>
- val message = new java.io.StringWriter()
- ex.printStackTrace(new java.io.PrintWriter(message))
- initError = message.toString
+ initError = stackTraceString(ex)
throw ex
} finally {
initIsComplete = true
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index 99ce22ddb9..773d9a6f50 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -12,6 +12,8 @@ import symtab.Flags.{ PRIVATE, PROTECTED, IS_ERROR }
import scala.compat.Platform.EOL
import scala.reflect.runtime.ReflectionUtils
import scala.reflect.macros.runtime.AbortMacroException
+import scala.util.control.NonFatal
+import scala.tools.nsc.util.stackTraceString
trait ContextErrors {
self: Analyzer =>
@@ -687,13 +689,14 @@ trait ContextErrors {
relevantElements = relevantElements dropRight threshold
realex.setStackTrace(relevantElements)
- val message = new java.io.StringWriter()
- realex.printStackTrace(new java.io.PrintWriter(message))
- Some(EOL + message)
+ Some(EOL + stackTraceString(realex))
}
} catch {
// if the magic above goes boom, just fall back to uninformative, but better than nothing, getMessage
- case ex: Throwable =>
+ case NonFatal(ex) =>
+ macroLogVerbose("got an exception when processing a macro generated exception\n" +
+ "offender = " + stackTraceString(realex) + "\n" +
+ "error = " + stackTraceString(ex))
None
}
} getOrElse {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index ed38c1750b..abfefcd31e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -398,7 +398,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
macroLogVerbose("typechecked1:%n%s%n%s".format(typechecked, showRaw(typechecked)))
typechecked
} finally {
- openMacros = openMacros.tail
+ popMacroContext()
}
case Fallback(fallback) =>
typer.typed1(fallback, EXPRmode, WildcardType)
@@ -461,7 +461,11 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
map2(aparamss.flatten, rparamss.flatten)((aparam, rparam) => {
if (aparam.name != rparam.name && !rparam.isSynthetic) MacroImplParamNameMismatchError(aparam, rparam)
if (isRepeated(aparam) ^ isRepeated(rparam)) MacroImplVarargMismatchError(aparam, rparam)
- checkMacroImplParamTypeMismatch(stripOffPrefixTypeRefinement(atpeToRtpe(aparam.tpe)), rparam)
+ val aparamtpe = aparam.tpe.dealias match {
+ case RefinedType(List(tpe), Scope(sym)) if tpe == MacroContextClass.tpe && sym.allOverriddenSymbols.contains(MacroContextPrefixType) => tpe
+ case tpe => tpe
+ }
+ checkMacroImplParamTypeMismatch(atpeToRtpe(aparamtpe), rparam)
})
checkMacroImplResultTypeMismatch(atpeToRtpe(aret), rret)
@@ -510,7 +514,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
* @return Requested runtime if macro implementation can be loaded successfully from either of the mirrors,
* `null` otherwise.
*/
- type MacroRuntime = List[Any] => Any
+ type MacroRuntime = MacroArgs => Any
private val macroRuntimesCache = perRunCaches.newWeakMap[Symbol, MacroRuntime]
private def macroRuntime(macroDef: Symbol): MacroRuntime = {
macroTraceVerbose("looking for macro implementation: ")(macroDef)
@@ -538,7 +542,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
val implMeths = implObj.getClass.getDeclaredMethods.find(_.getName == methName)
val implMeth = implMeths getOrElse { throw new NoSuchMethodException(s"$className.$methName") }
macroLogVerbose("successfully loaded macro impl as (%s, %s)".format(implObj, implMeth))
- (args: List[Any]) => implMeth.invoke(implObj, (args map (_.asInstanceOf[AnyRef])): _*)
+ args => implMeth.invoke(implObj, ((args.c +: args.others) map (_.asInstanceOf[AnyRef])): _*)
} catch {
case ex: Exception =>
macroTraceVerbose(s"macro runtime failed to load: ")(ex.toString)
@@ -561,7 +565,8 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
/** Calculate the arguments to pass to a macro implementation when expanding the provided tree.
*/
- private def macroArgs(typer: Typer, expandee: Tree): List[Any] = {
+ case class MacroArgs(c: MacroContext, others: List[Any])
+ private def macroArgs(typer: Typer, expandee: Tree): MacroArgs = {
val macroDef = expandee.symbol
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))
@@ -583,12 +588,13 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
val nullaryArgsEmptyParams = exprArgs.isEmpty && macroDef.paramss == ListOfNil
if (argcDoesntMatch && !nullaryArgsEmptyParams) { typer.TyperErrorGen.MacroPartialApplicationError(expandee) }
- var argss: List[List[Any]] = List(context) :: exprArgs.toList
+ var argss: List[List[Any]] = exprArgs.toList
+ macroTraceVerbose("context: ")(context)
macroTraceVerbose("argss: ")(argss)
- val rawArgss =
+ val preparedArgss: List[List[Any]] =
if (fastTrack contains macroDef) {
- if (fastTrack(macroDef) validate argss) argss
+ if (fastTrack(macroDef) validate context) argss
else typer.TyperErrorGen.MacroPartialApplicationError(expandee)
} else {
val binding = loadMacroImplBinding(macroDef)
@@ -631,28 +637,31 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
argss = if (hasImplicitParams) argss.dropRight(1) :+ (tags ++ argss.last) else argss :+ tags
// transforms argss taking into account varargness of paramss
- // not all argument lists in argss map to macroDef.paramss, so we need to apply extra care
- // namely:
- // 1) the first argument list represents (c: Context) in macroImpl, so it doesn't have correspondence in macroDef
- // 2) typetag context bounds are only declared on macroImpls, so this optional arglist also doesn't match macroDef
+ // note that typetag context bounds are only declared on macroImpls
+ // so this optional arglist might not match macroDef's paramlist
// nb! varargs can apply to any parameter section, not necessarily to the last one
- mapWithIndex(argss)((as, i_argss) => {
- val i_paramss = i_argss - 1
- val mapsToParamss = 0 <= i_paramss && i_paramss < macroDef.paramss.length
+ mapWithIndex(argss)((as, i) => {
+ val mapsToParamss = macroDef.paramss.indices contains i
if (mapsToParamss) {
- val ps = macroDef.paramss(i_paramss)
- if (isVarArgsList(ps)) as.take(ps.length - 1) :+ as.drop(ps.length - 1)
- else as
+ val ps = macroDef.paramss(i)
+ if (isVarArgsList(ps)) {
+ val (normal, varargs) = as splitAt (ps.length - 1)
+ normal :+ varargs // pack all varargs into a single List argument
+ } else as
} else as
})
}
- macroTraceVerbose("rawArgs: ")(rawArgss.flatten)
+ macroTraceVerbose("preparedArgss: ")(preparedArgss)
+ MacroArgs(context, preparedArgss.flatten)
}
/** Keeps track of macros in-flight.
* See more informations in comments to `openMacros` in `scala.reflect.macros.Context`.
*/
- var openMacros = List[MacroContext]()
+ private var _openMacros = List[MacroContext]()
+ def openMacros = _openMacros
+ private def pushMacroContext(c: MacroContext) = _openMacros ::= c
+ private def popMacroContext() = _openMacros = _openMacros.tail
def enclosingMacroPosition = openMacros map (_.macroApplication.pos) find (_ ne NoPosition) getOrElse NoPosition
private sealed abstract class MacroExpansionResult
@@ -708,7 +717,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
typechecked = typecheck("expected type", typechecked, pt)
typechecked addAttachment MacroExpansionAttachment(expandee)
} finally {
- openMacros = openMacros.tail
+ popMacroContext()
}
case Fallback(fallback) =>
typer.context.withImplicitsEnabled(typer.typed(fallback, EXPRmode, pt))
@@ -745,63 +754,49 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
* Meant for internal use within the macro infrastructure, don't use it elsewhere.
*/
private def macroExpandWithRuntime(typer: Typer, expandee: Tree, runtime: MacroRuntime): MacroExpansionResult = {
- import typer.TyperErrorGen._
- try {
- def performExpansion(args: List[Any]): MacroExpansionResult = {
- val numErrors = reporter.ERROR.count
- def hasNewErrors = reporter.ERROR.count > numErrors
- val expanded = runtime(args)
- if (hasNewErrors) MacroGeneratedTypeError(expandee)
-
- expanded match {
- case expanded: Expr[_] =>
- macroLogVerbose("original:")
- macroLogLite("" + expanded.tree + "\n" + showRaw(expanded.tree))
- val freeSyms = expanded.tree.freeTerms ++ expanded.tree.freeTypes
- freeSyms foreach (sym => MacroFreeSymbolError(expandee, sym))
- Success(atPos(enclosingMacroPosition.focus)(expanded.tree))
- case _ =>
- MacroExpansionIsNotExprError(expandee, expanded)
- }
- }
-
- val wasDelayed = isDelayed(expandee)
- val undetparams = calculateUndetparams(expandee)
- val nowDelayed = !typer.context.macrosEnabled || undetparams.nonEmpty
-
- if (wasDelayed || nowDelayed) {
- if (!wasDelayed && nowDelayed) {
- macroLogLite("macro expansion is delayed: %s".format(expandee))
- delayed += expandee -> undetparams
- val macroContext = macroArgs(typer, expandee).head.asInstanceOf[MacroContext]
- expandee addAttachment MacroRuntimeAttachment(delayed = true, typerContext = typer.context, macroContext = Some(macroContext))
- Delay(expandee)
- } else if (wasDelayed && nowDelayed) {
- Delay(expandee)
- } else /* if (wasDelayed && !nowDelayed) */ {
- Skip(macroExpandAll(typer, expandee))
- }
- } else {
+ val wasDelayed = isDelayed(expandee)
+ val undetparams = calculateUndetparams(expandee)
+ val nowDelayed = !typer.context.macrosEnabled || undetparams.nonEmpty
+
+ (wasDelayed, nowDelayed) match {
+ case (true, true) => Delay(expandee)
+ case (true, false) => Skip(macroExpandAll(typer, expandee))
+ case (false, true) =>
+ macroLogLite("macro expansion is delayed: %s".format(expandee))
+ delayed += expandee -> undetparams
+ expandee addAttachment MacroRuntimeAttachment(delayed = true, typerContext = typer.context, macroContext = Some(macroArgs(typer, expandee).c))
+ Delay(expandee)
+ case (false, false) =>
+ import typer.TyperErrorGen._
macroLogLite("performing macro expansion %s at %s".format(expandee, expandee.pos))
val args = macroArgs(typer, expandee)
- openMacros ::= args.head.asInstanceOf[MacroContext]
- var isSuccess = false
- try performExpansion(args) match {
- case x: Success => isSuccess = true ; x
- case x => x
+ try {
+ val numErrors = reporter.ERROR.count
+ def hasNewErrors = reporter.ERROR.count > numErrors
+ val expanded = { pushMacroContext(args.c); runtime(args) }
+ if (hasNewErrors) MacroGeneratedTypeError(expandee)
+ expanded match {
+ case expanded: Expr[_] =>
+ macroLogVerbose("original:")
+ macroLogLite("" + expanded.tree + "\n" + showRaw(expanded.tree))
+ val freeSyms = expanded.tree.freeTerms ++ expanded.tree.freeTypes
+ freeSyms foreach (sym => MacroFreeSymbolError(expandee, sym))
+ Success(atPos(enclosingMacroPosition.focus)(expanded.tree))
+ case _ =>
+ MacroExpansionIsNotExprError(expandee, expanded)
+ }
+ } catch {
+ case ex: Throwable =>
+ popMacroContext()
+ val realex = ReflectionUtils.unwrapThrowable(ex)
+ realex match {
+ case ex: AbortMacroException => MacroGeneratedAbort(expandee, ex)
+ case ex: ControlThrowable => throw ex
+ case ex: TypeError => MacroGeneratedTypeError(expandee, ex)
+ case _ => MacroGeneratedException(expandee, realex)
+ }
} finally {
expandee.removeAttachment[MacroRuntimeAttachment]
- if (!isSuccess) openMacros = openMacros.tail
- }
- }
- } catch {
- case ex: Throwable =>
- val realex = ReflectionUtils.unwrapThrowable(ex)
- realex match {
- case ex: AbortMacroException => MacroGeneratedAbort(expandee, ex)
- case ex: ControlThrowable => throw ex
- case ex: TypeError => MacroGeneratedTypeError(expandee, ex)
- case _ => MacroGeneratedException(expandee, realex)
}
}
}
@@ -810,8 +805,8 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
* Meant for internal use within the macro infrastructure, don't use it elsewhere.
*/
private def macroExpandWithoutRuntime(typer: Typer, expandee: Tree): MacroExpansionResult = {
- val fallbackSym = expandee.symbol.allOverriddenSymbols.headOption.getOrElse(NoSymbol)
- if (fallbackSym == NoSymbol) typer.TyperErrorGen.MacroImplementationNotFoundError(expandee)
+ import typer.TyperErrorGen._
+ val fallbackSym = expandee.symbol.nextOverriddenSymbol orElse MacroImplementationNotFoundError(expandee)
macroTraceLite("falling back to: ")(fallbackSym)
def mkFallbackTree(tree: Tree): Tree = {
diff --git a/src/compiler/scala/tools/reflect/FastTrack.scala b/src/compiler/scala/tools/reflect/FastTrack.scala
index f84877cccb..07c972899e 100644
--- a/src/compiler/scala/tools/reflect/FastTrack.scala
+++ b/src/compiler/scala/tools/reflect/FastTrack.scala
@@ -17,16 +17,11 @@ trait FastTrack {
private implicit def context2taggers(c0: MacroContext): Taggers { val c: c0.type } = new { val c: c0.type = c0 } with Taggers
private implicit def context2macroimplementations(c0: MacroContext): MacroImplementations { val c: c0.type } = new { val c: c0.type = c0 } with MacroImplementations
- implicit def fastTrackEntry2MacroRuntime(entry: FastTrackEntry): MacroRuntime = args => entry.run(args)
+ implicit def fastTrackEntry2MacroRuntime(entry: FastTrackEntry): MacroRuntime = args => entry.run(args.c)
type FastTrackExpander = PartialFunction[(MacroContext, Tree), Tree]
case class FastTrackEntry(sym: Symbol, expander: FastTrackExpander) {
- def validate(argss: List[List[Any]]): Boolean = {
- val c = argss.flatten.apply(0).asInstanceOf[MacroContext]
- val isValid = expander isDefinedAt (c, c.expandee)
- isValid
- }
- def run(args: List[Any]): Any = {
- val c = args(0).asInstanceOf[MacroContext]
+ def validate(c: MacroContext): Boolean = expander.isDefinedAt((c, c.expandee))
+ def run(c: MacroContext): Any = {
val result = expander((c, c.expandee))
c.Expr[Nothing](result)(c.AbsTypeTag.Nothing)
}
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index a1f44ace6e..98d42b724c 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -462,7 +462,7 @@ trait Definitions extends api.StandardDefinitions {
def ReflectRuntimeUniverse = if (ReflectRuntimePackage != NoSymbol) getMemberValue(ReflectRuntimePackage, nme.universe) else NoSymbol
def ReflectRuntimeCurrentMirror = if (ReflectRuntimePackage != NoSymbol) getMemberMethod(ReflectRuntimePackage, nme.currentMirror) else NoSymbol
- lazy val PartialManifestClass = getMemberType(ReflectPackage, tpnme.ClassManifest)
+ lazy val PartialManifestClass = getTypeMember(ReflectPackage, tpnme.ClassManifest)
lazy val PartialManifestModule = requiredModule[scala.reflect.ClassManifestFactory.type]
lazy val FullManifestClass = requiredClass[scala.reflect.Manifest[_]]
lazy val FullManifestModule = requiredModule[scala.reflect.ManifestFactory.type]
@@ -494,7 +494,7 @@ trait Definitions extends api.StandardDefinitions {
lazy val MacroContextClass = getClassIfDefined("scala.reflect.macros.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 MacroContextPrefixType = if (MacroContextClass != NoSymbol) getTypeMember(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
lazy val MacroImplAnnotation = requiredClass[scala.reflect.macros.internal.macroImpl]
@@ -1012,10 +1012,10 @@ trait Definitions extends api.StandardDefinitions {
case _ => fatalMissingSymbol(owner, name, "member object")
}
}
- def getMemberType(owner: Symbol, name: Name): TypeSymbol = {
+ def getTypeMember(owner: Symbol, name: Name): TypeSymbol = {
getMember(owner, name.toTypeName) match {
case x: TypeSymbol => x
- case _ => fatalMissingSymbol(owner, name, "member type")
+ case _ => fatalMissingSymbol(owner, name, "type member")
}
}
def getMemberClass(owner: Symbol, name: Name): ClassSymbol = {
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index 52dd4a55cf..9514898ce5 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -6939,12 +6939,6 @@ trait Types extends api.Types { self: SymbolTable =>
else (ps :+ SerializableClass.tpe).toList
)
- def stripOffPrefixTypeRefinement(tpe: Type): Type =
- tpe.dealias match {
- case RefinedType(List(tpe), Scope(sym)) if tpe == MacroContextClass.tpe && sym.allOverriddenSymbols.contains(MacroContextPrefixType) => tpe
- case _ => tpe
- }
-
def objToAny(tp: Type): Type =
if (!phase.erasedTypes && tp.typeSymbol == ObjectClass) AnyClass.tpe
else tp