summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/typechecker/Macros.scala
diff options
context:
space:
mode:
authorEugene Burmako <xeno.by@gmail.com>2013-12-10 14:24:48 +0100
committerEugene Burmako <xeno.by@gmail.com>2013-12-10 23:11:13 +0100
commitbd615c62ac4b03816d681a9a0fc717b5bc5d5cea (patch)
treef4d7b6cff7d97688a8f44658e953d83fd95d8f4b /src/compiler/scala/tools/nsc/typechecker/Macros.scala
parentb345b42cac64aa97e3bbcc6f14ef8f08214ab56f (diff)
downloadscala-bd615c62ac4b03816d681a9a0fc717b5bc5d5cea.tar.gz
scala-bd615c62ac4b03816d681a9a0fc717b5bc5d5cea.tar.bz2
scala-bd615c62ac4b03816d681a9a0fc717b5bc5d5cea.zip
refactors macroExpandApply
Moves some code around to clearly define the concepts that the method operates on: 1) `innerPt`, which is expected type provided by the macro def return type, 2) `outerPt`, which is expected type provided by the enclosing context. Once everything is clearly defined, the gist of the expander fits in a few lines in its end. If blackbox, do this. If whitebox, do that. Note that unlike the subsequent commit, this commit doesn’t change the way how macro expansion works. It just clears everything out, so that the upcoming changes can be applied in a concise and comprehensible manner.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Macros.scala')
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala62
1 files changed, 35 insertions, 27 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index 27920dbd74..afefc39b0e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -600,39 +600,47 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
}
/** Expands a term macro used in apply role as `M(2)(3)` in `val x = M(2)(3)`.
+ * @param outerPt Expected type that comes from enclosing context (something that's traditionally called `pt`).
+ * @param innerPt Expected type that comes from the signature of a macro def, possibly wildcarded to help type inference.
* @see MacroExpander
*/
- def macroExpandApply(typer: Typer, expandee: Tree, mode: Mode, pt: Type): Tree = {
- object expander extends TermMacroExpander(APPLY_ROLE, typer, expandee, mode, pt) {
- override def onSuccess(expanded0: Tree) = {
- def approximate(tp: Type) = {
+ def macroExpandApply(typer: Typer, expandee: Tree, mode: Mode, outerPt: Type): Tree = {
+ object expander extends TermMacroExpander(APPLY_ROLE, typer, expandee, mode, outerPt) {
+ lazy val innerPt = {
+ val tp = if (isNullaryInvocation(expandee)) expandee.tpe.finalResultType else expandee.tpe
+ if (isBlackbox(expandee)) tp
+ else {
// approximation is necessary for whitebox macros to guide type inference
// read more in the comments for onDelayed below
- if (isBlackbox(expandee)) tp
+ val undetparams = tp collect { case tp if tp.typeSymbol.isTypeParameter => tp.typeSymbol }
+ deriveTypeWithWildcards(undetparams)(tp)
+ }
+ }
+ override def onSuccess(expanded0: Tree) = {
+ // prematurely annotate the tree with a macro expansion attachment
+ // so that adapt called indirectly by typer.typed knows that it needs to apply the existential fixup
+ linkExpandeeAndExpanded(expandee, expanded0)
+
+ def typecheck(label: String, tree: Tree, pt: Type): Tree = {
+ if (tree.isErrorTyped) tree
else {
- val undetparams = tp collect { case tp if tp.typeSymbol.isTypeParameter => tp.typeSymbol }
- deriveTypeWithWildcards(undetparams)(tp)
+ if (macroDebugVerbose) println(s"$label (against pt = $pt): $tree")
+ // `macroExpandApply` is called from `adapt`, where implicit conversions are disabled
+ // therefore we need to re-enable the conversions back temporarily
+ val result = typer.context.withImplicitsEnabled(typer.typed(tree, mode, pt))
+ if (result.isErrorTyped && macroDebugVerbose) println(s"$label has failed: ${typer.context.reportBuffer.errors}")
+ result
}
}
- val macroPt = approximate(if (isNullaryInvocation(expandee)) expandee.tpe.finalResultType else expandee.tpe)
- val expanded = if (isBlackbox(expandee)) atPos(enclosingMacroPosition.focus)(Typed(expanded0, TypeTree(macroPt))) else expanded0
- // prematurely annotate the tree with a macro expansion attachment
- // so that adapt called indirectly by typer.typed knows that it needs to apply the existential fixup
- linkExpandeeAndExpanded(expandee, expanded)
-
- // `macroExpandApply` is called from `adapt`, where implicit conversions are disabled
- // therefore we need to re-enable the conversions back temporarily
- if (macroDebugVerbose) println(s"typecheck #1 (against macroPt = $macroPt): $expanded")
- val expanded1 = typer.context.withImplicitsEnabled(typer.typed(expanded, mode, macroPt))
- if (expanded1.isErrorTyped) {
- if (macroDebugVerbose) println(s"typecheck #1 has failed: ${typer.context.reportBuffer.errors}")
- expanded1
+ if (isBlackbox(expandee)) {
+ val expanded1 = atPos(enclosingMacroPosition.focus)(Typed(expanded0, TypeTree(innerPt)))
+ val expanded2 = typecheck("blackbox typecheck #1", expanded1, innerPt)
+ typecheck("blackbox typecheck #2", expanded1, outerPt)
} else {
- if (macroDebugVerbose) println(s"typecheck #2 (against pt = $pt): $expanded1")
- val expanded2 = typer.context.withImplicitsEnabled(super.onSuccess(expanded1))
- if (macroDebugVerbose && expanded2.isErrorTyped) println(s"typecheck #2 has failed: ${typer.context.reportBuffer.errors}")
- expanded2
+ val expanded1 = expanded0
+ val expanded2 = typecheck("whitebox typecheck #1", expanded1, innerPt)
+ typecheck("whitebox typecheck #2", expanded2, outerPt)
}
}
override def onDelayed(delayed: Tree) = {
@@ -686,11 +694,11 @@ trait Macros extends FastTrack with MacroRuntimes with Traces with Helpers {
// Thanks to that the materializer can take a look at what's going on and react accordingly.
val shouldInstantiate = typer.context.undetparams.nonEmpty && !mode.inPolyMode
if (shouldInstantiate) {
- if (isBlackbox(expandee)) typer.instantiatePossiblyExpectingUnit(delayed, mode, pt)
+ if (isBlackbox(expandee)) typer.instantiatePossiblyExpectingUnit(delayed, mode, outerPt)
else {
forced += delayed
- typer.infer.inferExprInstance(delayed, typer.context.extractUndetparams(), pt, keepNothings = false)
- macroExpandApply(typer, delayed, mode, pt)
+ typer.infer.inferExprInstance(delayed, typer.context.extractUndetparams(), outerPt, keepNothings = false)
+ macroExpandApply(typer, delayed, mode, outerPt)
}
} else delayed
}