Skip to content

Commit 69887dd

Browse files
committed
Merge pull request scala#2577 from scalamacros/pullrequest/paradise
Backport from paradise/macros
2 parents c1cd65b + 82f0925 commit 69887dd

File tree

332 files changed

+2585
-1794
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

332 files changed

+2585
-1794
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
f9f41fb909df6a0178906c9fd02e5d0efa15c9ed ?scala-compiler-src.jar
1+
19d04510ac6f25d088da82527d8435b68c00153d ?scala-compiler-src.jar
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
c4cd524dc29d298a5034637f6b31122dccb300d6 ?scala-compiler.jar
1+
3585351c6a62186097be55fff88bee88a985f5c0 ?scala-compiler.jar
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2cba5a13ef44bf93133be26cc89ba3a640a5c28f ?scala-library-src.jar
1+
e606934dc00ced6bfac715bbdba427f9c2c18bc7 ?scala-library-src.jar

lib/scala-library.jar.desired.sha1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
d7c6e69eba3dba2f75a0f44e56480cd3dbab8931 ?scala-library.jar
1+
36456c52b0395fc1e6e367291e45bd503fa019c5 ?scala-library.jar
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
dbc00bd4b09012aa52e802926dee3f8a02a767ff ?scala-reflect-src.jar
1+
51787a41cae5b0ec6910c5a1a6af392e17550856 ?scala-reflect-src.jar

lib/scala-reflect.jar.desired.sha1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
c0eed5dee0a3204239c9b35134cad8b3ad140121 ?scala-reflect.jar
1+
d4a4c0aab882412461fbd9d39cf47da5a619855e ?scala-reflect.jar
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package scala.reflect.macros
2+
package compiler
3+
4+
import scala.tools.nsc.Global
5+
import scala.reflect.macros.contexts.Context
6+
7+
abstract class DefaultMacroCompiler extends Resolvers
8+
with Validators
9+
with Errors {
10+
val global: Global
11+
import global._
12+
13+
val typer: global.analyzer.Typer
14+
private implicit val context0 = typer.context
15+
val context = typer.context
16+
17+
val macroDdef: DefDef
18+
lazy val macroDef = macroDdef.symbol
19+
20+
private case class MacroImplResolutionException(pos: Position, msg: String) extends Exception
21+
def abort(pos: Position, msg: String) = throw MacroImplResolutionException(pos, msg)
22+
23+
def resolveMacroImpl: Tree = {
24+
try {
25+
validateMacroImplRef()
26+
macroImplRef
27+
} catch {
28+
case MacroImplResolutionException(pos, msg) =>
29+
context.error(pos, msg)
30+
EmptyTree
31+
}
32+
}
33+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package scala.reflect.macros
2+
package compiler
3+
4+
import scala.compat.Platform.EOL
5+
import scala.reflect.macros.util.Traces
6+
7+
trait Errors extends Traces {
8+
self: DefaultMacroCompiler =>
9+
10+
import global._
11+
import analyzer._
12+
import definitions._
13+
import typer.TyperErrorGen._
14+
import typer.infer.InferErrorGen._
15+
def globalSettings = global.settings
16+
17+
// sanity check errors
18+
19+
private def implRefError(message: String) = abort(macroDdef.pos, message)
20+
21+
def MacroImplReferenceWrongShapeError() = implRefError(
22+
"macro implementation reference has wrong shape. required:\n"+
23+
"macro [<static object>].<method name>[[<type args>]] or\n" +
24+
"macro [<macro bundle>].<method name>[[<type args>]]")
25+
26+
def MacroImplNotPublicError() = implRefError("macro implementation must be public")
27+
28+
def MacroImplOverloadedError() = implRefError("macro implementation cannot be overloaded")
29+
30+
def MacroImplWrongNumberOfTypeArgumentsError() = implRefError(TypedApplyWrongNumberOfTpeParametersErrorMessage(macroImplRef))
31+
32+
// compatibility errors
33+
34+
// helpers
35+
36+
private def lengthMsg(flavor: String, violation: String, extra: Symbol) = {
37+
val noun = if (flavor == "value") "parameter" else "type parameter"
38+
val message = noun + " lists have different length, " + violation + " extra " + noun
39+
val suffix = if (extra ne NoSymbol) " " + extra.defString else ""
40+
message + suffix
41+
}
42+
43+
private def abbreviateCoreAliases(s: String): String = List("WeakTypeTag", "Expr").foldLeft(s)((res, x) => res.replace("c.universe." + x, "c." + x))
44+
45+
private def showMeth(pss: List[List[Symbol]], restpe: Type, abbreviate: Boolean) = {
46+
var argsPart = (pss map (ps => ps map (_.defString) mkString ("(", ", ", ")"))).mkString
47+
if (abbreviate) argsPart = abbreviateCoreAliases(argsPart)
48+
var retPart = restpe.toString
49+
if (abbreviate || macroDdef.tpt.tpe == null) retPart = abbreviateCoreAliases(retPart)
50+
argsPart + ": " + retPart
51+
}
52+
53+
// not exactly an error generator, but very related
54+
// and I dearly wanted to push it away from Macros.scala
55+
private def checkConforms(slot: String, rtpe: Type, atpe: Type) = {
56+
val verbose = macroDebugVerbose || settings.explaintypes.value
57+
58+
def check(rtpe: Type, atpe: Type): Boolean = {
59+
def success() = { if (verbose) println(rtpe + " <: " + atpe + "?" + EOL + "true"); true }
60+
(rtpe, atpe) match {
61+
case _ if rtpe eq atpe => success()
62+
case (TypeRef(_, RepeatedParamClass, rtpe :: Nil), TypeRef(_, RepeatedParamClass, atpe :: Nil)) => check(rtpe, atpe)
63+
case (ExprClassOf(_), TreeType()) => success()
64+
case (TreeType(), ExprClassOf(_)) => success()
65+
case _ => rtpe <:< atpe
66+
}
67+
}
68+
69+
val ok =
70+
if (verbose) withTypesExplained(check(rtpe, atpe))
71+
else check(rtpe, atpe)
72+
if (!ok) {
73+
if (!macroDebugVerbose)
74+
explainTypes(rtpe, atpe)
75+
compatibilityError("type mismatch for %s: %s does not conform to %s".format(slot, abbreviateCoreAliases(rtpe.toString), abbreviateCoreAliases(atpe.toString)))
76+
}
77+
}
78+
79+
private def compatibilityError(message: String) =
80+
implRefError(
81+
"macro implementation has wrong shape:"+
82+
"\n required: " + showMeth(rparamss, rret, abbreviate = true) +
83+
"\n found : " + showMeth(aparamss, aret, abbreviate = false) +
84+
"\n" + message)
85+
86+
def MacroImplNonTagImplicitParameters(params: List[Symbol]) = compatibilityError("macro implementations cannot have implicit parameters other than WeakTypeTag evidences")
87+
88+
def MacroImplParamssMismatchError() = compatibilityError("number of parameter sections differ")
89+
90+
def MacroImplExtraParamsError(aparams: List[Symbol], rparams: List[Symbol]) = compatibilityError(lengthMsg("value", "found", aparams(rparams.length)))
91+
92+
def MacroImplMissingParamsError(aparams: List[Symbol], rparams: List[Symbol]) = compatibilityError(abbreviateCoreAliases(lengthMsg("value", "required", rparams(aparams.length))))
93+
94+
def checkMacroImplParamTypeMismatch(atpe: Type, rparam: Symbol) = checkConforms("parameter " + rparam.name, rparam.tpe, atpe)
95+
96+
def checkMacroImplResultTypeMismatch(atpe: Type, rret: Type) = checkConforms("return type", atpe, rret)
97+
98+
def MacroImplParamNameMismatchError(aparam: Symbol, rparam: Symbol) = compatibilityError("parameter names differ: " + rparam.name + " != " + aparam.name)
99+
100+
def MacroImplVarargMismatchError(aparam: Symbol, rparam: Symbol) = {
101+
def fail(paramName: Name) = compatibilityError("types incompatible for parameter " + paramName + ": corresponding is not a vararg parameter")
102+
if (isRepeated(rparam) && !isRepeated(aparam)) fail(rparam.name)
103+
if (!isRepeated(rparam) && isRepeated(aparam)) fail(aparam.name)
104+
}
105+
106+
def MacroImplTargMismatchError(atargs: List[Type], atparams: List[Symbol]) =
107+
compatibilityError(NotWithinBoundsErrorMessage("", atargs, atparams, macroDebugVerbose || settings.explaintypes.value))
108+
109+
def MacroImplTparamInstantiationError(atparams: List[Symbol], ex: NoInstance) =
110+
compatibilityError(
111+
"type parameters "+(atparams map (_.defString) mkString ", ")+" cannot be instantiated\n"+
112+
ex.getMessage)
113+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package scala.reflect.macros
2+
package compiler
3+
4+
import scala.reflect.internal.Flags._
5+
import scala.reflect.macros.TypecheckException
6+
7+
trait Resolvers {
8+
self: DefaultMacroCompiler =>
9+
10+
import global._
11+
import analyzer._
12+
import definitions._
13+
import treeInfo._
14+
import gen._
15+
16+
/** Determines the type of context implied by the macro def.
17+
*/
18+
val ctxTpe = MacroContextClass.tpe
19+
20+
/** Resolves a macro impl reference provided in the right-hand side of the given macro definition.
21+
*
22+
* Acceptable shapes of the right-hand side:
23+
* 1) [<static object>].<method name>[[<type args>]] // vanilla macro def
24+
* 2) [<macro bundle>].<method name>[[<type args>]] // shiny new macro bundle
25+
*
26+
* Produces a tree, which represents a reference to a macro implementation if everything goes well,
27+
* otherwise reports found errors and returns EmptyTree. The resulting tree should have the following format:
28+
*
29+
* qualifier.method[targs]
30+
*
31+
* Qualifier here might be omitted (local macro defs), be a static object (vanilla macro defs)
32+
* or be a dummy instance of a macro bundle (e.g. new MyMacro(???).expand).
33+
*/
34+
lazy val macroImplRef: Tree = {
35+
val (maybeBundleRef, methName, targs) = macroDdef.rhs match {
36+
case Applied(methRef @ Select(bundleRef @ RefTree(qual, bundleName), methName), targs, Nil) =>
37+
(RefTree(qual, bundleName.toTypeName), methName, targs)
38+
case Applied(Ident(methName), targs, Nil) =>
39+
(Ident(context.owner.enclClass), methName, targs)
40+
case _ =>
41+
(EmptyTree, TermName(""), Nil)
42+
}
43+
44+
val untypedImplRef = typer.silent(_.typedType(maybeBundleRef)) match {
45+
case SilentResultValue(result) if isMacroBundleType(result.tpe) =>
46+
val bundleClass = result.tpe.typeSymbol
47+
if (!bundleClass.owner.isPackageClass) abort(macroDef.pos, "macro bundles can only be defined as top-level classes or traits")
48+
49+
// synthesize the invoker, i.e. given a top-level `trait Foo extends Macro { def expand = ... } `
50+
// create a top-level definition `class FooInvoker(val c: Context) extends Foo` in MACRO_INVOKER_PACKAGE
51+
val invokerPid = gen.mkUnattributedRef(nme.MACRO_INVOKER_PACKAGE)
52+
val invokerName = TypeName(bundleClass.fullName.split('.').map(_.capitalize).mkString("") + nme.MACRO_INVOKER_SUFFIX)
53+
val invokerFullName = TypeName(s"$invokerPid.$invokerName")
54+
val existingInvoker = rootMirror.getClassIfDefined(invokerFullName)
55+
if (!currentRun.compiles(existingInvoker)) {
56+
def mkContextValDef(flags: Long) = ValDef(Modifiers(flags), nme.c, TypeTree(ctxTpe), EmptyTree)
57+
val contextField = mkContextValDef(PARAMACCESSOR)
58+
val contextParam = mkContextValDef(PARAM | PARAMACCESSOR)
59+
val invokerCtor = DefDef(Modifiers(), nme.CONSTRUCTOR, Nil, List(List(contextParam)), TypeTree(), Block(List(pendingSuperCall), Literal(Constant(()))))
60+
val invoker = atPos(bundleClass.pos)(ClassDef(NoMods, invokerName, Nil, Template(List(Ident(bundleClass)), emptyValDef, List(contextField, invokerCtor))))
61+
currentRun.compileLate(PackageDef(invokerPid, List(invoker)))
62+
}
63+
64+
// synthesize the macro impl reference, which is going to look like:
65+
// `new Foo$invoker(???).expand` plus the optional type arguments
66+
val instanceOfInvoker = New(Select(invokerPid, invokerName), List(List(Select(scalaDot(nme.Predef), nme.???))))
67+
gen.mkTypeApply(Select(instanceOfInvoker, methName), targs)
68+
case _ =>
69+
macroDdef.rhs
70+
}
71+
72+
val typedImplRef = typer.silent(_.typed(markMacroImplRef(untypedImplRef)), reportAmbiguousErrors = false)
73+
typedImplRef match {
74+
case SilentResultValue(success) => success
75+
case SilentTypeError(err) => abort(err.errPos, err.errMsg)
76+
}
77+
}
78+
79+
// FIXME: cannot write this concisely because of SI-7507
80+
// lazy val (isImplBundle, macroImplOwner, macroImpl, macroImplTargs) =
81+
private lazy val dissectedMacroImplRef =
82+
macroImplRef match {
83+
case MacroImplReference(isBundle, owner, meth, targs) => (isBundle, owner, meth, targs)
84+
case _ => MacroImplReferenceWrongShapeError()
85+
}
86+
lazy val isImplBundle = dissectedMacroImplRef._1
87+
lazy val isImplMethod = !isImplBundle
88+
lazy val macroImplOwner = dissectedMacroImplRef._2
89+
lazy val macroImpl = dissectedMacroImplRef._3
90+
lazy val targs = dissectedMacroImplRef._4
91+
}

0 commit comments

Comments
 (0)