aboutsummaryrefslogblamecommitdiff
path: root/src/dotty/tools/dotc/transform/MacroTransform.scala
blob: eacbd1717e1c537a45951cf34c20f085f9636dd5 (plain) (tree)






















                                                                           
                                                                  
 








                                                                                           











                                                                                                   

                                            
                                               











                                                     
package dotty.tools.dotc
package transform

import core._
import typer._
import Phases._
import ast.Trees._
import Contexts._
import Symbols._
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)
  }

  protected def newTransformer(implicit ctx: Context): Transformer

  class Transformer extends TreeMap {

    protected def localCtx(tree: Tree)(implicit ctx: Context) =
      ctx.fresh.setTree(tree).setOwner(tree.symbol)

    /** The current enclosing class
     *  @pre  We must be inside a class
     */
    def currentClass(implicit ctx: Context): ClassSymbol = ctx.owner.enclosingClass.asClass

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

    override def transform(tree: Tree)(implicit ctx: Context): Tree = {
      tree match {
        case _: PackageDef | _: MemberDef =>
          super.transform(tree)(localCtx(tree))
        case Template(constr, parents, self, body) =>
          cpy.Template(tree,
            transformSub(constr),
            transform(parents),
            transformSub(self),
            transformStats(body, tree.symbol))
        case _ =>
          super.transform(tree)
      }
    }
  }
}