@@ -2,16 +2,30 @@ package dotty.tools.dotc
2
2
package quoted
3
3
4
4
import dotty .tools .backend .jvm .GenBCode
5
+ import dotty .tools .dotc .ast .tpd
6
+
5
7
import dotty .tools .dotc .core .Contexts .Context
8
+ import dotty .tools .dotc .core .Flags .{EmptyFlags , Method }
6
9
import dotty .tools .dotc .core .{Mode , Phases }
7
10
import dotty .tools .dotc .core .Phases .Phase
11
+ import dotty .tools .dotc .core .Scopes .{EmptyScope , newScope }
12
+ import dotty .tools .dotc .core .StdNames .nme
13
+ import dotty .tools .dotc .core .Symbols .defn
14
+ import dotty .tools .dotc .core .Types .ExprType
15
+ import dotty .tools .dotc .core .quoted .PickledQuotes
8
16
import dotty .tools .dotc .transform .Pickler
9
- import dotty .tools .io .VirtualDirectory
17
+ import dotty .tools .dotc .typer .FrontEnd
18
+ import dotty .tools .dotc .util .Positions .Position
19
+ import dotty .tools .dotc .util .SourceFile
20
+ import dotty .tools .io .{Path , PlainFile , VirtualDirectory }
21
+
22
+ import scala .quoted .Expr
10
23
11
24
/** Compiler that takes the contents of a quoted expression `expr` and produces
12
25
* a class file with `class ' { def apply: Object = expr }`.
13
26
*/
14
27
class ExprCompiler (directory : VirtualDirectory ) extends Compiler {
28
+ import tpd ._
15
29
16
30
/** A GenBCode phase that outputs to a virtual directory */
17
31
private class ExprGenBCode extends GenBCode {
@@ -33,4 +47,50 @@ class ExprCompiler(directory: VirtualDirectory) extends Compiler {
33
47
reset()
34
48
new ExprRun (this , ctx.addMode(Mode .ReadPositions ))
35
49
}
50
+
51
+ /** Frontend that receives scala.quoted.Expr as input */
52
+ class ExprFrontend (putInClass : Boolean ) extends FrontEnd {
53
+ import tpd ._
54
+
55
+ override def isTyper = false
56
+
57
+ override def runOn (units : List [CompilationUnit ])(implicit ctx : Context ): List [CompilationUnit ] = {
58
+ units.map {
59
+ case exprUnit : ExprCompilationUnit =>
60
+ val tree =
61
+ if (putInClass) inClass(exprUnit.expr)
62
+ else PickledQuotes .quotedToTree(exprUnit.expr)
63
+ val source = new SourceFile (" " , Seq ())
64
+ CompilationUnit .mkCompilationUnit(source, tree, forceTrees = true )
65
+ }
66
+ }
67
+
68
+ /** Places the contents of expr in a compilable tree for a class
69
+ * with the following format.
70
+ * `package __root__ { class ' { def apply: Any = <expr> } }`
71
+ */
72
+ private def inClass (expr : Expr [_])(implicit ctx : Context ): Tree = {
73
+ val pos = Position (0 )
74
+ val assocFile = new PlainFile (Path (" <quote>" ))
75
+
76
+ val cls = ctx.newCompleteClassSymbol(defn.RootClass , nme.QUOTE .toTypeName, EmptyFlags ,
77
+ defn.ObjectType :: Nil , newScope, coord = pos, assocFile = assocFile).entered.asClass
78
+ cls.enter(ctx.newDefaultConstructor(cls), EmptyScope )
79
+ val meth = ctx.newSymbol(cls, nme.apply, Method , ExprType (defn.AnyType ), coord = pos).entered
80
+
81
+ val quoted = PickledQuotes .quotedToTree(expr)(ctx.withOwner(meth))
82
+
83
+ val run = DefDef (meth, quoted)
84
+ val classTree = ClassDef (cls, DefDef (cls.primaryConstructor.asTerm), run :: Nil )
85
+ PackageDef (ref(defn.RootPackage ).asInstanceOf [Ident ], classTree :: Nil ).withPos(pos)
86
+ }
87
+ }
88
+
89
+ class ExprRun (comp : Compiler , ictx : Context ) extends Run (comp, ictx) {
90
+ def compileExpr (expr : Expr [_]): Unit = {
91
+ val units = new ExprCompilationUnit (expr) :: Nil
92
+ compileUnits(units)
93
+ }
94
+ }
95
+
36
96
}
0 commit comments