@@ -14,6 +14,7 @@ import dotty.tools.dotc.core.Phases.Phase
1414import dotty .tools .dotc .core .StdNames ._
1515import dotty .tools .dotc .core .Symbols ._
1616import dotty .tools .dotc .reporting .diagnostic .messages
17+ import dotty .tools .dotc .transform .PostTyper
1718import dotty .tools .dotc .typer .{FrontEnd , ImportInfo }
1819import dotty .tools .dotc .util .Positions ._
1920import dotty .tools .dotc .util .SourceFile
@@ -23,42 +24,52 @@ import dotty.tools.repl.results._
2324
2425import scala .collection .mutable
2526
26- /** This subclass of `Compiler` replaces the appropriate phases in order to
27- * facilitate the REPL
27+ /** This subclass of `Compiler` is adapted for use in the REPL.
2828 *
29- * Specifically it replaces the front end with `REPLFrontEnd`, and adds a
30- * custom subclass of `GenBCode`. The custom `GenBCode`, `REPLGenBCode`, works
31- * in conjunction with a specialized class loader in order to load virtual
32- * classfiles.
29+ * - compiles parsed expression in the current REPL state:
30+ * - adds the appropriate imports in scope
31+ * - wraps expressions into a dummy object
32+ * - provides utility to query the type of an expression
33+ * - provides utility to query the documentation of an expression
3334 */
3435class ReplCompiler extends Compiler {
35- override protected def frontendPhases : List [List [Phase ]] =
36- Phases .replace(classOf [FrontEnd ], _ => new REPLFrontEnd :: Nil , super .frontendPhases)
3736
38- def newRun (initCtx : Context , objectIndex : Int ) = new Run (this , initCtx) {
39- override protected [this ] def rootContext (implicit ctx : Context ) =
40- addMagicImports(super .rootContext)
41-
42- private def addMagicImports (initCtx : Context ): Context = {
43- def addImport (path : TermName )(implicit ctx : Context ) = {
44- val importInfo = ImportInfo .rootImport { () =>
45- ctx.requiredModuleRef(path)
46- }
47- ctx.fresh.setNewScope.setImportInfo(importInfo)
37+ override protected def frontendPhases : List [List [Phase ]] = List (
38+ List (new REPLFrontEnd ),
39+ List (new CollectTopLevelImports ),
40+ List (new PostTyper )
41+ )
42+
43+ def newRun (initCtx : Context , state : State ): Run = new Run (this , initCtx) {
44+
45+ /** Import previous runs and user defined imports */
46+ override protected [this ] def rootContext (implicit ctx : Context ): Context = {
47+ def importContext (imp : tpd.Import )(implicit ctx : Context ) =
48+ ctx.importContext(imp, imp.symbol)
49+
50+ def importPreviousRun (id : Int )(implicit ctx : Context ) = {
51+ // we first import the wrapper object id
52+ val path = nme.EMPTY_PACKAGE ++ " ." ++ objectNames(id)
53+ val importInfo = ImportInfo .rootImport(() =>
54+ ctx.requiredModuleRef(path))
55+ val ctx0 = ctx.fresh.setNewScope.setImportInfo(importInfo)
56+
57+ // then its user defined imports
58+ val imports = state.imports.getOrElse(id, Nil )
59+ if (imports.isEmpty) ctx0
60+ else imports.foldLeft(ctx0.fresh.setNewScope)((ctx, imp) =>
61+ importContext(imp)(ctx))
4862 }
4963
50- (1 to objectIndex)
51- .foldLeft(initCtx) { (ictx, i) =>
52- addImport(nme.EMPTY_PACKAGE ++ " ." ++ objectNames(i))(ictx)
53- }
64+ (1 to state.objectIndex).foldLeft(super .rootContext)((ctx, id) =>
65+ importPreviousRun(id)(ctx))
5466 }
5567 }
5668
5769 private [this ] val objectNames = mutable.Map .empty[Int , TermName ]
5870 private def objectName (state : State ) =
59- objectNames.getOrElseUpdate(state.objectIndex, {
60- (str.REPL_SESSION_LINE + state.objectIndex).toTermName
61- })
71+ objectNames.getOrElseUpdate(state.objectIndex,
72+ (str.REPL_SESSION_LINE + state.objectIndex).toTermName)
6273
6374 private case class Definitions (stats : List [untpd.Tree ], state : State )
6475
@@ -86,7 +97,7 @@ class ReplCompiler extends Compiler {
8697 }
8798
8899 Definitions (
89- state.imports ++ defs,
100+ defs,
90101 state.copy(
91102 objectIndex = state.objectIndex + (if (defs.isEmpty) 0 else 1 ),
92103 valIndex = valIdx
@@ -158,19 +169,18 @@ class ReplCompiler extends Compiler {
158169 def docOf (expr : String )(implicit state : State ): Result [String ] = {
159170 implicit val ctx : Context = state.context
160171
161- /**
162- * Extract the "selected" symbol from `tree`.
172+ /** Extract the "selected" symbol from `tree`.
163173 *
164- * Because the REPL typechecks an expression, special syntax is needed to get the documentation
165- * of certain symbols:
174+ * Because the REPL typechecks an expression, special syntax is needed to get the documentation
175+ * of certain symbols:
166176 *
167- * - To select the documentation of classes, the user needs to pass a call to the class' constructor
168- * (e.g. `new Foo` to select `class Foo`)
169- * - When methods are overloaded, the user needs to enter a lambda to specify which functions he wants
170- * (e.g. `foo(_: Int)` to select `def foo(x: Int)` instead of `def foo(x: String)`
177+ * - To select the documentation of classes, the user needs to pass a call to the class' constructor
178+ * (e.g. `new Foo` to select `class Foo`)
179+ * - When methods are overloaded, the user needs to enter a lambda to specify which functions he wants
180+ * (e.g. `foo(_: Int)` to select `def foo(x: Int)` instead of `def foo(x: String)`
171181 *
172- * This function returns the right symbol for the received expression, and all the symbols that are
173- * overridden.
182+ * This function returns the right symbol for the received expression, and all the symbols that are
183+ * overridden.
174184 */
175185 def extractSymbols (tree : tpd.Tree ): Iterator [Symbol ] = {
176186 val sym = tree match {
@@ -210,7 +220,7 @@ class ReplCompiler extends Compiler {
210220 import untpd ._
211221
212222 val valdef = ValDef (" expr" .toTermName, TypeTree (), Block (trees, unitLiteral))
213- val tmpl = Template (emptyConstructor, Nil , EmptyValDef , state.imports :+ valdef)
223+ val tmpl = Template (emptyConstructor, Nil , EmptyValDef , List ( valdef) )
214224 val wrapper = TypeDef (" $wrapper" .toTypeName, tmpl)
215225 .withMods(Modifiers (Final ))
216226 .withPos(Position (0 , expr.length))
@@ -261,9 +271,8 @@ class ReplCompiler extends Compiler {
261271
262272 if (errorsAllowed || ! ctx.reporter.hasErrors)
263273 unwrapped(unit.tpdTree, src)
264- else {
265- ctx.reporter.removeBufferedMessages.errors
266- }
274+ else
275+ ctx.reporter.removeBufferedMessages.errors[tpd.ValDef ] // Workaround #4988
267276 }
268277 }
269278}
0 commit comments