scala.reflect.macros.util.Helpers.scala Maven / Gradle / Ivy
The newest version!
/*
* Scala (https://www.scala-lang.org)
*
* Copyright EPFL and Lightbend, Inc.
*
* Licensed under Apache License 2.0
* (http://www.apache.org/licenses/LICENSE-2.0).
*
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*/
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 runDefinitions = currentRun.runDefinitions
import runDefinitions._
val MacroContextUniverse = definitions.MacroContextUniverse
val treeInfo.MacroImplReference(isBundle, _, _, macroImpl, _) = macroImplRef: @unchecked
val paramss = macroImpl.paramss
val ContextParam = paramss match {
case Nil | _ :+ Nil => NoSymbol // no implicit parameters in the signature => nothing to do
case _ if isBundle => macroImpl.owner.tpe member nme.c
case (cparam :: _) :: _ if isMacroContextType(cparam.tpe) => cparam
case _ => NoSymbol // no context parameter in the signature => nothing to do
}
def transformTag(param: Symbol): Symbol = param.tpe.dealias match {
case TypeRef(SingleType(SingleType(_, ContextParam), MacroContextUniverse), WeakTypeTagClass, targ :: Nil) => transform(param, targ.typeSymbol)
case _ => param
}
ContextParam match {
case NoSymbol => paramss
case _ =>
paramss.last map transformTag filter (_.exists) match {
case Nil => paramss.init
case transformed => paramss.init :+ transformed
}
}
}
/** 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 =
transparentShallowTransform(RepeatedParamClass, tp) {
case tp => typeRef(pre, MacroContextExprClass, List(tp))
}
/** Transforms c.Expr[T] types into c.Tree and leaves the rest unchanged.
*/
def untypeMetalevel(tp: Type): Type = {
val runDefinitions = currentRun.runDefinitions
import runDefinitions._
transparentShallowTransform(RepeatedParamClass, tp) {
case ExprClassOf(_) => typeRef(tp.prefix, TreesTreeType, Nil)
case tp => tp
}
}
/** Decreases metalevel of the type, i.e. transforms:
* * c.Expr[T] to T
* * Nothing to Nothing
* * Anything else to NoType
*
* @see Metalevels.scala for more information and examples about metalevels
*/
def decreaseMetalevel(tp: Type): Type = {
val runDefinitions = currentRun.runDefinitions
import runDefinitions._
transparentShallowTransform(RepeatedParamClass, tp) {
case ExprClassOf(runtimeType) => runtimeType
// special-casing Nothing here is a useful convention
// that enables no-hassle prototyping with `macro ???` and `macro { ...; ??? }`
case nothing if nothing =:= NothingTpe => NothingTpe
case _ => NoType
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy