Skip to content

Commit 1b129cd

Browse files
committed
Use single compiler instance instead of split pipeline
1 parent 8b1352d commit 1b129cd

File tree

7 files changed

+140
-231
lines changed

7 files changed

+140
-231
lines changed

repl/src/dotty/tools/repl/InjectableTree.scala

Lines changed: 0 additions & 46 deletions
This file was deleted.

repl/src/dotty/tools/repl/Repl.scala

Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,18 @@ import dotc.{ Compiler, Driver }
1313
import AmmoniteReader._
1414
import results._
1515

16+
case class State(objects: Int, freeValues: Int, history: History, ictx: Context)
17+
object State {
18+
def initial(ctx: Context): State = new State(0, 0, Nil, ctx)
19+
}
20+
1621
class Repl(settings: Array[String]) extends Driver {
1722

1823
// FIXME: Change the Driver API to not require implementing this method
1924
override protected def newCompiler(implicit ctx: Context): Compiler =
2025
???
2126

22-
private[this] def initializeCtx = {
27+
protected[this] def initializeCtx = {
2328
val rootCtx = initCtx.fresh
2429
val summary = CompilerCommand.distill(settings)(rootCtx)
2530
val ictx = rootCtx.setSettings(summary.sstate)
@@ -28,75 +33,69 @@ class Repl(settings: Array[String]) extends Driver {
2833
}
2934

3035
protected[this] var myCtx = initializeCtx: Context
31-
protected[this] var typer = new ReplTyper(myCtx)
3236
protected[this] var compiler = new ReplCompiler(myCtx)
3337

3438
private def readLine(history: History) =
3539
AmmoniteReader(history)(myCtx).prompt()
3640

3741
@tailrec
38-
final def run(history: History = Nil,
39-
tree: InjectableTree = InjectableTree()(myCtx)): Unit =
40-
readLine(history) match {
42+
final def run(state: State = State.initial(myCtx)): Unit =
43+
readLine(state.history) match {
4144
case (parsed: Parsed, history) =>
42-
val newTree = compile(parsed, tree)(myCtx)
43-
run(history, newTree)
45+
val newState = compile(parsed, state)
46+
run(newState.copy(history = history))
4447

4548
case (SyntaxErrors(errs, ctx), history) =>
4649
displayErrors(errs)(ctx)
47-
run(history)
50+
run(state)
4851

4952
case (Newline, history) =>
50-
run(history)
53+
run(state)
5154

5255
case (cmd: Command, history) =>
53-
interpretCommand(cmd, history)
56+
interpretCommand(cmd, state)
5457
}
5558

56-
def compile(parsed: Parsed, tree: InjectableTree)(implicit ctx: Context): InjectableTree = {
57-
val res = for {
58-
typed <- typer.typeCheck(parsed, tree.nextId)
59-
injected <- InjectableTree.patch(tree, typed)(typed.newCtx)
60-
_ <- compiler.compile(injected.obj)(typed.newCtx)
61-
} yield (injected, typed.newCtx)
62-
63-
// Fold over result, on failure - report errors and return old `tree`:
64-
res.fold(
65-
errors => {
66-
displayErrors(errors.msgs)
67-
tree
68-
},
69-
(injected, newCtx) => {
70-
myCtx = newCtx
71-
injected
72-
}
73-
)
59+
def compile(parsed: Parsed, state: State): State = {
60+
implicit val ctx = state.ictx
61+
compiler
62+
.compile(parsed, state)
63+
.fold(
64+
errors => {
65+
displayErrors(errors.msgs)
66+
state
67+
},
68+
state => {
69+
myCtx = state.ictx
70+
state
71+
}
72+
)
7473
}
7574

76-
def interpretCommand(cmd: Command, history: History): Unit = cmd match {
75+
def interpretCommand(cmd: Command, state: State): Unit = cmd match {
7776
case UnknownCommand(cmd) => {
7877
println(s"""Unknown command: "$cmd", run ":help" for a list of commands""")
79-
run(history)
78+
run(state)
8079
}
8180

8281
case Help => {
8382
println(Help.text)
84-
run(history)
83+
run(state)
8584
}
8685

8786
case Reset => {
8887
myCtx = initCtx.fresh
89-
run(Nil)
88+
run()
9089
}
9190

9291
case Load(path) =>
9392
if ((new java.io.File(path)).exists) {
9493
val contents = scala.io.Source.fromFile(path).mkString
95-
run(contents :: history)
94+
run(state.copy(history = contents :: state.history))
9695
}
9796
else {
9897
println(s"""Couldn't find file "$path"""")
99-
run(history)
98+
run(state)
10099
}
101100

102101
case Quit =>
Lines changed: 94 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,44 @@
11
package dotty.tools
22
package repl
33

4+
import java.io.{ File => JFile }
5+
6+
import dotc.ast.untpd
47
import dotc.ast.tpd
5-
import dotc.core.{ Phases, Decorators, Flags }
6-
import dotc.core.Contexts.Context
78
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
813
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._
918
import io._
19+
1020
import results._
1121

1222
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+
1342
/** A GenBCode phase that outputs to a virtual directory */
1443
private class REPLGenBCode extends GenBCode {
1544
override def phaseName = "replGenBCode"
@@ -24,12 +53,68 @@ class ReplCompiler(ictx: Context) extends Compiler {
2453
override def outputDir(implicit ctx: Context) = virtualDirectory
2554
}
2655

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+
}
3393

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+
}
35120
}

repl/src/dotty/tools/repl/ReplTyper.scala

Lines changed: 0 additions & 90 deletions
This file was deleted.

0 commit comments

Comments
 (0)