aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/ast/PluggableTransformers.scala
blob: a584230a24199bb00495bd0595626ac52303f58c (plain) (blame)
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package dotty.tools.dotc
package ast


object PluggableTransformers {
/*
  import Trees._, Contexts._

  abstract class PluggableTransformer[T] extends TreeTransformer[T, Context] {
    type PluginOp[-N <: Tree[T]] = N => Tree[T]

    private[this] var _ctx: Context = _
    private[this] var _oldTree: Tree[T] = _

    protected implicit def ctx: Context = _ctx
    protected def oldTree: Tree[T] = _oldTree
    protected def thisTransformer: PluggableTransformer[T] = this

    class PluginOps[-N <: Tree[T]](op: PluginOp[N], val next: Plugins) {
      def apply(tree: N, old: Tree[T], c: Context): Tree[T] = {
        val savedCtx = _ctx
        val savedOld = _oldTree
        try {
          op(tree)
        } finally {
          _oldTree = savedOld
          _ctx = savedCtx
        }
      }
    }

    val NoOp: PluginOp[Tree[T]] = identity
    val NoOps = new PluginOps(NoOp, null)

    class Plugins {
      def next: Plugins = null

      def processIdent: PluginOp[Ident[T]] = NoOp
      def processSelect: PluginOp[Select[T]] = NoOp

      val IdentOps: PluginOps[Ident[T]] = NoOps
      val SelectOps: PluginOps[Select[T]] = NoOps
    }

    val EmptyPlugin = new Plugins

    private[this] var _plugins: Plugins = EmptyPlugin

    override def plugins: Plugins = _plugins

    class Plugin extends Plugins {
      override val next = _plugins
      _plugins = this

      private def push[N <: Tree[T]](op: PluginOp[N], ops: => PluginOps[N]): PluginOps[N] =
        if (op == NoOp) ops else new PluginOps(op, next)

      override val IdentOps: PluginOps[Ident[T]] = push(processIdent, next.IdentOps)
      override val SelectOps: PluginOps[Select[T]] = push(processSelect, next.SelectOps)
    }

    def postIdent(tree: Ident[T], old: Tree[T], c: Context, ops: PluginOps[Ident[T]]) =
      if (ops eq NoOps) tree
      else finishIdent(ops(tree, old, c), old, c, ops.next)

    override def finishIdent(tree: Tree[T], old: Tree[T], c: Context, plugins: Plugins): Tree[T] = tree match {
      case tree: Ident[_] => postIdent(tree, old, c, plugins.IdentOps)
      case _ => postProcess(tree, old, c, plugins)
    }

    def postSelect(tree: Select[T], old: Tree[T], c: Context, ops: PluginOps[Select[T]]) =
      if (ops eq NoOps) tree
      else finishSelect(ops(tree, old, c), old, c, ops.next)

    override def finishSelect(tree: Tree[T], old: Tree[T], c: Context, plugins: Plugins): Tree[T] = tree match {
      case tree: Select[_] => postSelect(tree, old, c, plugins.SelectOps)
      case _ => postProcess(tree, old, c, plugins)
    }

    protected def postProcess(tree: Tree[T], old: Tree[T], c: Context, plugins: Plugins): Tree[T] = tree match {
      case tree: Ident[_] => finishIdent(tree, old, c, plugins)
      case tree: Select[_] => finishSelect(tree, old, c, plugins)
    }
  }
}

import PluggableTransformers._, Types._, Trees._, Contexts._

class ExampleTransformer extends PluggableTransformer[Type] {

  object ExamplePlugin extends Plugin {
    override def processIdent = {
      case tree @ Ident(x) if x.isTypeName => tree.derivedSelect(tree, x)
      case tree => tpd.Ident(???)
    }
    override def processSelect = { tree =>
      if (tree.isType) tree.derivedIdent(tree.name)
      else tpd.EmptyTree
    }
  }

  override def transform(tree: tpd.Tree, ctx: Context) =
    super.transform(tree, ctx)
*/
}