1
1
package dotty .tools
2
2
package repl
3
3
4
+ import java .io .{ File => JFile }
5
+
6
+ import dotc .ast .untpd
4
7
import dotc .ast .tpd
5
- import dotc .core .{ Phases , Decorators , Flags }
6
- import dotc .core .Contexts .Context
7
8
import dotc .{ CompilationUnit , Compiler }
9
+ import dotc .core .{ Phases , Decorators , Flags }
10
+ import Decorators ._ , Flags ._
11
+ import dotc .util .SourceFile
12
+ import dotc .typer .FrontEnd
8
13
import backend .jvm .GenBCode
14
+ import dotc .core .Contexts .Context
15
+ import dotc .util .Positions ._
16
+ import dotc .reporting .diagnostic .MessageContainer
17
+ import dotc .reporting ._
9
18
import io ._
19
+
10
20
import results ._
11
21
12
22
class ReplCompiler (ictx : Context ) extends Compiler {
23
+
24
+ type NextRes = Int
25
+
26
+ private class REPLFrontEnd extends FrontEnd {
27
+ override def phaseName = " replFrontEnd"
28
+
29
+ override def runOn (units : List [CompilationUnit ])(implicit ctx : Context ) = {
30
+ val unitContexts = for (unit <- units) yield ctx.fresh.setCompilationUnit(unit)
31
+ var remaining = unitContexts
32
+ while (remaining.nonEmpty) {
33
+ enterSyms(remaining.head)
34
+ remaining = remaining.tail
35
+ }
36
+ unitContexts.foreach(enterAnnotations(_))
37
+ unitContexts.foreach(typeCheck(_))
38
+ unitContexts.map(_.compilationUnit).filterNot(discardAfterTyper)
39
+ }
40
+ }
41
+
13
42
/** A GenBCode phase that outputs to a virtual directory */
14
43
private class REPLGenBCode extends GenBCode {
15
44
override def phaseName = " replGenBCode"
@@ -24,12 +53,68 @@ class ReplCompiler(ictx: Context) extends Compiler {
24
53
override def outputDir (implicit ctx : Context ) = virtualDirectory
25
54
}
26
55
27
- /** Phases without `FrontEnd`, and a modified `GenBCode` */
28
- override def phases = Phases .replace(
29
- classOf [GenBCode ],
30
- _ => new REPLGenBCode :: Nil ,
31
- super .phases.tail
32
- )
56
+ override def phases = {
57
+ val replacedFrontend = Phases .replace(
58
+ classOf [FrontEnd ],
59
+ _ => new REPLFrontEnd :: Nil ,
60
+ super .phases
61
+ )
62
+
63
+ Phases .replace(
64
+ classOf [GenBCode ],
65
+ _ => new REPLGenBCode :: Nil ,
66
+ replacedFrontend
67
+ )
68
+ }
69
+
70
+ def freeToAssigned (trees : Seq [untpd.Tree ], state : State )
71
+ (implicit ctx : Context ): (State , Seq [untpd.Tree ]) = {
72
+ import untpd ._
73
+
74
+ def freeExpression (t : Tree ) =
75
+ t.isTerm && ! t.isInstanceOf [Assign ]
76
+
77
+ val (exps, other) = trees.partition(freeExpression)
78
+ val resX = exps.zipWithIndex.map { (exp, i) =>
79
+ ValDef (s " res ${i + state.freeValues}" .toTermName, TypeTree (), exp)
80
+ .withPos(exp.pos)
81
+ }
82
+
83
+ (state.copy(freeValues = state.freeValues + resX.length), resX ++ other)
84
+ }
85
+
86
+ def wrapped (trees : Seq [untpd.Tree ], nextId : Int )(implicit ctx : Context ): untpd.PackageDef = {
87
+ import untpd ._
88
+ import dotc .core .StdNames ._
89
+
90
+ val imports = List .range(0 , nextId).map{ i =>
91
+ Import (Ident ((" ReplSession$" + i).toTermName), Ident (nme.WILDCARD ) :: Nil )
92
+ }
33
93
34
- def compile (tree : tpd.Tree )(implicit ctx : Context ): Result [Unit ] = ()
94
+ val tmpl = Template (emptyConstructor, Nil , EmptyValDef , imports ++ trees)
95
+ PackageDef (Ident (nme.NO_NAME ),
96
+ ModuleDef ((" ReplSession$" + nextId).toTermName, tmpl)
97
+ .withMods(new Modifiers (Module | Final ))
98
+ .withPos(Position (trees.head.pos.start, trees.last.pos.end)) :: Nil
99
+ )
100
+ }
101
+
102
+ def compile (parsed : Parsed , state : State )(implicit ctx : Context ): Result [State ] = {
103
+ val reporter = new StoreReporter (null ) with UniqueMessagePositions with HideNonSensicalMessages
104
+
105
+ val unit = new CompilationUnit (new SourceFile (" ReplSession$" + (state.objects + 1 ), parsed.sourceCode))
106
+ val (stateAfterAssign, trees) = freeToAssigned(parsed.trees, state)
107
+ unit.untpdTree = wrapped(trees, 0 )
108
+
109
+ val run = newRun(ctx.fresh.setReporter(reporter))
110
+ run.compileUnits(unit :: Nil )
111
+
112
+ val errs = reporter.removeBufferedMessages
113
+ if (errs.isEmpty) state.copy(
114
+ freeValues = stateAfterAssign.freeValues,
115
+ objects = state.objects + 1 ,
116
+ ictx = run.runContext
117
+ )
118
+ else Errors (errs)
119
+ }
35
120
}
0 commit comments