1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
package scala.reflect.macros
package util
import scala.tools.nsc.typechecker.Analyzer
trait Helpers {
self: Analyzer =>
import global._
import definitions._
/** Transforms parameters lists of a macro impl.
* The `transform` function is invoked only for WeakTypeTag evidence parameters.
*
* The transformer takes two arguments: a value parameter from the parameter list
* and a type parameter that is witnesses by the value parameter.
*
* If the transformer returns a NoSymbol, the value parameter is not included from the result.
* If the transformer returns something else, this something else is included in the result instead of the value parameter.
*
* Despite of being highly esoteric, this function significantly simplifies signature analysis.
* For example, it can be used to strip macroImpl.paramss from the evidences (necessary when checking def <-> impl correspondence)
* or to streamline creation of the list of macro arguments.
*/
def transformTypeTagEvidenceParams(macroImplRef: Tree, transform: (Symbol, Symbol) => Symbol): List[List[Symbol]] = {
val treeInfo.MacroImplReference(isBundle, owner, macroImpl, _) = macroImplRef
val paramss = macroImpl.paramss
if (paramss.isEmpty || paramss.last.isEmpty) return paramss // no implicit parameters in the signature => nothing to do
val rc =
if (isBundle) macroImpl.owner.tpe.member(nme.c)
else {
def cparam = paramss.head.head
if (paramss.head.isEmpty || !(cparam.tpe <:< MacroContextClass.tpe)) return paramss // no context parameter in the signature => nothing to do
cparam
}
def transformTag(param: Symbol): Symbol = param.tpe.dealias match {
case TypeRef(SingleType(SingleType(_, ac), universe), WeakTypeTagClass, targ :: Nil)
if ac == rc && universe == MacroContextUniverse =>
transform(param, targ.typeSymbol)
case _ =>
param
}
val transformed = paramss.last map transformTag filter (_ ne NoSymbol)
if (transformed.isEmpty) paramss.init else paramss.init :+ transformed
}
private def dealiasAndRewrap(tp: Type)(fn: Type => Type): Type = {
if (isRepeatedParamType(tp)) scalaRepeatedType(fn(tp.typeArgs.head.dealias))
else fn(tp.dealias)
}
/** Increases metalevel of the type, i.e. transforms:
* * T to c.Expr[T]
*
* @see Metalevels.scala for more information and examples about metalevels
*/
def increaseMetalevel(pre: Type, tp: Type): Type = dealiasAndRewrap(tp) {
case tp => typeRef(pre, MacroContextExprClass, List(tp))
}
/** Decreases metalevel of the type, i.e. transforms:
* * c.Expr[T] to T
* * Anything else to Any
*
* @see Metalevels.scala for more information and examples about metalevels
*/
def decreaseMetalevel(tp: Type): Type = dealiasAndRewrap(tp) {
case ExprClassOf(runtimeType) => runtimeType
case _ => AnyClass.tpe // so that macro impls with rhs = ??? don't screw up our inference
}
}
|