diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2013-12-10 14:24:48 +0100 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2013-12-10 23:11:13 +0100 |
commit | bd615c62ac4b03816d681a9a0fc717b5bc5d5cea (patch) | |
tree | f4d7b6cff7d97688a8f44658e953d83fd95d8f4b | |
parent | b345b42cac64aa97e3bbcc6f14ef8f08214ab56f (diff) | |
download | scala-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.
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Macros.scala | 62 |
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 } |