Skip to content

Commit

Permalink
Removes unnecessary generality in the macro engine
Browse files Browse the repository at this point in the history
In Jan 2013, I submitted a number of pull requests that built up a foundation
for the upcoming type macros pull request. Unfortunately, type macros
ended up being rejected, but the extra generality introduced in advance
still persisted in the compiler until now.

This commit takes care of unused generality in the macro engine,
keeping the internal implementation as well as the public API clean.
  • Loading branch information
xeno-by committed Jan 8, 2014
1 parent 6e4c926 commit 94eb751
Show file tree
Hide file tree
Showing 5 changed files with 12 additions and 62 deletions.
4 changes: 0 additions & 4 deletions src/compiler/scala/reflect/macros/contexts/Enclosures.scala
Expand Up @@ -8,10 +8,6 @@ trait Enclosures {


import universe._ import universe._


type MacroRole = analyzer.MacroRole
def APPLY_ROLE = analyzer.APPLY_ROLE
def macroRole: MacroRole

private lazy val site = callsiteTyper.context private lazy val site = callsiteTyper.context
private lazy val enclTrees = site.enclosingContextChain map (_.tree) private lazy val enclTrees = site.enclosingContextChain map (_.tree)
private lazy val enclPoses = enclosingMacros map (_.macroApplication.pos) filterNot (_ eq NoPosition) private lazy val enclPoses = enclosingMacros map (_.macroApplication.pos) filterNot (_ eq NoPosition)
Expand Down
4 changes: 0 additions & 4 deletions src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
Expand Up @@ -726,10 +726,6 @@ trait ContextErrors {
NormalTypeError(expandee, "too many argument lists for " + fun) NormalTypeError(expandee, "too many argument lists for " + fun)
} }


def MacroInvalidExpansionError(expandee: Tree, role: String, allowedExpansions: String) = {
issueNormalTypeError(expandee, s"macro in $role role can only expand into $allowedExpansions")
}

def MacroIncompatibleEngineError(macroEngine: String) = { def MacroIncompatibleEngineError(macroEngine: String) = {
val message = s"macro cannot be expanded, because it was compiled by an incompatible macro engine $macroEngine" val message = s"macro cannot be expanded, because it was compiled by an incompatible macro engine $macroEngine"
issueNormalTypeError(lastTreeToTyper, message) issueNormalTypeError(lastTreeToTyper, message)
Expand Down
45 changes: 8 additions & 37 deletions src/compiler/scala/tools/nsc/typechecker/Macros.scala
Expand Up @@ -354,7 +354,6 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
val universe: self.global.type = self.global val universe: self.global.type = self.global
val callsiteTyper: universe.analyzer.Typer = typer.asInstanceOf[global.analyzer.Typer] val callsiteTyper: universe.analyzer.Typer = typer.asInstanceOf[global.analyzer.Typer]
val expandee = universe.analyzer.macroExpanderAttachment(expandeeTree).original orElse duplicateAndKeepPositions(expandeeTree) val expandee = universe.analyzer.macroExpanderAttachment(expandeeTree).original orElse duplicateAndKeepPositions(expandeeTree)
val macroRole = universe.analyzer.macroExpanderAttachment(expandeeTree).role
} with UnaffiliatedMacroContext { } with UnaffiliatedMacroContext {
val prefix = Expr[Nothing](prefixTree)(TypeTag.Nothing) val prefix = Expr[Nothing](prefixTree)(TypeTag.Nothing)
override def toString = "MacroContext(%s@%s +%d)".format(expandee.symbol.name, expandee.pos, enclosingMacros.length - 1 /* exclude myself */) override def toString = "MacroContext(%s@%s +%d)".format(expandee.symbol.name, expandee.pos, enclosingMacros.length - 1 /* exclude myself */)
Expand Down Expand Up @@ -487,12 +486,6 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
def popMacroContext() = _openMacros = _openMacros.tail def popMacroContext() = _openMacros = _openMacros.tail
def enclosingMacroPosition = openMacros map (_.macroApplication.pos) find (_ ne NoPosition) getOrElse NoPosition def enclosingMacroPosition = openMacros map (_.macroApplication.pos) find (_ ne NoPosition) getOrElse NoPosition


/** Describes the role that the macro expandee is performing.
*/
type MacroRole = scala.tools.nsc.typechecker.MacroRole
final def APPLY_ROLE = MacroRole.Apply
final def UNAPPLY_ROLE = MacroRole.Unapply

/** Performs macro expansion: /** Performs macro expansion:
* *
* ========= Expandable trees ========= * ========= Expandable trees =========
Expand Down Expand Up @@ -535,12 +528,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
* the expandee with an error marker set if the expansion has been cancelled due malformed arguments or implementation * the expandee with an error marker set if the expansion has been cancelled due malformed arguments or implementation
* the expandee with an error marker set if there has been an error * the expandee with an error marker set if there has been an error
*/ */
abstract class MacroExpander(val role: MacroRole, val typer: Typer, val expandee: Tree) { abstract class MacroExpander(val typer: Typer, val expandee: Tree) {
def allowExpandee(expandee: Tree): Boolean = true
def allowExpanded(expanded: Tree): Boolean = true
def allowedExpansions: String = "anything"
def allowResult(result: Tree): Boolean = true

def onSuccess(expanded: Tree): Tree def onSuccess(expanded: Tree): Tree
def onFallback(expanded: Tree): Tree def onFallback(expanded: Tree): Tree
def onSuppressed(expandee: Tree): Tree = expandee def onSuppressed(expandee: Tree): Tree = expandee
Expand All @@ -557,8 +545,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
def showDetailed(tree: Tree) = showRaw(tree, printIds = true, printTypes = true) def showDetailed(tree: Tree) = showRaw(tree, printIds = true, printTypes = true)
def summary() = s"expander = $this, expandee = ${showDetailed(expandee)}, desugared = ${if (expandee == desugared) () else showDetailed(desugared)}" def summary() = s"expander = $this, expandee = ${showDetailed(expandee)}, desugared = ${if (expandee == desugared) () else showDetailed(desugared)}"
if (macroDebugVerbose) println(s"macroExpand: ${summary()}") if (macroDebugVerbose) println(s"macroExpand: ${summary()}")
assert(allowExpandee(expandee), summary()) linkExpandeeAndDesugared(expandee, desugared)
linkExpandeeAndDesugared(expandee, desugared, role)


val start = if (Statistics.canEnable) Statistics.startTimer(macroExpandNanos) else null val start = if (Statistics.canEnable) Statistics.startTimer(macroExpandNanos) else null
if (Statistics.canEnable) Statistics.incCounter(macroExpandCount) if (Statistics.canEnable) Statistics.incCounter(macroExpandCount)
Expand All @@ -576,18 +563,11 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
} }
expanded match { expanded match {
case Success(expanded) => case Success(expanded) =>
if (allowExpanded(expanded)) { // also see http://groups.google.com/group/scala-internals/browse_thread/thread/492560d941b315cc
// also see http://groups.google.com/group/scala-internals/browse_thread/thread/492560d941b315cc val expanded1 = try onSuccess(duplicateAndKeepPositions(expanded)) finally popMacroContext()
val expanded1 = try onSuccess(duplicateAndKeepPositions(expanded)) finally popMacroContext() if (!hasMacroExpansionAttachment(expanded1)) linkExpandeeAndExpanded(expandee, expanded1)
if (!hasMacroExpansionAttachment(expanded1)) linkExpandeeAndExpanded(expandee, expanded1) if (settings.Ymacroexpand.value == settings.MacroExpand.Discard) expandee.setType(expanded1.tpe)
if (allowResult(expanded1)) { else expanded1
if (settings.Ymacroexpand.value == settings.MacroExpand.Discard) expandee.setType(expanded1.tpe)
else expanded1
} else onFailure(expanded)
} else {
typer.TyperErrorGen.MacroInvalidExpansionError(expandee, role.name, allowedExpansions)
onFailure(expanded)
}
case Fallback(fallback) => onFallback(fallback) case Fallback(fallback) => onFallback(fallback)
case Delayed(delayed) => onDelayed(delayed) case Delayed(delayed) => onDelayed(delayed)
case Skipped(skipped) => onSkipped(skipped) case Skipped(skipped) => onSkipped(skipped)
Expand All @@ -608,7 +588,7 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
* @param innerPt Expected type that comes from the signature of a macro def, possibly wildcarded to help type inference. * @param innerPt Expected type that comes from the signature of a macro def, possibly wildcarded to help type inference.
*/ */
class DefMacroExpander(typer: Typer, expandee: Tree, mode: Mode, outerPt: Type) class DefMacroExpander(typer: Typer, expandee: Tree, mode: Mode, outerPt: Type)
extends MacroExpander(APPLY_ROLE, typer, expandee) { extends MacroExpander(typer, expandee) {
lazy val innerPt = { lazy val innerPt = {
val tp = if (isNullaryInvocation(expandee)) expandee.tpe.finalResultType else expandee.tpe val tp = if (isNullaryInvocation(expandee)) expandee.tpe.finalResultType else expandee.tpe
if (isBlackbox(expandee)) tp if (isBlackbox(expandee)) tp
Expand Down Expand Up @@ -922,12 +902,3 @@ object Fingerprint {
val LiftedTyped = new Fingerprint(-2) val LiftedTyped = new Fingerprint(-2)
val LiftedUntyped = new Fingerprint(-3) val LiftedUntyped = new Fingerprint(-3)
} }

class MacroRole private[MacroRole](val name: String) extends AnyVal {
override def toString = name
}

object MacroRole {
val Apply = new MacroRole("apply")
val Unapply = new MacroRole("unapply")
}
8 changes: 4 additions & 4 deletions src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala
Expand Up @@ -16,23 +16,23 @@ trait StdAttachments {


/** Scratchpad for the macro expander, which is used to store all intermediate data except the details about the runtime. /** Scratchpad for the macro expander, which is used to store all intermediate data except the details about the runtime.
*/ */
case class MacroExpanderAttachment(original: Tree, desugared: Tree, role: MacroRole) case class MacroExpanderAttachment(original: Tree, desugared: Tree)


/** Loads underlying MacroExpanderAttachment from a macro expandee or returns a default value for that attachment. /** Loads underlying MacroExpanderAttachment from a macro expandee or returns a default value for that attachment.
*/ */
def macroExpanderAttachment(tree: Tree): MacroExpanderAttachment = def macroExpanderAttachment(tree: Tree): MacroExpanderAttachment =
tree.attachments.get[MacroExpanderAttachment] getOrElse { tree.attachments.get[MacroExpanderAttachment] getOrElse {
tree match { tree match {
case Apply(fn, _) if tree.isInstanceOf[ApplyToImplicitArgs] => macroExpanderAttachment(fn) case Apply(fn, _) if tree.isInstanceOf[ApplyToImplicitArgs] => macroExpanderAttachment(fn)
case _ => MacroExpanderAttachment(tree, EmptyTree, APPLY_ROLE) case _ => MacroExpanderAttachment(tree, EmptyTree)
} }
} }


/** After macro expansion is completed, links the expandee and the expansion result /** After macro expansion is completed, links the expandee and the expansion result
* by annotating them both with a `MacroExpansionAttachment`. * by annotating them both with a `MacroExpansionAttachment`.
*/ */
def linkExpandeeAndDesugared(expandee: Tree, desugared: Tree, role: MacroRole): Unit = { def linkExpandeeAndDesugared(expandee: Tree, desugared: Tree): Unit = {
val metadata = MacroExpanderAttachment(expandee, desugared, role) val metadata = MacroExpanderAttachment(expandee, desugared)
expandee updateAttachment metadata expandee updateAttachment metadata
desugared updateAttachment metadata desugared updateAttachment metadata
} }
Expand Down
13 changes: 0 additions & 13 deletions src/reflect/scala/reflect/macros/Enclosures.scala
Expand Up @@ -20,19 +20,6 @@ trait Enclosures {
*/ */
def macroApplication: Tree def macroApplication: Tree


/** The semantic role that `macroApplication` plays in the code.
*/
type MacroRole

/** The role that represents an application of a term macro,
* e.g. `M(2)(3)` in `val x = M(2)(3)` or `M(a, b)` in `x match { case x @ M(a, b) => }`.
*/
def APPLY_ROLE: MacroRole

/** The semantic role that `macroApplication` plays in the code.
*/
def macroRole: MacroRole

/** Contexts that represent macros in-flight, including the current one. Very much like a stack trace, but for macros only. /** 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. * Can be useful for interoperating with other macros and for imposing compiler-friendly limits on macro expansion.
* *
Expand Down

0 comments on commit 94eb751

Please sign in to comment.