blob: eb37e83cadb4772107b382dcaa66c46b1f522428 (
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
|
package scala
package reflect
package macros
/**
* <span class="badge badge-red" style="float: right;">EXPERIMENTAL</span>
*
* A slice of [[scala.reflect.macros.BlackboxContext the Scala macros context]] that provides
* a facility to evaluate trees.
*/
trait Evals {
self: BlackboxContext =>
/** Takes a typed wrapper for a tree of type `T` and evaluates it to a value of type `T`.
*
* Can be used to perform compile-time computations on macro arguments to the extent
* permitted by the shape of the arguments.
*
* Known issues: because of [[https://issues.scala-lang.org/browse/SI-5748 https://issues.scala-lang.org/browse/SI-5748]]
* trees being evaluated first need to undergo `resetAllAttrs`. Resetting symbols and types
* mutates the tree in place, therefore the conventional approach is to `duplicate` the tree first.
*
* {{{
* scala> def impl(c: BlackboxContext)(x: c.Expr[String]) = {
* | val x1 = c.Expr[String](c.resetAllAttrs(x.tree.duplicate))
* | println(s"compile-time value is: \${c.eval(x1)}")
* | x
* | }
* impl: (c: BlackboxContext)(x: c.Expr[String])c.Expr[String]
*
* scala> def test(x: String) = macro impl
* test: (x: String)String
*
* scala> test("x")
* compile-time value is: x
* res0: String = x
*
* scala> test("x" + "y")
* compile-time value is: xy
* res1: String = xy
*
* scala> val x = "x"
* x: String = x
*
* scala> test(x + "y")
* compile-time value is: xy
* res2: String = xy
*
* scala> { val x = "x"; test(x + "y") }
* error: exception during macro expansion:
* scala.tools.reflect.ToolBoxError: reflective compilation failed
* }}}
*
* Note that in the last case evaluation has failed, because the argument of a macro
* refers to a runtime value `x`, which is unknown at compile time.
*/
def eval[T](expr: Expr[T]): T
}
|