Skip to content

Commit 8da7e37

Browse files
committed
Cleanups to the previous repl commits.
1 parent 31ed2e8 commit 8da7e37

File tree

5 files changed

+97
-117
lines changed

5 files changed

+97
-117
lines changed

src/compiler/scala/tools/nsc/interpreter/ILoop.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,8 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
329329
}
330330
}
331331

332-
private def pathToPhaseWrapper = intp.pathToTerm("$r") + ".phased.atCurrent"
332+
private def pathToPhaseWrapper = intp.originalPath("$r") + ".phased.atCurrent"
333+
333334
private def phaseCommand(name: String): Result = {
334335
val phased: Phased = power.phased
335336
import phased.NoPhaseName

src/compiler/scala/tools/nsc/interpreter/IMain.scala

Lines changed: 53 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,23 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
177177
import global._
178178
import definitions.{ ObjectClass, termMember, typeMember, dropNullaryMethod}
179179

180+
lazy val runtimeMirror = ru.runtimeMirror(classLoader)
181+
182+
private def noFatal(body: => Symbol): Symbol = try body catch { case _: FatalError => NoSymbol }
183+
184+
def getClassIfDefined(path: String) = (
185+
noFatal(runtimeMirror staticClass path)
186+
orElse noFatal(rootMirror staticClass path)
187+
)
188+
def getModuleIfDefined(path: String) = (
189+
noFatal(runtimeMirror staticModule path)
190+
orElse noFatal(rootMirror staticModule path)
191+
)
192+
def getPathIfDefined(path: String) = (
193+
if (path endsWith "$") getModuleIfDefined(path.init)
194+
else getClassIfDefined(path)
195+
)
196+
180197
implicit class ReplTypeOps(tp: Type) {
181198
def orElse(other: => Type): Type = if (tp ne NoType) tp else other
182199
def andAlso(fn: Type => Type): Type = if (tp eq NoType) tp else fn(tp)
@@ -307,9 +324,10 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
307324
def shift[T](op: => T): T = exitingFlatten(op)
308325
}
309326

310-
def originalPath(name: Name): String = typerOp path name
311-
def originalPath(sym: Symbol): String = typerOp path sym
312-
def flatPath(sym: Symbol): String = flatOp shift sym.javaClassName
327+
def originalPath(name: String): String = originalPath(name: TermName)
328+
def originalPath(name: Name): String = typerOp path name
329+
def originalPath(sym: Symbol): String = typerOp path sym
330+
def flatPath(sym: Symbol): String = flatOp shift sym.javaClassName
313331
// def translatePath(path: String) = symbolOfPath(path).fold(Option.empty[String])(flatPath)
314332
def translatePath(path: String) = {
315333
val sym = if (path endsWith "$") symbolOfTerm(path.init) else symbolOfIdent(path)
@@ -341,13 +359,8 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
341359
// Set the current Java "context" class loader to this interpreter's class loader
342360
def setContextClassLoader() = classLoader.setAsContext()
343361

344-
def allDefinedNames = exitingTyper(replScope.toList.map(_.name).sorted)
345-
def pathToType(id: String): String = pathToName(newTypeName(id))
346-
def pathToTerm(id: String): String = pathToName(newTermName(id))
347-
def pathToName(name: Name): String = replScope lookup name match {
348-
case NoSymbol => name.toString
349-
case sym => exitingTyper(sym.fullName)
350-
}
362+
def allDefinedNames: List[Name] = exitingTyper(replScope.toList.map(_.name).sorted)
363+
def unqualifiedIds: List[String] = allDefinedNames map (_.decode) sorted
351364

352365
/** Most recent tree handled which wasn't wholly synthetic. */
353366
private def mostRecentlyHandledTree: Option[Tree] = {
@@ -401,9 +414,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
401414
}
402415
exitingTyper {
403416
req.imports foreach (sym => updateReplScope(sym, isDefined = false))
404-
req.defines foreach { sym =>
405-
updateReplScope(sym, isDefined = true)
406-
}
417+
req.defines foreach (sym => updateReplScope(sym, isDefined = true))
407418
}
408419
}
409420

@@ -746,7 +757,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
746757
* following accessPath into the outer one.
747758
*/
748759
def resolvePathToSymbol(accessPath: String): Symbol = {
749-
val readRoot = getRequiredModule(readPath) // the outermost wrapper
760+
val readRoot = getModuleIfDefined(readPath) // the outermost wrapper
750761
(accessPath split '.').foldLeft(readRoot: Symbol) {
751762
case (sym, "") => sym
752763
case (sym, name) => exitingTyper(termMember(sym, name))
@@ -823,7 +834,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
823834
* append to objectName to access anything bound by request.
824835
*/
825836
val ComputedImports(importsPreamble, importsTrailer, accessPath) =
826-
importsCode(referencedNames.toSet)
837+
exitingTyper(importsCode(referencedNames.toSet))
827838

828839
/** The unmangled symbol name, but supplemented with line info. */
829840
def disambiguated(name: Name): String = name + " (in " + lineRep + ")"
@@ -835,7 +846,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
835846

836847
/** generate the source code for the object that computes this request */
837848
private object ObjectSourceCode extends CodeAssembler[MemberHandler] {
838-
def path = pathToTerm("$intp")
849+
def path = originalPath("$intp")
839850
def envLines = {
840851
if (!isReplPower) Nil // power mode only for now
841852
// $intp is not bound; punt, but include the line.
@@ -930,9 +941,6 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
930941
/** String representations of same. */
931942
lazy val typeOf = typeMap[String](tp => exitingTyper(tp.toString))
932943

933-
// lazy val definedTypes: Map[Name, Type] = {
934-
// typeNames map (x => x -> exitingTyper(resultSymbol.info.nonPrivateDecl(x).tpe)) toMap
935-
// }
936944
lazy val definedSymbols = (
937945
termNames.map(x => x -> applyToResultMember(x, x => x)) ++
938946
typeNames.map(x => x -> compilerTypeOf(x).typeSymbolDirect)
@@ -965,33 +973,28 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
965973
private var mostRecentWarnings: List[(global.Position, String)] = Nil
966974
def lastWarnings = mostRecentWarnings
967975

968-
private lazy val globalImporter = global.mkImporter(ru)
969-
private lazy val importer = ru.mkImporter(global)
970-
971-
private implicit def importFromRu(sym: ru.Symbol): global.Symbol =
972-
globalImporter importSymbol sym
973-
974-
private implicit def importToRu(sym: global.Symbol): ru.Symbol =
975-
importer importSymbol sym
976-
977-
private def jmirror = ru.rootMirror match {
978-
case j: ru.JavaMirror => j
976+
private lazy val importToGlobal = global mkImporter ru
977+
private lazy val importToRuntime = ru mkImporter global
978+
private lazy val javaMirror = ru.rootMirror match {
979+
case x: ru.JavaMirror => x
979980
case _ => null
980981
}
982+
private implicit def importFromRu(sym: ru.Symbol): Symbol = importToGlobal importSymbol sym
983+
private implicit def importToRu(sym: Symbol): ru.Symbol = importToRuntime importSymbol sym
984+
981985
def classOfTerm(id: String): Option[JClass] = symbolOfTerm(id) match {
982986
case NoSymbol => None
983-
case sym => Some(jmirror runtimeClass (importer importSymbol sym).asClass)
987+
case sym => Some(javaMirror runtimeClass importToRu(sym).asClass)
984988
}
985989

986990
def typeOfTerm(id: String): Type = symbolOfTerm(id).tpe
987991

988992
def valueOfTerm(id: String): Option[Any] = exitingTyper {
989993
def value() = {
990994
val sym0 = symbolOfTerm(id)
991-
val sym = (importer importSymbol sym0).asTerm
992-
val mirror = ru.runtimeMirror(classLoader)
993-
val module = mirror.reflectModule(sym.owner.companionSymbol.asModule).instance
994-
val module1 = mirror.reflect(module)
995+
val sym = (importToRuntime importSymbol sym0).asTerm
996+
val module = runtimeMirror.reflectModule(sym.owner.companionSymbol.asModule).instance
997+
val module1 = runtimeMirror.reflect(module)
995998
val invoker = module1.reflectField(sym)
996999

9971000
invoker.get
@@ -1000,29 +1003,20 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
10001003
try Some(value()) catch { case _: Exception => None }
10011004
}
10021005

1003-
def symbolOfPath(path: String): Symbol = {
1004-
if (path contains '.') {
1005-
tryTwice {
1006-
if (path endsWith "$") rmirror.staticModule(path.init)
1007-
else rmirror.staticModule(path) orElse rmirror.staticClass(path)
1008-
}
1009-
}
1010-
else {
1011-
if (path endsWith "$") symbolOfTerm(path.init)
1012-
else symbolOfIdent(path) orElse rumirror.staticClass(path)
1013-
}
1014-
}
1015-
1016-
def tryTwice(op: => Symbol): Symbol = {
1017-
exitingTyper(op) orElse exitingFlatten(op)
1018-
}
1006+
/** It's a bit of a shotgun approach, but for now we will gain in
1007+
* robustness. Try a symbol-producing operation at phase typer, and
1008+
* if that is NoSymbol, try again at phase flatten. I'll be able to
1009+
* lose this and run only from exitingTyper as soon as I figure out
1010+
* exactly where a flat name is sneaking in when calculating imports.
1011+
*/
1012+
def tryTwice(op: => Symbol): Symbol = exitingTyper(op) orElse exitingFlatten(op)
10191013

1020-
def signatureOf(sym: Symbol) = typerOp sig sym
1021-
// exitingTyper(sym.defString)
1022-
def symbolOfIdent(id: String): Symbol = symbolOfTerm(id) orElse symbolOfType(id)
1023-
def symbolOfType(id: String): Symbol = tryTwice(replScope lookup (id: TypeName))
1024-
def symbolOfTerm(id: String): Symbol = tryTwice(replScope lookup (id: TermName))
1025-
def symbolOfName(id: Name): Symbol = replScope lookup id
1014+
def signatureOf(sym: Symbol) = typerOp sig sym
1015+
def symbolOfPath(path: String): Symbol = exitingTyper(getPathIfDefined(path))
1016+
def symbolOfIdent(id: String): Symbol = symbolOfTerm(id) orElse symbolOfType(id)
1017+
def symbolOfType(id: String): Symbol = tryTwice(replScope lookup (id: TypeName))
1018+
def symbolOfTerm(id: String): Symbol = tryTwice(replScope lookup (id: TermName))
1019+
def symbolOfName(id: Name): Symbol = replScope lookup id
10261020

10271021
def runtimeClassAndTypeOfTerm(id: String): Option[(JClass, Type)] = {
10281022
classOfTerm(id) flatMap { clazz =>
@@ -1068,8 +1062,8 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
10681062
def typeOfExpression(expr: String, silent: Boolean = true): Type =
10691063
exprTyper.typeOfExpression(expr, silent)
10701064

1071-
protected def onlyTerms(xs: List[Name]) = xs collect { case x: TermName => x }
1072-
protected def onlyTypes(xs: List[Name]) = xs collect { case x: TypeName => x }
1065+
protected def onlyTerms(xs: List[Name]): List[TermName] = xs collect { case x: TermName => x }
1066+
protected def onlyTypes(xs: List[Name]): List[TypeName] = xs collect { case x: TypeName => x }
10731067

10741068
def definedTerms = onlyTerms(allDefinedNames) filterNot isInternalTermName
10751069
def definedTypes = onlyTypes(allDefinedNames)
@@ -1144,14 +1138,6 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
11441138
def allImplicits = allHandlers filter (_.definesImplicit) flatMap (_.definedNames)
11451139
def importHandlers = allHandlers collect { case x: ImportHandler => x }
11461140

1147-
def visibleTermNames: List[Name] = definedTerms ++ importedTerms distinct
1148-
1149-
/** Another entry point for tab-completion, ids in scope */
1150-
def unqualifiedIds = visibleTermNames map (_.toString) filterNot (_ contains "$") sorted
1151-
1152-
/** Parse the ScalaSig to find type aliases */
1153-
def aliasForType(path: String) = ByteCode.aliasForType(path)
1154-
11551141
def withoutUnwrapping(op: => Unit): Unit = {
11561142
val saved = isettings.unwrapStrings
11571143
isettings.unwrapStrings = false

src/compiler/scala/tools/nsc/interpreter/Imports.scala

Lines changed: 31 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -148,44 +148,42 @@ trait Imports {
148148
code append "object %s {\n".format(impname)
149149
trailingBraces append "}\n"
150150
accessPath append ("." + impname)
151-
152-
currentImps.clear
151+
currentImps.clear()
152+
}
153+
def maybeWrap(names: Name*) = if (names exists currentImps) addWrapper()
154+
def wrapBeforeAndAfter[T](op: => T): T = {
155+
addWrapper()
156+
try op finally addWrapper()
153157
}
154-
155-
addWrapper()
156158

157159
// loop through previous requests, adding imports for each one
158-
for (ReqAndHandler(req, handler) <- reqsToUse) {
159-
handler match {
160-
// If the user entered an import, then just use it; add an import wrapping
161-
// level if the import might conflict with some other import
162-
case x: ImportHandler =>
163-
if (x.importsWildcard || currentImps.exists(x.importedNames contains _))
164-
addWrapper()
165-
166-
code append (x.member + "\n")
167-
168-
// give wildcard imports a import wrapper all to their own
169-
if (x.importsWildcard) addWrapper()
170-
else currentImps ++= x.importedNames
171-
172-
// For other requests, import each defined name.
173-
// import them explicitly instead of with _, so that
174-
// ambiguity errors will not be generated. Also, quote
175-
// the name of the variable, so that we don't need to
176-
// handle quoting keywords separately.
177-
case x =>
178-
for (sym <- x.definedSymbols) {
179-
if (currentImps contains sym.name) addWrapper()
180-
181-
code append (s"import ${x.path}\n")
182-
currentImps += sym.name
183-
}
160+
wrapBeforeAndAfter {
161+
for (ReqAndHandler(req, handler) <- reqsToUse) {
162+
handler match {
163+
// If the user entered an import, then just use it; add an import wrapping
164+
// level if the import might conflict with some other import
165+
case x: ImportHandler if x.importsWildcard =>
166+
wrapBeforeAndAfter(code append (x.member + "\n"))
167+
case x: ImportHandler =>
168+
maybeWrap(x.importedNames: _*)
169+
code append (x.member + "\n")
170+
currentImps ++= x.importedNames
171+
172+
// For other requests, import each defined name.
173+
// import them explicitly instead of with _, so that
174+
// ambiguity errors will not be generated. Also, quote
175+
// the name of the variable, so that we don't need to
176+
// handle quoting keywords separately.
177+
case x =>
178+
for (sym <- x.definedSymbols) {
179+
maybeWrap(sym.name)
180+
code append s"import ${x.path}\n"
181+
currentImps += sym.name
182+
}
183+
}
184184
}
185185
}
186-
// add one extra wrapper, to prevent warnings in the common case of
187-
// redefining the value bound in the last interpreter request.
188-
addWrapper()
186+
189187
ComputedImports(code.toString, trailingBraces.toString, accessPath.toString)
190188
}
191189

src/compiler/scala/tools/nsc/interpreter/Power.scala

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re
145145
// First we create the ReplVals instance and bind it to $r
146146
intp.bind("$r", replVals)
147147
// Then we import everything from $r.
148-
intp interpret ("import " + intp.pathToTerm("$r") + "._")
148+
intp interpret ("import " + intp.originalPath("$r") + "._")
149149
// And whatever else there is to do.
150150
init.lines foreach (intp interpret _)
151151
}
@@ -406,20 +406,15 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re
406406
lazy val rutil: ReplUtilities = new ReplUtilities { }
407407
lazy val phased: Phased = new { val global: intp.global.type = intp.global } with Phased { }
408408

409-
def context(code: String) = analyzer.rootContext(unit(code))
410-
def source(code: String) = newSourceFile(code)
411-
def unit(code: String) = newCompilationUnit(code)
412-
def trees(code: String) = parse(code) getOrElse Nil
413-
def typeOf(id: String) = intp.typeOfExpression(id)
409+
def context(code: String) = analyzer.rootContext(unit(code))
410+
def source(code: String) = newSourceFile(code)
411+
def unit(code: String) = newCompilationUnit(code)
412+
def trees(code: String) = parse(code) getOrElse Nil
413+
def typeOf(id: String) = intp.typeOfExpression(id)
414414

415-
override def toString = """
415+
override def toString = s"""
416416
|** Power mode status **
417-
|Default phase: %s
418-
|Names: %s
419-
|Identifiers: %s
420-
""".stripMargin.format(
421-
phased.get,
422-
intp.allDefinedNames mkString " ",
423-
intp.unqualifiedIds mkString " "
424-
)
417+
|Default phase: ${phased.get}
418+
|Names: ${intp.unqualifiedIds mkString " "}
419+
""".stripMargin
425420
}

test/files/jvm/interpreter.check

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ defined class Term
357357
scala> def f(e: Exp) = e match { // non-exhaustive warning here
358358
case _:Fact => 3
359359
}
360-
<console>:16: warning: match is not exhaustive!
360+
<console>:18: warning: match is not exhaustive!
361361
missing combination Exp
362362
missing combination Term
363363

0 commit comments

Comments
 (0)