Skip to content

Cache initial context in REPL #4654

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 22 additions & 22 deletions compiler/src/dotty/tools/repl/ReplDriver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,13 @@ class ReplDriver(settings: Array[String],
*/
override def sourcesRequired = false

/** Create a fresh and initialized context with IDE mode enabled */
private[this] def initialCtx = {
val rootCtx = initCtx.fresh.addMode(Mode.ReadPositions).addMode(Mode.Interactive)
val ictx = setup(settings, rootCtx)._2.fresh
ictx.base.initialize()(ictx)
ictx
}
private[this] var myInitCtx: Context = _
protected[this] var compiler: ReplCompiler = _
protected[this] var rendering: Rendering = _

/** the initial, empty state of the REPL session */
protected[this] def initState = State(0, 0, Nil, Nil, compiler.newRun(rootCtx, 0))
// initialize the REPL session as part of the constructor so that once `run`
// is called, we're in business
resetToInitial()

/** Reset state of repl to the initial state
*
Expand All @@ -107,27 +104,30 @@ class ReplDriver(settings: Array[String],
* everything properly
*/
protected[this] def resetToInitial(): Unit = {
rootCtx = initialCtx
val rootCtx = initCtx.fresh.addMode(Mode.ReadPositions).addMode(Mode.Interactive)
implicit val ctx = setup(settings, rootCtx)._2
ctx.initialize()

val outDir: AbstractFile = {
if (rootCtx.settings.outputDir.isDefault(rootCtx))
if (ctx.settings.outputDir.isDefault)
new VirtualDirectory("(memory)", None)
else {
val path = Directory(rootCtx.settings.outputDir.value(rootCtx))
val path = Directory(ctx.settings.outputDir.value(ctx))
assert(path.isDirectory)
new PlainDirectory(path)
}
}

myInitCtx = ctx
compiler = new ReplCompiler(outDir)
rendering = new Rendering(compiler, classLoader)
}

protected[this] var rootCtx: Context = _
protected[this] var compiler: ReplCompiler = _
protected[this] var rendering: Rendering = _
/** Create a fresh and initialized context with IDE mode enabled */
protected[this] def initialCtx: Context = myInitCtx.fresh

// initialize the REPL session as part of the constructor so that once `run`
// is called, we're in business
resetToInitial()
/** the initial, empty state of the REPL session */
protected[this] def initState = State(0, 0, Nil, Nil, compiler.newRun(initialCtx, 0))

/** Run REPL with `state` until `:quit` command found
*
Expand All @@ -146,7 +146,7 @@ class ReplDriver(settings: Array[String],
else {
// readLine potentially destroys the run, so a new one is needed for the
// rest of the interpretation:
implicit val freshState = state.newRun(compiler, rootCtx)
implicit val freshState = state.newRun(compiler, initialCtx)
loop(interpret(res))
}
}
Expand All @@ -156,7 +156,7 @@ class ReplDriver(settings: Array[String],

final def run(input: String)(implicit state: State): State = withRedirectedOutput {
val parsed = ParseResult(input)(state.run.runContext)
interpret(parsed)(state.newRun(compiler, rootCtx))
interpret(parsed)(state.newRun(compiler, initialCtx))
}

private def withRedirectedOutput(op: => State): State =
Expand All @@ -165,7 +165,7 @@ class ReplDriver(settings: Array[String],
/** Extract possible completions at the index of `cursor` in `expr` */
protected[this] final def completions(cursor: Int, expr: String, state0: State): Completions = {
// TODO move some of this logic to `Interactive`
implicit val state = state0.newRun(compiler, rootCtx)
implicit val state = state0.newRun(compiler, initialCtx)
compiler
.typeCheck(expr, errorsAllowed = true)
.map { tree =>
Expand Down Expand Up @@ -202,7 +202,7 @@ class ReplDriver(settings: Array[String],
case parsed: Parsed if parsed.trees.nonEmpty =>
compile(parsed)
.withHistory(parsed.sourceCode :: state.history)
.newRun(compiler, rootCtx)
.newRun(compiler, initialCtx)

case SyntaxErrors(src, errs, _) =>
displayErrors(errs)
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/dotty/tools/repl/ReplTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class ReplTest private (out: ByteArrayOutputStream) extends ReplDriver(

implicit class TestingState(state: State) {
def andThen[A](op: State => A): A =
op(state.newRun(compiler, rootCtx))
op(state.newRun(compiler, initialCtx))
}
}

Expand Down
1 change: 0 additions & 1 deletion compiler/test/dotty/tools/repl/ScriptedTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ class ScriptedTests extends ReplTest with MessageRendering {
Source.fromFile(f).getLines().flatMap(filterEmpties).mkString("\n")
val actualOutput = {
resetToInitial()
init()
val inputRes = extractInputs(prompt)
val buf = new ArrayBuffer[String]
inputRes.foldLeft(initState) { (state, input) =>
Expand Down