All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dotty.tools.dotc.transform.MacroTransform.scala Maven / Gradle / Ivy

The newest version!
package dotty.tools.dotc
package transform

import core._
import Phases._
import ast.Trees._
import Contexts._
import Symbols._
import Flags.PackageVal
import Decorators._

/** A base class for transforms.
 *  A transform contains a compiler phase which applies a tree transformer.
 */
abstract class MacroTransform extends Phase {

  import ast.tpd._

  override def run(implicit ctx: Context): Unit = {
    val unit = ctx.compilationUnit
    unit.tpdTree = newTransformer.transform(unit.tpdTree)(ctx.withPhase(transformPhase))
  }

  protected def newTransformer(implicit ctx: Context): Transformer

  /** The phase in which the transformation should be run.
   *  By default this is the phase given by the this macro transformer,
   *  but it could be overridden to be the phase following that one.
   */
  protected def transformPhase(implicit ctx: Context): Phase = this

  class Transformer extends TreeMap(cpy = cpyBetweenPhases) {

    protected def localCtx(tree: Tree)(implicit ctx: Context): FreshContext = {
      val sym = tree.symbol
      val owner = if (sym.is(PackageVal)) sym.moduleClass else sym
      ctx.fresh.setTree(tree).setOwner(owner)
    }

    def transformStats(trees: List[Tree], exprOwner: Symbol)(implicit ctx: Context): List[Tree] = {
      def transformStat(stat: Tree): Tree = stat match {
        case _: Import | _: DefTree => transform(stat)
        case _ => transform(stat)(ctx.exprContext(stat, exprOwner))
      }
      flatten(trees.mapconserve(transformStat(_)))
    }

    override def transform(tree: Tree)(implicit ctx: Context): Tree =
      try
        tree match {
          case EmptyValDef =>
            tree
          case _: PackageDef | _: MemberDef =>
            super.transform(tree)(localCtx(tree))
          case impl @ Template(constr, parents, self, _) =>
            cpy.Template(tree)(
              transformSub(constr),
              transform(parents)(ctx.superCallContext),
              Nil,
              transformSelf(self),
              transformStats(impl.body, tree.symbol))
          case _ =>
            super.transform(tree)
        }
      catch {
        case ex: TypeError =>
          ctx.error(ex.toMessage, tree.sourcePos, sticky = true)
          tree
      }

    def transformSelf(vd: ValDef)(implicit ctx: Context): ValDef =
      cpy.ValDef(vd)(tpt = transform(vd.tpt))
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy