@@ -2,16 +2,30 @@ package dotty.tools.dotc
22package quoted
33
44import dotty .tools .backend .jvm .GenBCode
5+ import dotty .tools .dotc .ast .tpd
6+
57import dotty .tools .dotc .core .Contexts .Context
8+ import dotty .tools .dotc .core .Flags .{EmptyFlags , Method }
69import dotty .tools .dotc .core .{Mode , Phases }
710import 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
816import 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
1023
1124/** Compiler that takes the contents of a quoted expression `expr` and produces
1225 * a class file with `class ' { def apply: Object = expr }`.
1326 */
1427class ExprCompiler (directory : VirtualDirectory ) extends Compiler {
28+ import tpd ._
1529
1630 /** A GenBCode phase that outputs to a virtual directory */
1731 private class ExprGenBCode extends GenBCode {
@@ -33,4 +47,50 @@ class ExprCompiler(directory: VirtualDirectory) extends Compiler {
3347 reset()
3448 new ExprRun (this , ctx.addMode(Mode .ReadPositions ))
3549 }
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+
3696}
0 commit comments