summaryrefslogtreecommitdiff
path: root/src/library/scala/reflect/makro/Infrastructure.scala
blob: e6bfe33366429490205cbce3bfab7d9dadf4a820 (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
package scala.reflect
package makro

trait Infrastructure {
  self: Context =>

  /** Determines whether the compiler expanding a macro targets JVM.
   */
  val forJVM: Boolean

  /** Determines whether the compiler expanding a macro targets CLR.
   */
  val forMSIL: Boolean

  /** Determines whether the compiler expanding a macro is a presentation compiler.
   */
  val forInteractive: Boolean

  /** Determines whether the compiler expanding a macro is a Scaladoc compiler.
   */
  val forScaladoc: Boolean

  /** Exposes current compilation run.
   */
  val currentRun: Run

  /** Exposes library classpath.
   */
  val libraryClassPath: List[java.net.URL]

  /** Exposes a classloader that corresponds to the library classpath.
   *
   *  With this classloader you can perform on-the-fly evaluation of macro arguments.
   *  For example, consider this code snippet:
   *
   *    def staticEval[T](x: T) = macro staticEval[T]
   *
   *    def staticEval[T: c.TypeTag](c: Context)(x: c.Expr[T]) = {
   *      import scala.reflect.runtime.{universe => ru}
   *      val mirror = ru.runtimeMirror(c.libraryClassLoader)
   *      import scala.tools.reflect.ToolBox
   *      val toolBox = mirror.mkToolBox()
   *      val importer = ru.mkImporter(c.universe).asInstanceOf[ru.Importer { val from: c.universe.type }]
   *      val tree = c.resetAllAttrs(x.tree.duplicate)
   *      val imported = importer.importTree(tree)
   *      val valueOfX = toolBox.runExpr(imported).asInstanceOf[T]
   *      ...
   *    }
   *
   *  // [Eugene++] using this guy will tremendously slow down the compilation
   *  // https://twitter.com/xeno_by/status/201248317831774208
   *  // todo. we need to address this somehow
   */
  def libraryClassLoader: ClassLoader

  /** As seen by macro API, compilation run is an opaque type that can be deconstructed into:
   *    1) Current compilation unit
   *    2) List of all compilation units that comprise the run
   */
  type Run

  val Run: RunExtractor

  abstract class RunExtractor {
    def unapply(run: Run): Option[(CompilationUnit, List[CompilationUnit])]
  }

  /** As seen by macro API, compilation unit is an opaque type that can be deconstructed into:
   *    1) File that corresponds to the unit (if not applicable, null)
   *    2) Content of the file (if not applicable, empty array)
   *    3) Body, i.e. the AST that represents the compilation unit
   */
  type CompilationUnit

  val CompilationUnit: CompilationUnitExtractor

  abstract class CompilationUnitExtractor {
    def unapply(compilationUnit: CompilationUnit): Option[(java.io.File, Array[Char], Tree)]
  }

  /** Returns a macro definition which triggered this macro expansion.
   */
  val currentMacro: Symbol

  // todo. redo caches as discussed on Reflecting Meeting 2012/03/29
  // https://docs.google.com/document/d/1oUZGQpdt2qwioTlJcSt8ZFQwVLTvpxn8xa67P8OGVpU/edit

  /** A cache shared by all invocations of all macros across all compilation runs.
   *
   *  Needs to be used with extreme care, since memory leaks here will swiftly crash the presentation compiler.
   *  For example, Scala IDE typically launches a compiler run on every edit action so there might be hundreds of runs per minute.
   */
  val globalCache: collection.mutable.Map[Any, Any]

  /** A cache shared by all invocations of the same macro within a single compilation run.
   *
   *  This cache is cleared automatically after a compilation run is completed or abandoned.
   *  It is also specific to a particular macro definition.
   *
   *  To share data between different macros and/or different compilation runs, use ``globalCache''.
   */
  val cache: collection.mutable.Map[Any, Any]
}