@@ -14,6 +14,7 @@ import dotty.tools.dotc.core.Phases.Phase
14
14
import dotty .tools .dotc .core .StdNames ._
15
15
import dotty .tools .dotc .core .Symbols ._
16
16
import dotty .tools .dotc .reporting .diagnostic .messages
17
+ import dotty .tools .dotc .transform .PostTyper
17
18
import dotty .tools .dotc .typer .{FrontEnd , ImportInfo }
18
19
import dotty .tools .dotc .util .Positions ._
19
20
import dotty .tools .dotc .util .SourceFile
@@ -23,42 +24,52 @@ import dotty.tools.repl.results._
23
24
24
25
import scala .collection .mutable
25
26
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.
28
28
*
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
33
34
*/
34
35
class ReplCompiler extends Compiler {
35
- override protected def frontendPhases : List [List [Phase ]] =
36
- Phases .replace(classOf [FrontEnd ], _ => new REPLFrontEnd :: Nil , super .frontendPhases)
37
36
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))
48
62
}
49
63
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))
54
66
}
55
67
}
56
68
57
69
private [this ] val objectNames = mutable.Map .empty[Int , TermName ]
58
70
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)
62
73
63
74
private case class Definitions (stats : List [untpd.Tree ], state : State )
64
75
@@ -86,7 +97,7 @@ class ReplCompiler extends Compiler {
86
97
}
87
98
88
99
Definitions (
89
- state.imports ++ defs,
100
+ defs,
90
101
state.copy(
91
102
objectIndex = state.objectIndex + (if (defs.isEmpty) 0 else 1 ),
92
103
valIndex = valIdx
@@ -158,19 +169,18 @@ class ReplCompiler extends Compiler {
158
169
def docOf (expr : String )(implicit state : State ): Result [String ] = {
159
170
implicit val ctx : Context = state.context
160
171
161
- /**
162
- * Extract the "selected" symbol from `tree`.
172
+ /** Extract the "selected" symbol from `tree`.
163
173
*
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:
166
176
*
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)`
171
181
*
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.
174
184
*/
175
185
def extractSymbols (tree : tpd.Tree ): Iterator [Symbol ] = {
176
186
val sym = tree match {
@@ -210,7 +220,7 @@ class ReplCompiler extends Compiler {
210
220
import untpd ._
211
221
212
222
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) )
214
224
val wrapper = TypeDef (" $wrapper" .toTypeName, tmpl)
215
225
.withMods(Modifiers (Final ))
216
226
.withPos(Position (0 , expr.length))
@@ -261,9 +271,8 @@ class ReplCompiler extends Compiler {
261
271
262
272
if (errorsAllowed || ! ctx.reporter.hasErrors)
263
273
unwrapped(unit.tpdTree, src)
264
- else {
274
+ else
265
275
ctx.reporter.removeBufferedMessages.errors
266
- }
267
276
}
268
277
}
269
278
}
0 commit comments