summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-10-28 14:27:21 -0700
committerPaul Phillips <paulp@improving.org>2012-11-09 16:48:19 -0700
commit8da7e37674d771e177445cc0c56eab7b7016c2f2 (patch)
tree4c66a68fc6ad0ea19a4c4240c3d11f9c8d0be6b1 /src
parent31ed2e8da246da07a3318c34cdfae2ca02740524 (diff)
downloadscala-8da7e37674d771e177445cc0c56eab7b7016c2f2.tar.gz
scala-8da7e37674d771e177445cc0c56eab7b7016c2f2.tar.bz2
scala-8da7e37674d771e177445cc0c56eab7b7016c2f2.zip
Cleanups to the previous repl commits.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ILoop.scala3
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/IMain.scala120
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Imports.scala64
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Power.scala25
4 files changed, 96 insertions, 116 deletions
diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
index cde8d81611..cf525d5cfc 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
@@ -329,7 +329,8 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
}
}
- private def pathToPhaseWrapper = intp.pathToTerm("$r") + ".phased.atCurrent"
+ private def pathToPhaseWrapper = intp.originalPath("$r") + ".phased.atCurrent"
+
private def phaseCommand(name: String): Result = {
val phased: Phased = power.phased
import phased.NoPhaseName
diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
index c5f9553634..0ef27ac96a 100644
--- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
@@ -177,6 +177,23 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
import global._
import definitions.{ ObjectClass, termMember, typeMember, dropNullaryMethod}
+ lazy val runtimeMirror = ru.runtimeMirror(classLoader)
+
+ private def noFatal(body: => Symbol): Symbol = try body catch { case _: FatalError => NoSymbol }
+
+ def getClassIfDefined(path: String) = (
+ noFatal(runtimeMirror staticClass path)
+ orElse noFatal(rootMirror staticClass path)
+ )
+ def getModuleIfDefined(path: String) = (
+ noFatal(runtimeMirror staticModule path)
+ orElse noFatal(rootMirror staticModule path)
+ )
+ def getPathIfDefined(path: String) = (
+ if (path endsWith "$") getModuleIfDefined(path.init)
+ else getClassIfDefined(path)
+ )
+
implicit class ReplTypeOps(tp: Type) {
def orElse(other: => Type): Type = if (tp ne NoType) tp else other
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
def shift[T](op: => T): T = exitingFlatten(op)
}
- def originalPath(name: Name): String = typerOp path name
- def originalPath(sym: Symbol): String = typerOp path sym
- def flatPath(sym: Symbol): String = flatOp shift sym.javaClassName
+ def originalPath(name: String): String = originalPath(name: TermName)
+ def originalPath(name: Name): String = typerOp path name
+ def originalPath(sym: Symbol): String = typerOp path sym
+ def flatPath(sym: Symbol): String = flatOp shift sym.javaClassName
// def translatePath(path: String) = symbolOfPath(path).fold(Option.empty[String])(flatPath)
def translatePath(path: String) = {
val sym = if (path endsWith "$") symbolOfTerm(path.init) else symbolOfIdent(path)
@@ -341,13 +359,8 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
// Set the current Java "context" class loader to this interpreter's class loader
def setContextClassLoader() = classLoader.setAsContext()
- def allDefinedNames = exitingTyper(replScope.toList.map(_.name).sorted)
- def pathToType(id: String): String = pathToName(newTypeName(id))
- def pathToTerm(id: String): String = pathToName(newTermName(id))
- def pathToName(name: Name): String = replScope lookup name match {
- case NoSymbol => name.toString
- case sym => exitingTyper(sym.fullName)
- }
+ def allDefinedNames: List[Name] = exitingTyper(replScope.toList.map(_.name).sorted)
+ def unqualifiedIds: List[String] = allDefinedNames map (_.decode) sorted
/** Most recent tree handled which wasn't wholly synthetic. */
private def mostRecentlyHandledTree: Option[Tree] = {
@@ -401,9 +414,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
}
exitingTyper {
req.imports foreach (sym => updateReplScope(sym, isDefined = false))
- req.defines foreach { sym =>
- updateReplScope(sym, isDefined = true)
- }
+ req.defines foreach (sym => updateReplScope(sym, isDefined = true))
}
}
@@ -746,7 +757,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
* following accessPath into the outer one.
*/
def resolvePathToSymbol(accessPath: String): Symbol = {
- val readRoot = getRequiredModule(readPath) // the outermost wrapper
+ val readRoot = getModuleIfDefined(readPath) // the outermost wrapper
(accessPath split '.').foldLeft(readRoot: Symbol) {
case (sym, "") => sym
case (sym, name) => exitingTyper(termMember(sym, name))
@@ -823,7 +834,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
* append to objectName to access anything bound by request.
*/
val ComputedImports(importsPreamble, importsTrailer, accessPath) =
- importsCode(referencedNames.toSet)
+ exitingTyper(importsCode(referencedNames.toSet))
/** The unmangled symbol name, but supplemented with line info. */
def disambiguated(name: Name): String = name + " (in " + lineRep + ")"
@@ -835,7 +846,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
/** generate the source code for the object that computes this request */
private object ObjectSourceCode extends CodeAssembler[MemberHandler] {
- def path = pathToTerm("$intp")
+ def path = originalPath("$intp")
def envLines = {
if (!isReplPower) Nil // power mode only for now
// $intp is not bound; punt, but include the line.
@@ -930,9 +941,6 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
/** String representations of same. */
lazy val typeOf = typeMap[String](tp => exitingTyper(tp.toString))
- // lazy val definedTypes: Map[Name, Type] = {
- // typeNames map (x => x -> exitingTyper(resultSymbol.info.nonPrivateDecl(x).tpe)) toMap
- // }
lazy val definedSymbols = (
termNames.map(x => x -> applyToResultMember(x, x => x)) ++
typeNames.map(x => x -> compilerTypeOf(x).typeSymbolDirect)
@@ -965,22 +973,18 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
private var mostRecentWarnings: List[(global.Position, String)] = Nil
def lastWarnings = mostRecentWarnings
- private lazy val globalImporter = global.mkImporter(ru)
- private lazy val importer = ru.mkImporter(global)
-
- private implicit def importFromRu(sym: ru.Symbol): global.Symbol =
- globalImporter importSymbol sym
-
- private implicit def importToRu(sym: global.Symbol): ru.Symbol =
- importer importSymbol sym
-
- private def jmirror = ru.rootMirror match {
- case j: ru.JavaMirror => j
+ private lazy val importToGlobal = global mkImporter ru
+ private lazy val importToRuntime = ru mkImporter global
+ private lazy val javaMirror = ru.rootMirror match {
+ case x: ru.JavaMirror => x
case _ => null
}
+ private implicit def importFromRu(sym: ru.Symbol): Symbol = importToGlobal importSymbol sym
+ private implicit def importToRu(sym: Symbol): ru.Symbol = importToRuntime importSymbol sym
+
def classOfTerm(id: String): Option[JClass] = symbolOfTerm(id) match {
case NoSymbol => None
- case sym => Some(jmirror runtimeClass (importer importSymbol sym).asClass)
+ case sym => Some(javaMirror runtimeClass importToRu(sym).asClass)
}
def typeOfTerm(id: String): Type = symbolOfTerm(id).tpe
@@ -988,10 +992,9 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
def valueOfTerm(id: String): Option[Any] = exitingTyper {
def value() = {
val sym0 = symbolOfTerm(id)
- val sym = (importer importSymbol sym0).asTerm
- val mirror = ru.runtimeMirror(classLoader)
- val module = mirror.reflectModule(sym.owner.companionSymbol.asModule).instance
- val module1 = mirror.reflect(module)
+ val sym = (importToRuntime importSymbol sym0).asTerm
+ val module = runtimeMirror.reflectModule(sym.owner.companionSymbol.asModule).instance
+ val module1 = runtimeMirror.reflect(module)
val invoker = module1.reflectField(sym)
invoker.get
@@ -1000,29 +1003,20 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
try Some(value()) catch { case _: Exception => None }
}
- def symbolOfPath(path: String): Symbol = {
- if (path contains '.') {
- tryTwice {
- if (path endsWith "$") rmirror.staticModule(path.init)
- else rmirror.staticModule(path) orElse rmirror.staticClass(path)
- }
- }
- else {
- if (path endsWith "$") symbolOfTerm(path.init)
- else symbolOfIdent(path) orElse rumirror.staticClass(path)
- }
- }
-
- def tryTwice(op: => Symbol): Symbol = {
- exitingTyper(op) orElse exitingFlatten(op)
- }
+ /** It's a bit of a shotgun approach, but for now we will gain in
+ * robustness. Try a symbol-producing operation at phase typer, and
+ * if that is NoSymbol, try again at phase flatten. I'll be able to
+ * lose this and run only from exitingTyper as soon as I figure out
+ * exactly where a flat name is sneaking in when calculating imports.
+ */
+ def tryTwice(op: => Symbol): Symbol = exitingTyper(op) orElse exitingFlatten(op)
- def signatureOf(sym: Symbol) = typerOp sig sym
- // exitingTyper(sym.defString)
- def symbolOfIdent(id: String): Symbol = symbolOfTerm(id) orElse symbolOfType(id)
- def symbolOfType(id: String): Symbol = tryTwice(replScope lookup (id: TypeName))
- def symbolOfTerm(id: String): Symbol = tryTwice(replScope lookup (id: TermName))
- def symbolOfName(id: Name): Symbol = replScope lookup id
+ def signatureOf(sym: Symbol) = typerOp sig sym
+ def symbolOfPath(path: String): Symbol = exitingTyper(getPathIfDefined(path))
+ def symbolOfIdent(id: String): Symbol = symbolOfTerm(id) orElse symbolOfType(id)
+ def symbolOfType(id: String): Symbol = tryTwice(replScope lookup (id: TypeName))
+ def symbolOfTerm(id: String): Symbol = tryTwice(replScope lookup (id: TermName))
+ def symbolOfName(id: Name): Symbol = replScope lookup id
def runtimeClassAndTypeOfTerm(id: String): Option[(JClass, Type)] = {
classOfTerm(id) flatMap { clazz =>
@@ -1068,8 +1062,8 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
def typeOfExpression(expr: String, silent: Boolean = true): Type =
exprTyper.typeOfExpression(expr, silent)
- protected def onlyTerms(xs: List[Name]) = xs collect { case x: TermName => x }
- protected def onlyTypes(xs: List[Name]) = xs collect { case x: TypeName => x }
+ protected def onlyTerms(xs: List[Name]): List[TermName] = xs collect { case x: TermName => x }
+ protected def onlyTypes(xs: List[Name]): List[TypeName] = xs collect { case x: TypeName => x }
def definedTerms = onlyTerms(allDefinedNames) filterNot isInternalTermName
def definedTypes = onlyTypes(allDefinedNames)
@@ -1144,14 +1138,6 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
def allImplicits = allHandlers filter (_.definesImplicit) flatMap (_.definedNames)
def importHandlers = allHandlers collect { case x: ImportHandler => x }
- def visibleTermNames: List[Name] = definedTerms ++ importedTerms distinct
-
- /** Another entry point for tab-completion, ids in scope */
- def unqualifiedIds = visibleTermNames map (_.toString) filterNot (_ contains "$") sorted
-
- /** Parse the ScalaSig to find type aliases */
- def aliasForType(path: String) = ByteCode.aliasForType(path)
-
def withoutUnwrapping(op: => Unit): Unit = {
val saved = isettings.unwrapStrings
isettings.unwrapStrings = false
diff --git a/src/compiler/scala/tools/nsc/interpreter/Imports.scala b/src/compiler/scala/tools/nsc/interpreter/Imports.scala
index 021f07002b..c5048ebfd8 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Imports.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/Imports.scala
@@ -148,44 +148,42 @@ trait Imports {
code append "object %s {\n".format(impname)
trailingBraces append "}\n"
accessPath append ("." + impname)
-
- currentImps.clear
+ currentImps.clear()
+ }
+ def maybeWrap(names: Name*) = if (names exists currentImps) addWrapper()
+ def wrapBeforeAndAfter[T](op: => T): T = {
+ addWrapper()
+ try op finally addWrapper()
}
-
- addWrapper()
// loop through previous requests, adding imports for each one
- for (ReqAndHandler(req, handler) <- reqsToUse) {
- handler match {
- // If the user entered an import, then just use it; add an import wrapping
- // level if the import might conflict with some other import
- case x: ImportHandler =>
- if (x.importsWildcard || currentImps.exists(x.importedNames contains _))
- addWrapper()
-
- code append (x.member + "\n")
-
- // give wildcard imports a import wrapper all to their own
- if (x.importsWildcard) addWrapper()
- else currentImps ++= x.importedNames
-
- // For other requests, import each defined name.
- // import them explicitly instead of with _, so that
- // ambiguity errors will not be generated. Also, quote
- // the name of the variable, so that we don't need to
- // handle quoting keywords separately.
- case x =>
- for (sym <- x.definedSymbols) {
- if (currentImps contains sym.name) addWrapper()
-
- code append (s"import ${x.path}\n")
- currentImps += sym.name
- }
+ wrapBeforeAndAfter {
+ for (ReqAndHandler(req, handler) <- reqsToUse) {
+ handler match {
+ // If the user entered an import, then just use it; add an import wrapping
+ // level if the import might conflict with some other import
+ case x: ImportHandler if x.importsWildcard =>
+ wrapBeforeAndAfter(code append (x.member + "\n"))
+ case x: ImportHandler =>
+ maybeWrap(x.importedNames: _*)
+ code append (x.member + "\n")
+ currentImps ++= x.importedNames
+
+ // For other requests, import each defined name.
+ // import them explicitly instead of with _, so that
+ // ambiguity errors will not be generated. Also, quote
+ // the name of the variable, so that we don't need to
+ // handle quoting keywords separately.
+ case x =>
+ for (sym <- x.definedSymbols) {
+ maybeWrap(sym.name)
+ code append s"import ${x.path}\n"
+ currentImps += sym.name
+ }
+ }
}
}
- // add one extra wrapper, to prevent warnings in the common case of
- // redefining the value bound in the last interpreter request.
- addWrapper()
+
ComputedImports(code.toString, trailingBraces.toString, accessPath.toString)
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/Power.scala b/src/compiler/scala/tools/nsc/interpreter/Power.scala
index 0af295c8af..ab0f1c0033 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Power.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/Power.scala
@@ -145,7 +145,7 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re
// First we create the ReplVals instance and bind it to $r
intp.bind("$r", replVals)
// Then we import everything from $r.
- intp interpret ("import " + intp.pathToTerm("$r") + "._")
+ intp interpret ("import " + intp.originalPath("$r") + "._")
// And whatever else there is to do.
init.lines foreach (intp interpret _)
}
@@ -406,20 +406,15 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re
lazy val rutil: ReplUtilities = new ReplUtilities { }
lazy val phased: Phased = new { val global: intp.global.type = intp.global } with Phased { }
- def context(code: String) = analyzer.rootContext(unit(code))
- def source(code: String) = newSourceFile(code)
- def unit(code: String) = newCompilationUnit(code)
- def trees(code: String) = parse(code) getOrElse Nil
- def typeOf(id: String) = intp.typeOfExpression(id)
+ def context(code: String) = analyzer.rootContext(unit(code))
+ def source(code: String) = newSourceFile(code)
+ def unit(code: String) = newCompilationUnit(code)
+ def trees(code: String) = parse(code) getOrElse Nil
+ def typeOf(id: String) = intp.typeOfExpression(id)
- override def toString = """
+ override def toString = s"""
|** Power mode status **
- |Default phase: %s
- |Names: %s
- |Identifiers: %s
- """.stripMargin.format(
- phased.get,
- intp.allDefinedNames mkString " ",
- intp.unqualifiedIds mkString " "
- )
+ |Default phase: ${phased.get}
+ |Names: ${intp.unqualifiedIds mkString " "}
+ """.stripMargin
}