summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2013-03-10 17:17:58 -0700
committerPaul Phillips <paulp@improving.org>2013-03-11 20:07:24 -0700
commit48cc8b47fcadaa187026ca0422178c9094e4b412 (patch)
tree32f3cce4559030e3088741390024c19eb5110bbe /src/compiler/scala/tools/nsc
parent1b6297f642877dcc7edcd704a5d3cf99a12e54b8 (diff)
downloadscala-48cc8b47fcadaa187026ca0422178c9094e4b412.tar.gz
scala-48cc8b47fcadaa187026ca0422178c9094e4b412.tar.bz2
scala-48cc8b47fcadaa187026ca0422178c9094e4b412.zip
Modularized the repl.
Following in the footsteps of scaladoc and interactive. The interpreter sources move into src/repl, and are given a separate build target. As with the others, at present they are still packaged into scala-compiler.jar. A summary of changes: - repl requires use of ReplGlobal (this was already implied) - macro code's repl-specific classloader hack pulled into overridable method and overridden in ReplGlobal - removed -Ygen-javap option to eliminate backend's dependency on javap - removed -Yrepl-debug option (can still be enabled with -Dscala.repl.debug) - pushed javap code into src/repl so javax.tools dependency can bee weakened to the repl only - removed some "show pickled" related code which hasn't worked right in a while and isn't the right way to do it anymore anyway. Will return to fix showPickled and provide it with some tests.
Diffstat (limited to 'src/compiler/scala/tools/nsc')
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala2
-rw-r--r--src/compiler/scala/tools/nsc/Interpreter.scala12
-rw-r--r--src/compiler/scala/tools/nsc/InterpreterLoop.scala12
-rw-r--r--src/compiler/scala/tools/nsc/MainGenericRunner.scala106
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala30
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala59
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala41
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ByteCode.scala42
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/CommandLine.scala13
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Completion.scala49
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/CompletionAware.scala53
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala85
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala63
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Delimited.scala41
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala99
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Formatting.scala35
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ILoop.scala749
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/IMain.scala1121
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ISettings.scala54
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Imports.scala181
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala49
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala352
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/JLineReader.scala68
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Logger.scala14
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/LoopCommands.scala86
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala219
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/NamedParam.scala45
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Naming.scala105
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Parsed.scala60
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Pasted.scala101
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Phased.scala143
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Power.scala326
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ReplConfig.scala49
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ReplDir.scala48
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ReplGlobal.scala56
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ReplProps.scala27
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ReplReporter.scala34
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ReplStrings.scala32
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ReplVals.scala82
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Results.scala22
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/RichClass.scala36
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala40
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/package.scala157
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/session/FileBackedHistory.scala84
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/session/History.scala22
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/session/JLineHistory.scala49
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/session/SimpleHistory.scala58
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/session/package.scala23
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala1
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala23
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TypeStrings.scala (renamed from src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala)18
-rw-r--r--src/compiler/scala/tools/nsc/util/AbstractFileClassLoader.scala (renamed from src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala)5
-rw-r--r--src/compiler/scala/tools/nsc/util/ShowPickled.scala4
53 files changed, 47 insertions, 5238 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index c0f611daa7..7ee3ee551f 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -999,7 +999,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
object typeDeconstruct extends {
val global: Global.this.type = Global.this
- } with interpreter.StructuredTypeStrings
+ } with typechecker.StructuredTypeStrings
/** There are common error conditions where when the exception hits
* here, currentRun.currentUnit is null. This robs us of the knowledge
diff --git a/src/compiler/scala/tools/nsc/Interpreter.scala b/src/compiler/scala/tools/nsc/Interpreter.scala
deleted file mode 100644
index 434f19f21b..0000000000
--- a/src/compiler/scala/tools/nsc/Interpreter.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-package scala.tools.nsc
-
-import interpreter._
-import java.io._
-
-/** A compatibility stub.
- */
-@deprecated("Use a class in the scala.tools.nsc.interpreter package.", "2.9.0")
-class Interpreter(settings: Settings, out: PrintWriter) extends IMain(settings, out) {
- def this(settings: Settings) = this(settings, new NewLinePrintWriter(new ConsoleWriter, true))
- def this() = this(new Settings())
-} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/InterpreterLoop.scala b/src/compiler/scala/tools/nsc/InterpreterLoop.scala
deleted file mode 100644
index a0be3f4fdb..0000000000
--- a/src/compiler/scala/tools/nsc/InterpreterLoop.scala
+++ /dev/null
@@ -1,12 +0,0 @@
-package scala.tools.nsc
-
-import interpreter._
-import java.io._
-
-/** A compatibility stub.
- */
-@deprecated("Use a class in the scala.tools.nsc.interpreter package.", "2.9.0")
-class InterpreterLoop(in0: Option[BufferedReader], out: PrintWriter) extends ILoop(in0, out) {
- def this(in0: BufferedReader, out: PrintWriter) = this(Some(in0), out)
- def this() = this(None, new PrintWriter(scala.Console.out))
-}
diff --git a/src/compiler/scala/tools/nsc/MainGenericRunner.scala b/src/compiler/scala/tools/nsc/MainGenericRunner.scala
deleted file mode 100644
index adb03ca374..0000000000
--- a/src/compiler/scala/tools/nsc/MainGenericRunner.scala
+++ /dev/null
@@ -1,106 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2006-2013 LAMP/EPFL
- * @author Lex Spoon
- */
-
-package scala.tools.nsc
-
-import io.{ File }
-import util.{ ClassPath, ScalaClassLoader }
-import Properties.{ versionString, copyrightString }
-import interpreter.{ ILoop }
-import GenericRunnerCommand._
-
-object JarRunner extends CommonRunner {
- def runJar(settings: GenericRunnerSettings, jarPath: String, arguments: Seq[String]): Either[Throwable, Boolean] = {
- val jar = new io.Jar(jarPath)
- val mainClass = jar.mainClass getOrElse sys.error("Cannot find main class for jar: " + jarPath)
- val jarURLs = ClassPath expandManifestPath jarPath
- val urls = if (jarURLs.isEmpty) File(jarPath).toURL +: settings.classpathURLs else jarURLs
-
- if (settings.Ylogcp.value) {
- Console.err.println("Running jar with these URLs as the classpath:")
- urls foreach println
- }
-
- runAndCatch(urls, mainClass, arguments)
- }
-}
-
-/** An object that runs Scala code. It has three possible
- * sources for the code to run: pre-compiled code, a script file,
- * or interactive entry.
- */
-class MainGenericRunner {
- def errorFn(ex: Throwable): Boolean = {
- ex.printStackTrace()
- false
- }
- def errorFn(str: String): Boolean = {
- Console.err println str
- false
- }
-
- def process(args: Array[String]): Boolean = {
- val command = new GenericRunnerCommand(args.toList, (x: String) => errorFn(x))
- import command.{ settings, howToRun, thingToRun }
- def sampleCompiler = new Global(settings) // def so its not created unless needed
-
- if (!command.ok) return errorFn("\n" + command.shortUsageMsg)
- else if (settings.version.value) return errorFn("Scala code runner %s -- %s".format(versionString, copyrightString))
- else if (command.shouldStopWithInfo) return errorFn(command getInfoMessage sampleCompiler)
-
- def isE = !settings.execute.isDefault
- def dashe = settings.execute.value
-
- def isI = !settings.loadfiles.isDefault
- def dashi = settings.loadfiles.value
-
- // Deadlocks on startup under -i unless we disable async.
- if (isI)
- settings.Yreplsync.value = true
-
- def combinedCode = {
- val files = if (isI) dashi map (file => File(file).slurp()) else Nil
- val str = if (isE) List(dashe) else Nil
-
- files ++ str mkString "\n\n"
- }
-
- def runTarget(): Either[Throwable, Boolean] = howToRun match {
- case AsObject =>
- ObjectRunner.runAndCatch(settings.classpathURLs, thingToRun, command.arguments)
- case AsScript =>
- ScriptRunner.runScriptAndCatch(settings, thingToRun, command.arguments)
- case AsJar =>
- JarRunner.runJar(settings, thingToRun, command.arguments)
- case Error =>
- Right(false)
- case _ =>
- // We start the repl when no arguments are given.
- Right(new ILoop process settings)
- }
-
- /** If -e and -i were both given, we want to execute the -e code after the
- * -i files have been included, so they are read into strings and prepended to
- * the code given in -e. The -i option is documented to only make sense
- * interactively so this is a pretty reasonable assumption.
- *
- * This all needs a rewrite though.
- */
- if (isE) {
- ScriptRunner.runCommand(settings, combinedCode, thingToRun +: command.arguments)
- }
- else runTarget() match {
- case Left(ex) => errorFn(ex)
- case Right(b) => b
- }
- }
-}
-
-object MainGenericRunner extends MainGenericRunner {
- def main(args: Array[String]) {
- if (!process(args))
- sys.exit(1)
- }
-}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
index 941ccd9a2d..c1cd3204e0 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
@@ -9,7 +9,6 @@ package backend.jvm
import java.io.{ DataOutputStream, FileOutputStream, OutputStream, File => JFile }
import scala.tools.nsc.io._
import scala.tools.nsc.util.ScalaClassLoader
-import scala.tools.util.{ Javap, JavapClass }
import java.util.jar.Attributes.Name
import scala.language.postfixOps
@@ -59,35 +58,6 @@ trait BytecodeWriters {
override def close() = writer.close()
}
- /** To be mixed-in with the BytecodeWriter that generates
- * the class file to be disassembled.
- */
- trait JavapBytecodeWriter extends BytecodeWriter {
- val baseDir = Directory(settings.Ygenjavap.value).createDirectory()
- val cl = ScalaClassLoader.appLoader
-
- def emitJavap(classFile: AbstractFile, javapFile: File) {
- val pw = javapFile.printWriter()
- try {
- val javap = new JavapClass(cl, pw) {
- override def findBytes(path: String): Array[Byte] = classFile.toByteArray
- }
- javap(Seq("-verbose", "-protected", classFile.name)) foreach (_.show())
- } finally pw.close()
- }
- abstract override def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol) {
- super.writeClass(label, jclassName, jclassBytes, sym)
-
- val classFile = getFile(sym, jclassName, ".class")
- val segments = jclassName.split("[./]")
- val javapFile = segments.foldLeft(baseDir: Path)(_ / _) changeExtension "javap" toFile;
- javapFile.parent.createDirectory()
-
- if (Javap.isAvailable(cl)) emitJavap(classFile, javapFile)
- else warning("No javap on classpath, skipping javap output.")
- }
- }
-
trait ClassBytecodeWriter extends BytecodeWriter {
def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol) {
val outfile = getFile(sym, jclassName, ".class")
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
index 388efb4625..4a3d1805d9 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
@@ -72,19 +72,10 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
new DirectToJarfileWriter(f.file)
case _ =>
- import scala.tools.util.Javap
- if (settings.Ygenjavap.isDefault) {
- if(settings.Ydumpclasses.isDefault)
- new ClassBytecodeWriter { }
- else
- new ClassBytecodeWriter with DumpBytecodeWriter { }
- }
- else if (Javap.isAvailable()) new ClassBytecodeWriter with JavapBytecodeWriter { }
- else {
- warning("No javap on classpath, skipping javap output.")
+ if (settings.Ydumpclasses.isDefault)
new ClassBytecodeWriter { }
- }
-
+ else
+ new ClassBytecodeWriter with DumpBytecodeWriter { }
// TODO A ScalapBytecodeWriter could take asm.util.Textifier as starting point.
// Three areas where javap ouput is less than ideal (e.g. when comparing versions of the same classfile) are:
// (a) unreadable pickle;
@@ -2519,7 +2510,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
if (nextBlock != whereto)
jcode goTo labels(whereto)
// SI-6102: Determine whether eliding this JUMP results in an empty range being covered by some EH.
- // If so, emit a NOP in place of the elided JUMP, to avoid "java.lang.ClassFormatError: Illegal exception table range"
+ // If so, emit a NOP in place of the elided JUMP, to avoid "java.lang.ClassFormatError: Illegal exception table range"
else if (newNormal.isJumpOnly(b) && m.exh.exists(eh => eh.covers(b))) {
debugwarn("Had a jump only block that wasn't collapsed")
emit(asm.Opcodes.NOP)
@@ -3084,7 +3075,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
assert(nonICode.hasNext, "empty block")
nonICode.next.isInstanceOf[JUMP]
}
-
+
/**
* Returns the list of instructions in a block that follow all ICode only instructions,
* where an ICode only instruction is one that won't make it to the JVM
@@ -3101,7 +3092,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
* Returns the target of a block that is "jump only" which is defined
* as being a block that consists only of 0 or more instructions that
* won't make it to the JVM followed by a JUMP.
- *
+ *
* @param b The basic block to examine
* @return Some(target) if b is a "jump only" block or None if it's not
*/
@@ -3150,12 +3141,12 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
def rephraseGotos(detour: mutable.Map[BasicBlock, BasicBlock]) {
def lookup(b: BasicBlock) = detour.getOrElse(b, b)
-
+
m.code.startBlock = lookup(m.code.startBlock)
-
+
for(eh <- m.exh)
eh.setStartBlock(lookup(eh.startBlock))
-
+
for (b <- m.blocks) {
def replaceLastInstruction(i: Instruction) = {
if (b.lastInstruction != i) {
@@ -3164,18 +3155,18 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
b.replaceInstruction(idxLast, i)
}
}
-
+
b.lastInstruction match {
case JUMP(whereto) =>
replaceLastInstruction(JUMP(lookup(whereto)))
case CJUMP(succ, fail, cond, kind) =>
replaceLastInstruction(CJUMP(lookup(succ), lookup(fail), cond, kind))
- case CZJUMP(succ, fail, cond, kind) =>
+ case CZJUMP(succ, fail, cond, kind) =>
replaceLastInstruction(CZJUMP(lookup(succ), lookup(fail), cond, kind))
case SWITCH(tags, labels) =>
val newLabels = (labels map lookup)
replaceLastInstruction(SWITCH(tags, newLabels))
- case _ => ()
+ case _ => ()
}
}
}
@@ -3203,7 +3194,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
// blocks
for (key <- detour.keySet) {
// we use the Robert Floyd's classic Tortoise and Hare algorithm
- @tailrec
+ @tailrec
def findDestination(tortoise: BasicBlock, hare: BasicBlock): BasicBlock = {
if (tortoise == hare)
// cycle detected, map key to key
@@ -3227,7 +3218,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
}
detour
}
-
+
val detour = computeDetour
rephraseGotos(detour)
@@ -3235,33 +3226,33 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
val (remappings, cycles) = detour partition {case (source, target) => source != target}
for ((source, target) <- remappings) {
debuglog(s"Will elide jump only block $source because it can be jumped around to get to $target.")
- if (m.startBlock == source) debugwarn("startBlock should have been re-wired by now")
+ if (m.startBlock == source) debugwarn("startBlock should have been re-wired by now")
}
val sources = remappings.keySet
val targets = remappings.values.toSet
val intersection = sources intersect targets
-
+
if (intersection.nonEmpty) debugwarn(s"contradiction: we seem to have some source and target overlap in blocks ${intersection.mkString}. Map was ${detour.mkString}")
-
+
for ((source, _) <- cycles) {
debuglog(s"Block $source is in a do-nothing infinite loop. Did the user write 'while(true){}'?")
}
}
}
-
+
/**
* Removes all blocks that are unreachable in a method using a standard reachability analysis.
*/
def elimUnreachableBlocks(m: IMethod) {
- assert(m.hasCode, "code-less method")
-
+ assert(m.hasCode, "code-less method")
+
// assume nothing is reachable until we prove it can be reached
val reachable = mutable.Set[BasicBlock]()
-
+
// the set of blocks that we know are reachable but have
// yet to be marked reachable, initially only the start block
val worklist = mutable.Set(m.startBlock)
-
+
while (worklist.nonEmpty) {
val block = worklist.head
worklist remove block
@@ -3271,7 +3262,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
// think are unreachable
worklist ++= (block.successors filterNot reachable)
}
-
+
// exception handlers need to be told not to cover unreachable blocks
// and exception handlers that no longer cover any blocks need to be
// removed entirely
@@ -3282,9 +3273,9 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
unusedExceptionHandlers += exh
}
}
-
+
// remove the unusued exception handler references
- if (settings.debug.value)
+ if (settings.debug.value)
for (exh <- unusedExceptionHandlers) debuglog(s"eliding exception handler $exh because it does not cover any reachable blocks")
m.exh = m.exh filterNot unusedExceptionHandlers
diff --git a/src/compiler/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala b/src/compiler/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala
deleted file mode 100644
index e66e4eff29..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/AbstractOrMissingHandler.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-class AbstractOrMissingHandler[T](onError: String => Unit, value: T) extends PartialFunction[Throwable, T] {
- def isDefinedAt(t: Throwable) = t match {
- case _: AbstractMethodError => true
- case _: NoSuchMethodError => true
- case _: MissingRequirementError => true
- case _: NoClassDefFoundError => true
- case _ => false
- }
- def apply(t: Throwable) = t match {
- case x @ (_: AbstractMethodError | _: NoSuchMethodError | _: NoClassDefFoundError) =>
- onError("""
- |Failed to initialize compiler: %s.
- |This is most often remedied by a full clean and recompile.
- |Otherwise, your classpath may continue bytecode compiled by
- |different and incompatible versions of scala.
- |""".stripMargin.format(x.getClass.getName split '.' last)
- )
- x.printStackTrace()
- value
- case x: MissingRequirementError =>
- onError("""
- |Failed to initialize compiler: %s not found.
- |** Note that as of 2.8 scala does not assume use of the java classpath.
- |** For the old behavior pass -usejavacp to scala, or if using a Settings
- |** object programatically, settings.usejavacp.value = true.""".stripMargin.format(x.req)
- )
- value
- }
-}
-
-object AbstractOrMissingHandler {
- def apply[T]() = new AbstractOrMissingHandler[T](Console println _, null.asInstanceOf[T])
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/ByteCode.scala b/src/compiler/scala/tools/nsc/interpreter/ByteCode.scala
deleted file mode 100644
index 48890a21c6..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/ByteCode.scala
+++ /dev/null
@@ -1,42 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import java.lang.reflect
-import util.ScalaClassLoader
-import ScalaClassLoader.appLoader
-import scala.reflect.NameTransformer._
-
-object ByteCode {
- /** Until I figure out why I can't get scalap onto the classpath such
- * that the compiler will bootstrap, we have to use reflection.
- */
- private lazy val DECODER: Option[AnyRef] =
- for (clazz <- appLoader.tryToLoadClass[AnyRef]("scala.tools.scalap.Decode$")) yield
- clazz.getField(MODULE_INSTANCE_NAME).get(null)
-
- private def decoderMethod(name: String, args: JClass*): Option[reflect.Method] = {
- for (decoder <- DECODER ; m <- Option(decoder.getClass.getMethod(name, args: _*))) yield m
- }
-
- private lazy val aliasMap = {
- for (module <- DECODER ; method <- decoderMethod("typeAliases", classOf[String])) yield
- method.invoke(module, _: String).asInstanceOf[Option[Map[String, String]]]
- }
-
- /** Scala sig bytes.
- */
- def scalaSigBytesForPath(path: String) =
- for {
- module <- DECODER
- method <- decoderMethod("scalaSigAnnotationBytes", classOf[String])
- names <- method.invoke(module, path).asInstanceOf[Option[Array[Byte]]]
- }
- yield names
-
- def aliasesForPackage(pkg: String) = aliasMap flatMap (_(pkg))
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/CommandLine.scala b/src/compiler/scala/tools/nsc/interpreter/CommandLine.scala
deleted file mode 100644
index 0ab92ab769..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/CommandLine.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Lex Spoon
- */
-
-package scala.tools.nsc
-package interpreter
-
-/** A command line for the interpreter.
- */
-class CommandLine(arguments: List[String], error: String => Unit) extends CompilerCommand(arguments, error) {
- override def cmdName = "scala"
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/Completion.scala b/src/compiler/scala/tools/nsc/interpreter/Completion.scala
deleted file mode 100644
index 84a5cb49ae..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/Completion.scala
+++ /dev/null
@@ -1,49 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import Completion._
-
-/** An implementation-agnostic completion interface which makes no
- * reference to the jline classes.
- */
-trait Completion {
- type ExecResult
- def resetVerbosity(): Unit
- def completer(): ScalaCompleter
-}
-object NoCompletion extends Completion {
- type ExecResult = Nothing
- def resetVerbosity() = ()
- def completer() = NullCompleter
-}
-
-object Completion {
- case class Candidates(cursor: Int, candidates: List[String]) { }
- val NoCandidates = Candidates(-1, Nil)
-
- object NullCompleter extends ScalaCompleter {
- def complete(buffer: String, cursor: Int): Candidates = NoCandidates
- }
- trait ScalaCompleter {
- def complete(buffer: String, cursor: Int): Candidates
- }
-
- def looksLikeInvocation(code: String) = (
- (code != null)
- && (code startsWith ".")
- && !(code == ".")
- && !(code startsWith "./")
- && !(code startsWith "..")
- )
- object Forwarder {
- def apply(forwardTo: () => Option[CompletionAware]): CompletionAware = new CompletionAware {
- def completions(verbosity: Int) = forwardTo() map (_ completions verbosity) getOrElse Nil
- override def follow(s: String) = forwardTo() flatMap (_ follow s)
- }
- }
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/CompletionAware.scala b/src/compiler/scala/tools/nsc/interpreter/CompletionAware.scala
deleted file mode 100644
index 3dd5d93390..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/CompletionAware.scala
+++ /dev/null
@@ -1,53 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-/** An interface for objects which are aware of tab completion and
- * will supply their own candidates and resolve their own paths.
- */
-trait CompletionAware {
- /** The complete list of unqualified Strings to which this
- * object will complete.
- */
- def completions(verbosity: Int): List[String]
-
- /** The next completor in the chain.
- */
- def follow(id: String): Option[CompletionAware] = None
-
- /** A list of useful information regarding a specific uniquely
- * identified completion. This is specifically written for the
- * following situation, but should be useful elsewhere too:
- *
- * x.y.z.methodName<tab>
- *
- * If "methodName" is among z's completions, and verbosity > 0
- * indicating tab has been pressed twice consecutively, then we
- * call alternativesFor and show a list of overloaded method
- * signatures.
- */
- def alternativesFor(id: String): List[String] = Nil
-
- /** Given string 'buf', return a list of all the strings
- * to which it can complete. This may involve delegating
- * to other CompletionAware objects.
- */
- def completionsFor(parsed: Parsed): List[String] = {
- import parsed.{ buffer, verbosity }
- val comps = completions(verbosity) filter (_ startsWith buffer)
- val exact = comps contains buffer
-
- val results =
- if (parsed.isEmpty) comps
- else if (parsed.isUnqualified && !parsed.isLastDelimiter)
- if (verbosity > 0 && exact) alternativesFor(buffer)
- else comps
- else follow(parsed.bufferHead) map (_ completionsFor parsed.bufferTail) getOrElse Nil
-
- results.sorted
- }
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala b/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala
deleted file mode 100644
index d24ad60974..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala
+++ /dev/null
@@ -1,85 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-/** This has a lot of duplication with other methods in Symbols and Types,
- * but repl completion utility is very sensitive to precise output. Best
- * thing would be to abstract an interface for how such things are printed,
- * as is also in progress with error messages.
- */
-trait CompletionOutput {
- val global: Global
-
- import global._
- import definitions.{ isTupleType, isFunctionType, isRepeatedParamType }
-
- /** Reducing fully qualified noise for some common packages.
- */
- val typeTransforms = List(
- "java.lang." -> "",
- "scala.collection.immutable." -> "immutable.",
- "scala.collection.mutable." -> "mutable.",
- "scala.collection.generic." -> "generic."
- )
-
- def quietString(tp: String): String =
- typeTransforms.foldLeft(tp) {
- case (str, (prefix, replacement)) =>
- if (str startsWith prefix) replacement + (str stripPrefix prefix)
- else str
- }
-
- class MethodSymbolOutput(method: Symbol) {
- val pkg = method.ownerChain find (_.isPackageClass) map (_.fullName) getOrElse ""
-
- def relativize(str: String): String = quietString(str stripPrefix (pkg + "."))
- def relativize(tp: Type): String = relativize(tp.dealiasWiden.toString)
-
- def braceList(tparams: List[String]) = if (tparams.isEmpty) "" else (tparams map relativize).mkString("[", ", ", "]")
- def parenList(params: List[Any]) = params.mkString("(", ", ", ")")
-
- def methodTypeToString(mt: MethodType) =
- (mt.paramss map paramsString mkString "") + ": " + relativize(mt.finalResultType)
-
- def typeToString(tp: Type): String = relativize(
- tp match {
- case x if isFunctionType(x) => functionString(x)
- case x if isTupleType(x) => tupleString(x)
- case x if isRepeatedParamType(x) => typeToString(x.typeArgs.head) + "*"
- case mt @ MethodType(_, _) => methodTypeToString(mt)
- case x => x.toString
- }
- )
-
- def tupleString(tp: Type) = parenList(tp.dealiasWiden.typeArgs map relativize)
- def functionString(tp: Type) = tp.dealiasWiden.typeArgs match {
- case List(t, r) => t + " => " + r
- case xs => parenList(xs.init) + " => " + xs.last
- }
-
- def tparamsString(tparams: List[Symbol]) = braceList(tparams map (_.defString))
- def paramsString(params: List[Symbol]) = {
- def paramNameString(sym: Symbol) = if (sym.isSynthetic) "" else sym.nameString + ": "
- def paramString(sym: Symbol) = paramNameString(sym) + typeToString(sym.info.dealiasWiden)
-
- val isImplicit = params.nonEmpty && params.head.isImplicit
- val strs = (params map paramString) match {
- case x :: xs if isImplicit => ("implicit " + x) :: xs
- case xs => xs
- }
- parenList(strs)
- }
-
- def methodString() =
- method.keyString + " " + method.nameString + (method.info.dealiasWiden match {
- case NullaryMethodType(resType) => ": " + typeToString(resType)
- case PolyType(tparams, resType) => tparamsString(tparams) + typeToString(resType)
- case mt @ MethodType(_, _) => methodTypeToString(mt)
- case x => x.toString
- })
- }
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala b/src/compiler/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala
deleted file mode 100644
index 48af261937..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala
+++ /dev/null
@@ -1,63 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import scala.tools.jline.console.{ ConsoleReader, CursorBuffer }
-
-trait ConsoleReaderHelper extends ConsoleReader {
- def terminal = getTerminal()
- def width = terminal.getWidth()
- def height = terminal.getHeight()
-
- def readOneKey(prompt: String): Int
- def eraseLine(): Unit
-
- private val marginSize = 3
- private def morePrompt = "--More--"
- private def emulateMore(): Int = {
- val key = readOneKey(morePrompt)
- try key match {
- case '\r' | '\n' => 1
- case 'q' => -1
- case _ => height - 1
- }
- finally {
- eraseLine()
- // TODO: still not quite managing to erase --More-- and get
- // back to a scala prompt without another keypress.
- if (key == 'q') {
- putString(getPrompt())
- redrawLine()
- flush()
- }
- }
- }
-
- override def printColumns(items: JCollection[_ <: CharSequence]): Unit =
- printColumns(items: List[String])
-
- def printColumns(items: List[String]): Unit = {
- if (items forall (_ == ""))
- return
-
- val longest = items map (_.length) max
- var linesLeft = if (isPaginationEnabled()) height - 1 else Int.MaxValue
- val columnSize = longest + marginSize
- val padded = items map ("%-" + columnSize + "s" format _)
- val groupSize = 1 max (width / columnSize) // make sure it doesn't divide to 0
-
- padded grouped groupSize foreach { xs =>
- println(xs.mkString)
- linesLeft -= 1
- if (linesLeft <= 0) {
- linesLeft = emulateMore()
- if (linesLeft < 0)
- return
- }
- }
- }
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/Delimited.scala b/src/compiler/scala/tools/nsc/interpreter/Delimited.scala
deleted file mode 100644
index e88a044931..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/Delimited.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import scala.tools.jline.console.completer.ArgumentCompleter.{ ArgumentDelimiter, ArgumentList }
-
-class JLineDelimiter extends ArgumentDelimiter {
- def toJLine(args: List[String], cursor: Int) = args match {
- case Nil => new ArgumentList(new Array[String](0), 0, 0, cursor)
- case xs => new ArgumentList(xs.toArray, xs.size - 1, xs.last.length, cursor)
- }
-
- def delimit(buffer: CharSequence, cursor: Int) = {
- val p = Parsed(buffer.toString, cursor)
- toJLine(p.args, cursor)
- }
- def isDelimiter(buffer: CharSequence, cursor: Int) = Parsed(buffer.toString, cursor).isDelimiter
-}
-
-trait Delimited {
- self: Parsed =>
-
- def delimited: Char => Boolean
- def escapeChars: List[Char] = List('\\')
-
- /** Break String into args based on delimiting function.
- */
- protected def toArgs(s: String): List[String] =
- if (s == "") Nil
- else (s indexWhere isDelimiterChar) match {
- case -1 => List(s)
- case idx => (s take idx) :: toArgs(s drop (idx + 1))
- }
-
- def isDelimiterChar(ch: Char) = delimited(ch)
- def isEscapeChar(ch: Char): Boolean = escapeChars contains ch
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala b/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala
deleted file mode 100644
index 9edd54b939..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala
+++ /dev/null
@@ -1,99 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import scala.tools.nsc.ast.parser.Tokens.EOF
-
-trait ExprTyper {
- val repl: IMain
-
- import repl._
- import global.{ reporter => _, Import => _, _ }
- import definitions._
- import syntaxAnalyzer.UnitParser
- import naming.freshInternalVarName
-
- object codeParser {
- val global: repl.global.type = repl.global
- def applyRule[T](code: String, rule: UnitParser => T): T = {
- reporter.reset()
- val scanner = newUnitParser(code)
- val result = rule(scanner)
-
- if (!reporter.hasErrors)
- scanner.accept(EOF)
-
- result
- }
- def stmts(code: String) = applyRule(code, _.templateStats())
- }
-
- /** Parse a line into a sequence of trees. Returns None if the input is incomplete. */
- def parse(line: String): Option[List[Tree]] = debugging(s"""parse("$line")""") {
- var isIncomplete = false
- reporter.withIncompleteHandler((_, _) => isIncomplete = true) {
- val trees = codeParser.stmts(line)
- if (reporter.hasErrors) Some(Nil)
- else if (isIncomplete) None
- else Some(trees)
- }
- }
-
- def symbolOfLine(code: String): Symbol = {
- def asExpr(): Symbol = {
- val name = freshInternalVarName()
- // Typing it with a lazy val would give us the right type, but runs
- // into compiler bugs with things like existentials, so we compile it
- // behind a def and strip the NullaryMethodType which wraps the expr.
- val line = "def " + name + " = " + code
-
- interpretSynthetic(line) match {
- case IR.Success =>
- val sym0 = symbolOfTerm(name)
- // drop NullaryMethodType
- sym0.cloneSymbol setInfo exitingTyper(sym0.info.finalResultType)
- case _ => NoSymbol
- }
- }
- def asDefn(): Symbol = {
- val old = repl.definedSymbolList.toSet
-
- interpretSynthetic(code) match {
- case IR.Success =>
- repl.definedSymbolList filterNot old match {
- case Nil => NoSymbol
- case sym :: Nil => sym
- case syms => NoSymbol.newOverloaded(NoPrefix, syms)
- }
- case _ => NoSymbol
- }
- }
- def asError(): Symbol = {
- interpretSynthetic(code)
- NoSymbol
- }
- beSilentDuring(asExpr()) orElse beSilentDuring(asDefn()) orElse asError()
- }
-
- private var typeOfExpressionDepth = 0
- def typeOfExpression(expr: String, silent: Boolean = true): Type = {
- if (typeOfExpressionDepth > 2) {
- repldbg("Terminating typeOfExpression recursion for expression: " + expr)
- return NoType
- }
- typeOfExpressionDepth += 1
- // Don't presently have a good way to suppress undesirable success output
- // while letting errors through, so it is first trying it silently: if there
- // is an error, and errors are desired, then it re-evaluates non-silently
- // to induce the error message.
- try beSilentDuring(symbolOfLine(expr).tpe) match {
- case NoType if !silent => symbolOfLine(expr).tpe // generate error
- case tpe => tpe
- }
- finally typeOfExpressionDepth -= 1
- }
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/Formatting.scala b/src/compiler/scala/tools/nsc/interpreter/Formatting.scala
deleted file mode 100644
index 43e653edfd..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/Formatting.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import util.stringFromWriter
-
-trait Formatting {
- def prompt: String
-
- def spaces(code: String): String = {
- /** Heuristic to avoid indenting and thereby corrupting """-strings and XML literals. */
- val tokens = List("\"\"\"", "</", "/>")
- val noIndent = (code contains "\n") && (tokens exists code.contains)
-
- if (noIndent) ""
- else prompt drop 1 map (_ => ' ')
- }
- /** Indent some code by the width of the scala> prompt.
- * This way, compiler error messages read better.
- */
- def indentCode(code: String) = {
- val indent = spaces(code)
- stringFromWriter(str =>
- for (line <- code.lines) {
- str print indent
- str print (line + "\n")
- str.flush()
- }
- )
- }
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
deleted file mode 100644
index 2ea255319d..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
+++ /dev/null
@@ -1,749 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Alexander Spoon
- */
-
-package scala.tools.nsc
-package interpreter
-
-import Predef.{ println => _, _ }
-import java.io.{ BufferedReader, FileReader }
-import session._
-import scala.annotation.tailrec
-import scala.util.Properties.{ jdkHome, javaVersion, versionString, javaVmName }
-import scala.tools.util.{ Javap }
-import util.{ ClassPath, Exceptional, stringFromWriter, stringFromStream }
-import io.{ File, Directory }
-import util.ScalaClassLoader
-import ScalaClassLoader._
-import scala.tools.util._
-import scala.language.{implicitConversions, existentials}
-import scala.reflect.classTag
-import scala.tools.reflect.StdRuntimeTags._
-import scala.concurrent.{ ExecutionContext, Await, Future, future }
-import ExecutionContext.Implicits._
-
-/** The Scala interactive shell. It provides a read-eval-print loop
- * around the Interpreter class.
- * After instantiation, clients should call the main() method.
- *
- * If no in0 is specified, then input will come from the console, and
- * the class will attempt to provide input editing feature such as
- * input history.
- *
- * @author Moez A. Abdel-Gawad
- * @author Lex Spoon
- * @version 1.2
- */
-class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
- extends AnyRef
- with LoopCommands
-{
- def this(in0: BufferedReader, out: JPrintWriter) = this(Some(in0), out)
- def this() = this(None, new JPrintWriter(Console.out, true))
-
- @deprecated("Use `intp` instead.", "2.9.0") def interpreter = intp
- @deprecated("Use `intp` instead.", "2.9.0") def interpreter_= (i: Interpreter): Unit = intp = i
-
- var in: InteractiveReader = _ // the input stream from which commands come
- var settings: Settings = _
- var intp: IMain = _
-
- private var globalFuture: Future[Boolean] = _
-
- /** Print a welcome message */
- def printWelcome() {
- echo(s"""
- |Welcome to Scala $versionString ($javaVmName, Java $javaVersion).
- |Type in expressions to have them evaluated.
- |Type :help for more information.""".trim.stripMargin
- )
- replinfo("[info] started at " + new java.util.Date)
- }
-
- protected def asyncMessage(msg: String) {
- if (isReplInfo || isReplPower)
- echoAndRefresh(msg)
- }
-
- override def echoCommandMessage(msg: String) {
- intp.reporter printUntruncatedMessage msg
- }
-
- lazy val power = new Power(intp, new StdReplVals(this))(tagOfStdReplVals, classTag[StdReplVals])
- def history = in.history
-
- // classpath entries added via :cp
- var addedClasspath: String = ""
-
- /** A reverse list of commands to replay if the user requests a :replay */
- var replayCommandStack: List[String] = Nil
-
- /** A list of commands to replay if the user requests a :replay */
- def replayCommands = replayCommandStack.reverse
-
- /** Record a command for replay should the user request a :replay */
- def addReplay(cmd: String) = replayCommandStack ::= cmd
-
- def savingReplayStack[T](body: => T): T = {
- val saved = replayCommandStack
- try body
- finally replayCommandStack = saved
- }
- def savingReader[T](body: => T): T = {
- val saved = in
- try body
- finally in = saved
- }
-
- /** Close the interpreter and set the var to null. */
- def closeInterpreter() {
- if (intp ne null) {
- intp.close()
- intp = null
- }
- }
-
- class ILoopInterpreter extends IMain(settings, out) {
- outer =>
-
- override lazy val formatting = new Formatting {
- def prompt = ILoop.this.prompt
- }
- override protected def parentClassLoader =
- settings.explicitParentLoader.getOrElse( classOf[ILoop].getClassLoader )
- }
-
- /** Create a new interpreter. */
- def createInterpreter() {
- if (addedClasspath != "")
- settings.classpath append addedClasspath
-
- intp = new ILoopInterpreter
- }
-
- /** print a friendly help message */
- def helpCommand(line: String): Result = {
- if (line == "") helpSummary()
- else uniqueCommand(line) match {
- case Some(lc) => echo("\n" + lc.help)
- case _ => ambiguousError(line)
- }
- }
- private def helpSummary() = {
- val usageWidth = commands map (_.usageMsg.length) max
- val formatStr = "%-" + usageWidth + "s %s"
-
- echo("All commands can be abbreviated, e.g. :he instead of :help.")
-
- commands foreach { cmd =>
- echo(formatStr.format(cmd.usageMsg, cmd.help))
- }
- }
- private def ambiguousError(cmd: String): Result = {
- matchingCommands(cmd) match {
- case Nil => echo(cmd + ": no such command. Type :help for help.")
- case xs => echo(cmd + " is ambiguous: did you mean " + xs.map(":" + _.name).mkString(" or ") + "?")
- }
- Result(keepRunning = true, None)
- }
- private def matchingCommands(cmd: String) = commands filter (_.name startsWith cmd)
- private def uniqueCommand(cmd: String): Option[LoopCommand] = {
- // this lets us add commands willy-nilly and only requires enough command to disambiguate
- matchingCommands(cmd) match {
- case List(x) => Some(x)
- // exact match OK even if otherwise appears ambiguous
- case xs => xs find (_.name == cmd)
- }
- }
-
- /** Show the history */
- lazy val historyCommand = new LoopCommand("history", "show the history (optional num is commands to show)") {
- override def usage = "[num]"
- def defaultLines = 20
-
- def apply(line: String): Result = {
- if (history eq NoHistory)
- return "No history available."
-
- val xs = words(line)
- val current = history.index
- val count = try xs.head.toInt catch { case _: Exception => defaultLines }
- val lines = history.asStrings takeRight count
- val offset = current - lines.size + 1
-
- for ((line, index) <- lines.zipWithIndex)
- echo("%3d %s".format(index + offset, line))
- }
- }
-
- // When you know you are most likely breaking into the middle
- // of a line being typed. This softens the blow.
- protected def echoAndRefresh(msg: String) = {
- echo("\n" + msg)
- in.redrawLine()
- }
- protected def echo(msg: String) = {
- out println msg
- out.flush()
- }
-
- /** Search the history */
- def searchHistory(_cmdline: String) {
- val cmdline = _cmdline.toLowerCase
- val offset = history.index - history.size + 1
-
- for ((line, index) <- history.asStrings.zipWithIndex ; if line.toLowerCase contains cmdline)
- echo("%d %s".format(index + offset, line))
- }
-
- private val currentPrompt = Properties.shellPromptString
-
- /** Prompt to print when awaiting input */
- def prompt = currentPrompt
-
- import LoopCommand.{ cmd, nullary }
-
- /** Standard commands **/
- lazy val standardCommands = List(
- cmd("cp", "<path>", "add a jar or directory to the classpath", addClasspath),
- cmd("help", "[command]", "print this summary or command-specific help", helpCommand),
- historyCommand,
- cmd("h?", "<string>", "search the history", searchHistory),
- cmd("imports", "[name name ...]", "show import history, identifying sources of names", importsCommand),
- cmd("implicits", "[-v]", "show the implicits in scope", intp.implicitsCommand),
- cmd("javap", "<path|class>", "disassemble a file or class name", javapCommand),
- cmd("load", "<path>", "load and interpret a Scala file", loadCommand),
- nullary("paste", "enter paste mode: all input up to ctrl-D compiled together", pasteCommand),
- nullary("power", "enable power user mode", powerCmd),
- nullary("quit", "exit the interpreter", () => Result(keepRunning = false, None)),
- nullary("replay", "reset execution and replay all previous commands", replay),
- nullary("reset", "reset the repl to its initial state, forgetting all session entries", resetCommand),
- shCommand,
- nullary("silent", "disable/enable automatic printing of results", verbosity),
- cmd("type", "[-v] <expr>", "display the type of an expression without evaluating it", typeCommand),
- nullary("warnings", "show the suppressed warnings from the most recent line which had any", warningsCommand)
- )
-
- /** Power user commands */
- lazy val powerCommands: List[LoopCommand] = List(
- cmd("phase", "<phase>", "set the implicit phase for power commands", phaseCommand)
- )
-
- private def importsCommand(line: String): Result = {
- val tokens = words(line)
- val handlers = intp.languageWildcardHandlers ++ intp.importHandlers
-
- handlers.filterNot(_.importedSymbols.isEmpty).zipWithIndex foreach {
- case (handler, idx) =>
- val (types, terms) = handler.importedSymbols partition (_.name.isTypeName)
- val imps = handler.implicitSymbols
- val found = tokens filter (handler importsSymbolNamed _)
- val typeMsg = if (types.isEmpty) "" else types.size + " types"
- val termMsg = if (terms.isEmpty) "" else terms.size + " terms"
- val implicitMsg = if (imps.isEmpty) "" else imps.size + " are implicit"
- val foundMsg = if (found.isEmpty) "" else found.mkString(" // imports: ", ", ", "")
- val statsMsg = List(typeMsg, termMsg, implicitMsg) filterNot (_ == "") mkString ("(", ", ", ")")
-
- intp.reporter.printMessage("%2d) %-30s %s%s".format(
- idx + 1,
- handler.importString,
- statsMsg,
- foundMsg
- ))
- }
- }
-
- private def findToolsJar() = {
- val jdkPath = Directory(jdkHome)
- val jar = jdkPath / "lib" / "tools.jar" toFile
-
- if (jar isFile)
- Some(jar)
- else if (jdkPath.isDirectory)
- jdkPath.deepFiles find (_.name == "tools.jar")
- else None
- }
- private def addToolsJarToLoader() = {
- val cl = findToolsJar() match {
- case Some(tools) => ScalaClassLoader.fromURLs(Seq(tools.toURL), intp.classLoader)
- case _ => intp.classLoader
- }
- if (Javap.isAvailable(cl)) {
- repldbg(":javap available.")
- cl
- }
- else {
- repldbg(":javap unavailable: no tools.jar at " + jdkHome)
- intp.classLoader
- }
- }
-
- protected def newJavap() =
- JavapClass(addToolsJarToLoader(), new IMain.ReplStrippingWriter(intp), Some(intp))
-
- private lazy val javap = substituteAndLog[Javap]("javap", NoJavap)(newJavap())
-
- // Still todo: modules.
- private def typeCommand(line0: String): Result = {
- line0.trim match {
- case "" => ":type [-v] <expression>"
- case s if s startsWith "-v " => intp.typeCommandInternal(s stripPrefix "-v " trim, verbose = true)
- case s => intp.typeCommandInternal(s, verbose = false)
- }
- }
-
- private def warningsCommand(): Result = {
- if (intp.lastWarnings.isEmpty)
- "Can't find any cached warnings."
- else
- intp.lastWarnings foreach { case (pos, msg) => intp.reporter.warning(pos, msg) }
- }
-
- private def javapCommand(line: String): Result = {
- if (javap == null)
- ":javap unavailable, no tools.jar at %s. Set JDK_HOME.".format(jdkHome)
- else if (line == "")
- ":javap [-lcsvp] [path1 path2 ...]"
- else
- javap(words(line)) foreach { res =>
- if (res.isError) return "Failed: " + res.value
- else res.show()
- }
- }
-
- private def pathToPhaseWrapper = intp.originalPath("$r") + ".phased.atCurrent"
-
- private def phaseCommand(name: String): Result = {
- val phased: Phased = power.phased
- import phased.NoPhaseName
-
- if (name == "clear") {
- phased.set(NoPhaseName)
- intp.clearExecutionWrapper()
- "Cleared active phase."
- }
- else if (name == "") phased.get match {
- case NoPhaseName => "Usage: :phase <expr> (e.g. typer, erasure.next, erasure+3)"
- case ph => "Active phase is '%s'. (To clear, :phase clear)".format(phased.get)
- }
- else {
- val what = phased.parse(name)
- if (what.isEmpty || !phased.set(what))
- "'" + name + "' does not appear to represent a valid phase."
- else {
- intp.setExecutionWrapper(pathToPhaseWrapper)
- val activeMessage =
- if (what.toString.length == name.length) "" + what
- else "%s (%s)".format(what, name)
-
- "Active phase is now: " + activeMessage
- }
- }
- }
-
- /** Available commands */
- def commands: List[LoopCommand] = standardCommands ++ (
- if (isReplPower) powerCommands else Nil
- )
-
- val replayQuestionMessage =
- """|That entry seems to have slain the compiler. Shall I replay
- |your session? I can re-run each line except the last one.
- |[y/n]
- """.trim.stripMargin
-
- private val crashRecovery: PartialFunction[Throwable, Boolean] = {
- case ex: Throwable =>
- echo(intp.global.throwableAsString(ex))
-
- ex match {
- case _: NoSuchMethodError | _: NoClassDefFoundError =>
- echo("\nUnrecoverable error.")
- throw ex
- case _ =>
- def fn(): Boolean =
- try in.readYesOrNo(replayQuestionMessage, { echo("\nYou must enter y or n.") ; fn() })
- catch { case _: RuntimeException => false }
-
- if (fn()) replay()
- else echo("\nAbandoning crashed session.")
- }
- true
- }
-
- // return false if repl should exit
- def processLine(line: String): Boolean = {
- import scala.concurrent.duration._
- Await.ready(globalFuture, 60.seconds)
-
- (line ne null) && (command(line) match {
- case Result(false, _) => false
- case Result(_, Some(line)) => addReplay(line) ; true
- case _ => true
- })
- }
-
- private def readOneLine() = {
- out.flush()
- in readLine prompt
- }
-
- /** The main read-eval-print loop for the repl. It calls
- * command() for each line of input, and stops when
- * command() returns false.
- */
- @tailrec final def loop() {
- if ( try processLine(readOneLine()) catch crashRecovery )
- loop()
- }
-
- /** interpret all lines from a specified file */
- def interpretAllFrom(file: File) {
- savingReader {
- savingReplayStack {
- file applyReader { reader =>
- in = SimpleReader(reader, out, interactive = false)
- echo("Loading " + file + "...")
- loop()
- }
- }
- }
- }
-
- /** create a new interpreter and replay the given commands */
- def replay() {
- reset()
- if (replayCommandStack.isEmpty)
- echo("Nothing to replay.")
- else for (cmd <- replayCommands) {
- echo("Replaying: " + cmd) // flush because maybe cmd will have its own output
- command(cmd)
- echo("")
- }
- }
- def resetCommand() {
- echo("Resetting interpreter state.")
- if (replayCommandStack.nonEmpty) {
- echo("Forgetting this session history:\n")
- replayCommands foreach echo
- echo("")
- replayCommandStack = Nil
- }
- if (intp.namedDefinedTerms.nonEmpty)
- echo("Forgetting all expression results and named terms: " + intp.namedDefinedTerms.mkString(", "))
- if (intp.definedTypes.nonEmpty)
- echo("Forgetting defined types: " + intp.definedTypes.mkString(", "))
-
- reset()
- }
- def reset() {
- intp.reset()
- unleashAndSetPhase()
- }
-
- /** fork a shell and run a command */
- lazy val shCommand = new LoopCommand("sh", "run a shell command (result is implicitly => List[String])") {
- override def usage = "<command line>"
- def apply(line: String): Result = line match {
- case "" => showUsage()
- case _ =>
- val toRun = classOf[ProcessResult].getName + "(" + string2codeQuoted(line) + ")"
- intp interpret toRun
- ()
- }
- }
-
- def withFile(filename: String)(action: File => Unit) {
- val f = File(filename)
-
- if (f.exists) action(f)
- else echo("That file does not exist")
- }
-
- def loadCommand(arg: String) = {
- var shouldReplay: Option[String] = None
- withFile(arg)(f => {
- interpretAllFrom(f)
- shouldReplay = Some(":load " + arg)
- })
- Result(keepRunning = true, shouldReplay)
- }
-
- def addClasspath(arg: String): Unit = {
- val f = File(arg).normalize
- if (f.exists) {
- addedClasspath = ClassPath.join(addedClasspath, f.path)
- val totalClasspath = ClassPath.join(settings.classpath.value, addedClasspath)
- echo("Added '%s'. Your new classpath is:\n\"%s\"".format(f.path, totalClasspath))
- replay()
- }
- else echo("The path '" + f + "' doesn't seem to exist.")
- }
-
- def powerCmd(): Result = {
- if (isReplPower) "Already in power mode."
- else enablePowerMode(isDuringInit = false)
- }
- def enablePowerMode(isDuringInit: Boolean) = {
- replProps.power setValue true
- unleashAndSetPhase()
- asyncEcho(isDuringInit, power.banner)
- }
- private def unleashAndSetPhase() {
- if (isReplPower) {
- power.unleash()
- // Set the phase to "typer"
- intp beSilentDuring phaseCommand("typer")
- }
- }
-
- def asyncEcho(async: Boolean, msg: => String) {
- if (async) asyncMessage(msg)
- else echo(msg)
- }
-
- def verbosity() = {
- val old = intp.printResults
- intp.printResults = !old
- echo("Switched " + (if (old) "off" else "on") + " result printing.")
- }
-
- /** Run one command submitted by the user. Two values are returned:
- * (1) whether to keep running, (2) the line to record for replay,
- * if any. */
- def command(line: String): Result = {
- if (line startsWith ":") {
- val cmd = line.tail takeWhile (x => !x.isWhitespace)
- uniqueCommand(cmd) match {
- case Some(lc) => lc(line.tail stripPrefix cmd dropWhile (_.isWhitespace))
- case _ => ambiguousError(cmd)
- }
- }
- else if (intp.global == null) Result(keepRunning = false, None) // Notice failure to create compiler
- else Result(keepRunning = true, interpretStartingWith(line))
- }
-
- private def readWhile(cond: String => Boolean) = {
- Iterator continually in.readLine("") takeWhile (x => x != null && cond(x))
- }
-
- def pasteCommand(): Result = {
- echo("// Entering paste mode (ctrl-D to finish)\n")
- val code = readWhile(_ => true) mkString "\n"
- echo("\n// Exiting paste mode, now interpreting.\n")
- intp interpret code
- ()
- }
-
- private object paste extends Pasted {
- val ContinueString = " | "
- val PromptString = "scala> "
-
- def interpret(line: String): Unit = {
- echo(line.trim)
- intp interpret line
- echo("")
- }
-
- def transcript(start: String) = {
- echo("\n// Detected repl transcript paste: ctrl-D to finish.\n")
- apply(Iterator(start) ++ readWhile(_.trim != PromptString.trim))
- }
- }
- import paste.{ ContinueString, PromptString }
-
- /** Interpret expressions starting with the first line.
- * Read lines until a complete compilation unit is available
- * or until a syntax error has been seen. If a full unit is
- * read, go ahead and interpret it. Return the full string
- * to be recorded for replay, if any.
- */
- def interpretStartingWith(code: String): Option[String] = {
- // signal completion non-completion input has been received
- in.completion.resetVerbosity()
-
- def reallyInterpret = {
- val reallyResult = intp.interpret(code)
- (reallyResult, reallyResult match {
- case IR.Error => None
- case IR.Success => Some(code)
- case IR.Incomplete =>
- if (in.interactive && code.endsWith("\n\n")) {
- echo("You typed two blank lines. Starting a new command.")
- None
- }
- else in.readLine(ContinueString) match {
- case null =>
- // we know compilation is going to fail since we're at EOF and the
- // parser thinks the input is still incomplete, but since this is
- // a file being read non-interactively we want to fail. So we send
- // it straight to the compiler for the nice error message.
- intp.compileString(code)
- None
-
- case line => interpretStartingWith(code + "\n" + line)
- }
- })
- }
-
- /** Here we place ourselves between the user and the interpreter and examine
- * the input they are ostensibly submitting. We intervene in several cases:
- *
- * 1) If the line starts with "scala> " it is assumed to be an interpreter paste.
- * 2) If the line starts with "." (but not ".." or "./") it is treated as an invocation
- * on the previous result.
- * 3) If the Completion object's execute returns Some(_), we inject that value
- * and avoid the interpreter, as it's likely not valid scala code.
- */
- if (code == "") None
- else if (!paste.running && code.trim.startsWith(PromptString)) {
- paste.transcript(code)
- None
- }
- else if (Completion.looksLikeInvocation(code) && intp.mostRecentVar != "") {
- interpretStartingWith(intp.mostRecentVar + code)
- }
- else if (code.trim startsWith "//") {
- // line comment, do nothing
- None
- }
- else
- reallyInterpret._2
- }
-
- // runs :load `file` on any files passed via -i
- def loadFiles(settings: Settings) = settings match {
- case settings: GenericRunnerSettings =>
- for (filename <- settings.loadfiles.value) {
- val cmd = ":load " + filename
- command(cmd)
- addReplay(cmd)
- echo("")
- }
- case _ =>
- }
-
- /** Tries to create a JLineReader, falling back to SimpleReader:
- * unless settings or properties are such that it should start
- * with SimpleReader.
- */
- def chooseReader(settings: Settings): InteractiveReader = {
- if (settings.Xnojline.value || Properties.isEmacsShell)
- SimpleReader()
- else try new JLineReader(
- if (settings.noCompletion.value) NoCompletion
- else new JLineCompletion(intp)
- )
- catch {
- case ex @ (_: Exception | _: NoClassDefFoundError) =>
- echo("Failed to created JLineReader: " + ex + "\nFalling back to SimpleReader.")
- SimpleReader()
- }
- }
-
- private def loopPostInit() {
- in match {
- case x: JLineReader => x.consoleReader.postInit
- case _ =>
- }
- // Bind intp somewhere out of the regular namespace where
- // we can get at it in generated code.
- intp.quietBind(NamedParam[IMain]("$intp", intp)(tagOfIMain, classTag[IMain]))
- // Auto-run code via some setting.
- ( replProps.replAutorunCode.option
- flatMap (f => io.File(f).safeSlurp())
- foreach (intp quietRun _)
- )
- // classloader and power mode setup
- intp.setContextClassLoader()
- if (isReplPower) {
- replProps.power setValue true
- unleashAndSetPhase()
- asyncMessage(power.banner)
- }
- }
- def process(settings: Settings): Boolean = savingContextLoader {
- this.settings = settings
- createInterpreter()
-
- // sets in to some kind of reader depending on environmental cues
- in = in0.fold(chooseReader(settings))(r => SimpleReader(r, out, interactive = true))
- globalFuture = future {
- intp.initializeSynchronous()
- loopPostInit()
- loadFiles(settings)
- !intp.reporter.hasErrors
- }
- printWelcome()
-
- try loop()
- catch AbstractOrMissingHandler()
- finally closeInterpreter()
-
- true
- }
-
- @deprecated("Use `process` instead", "2.9.0")
- def main(settings: Settings): Unit = process(settings) //used by sbt
-}
-
-object ILoop {
- implicit def loopToInterpreter(repl: ILoop): IMain = repl.intp
-
- // Designed primarily for use by test code: take a String with a
- // bunch of code, and prints out a transcript of what it would look
- // like if you'd just typed it into the repl.
- def runForTranscript(code: String, settings: Settings): String = {
- import java.io.{ BufferedReader, StringReader, OutputStreamWriter }
-
- stringFromStream { ostream =>
- Console.withOut(ostream) {
- val output = new JPrintWriter(new OutputStreamWriter(ostream), true) {
- override def write(str: String) = {
- // completely skip continuation lines
- if (str forall (ch => ch.isWhitespace || ch == '|')) ()
- // print a newline on empty scala prompts
- else if ((str contains '\n') && (str.trim == "scala> ")) super.write("\n")
- else super.write(str)
- }
- }
- val input = new BufferedReader(new StringReader(code)) {
- override def readLine(): String = {
- val s = super.readLine()
- // helping out by printing the line being interpreted.
- if (s != null)
- output.println(s)
- s
- }
- }
- val repl = new ILoop(input, output)
- if (settings.classpath.isDefault)
- settings.classpath.value = sys.props("java.class.path")
-
- repl process settings
- }
- }
- }
-
- /** Creates an interpreter loop with default settings and feeds
- * the given code to it as input.
- */
- def run(code: String, sets: Settings = new Settings): String = {
- import java.io.{ BufferedReader, StringReader, OutputStreamWriter }
-
- stringFromStream { ostream =>
- Console.withOut(ostream) {
- val input = new BufferedReader(new StringReader(code))
- val output = new JPrintWriter(new OutputStreamWriter(ostream), true)
- val repl = new ILoop(input, output)
-
- if (sets.classpath.isDefault)
- sets.classpath.value = sys.props("java.class.path")
-
- repl process sets
- }
- }
- }
- def run(lines: List[String]): String = run(lines map (_ + "\n") mkString)
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
deleted file mode 100644
index c54b01dbb0..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala
+++ /dev/null
@@ -1,1121 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Martin Odersky
- */
-
-package scala.tools.nsc
-package interpreter
-
-import Predef.{ println => _, _ }
-import util.stringFromWriter
-import scala.reflect.internal.util._
-import java.net.URL
-import scala.sys.BooleanProp
-import scala.tools.nsc.io.AbstractFile
-import reporters._
-import scala.tools.util.PathResolver
-import scala.tools.nsc.util.ScalaClassLoader
-import ScalaClassLoader.URLClassLoader
-import scala.tools.nsc.util.Exceptional.unwrap
-import scala.collection.{ mutable, immutable }
-import IMain._
-import java.util.concurrent.Future
-import scala.reflect.runtime.{ universe => ru }
-import scala.reflect.{ ClassTag, classTag }
-import scala.tools.reflect.StdRuntimeTags._
-
-/** An interpreter for Scala code.
- *
- * The main public entry points are compile(), interpret(), and bind().
- * The compile() method loads a complete Scala file. The interpret() method
- * executes one line of Scala code at the request of the user. The bind()
- * method binds an object to a variable that can then be used by later
- * interpreted code.
- *
- * The overall approach is based on compiling the requested code and then
- * using a Java classloader and Java reflection to run the code
- * and access its results.
- *
- * In more detail, a single compiler instance is used
- * to accumulate all successfully compiled or interpreted Scala code. To
- * "interpret" a line of code, the compiler generates a fresh object that
- * includes the line of code and which has public member(s) to export
- * all variables defined by that code. To extract the result of an
- * interpreted line to show the user, a second "result object" is created
- * which imports the variables exported by the above object and then
- * exports members called "$eval" and "$print". To accomodate user expressions
- * that read from variables or methods defined in previous statements, "import"
- * statements are used.
- *
- * This interpreter shares the strengths and weaknesses of using the
- * full compiler-to-Java. The main strength is that interpreted code
- * behaves exactly as does compiled code, including running at full speed.
- * The main weakness is that redefining classes and methods is not handled
- * properly, because rebinding at the Java level is technically difficult.
- *
- * @author Moez A. Abdel-Gawad
- * @author Lex Spoon
- */
-class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends Imports {
- imain =>
-
- object replOutput extends ReplOutput(settings.Yreploutdir) { }
-
- @deprecated("Use replOutput.dir instead", "2.11.0")
- def virtualDirectory = replOutput.dir
- // Used in a test case.
- def showDirectory() = replOutput.show(out)
-
- private[nsc] var printResults = true // whether to print result lines
- private[nsc] var totalSilence = false // whether to print anything
- private var _initializeComplete = false // compiler is initialized
- private var _isInitialized: Future[Boolean] = null // set up initialization future
- private var bindExceptions = true // whether to bind the lastException variable
- private var _executionWrapper = "" // code to be wrapped around all lines
-
- /** We're going to go to some trouble to initialize the compiler asynchronously.
- * It's critical that nothing call into it until it's been initialized or we will
- * run into unrecoverable issues, but the perceived repl startup time goes
- * through the roof if we wait for it. So we initialize it with a future and
- * use a lazy val to ensure that any attempt to use the compiler object waits
- * on the future.
- */
- private var _classLoader: AbstractFileClassLoader = null // active classloader
- private val _compiler: Global = newCompiler(settings, reporter) // our private compiler
-
- def compilerClasspath: Seq[URL] = (
- if (isInitializeComplete) global.classPath.asURLs
- else new PathResolver(settings).result.asURLs // the compiler's classpath
- )
- def settings = initialSettings
- // Run the code body with the given boolean settings flipped to true.
- def withoutWarnings[T](body: => T): T = beQuietDuring {
- val saved = settings.nowarn.value
- if (!saved)
- settings.nowarn.value = true
-
- try body
- finally if (!saved) settings.nowarn.value = false
- }
-
- /** construct an interpreter that reports to Console */
- def this(settings: Settings) = this(settings, new NewLinePrintWriter(new ConsoleWriter, true))
- def this() = this(new Settings())
-
- lazy val formatting: Formatting = new Formatting {
- val prompt = Properties.shellPromptString
- }
- lazy val reporter: ReplReporter = new ReplReporter(this)
-
- import formatting._
- import reporter.{ printMessage, withoutTruncating }
-
- // This exists mostly because using the reporter too early leads to deadlock.
- private def echo(msg: String) { Console println msg }
- private def _initSources = List(new BatchSourceFile("<init>", "class $repl_$init { }"))
- private def _initialize() = {
- try {
- // todo. if this crashes, REPL will hang
- new _compiler.Run() compileSources _initSources
- _initializeComplete = true
- true
- }
- catch AbstractOrMissingHandler()
- }
- private def tquoted(s: String) = "\"\"\"" + s + "\"\"\""
- private val logScope = scala.sys.props contains "scala.repl.scope"
- private def scopelog(msg: String) = if (logScope) Console.err.println(msg)
-
- // argument is a thunk to execute after init is done
- def initialize(postInitSignal: => Unit) {
- synchronized {
- if (_isInitialized == null) {
- _isInitialized = io.spawn {
- try _initialize()
- finally postInitSignal
- }
- }
- }
- }
- def initializeSynchronous(): Unit = {
- if (!isInitializeComplete) {
- _initialize()
- assert(global != null, global)
- }
- }
- def isInitializeComplete = _initializeComplete
-
- /** the public, go through the future compiler */
- lazy val global: Global = {
- if (isInitializeComplete) _compiler
- else {
- // If init hasn't been called yet you're on your own.
- if (_isInitialized == null) {
- repldbg("Warning: compiler accessed before init set up. Assuming no postInit code.")
- initialize(())
- }
- // blocks until it is ; false means catastrophic failure
- if (_isInitialized.get()) _compiler
- else null
- }
- }
-
- import global._
- import definitions.{ ObjectClass, termMember, 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)
- )
-
- implicit class ReplTypeOps(tp: Type) {
- def andAlso(fn: Type => Type): Type = if (tp eq NoType) tp else fn(tp)
- }
-
- // TODO: If we try to make naming a lazy val, we run into big time
- // scalac unhappiness with what look like cycles. It has not been easy to
- // reduce, but name resolution clearly takes different paths.
- object naming extends {
- val global: imain.global.type = imain.global
- } with Naming {
- // make sure we don't overwrite their unwisely named res3 etc.
- def freshUserTermName(): TermName = {
- val name = newTermName(freshUserVarName())
- if (replScope containsName name) freshUserTermName()
- else name
- }
- def isInternalTermName(name: Name) = isInternalVarName("" + name)
- }
- import naming._
-
- object deconstruct extends {
- val global: imain.global.type = imain.global
- } with StructuredTypeStrings
-
- lazy val memberHandlers = new {
- val intp: imain.type = imain
- } with MemberHandlers
- import memberHandlers._
-
- /** Temporarily be quiet */
- def beQuietDuring[T](body: => T): T = {
- val saved = printResults
- printResults = false
- try body
- finally printResults = saved
- }
- def beSilentDuring[T](operation: => T): T = {
- val saved = totalSilence
- totalSilence = true
- try operation
- finally totalSilence = saved
- }
-
- def quietRun[T](code: String) = beQuietDuring(interpret(code))
-
- /** takes AnyRef because it may be binding a Throwable or an Exceptional */
- private def withLastExceptionLock[T](body: => T, alt: => T): T = {
- assert(bindExceptions, "withLastExceptionLock called incorrectly.")
- bindExceptions = false
-
- try beQuietDuring(body)
- catch logAndDiscard("withLastExceptionLock", alt)
- finally bindExceptions = true
- }
-
- def executionWrapper = _executionWrapper
- def setExecutionWrapper(code: String) = _executionWrapper = code
- def clearExecutionWrapper() = _executionWrapper = ""
-
- /** interpreter settings */
- lazy val isettings = new ISettings(this)
-
- /** Instantiate a compiler. Overridable. */
- protected def newCompiler(settings: Settings, reporter: Reporter): ReplGlobal = {
- settings.outputDirs setSingleOutput replOutput.dir
- settings.exposeEmptyPackage.value = true
- new Global(settings, reporter) with ReplGlobal { override def toString: String = "<global>" }
- }
-
- /** Parent classloader. Overridable. */
- protected def parentClassLoader: ClassLoader =
- settings.explicitParentLoader.getOrElse( this.getClass.getClassLoader() )
-
- /* A single class loader is used for all commands interpreted by this Interpreter.
- It would also be possible to create a new class loader for each command
- to interpret. The advantages of the current approach are:
-
- - Expressions are only evaluated one time. This is especially
- significant for I/O, e.g. "val x = Console.readLine"
-
- The main disadvantage is:
-
- - Objects, classes, and methods cannot be rebound. Instead, definitions
- shadow the old ones, and old code objects refer to the old
- definitions.
- */
- def resetClassLoader() = {
- repldbg("Setting new classloader: was " + _classLoader)
- _classLoader = null
- ensureClassLoader()
- }
- final def ensureClassLoader() {
- if (_classLoader == null)
- _classLoader = makeClassLoader()
- }
- def classLoader: AbstractFileClassLoader = {
- ensureClassLoader()
- _classLoader
- }
-
- def backticked(s: String): String = (
- (s split '.').toList map {
- case "_" => "_"
- case s if nme.keywords(newTermName(s)) => s"`$s`"
- case s => s
- } mkString "."
- )
-
- abstract class PhaseDependentOps {
- def shift[T](op: => T): T
-
- def path(name: => Name): String = shift(path(symbolOfName(name)))
- def path(sym: Symbol): String = backticked(shift(sym.fullName))
- def sig(sym: Symbol): String = shift(sym.defString)
- }
- object typerOp extends PhaseDependentOps {
- def shift[T](op: => T): T = exitingTyper(op)
- }
- object flatOp extends PhaseDependentOps {
- def shift[T](op: => T): T = exitingFlatten(op)
- }
-
- 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) = {
- val sym = if (path endsWith "$") symbolOfTerm(path.init) else symbolOfIdent(path)
- sym match {
- case NoSymbol => None
- case _ => Some(flatPath(sym))
- }
- }
- def translateEnclosingClass(n: String) = {
- def enclosingClass(s: Symbol): Symbol =
- if (s == NoSymbol || s.isClass) s else enclosingClass(s.owner)
- enclosingClass(symbolOfTerm(n)) match {
- case NoSymbol => None
- case c => Some(flatPath(c))
- }
- }
-
- private class TranslatingClassLoader(parent: ClassLoader) extends AbstractFileClassLoader(replOutput.dir, parent) {
- /** Overridden here to try translating a simple name to the generated
- * class name if the original attempt fails. This method is used by
- * getResourceAsStream as well as findClass.
- */
- override protected def findAbstractFile(name: String): AbstractFile =
- super.findAbstractFile(name) match {
- case null => translatePath(name) map (super.findAbstractFile(_)) orNull
- case file => file
- }
- }
- private def makeClassLoader(): AbstractFileClassLoader =
- new TranslatingClassLoader(parentClassLoader match {
- case null => ScalaClassLoader fromURLs compilerClasspath
- case p => new URLClassLoader(compilerClasspath, p)
- })
-
- // Set the current Java "context" class loader to this interpreter's class loader
- def setContextClassLoader() = classLoader.setAsContext()
-
- 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] = {
- prevRequests.reverse foreach { req =>
- req.handlers.reverse foreach {
- case x: MemberDefHandler if x.definesValue && !isInternalTermName(x.name) => return Some(x.member)
- case _ => ()
- }
- }
- None
- }
-
- private def updateReplScope(sym: Symbol, isDefined: Boolean) {
- def log(what: String) {
- val mark = if (sym.isType) "t " else "v "
- val name = exitingTyper(sym.nameString)
- val info = cleanTypeAfterTyper(sym)
- val defn = sym defStringSeenAs info
-
- scopelog(f"[$mark$what%6s] $name%-25s $defn%s")
- }
- if (ObjectClass isSubClass sym.owner) return
- // unlink previous
- replScope lookupAll sym.name foreach { sym =>
- log("unlink")
- replScope unlink sym
- }
- val what = if (isDefined) "define" else "import"
- log(what)
- replScope enter sym
- }
-
- def recordRequest(req: Request) {
- if (req == null)
- return
-
- prevRequests += req
-
- // warning about serially defining companions. It'd be easy
- // enough to just redefine them together but that may not always
- // be what people want so I'm waiting until I can do it better.
- exitingTyper {
- req.defines filterNot (s => req.defines contains s.companionSymbol) foreach { newSym =>
- val oldSym = replScope lookup newSym.name.companionName
- if (Seq(oldSym, newSym).permutations exists { case Seq(s1, s2) => s1.isClass && s2.isModule }) {
- replwarn(s"warning: previously defined $oldSym is not a companion to $newSym.")
- replwarn("Companions must be defined together; you may wish to use :paste mode for this.")
- }
- }
- }
- exitingTyper {
- req.imports foreach (sym => updateReplScope(sym, isDefined = false))
- req.defines foreach (sym => updateReplScope(sym, isDefined = true))
- }
- }
-
- private[nsc] def replwarn(msg: => String) {
- if (!settings.nowarnings.value)
- printMessage(msg)
- }
-
- def compileSourcesKeepingRun(sources: SourceFile*) = {
- val run = new Run()
- reporter.reset()
- run compileSources sources.toList
- (!reporter.hasErrors, run)
- }
-
- /** Compile an nsc SourceFile. Returns true if there are
- * no compilation errors, or false otherwise.
- */
- def compileSources(sources: SourceFile*): Boolean =
- compileSourcesKeepingRun(sources: _*)._1
-
- /** Compile a string. Returns true if there are no
- * compilation errors, or false otherwise.
- */
- def compileString(code: String): Boolean =
- compileSources(new BatchSourceFile("<script>", code))
-
- /** Build a request from the user. `trees` is `line` after being parsed.
- */
- private def buildRequest(line: String, trees: List[Tree]): Request = {
- executingRequest = new Request(line, trees)
- executingRequest
- }
-
- private def safePos(t: Tree, alt: Int): Int =
- try t.pos.startOrPoint
- catch { case _: UnsupportedOperationException => alt }
-
- // Given an expression like 10 * 10 * 10 we receive the parent tree positioned
- // at a '*'. So look at each subtree and find the earliest of all positions.
- private def earliestPosition(tree: Tree): Int = {
- var pos = Int.MaxValue
- tree foreach { t =>
- pos = math.min(pos, safePos(t, Int.MaxValue))
- }
- pos
- }
-
- private def requestFromLine(line: String, synthetic: Boolean): Either[IR.Result, Request] = {
- val content = indentCode(line)
- val trees = parse(content) match {
- case None => return Left(IR.Incomplete)
- case Some(Nil) => return Left(IR.Error) // parse error or empty input
- case Some(trees) => trees
- }
- repltrace(
- trees map (t => {
- // [Eugene to Paul] previously it just said `t map ...`
- // because there was an implicit conversion from Tree to a list of Trees
- // however Martin and I have removed the conversion
- // (it was conflicting with the new reflection API),
- // so I had to rewrite this a bit
- val subs = t collect { case sub => sub }
- subs map (t0 =>
- " " + safePos(t0, -1) + ": " + t0.shortClass + "\n"
- ) mkString ""
- }) mkString "\n"
- )
- // If the last tree is a bare expression, pinpoint where it begins using the
- // AST node position and snap the line off there. Rewrite the code embodied
- // by the last tree as a ValDef instead, so we can access the value.
- trees.last match {
- case _:Assign => // we don't want to include assignments
- case _:TermTree | _:Ident | _:Select => // ... but do want other unnamed terms.
- val varName = if (synthetic) freshInternalVarName() else freshUserVarName()
- val rewrittenLine = (
- // In theory this would come out the same without the 1-specific test, but
- // it's a cushion against any more sneaky parse-tree position vs. code mismatches:
- // this way such issues will only arise on multiple-statement repl input lines,
- // which most people don't use.
- if (trees.size == 1) "val " + varName + " =\n" + content
- else {
- // The position of the last tree
- val lastpos0 = earliestPosition(trees.last)
- // Oh boy, the parser throws away parens so "(2+2)" is mispositioned,
- // with increasingly hard to decipher positions as we move on to "() => 5",
- // (x: Int) => x + 1, and more. So I abandon attempts to finesse and just
- // look for semicolons and newlines, which I'm sure is also buggy.
- val (raw1, raw2) = content splitAt lastpos0
- repldbg("[raw] " + raw1 + " <---> " + raw2)
-
- val adjustment = (raw1.reverse takeWhile (ch => (ch != ';') && (ch != '\n'))).size
- val lastpos = lastpos0 - adjustment
-
- // the source code split at the laboriously determined position.
- val (l1, l2) = content splitAt lastpos
- repldbg("[adj] " + l1 + " <---> " + l2)
-
- val prefix = if (l1.trim == "") "" else l1 + ";\n"
- // Note to self: val source needs to have this precise structure so that
- // error messages print the user-submitted part without the "val res0 = " part.
- val combined = prefix + "val " + varName + " =\n" + l2
-
- repldbg(List(
- " line" -> line,
- " content" -> content,
- " was" -> l2,
- "combined" -> combined) map {
- case (label, s) => label + ": '" + s + "'"
- } mkString "\n"
- )
- combined
- }
- )
- // Rewriting "foo ; bar ; 123"
- // to "foo ; bar ; val resXX = 123"
- requestFromLine(rewrittenLine, synthetic) match {
- case Right(req) => return Right(req withOriginalLine line)
- case x => return x
- }
- case _ =>
- }
- Right(buildRequest(line, trees))
- }
-
- // dealias non-public types so we don't see protected aliases like Self
- def dealiasNonPublic(tp: Type) = tp match {
- case TypeRef(_, sym, _) if sym.isAliasType && !sym.isPublic => tp.dealias
- case _ => tp
- }
-
- /**
- * Interpret one line of input. All feedback, including parse errors
- * and evaluation results, are printed via the supplied compiler's
- * reporter. Values defined are available for future interpreted strings.
- *
- * The return value is whether the line was interpreter successfully,
- * e.g. that there were no parse errors.
- */
- def interpret(line: String): IR.Result = interpret(line, synthetic = false)
- def interpretSynthetic(line: String): IR.Result = interpret(line, synthetic = true)
- def interpret(line: String, synthetic: Boolean): IR.Result = {
- def loadAndRunReq(req: Request) = {
- classLoader.setAsContext()
- val (result, succeeded) = req.loadAndRun
-
- /** To our displeasure, ConsoleReporter offers only printMessage,
- * which tacks a newline on the end. Since that breaks all the
- * output checking, we have to take one off to balance.
- */
- if (succeeded) {
- if (printResults && result != "")
- printMessage(result stripSuffix "\n")
- else if (isReplDebug) // show quiet-mode activity
- printMessage(result.trim.lines map ("[quiet] " + _) mkString "\n")
-
- // Book-keeping. Have to record synthetic requests too,
- // as they may have been issued for information, e.g. :type
- recordRequest(req)
- IR.Success
- }
- else {
- // don't truncate stack traces
- withoutTruncating(printMessage(result))
- IR.Error
- }
- }
-
- if (global == null) IR.Error
- else requestFromLine(line, synthetic) match {
- case Left(result) => result
- case Right(req) =>
- // null indicates a disallowed statement type; otherwise compile and
- // fail if false (implying e.g. a type error)
- if (req == null || !req.compile) IR.Error
- else loadAndRunReq(req)
- }
- }
-
- /** Bind a specified name to a specified value. The name may
- * later be used by expressions passed to interpret.
- *
- * @param name the variable name to bind
- * @param boundType the type of the variable, as a string
- * @param value the object value to bind to it
- * @return an indication of whether the binding succeeded
- */
- def bind(name: String, boundType: String, value: Any, modifiers: List[String] = Nil): IR.Result = {
- val bindRep = new ReadEvalPrint()
- bindRep.compile("""
- |object %s {
- | var value: %s = _
- | def set(x: Any) = value = x.asInstanceOf[%s]
- |}
- """.stripMargin.format(bindRep.evalName, boundType, boundType)
- )
- bindRep.callEither("set", value) match {
- case Left(ex) =>
- repldbg("Set failed in bind(%s, %s, %s)".format(name, boundType, value))
- repldbg(util.stackTraceString(ex))
- IR.Error
-
- case Right(_) =>
- val line = "%sval %s = %s.value".format(modifiers map (_ + " ") mkString, name, bindRep.evalPath)
- repldbg("Interpreting: " + line)
- interpret(line)
- }
- }
- def directBind(name: String, boundType: String, value: Any): IR.Result = {
- val result = bind(name, boundType, value)
- if (result == IR.Success)
- directlyBoundNames += newTermName(name)
- result
- }
- def directBind(p: NamedParam): IR.Result = directBind(p.name, p.tpe, p.value)
- def directBind[T: ru.TypeTag : ClassTag](name: String, value: T): IR.Result = directBind((name, value))
-
- def rebind(p: NamedParam): IR.Result = {
- val name = p.name
- val newType = p.tpe
- val tempName = freshInternalVarName()
-
- quietRun("val %s = %s".format(tempName, name))
- quietRun("val %s = %s.asInstanceOf[%s]".format(name, tempName, newType))
- }
- def quietBind(p: NamedParam): IR.Result = beQuietDuring(bind(p))
- def bind(p: NamedParam): IR.Result = bind(p.name, p.tpe, p.value)
- def bind[T: ru.TypeTag : ClassTag](name: String, value: T): IR.Result = bind((name, value))
-
- /** Reset this interpreter, forgetting all user-specified requests. */
- def reset() {
- clearExecutionWrapper()
- resetClassLoader()
- resetAllCreators()
- prevRequests.clear()
- resetReplScope()
- replOutput.dir.clear()
- }
-
- /** This instance is no longer needed, so release any resources
- * it is using. The reporter's output gets flushed.
- */
- def close() {
- reporter.flush()
- }
-
- /** Here is where we:
- *
- * 1) Read some source code, and put it in the "read" object.
- * 2) Evaluate the read object, and put the result in the "eval" object.
- * 3) Create a String for human consumption, and put it in the "print" object.
- *
- * Read! Eval! Print! Some of that not yet centralized here.
- */
- class ReadEvalPrint(lineId: Int) {
- def this() = this(freshLineId())
-
- val packageName = sessionNames.line + lineId
- val readName = sessionNames.read
- val evalName = sessionNames.eval
- val printName = sessionNames.print
- val resultName = sessionNames.result
-
- def bindError(t: Throwable) = {
- if (!bindExceptions) // avoid looping if already binding
- throw t
-
- val unwrapped = unwrap(t)
- withLastExceptionLock[String]({
- directBind[Throwable]("lastException", unwrapped)(tagOfThrowable, classTag[Throwable])
- util.stackTraceString(unwrapped)
- }, util.stackTraceString(unwrapped))
- }
-
- // TODO: split it out into a package object and a regular
- // object and we can do that much less wrapping.
- def packageDecl = "package " + packageName
-
- def pathTo(name: String) = packageName + "." + name
- def packaged(code: String) = packageDecl + "\n\n" + code
-
- def readPath = pathTo(readName)
- def evalPath = pathTo(evalName)
-
- def call(name: String, args: Any*): AnyRef = {
- val m = evalMethod(name)
- repldbg("Invoking: " + m)
- if (args.nonEmpty)
- repldbg(" with args: " + args.mkString(", "))
-
- m.invoke(evalClass, args.map(_.asInstanceOf[AnyRef]): _*)
- }
-
- def callEither(name: String, args: Any*): Either[Throwable, AnyRef] =
- try Right(call(name, args: _*))
- catch { case ex: Throwable => Left(ex) }
-
- class EvalException(msg: String, cause: Throwable) extends RuntimeException(msg, cause) { }
-
- private def evalError(path: String, ex: Throwable) =
- throw new EvalException("Failed to load '" + path + "': " + ex.getMessage, ex)
-
- private def load(path: String): Class[_] = {
- try Class.forName(path, true, classLoader)
- catch { case ex: Throwable => evalError(path, unwrap(ex)) }
- }
-
- lazy val evalClass = load(evalPath)
-
- def compile(source: String): Boolean = compileAndSaveRun("<console>", source)
-
- /** The innermost object inside the wrapper, found by
- * following accessPath into the outer one.
- */
- def resolvePathToSymbol(accessPath: String): Symbol = {
- val readRoot = getModuleIfDefined(readPath) // the outermost wrapper
- (accessPath split '.').foldLeft(readRoot: Symbol) {
- case (sym, "") => sym
- case (sym, name) => exitingTyper(termMember(sym, name))
- }
- }
- /** We get a bunch of repeated warnings for reasons I haven't
- * entirely figured out yet. For now, squash.
- */
- private def updateRecentWarnings(run: Run) {
- def loop(xs: List[(Position, String)]): List[(Position, String)] = xs match {
- case Nil => Nil
- case ((pos, msg)) :: rest =>
- val filtered = rest filter { case (pos0, msg0) =>
- (msg != msg0) || (pos.lineContent.trim != pos0.lineContent.trim) || {
- // same messages and same line content after whitespace removal
- // but we want to let through multiple warnings on the same line
- // from the same run. The untrimmed line will be the same since
- // there's no whitespace indenting blowing it.
- (pos.lineContent == pos0.lineContent)
- }
- }
- ((pos, msg)) :: loop(filtered)
- }
- val warnings = loop(run.allConditionalWarnings flatMap (_.warnings))
- if (warnings.nonEmpty)
- mostRecentWarnings = warnings
- }
- private def evalMethod(name: String) = evalClass.getMethods filter (_.getName == name) match {
- case Array(method) => method
- case xs => sys.error("Internal error: eval object " + evalClass + ", " + xs.mkString("\n", "\n", ""))
- }
- private def compileAndSaveRun(label: String, code: String) = {
- showCodeIfDebugging(code)
- val (success, run) = compileSourcesKeepingRun(new BatchSourceFile(label, packaged(code)))
- updateRecentWarnings(run)
- success
- }
- }
-
- /** One line of code submitted by the user for interpretation */
- class Request(val line: String, val trees: List[Tree]) {
- def defines = defHandlers flatMap (_.definedSymbols)
- def imports = importedSymbols
- def value = Some(handlers.last) filter (h => h.definesValue) map (h => definedSymbols(h.definesTerm.get)) getOrElse NoSymbol
-
- val lineRep = new ReadEvalPrint()
-
- private var _originalLine: String = null
- def withOriginalLine(s: String): this.type = { _originalLine = s ; this }
- def originalLine = if (_originalLine == null) line else _originalLine
-
- /** handlers for each tree in this request */
- val handlers: List[MemberHandler] = trees map (memberHandlers chooseHandler _)
- def defHandlers = handlers collect { case x: MemberDefHandler => x }
-
- /** list of names used by this expression */
- val referencedNames: List[Name] = handlers flatMap (_.referencedNames)
-
- /** def and val names */
- def termNames = handlers flatMap (_.definesTerm)
- def typeNames = handlers flatMap (_.definesType)
- def importedSymbols = handlers flatMap {
- case x: ImportHandler => x.importedSymbols
- case _ => Nil
- }
-
- /** Code to import bound names from previous lines - accessPath is code to
- * append to objectName to access anything bound by request.
- */
- val ComputedImports(importsPreamble, importsTrailer, accessPath) =
- exitingTyper(importsCode(referencedNames.toSet))
-
- /** the line of code to compute */
- def toCompute = line
-
- def fullPath(vname: String) = s"${lineRep.readPath}$accessPath.`$vname`"
-
- /** generate the source code for the object that computes this request */
- private object ObjectSourceCode extends CodeAssembler[MemberHandler] {
- def path = originalPath("$intp")
- def envLines = {
- if (!isReplPower) Nil // power mode only for now
- // $intp is not bound; punt, but include the line.
- else if (path == "$intp") List(
- "def $line = " + tquoted(originalLine),
- "def $trees = Nil"
- )
- else List(
- "def $line = " + tquoted(originalLine),
- "def $trees = Nil"
- )
- }
-
- val preamble = """
- |object %s {
- |%s%s%s
- """.stripMargin.format(lineRep.readName, envLines.map(" " + _ + ";\n").mkString, importsPreamble, indentCode(toCompute))
- val postamble = importsTrailer + "\n}"
- val generate = (m: MemberHandler) => m extraCodeToEvaluate Request.this
- }
-
- private object ResultObjectSourceCode extends CodeAssembler[MemberHandler] {
- /** We only want to generate this code when the result
- * is a value which can be referred to as-is.
- */
- val evalResult = Request.this.value match {
- case NoSymbol => ""
- case sym => "lazy val %s = %s".format(lineRep.resultName, originalPath(sym))
- }
- // first line evaluates object to make sure constructor is run
- // initial "" so later code can uniformly be: + etc
- val preamble = """
- |object %s {
- | %s
- | val %s: String = %s {
- | %s
- | (""
- """.stripMargin.format(
- lineRep.evalName, evalResult, lineRep.printName,
- executionWrapper, lineRep.readName + accessPath
- )
-
- val postamble = """
- | )
- | }
- |}
- """.stripMargin
- val generate = (m: MemberHandler) => m resultExtractionCode Request.this
- }
-
- /** Compile the object file. Returns whether the compilation succeeded.
- * If all goes well, the "types" map is computed. */
- lazy val compile: Boolean = {
- // error counting is wrong, hence interpreter may overlook failure - so we reset
- reporter.reset()
-
- // compile the object containing the user's code
- lineRep.compile(ObjectSourceCode(handlers)) && {
- // extract and remember types
- typeOf
- typesOfDefinedTerms
-
- // Assign symbols to the original trees
- // TODO - just use the new trees.
- defHandlers foreach { dh =>
- val name = dh.member.name
- definedSymbols get name foreach { sym =>
- dh.member setSymbol sym
- repldbg("Set symbol of " + name + " to " + symbolDefString(sym))
- }
- }
-
- // compile the result-extraction object
- withoutWarnings(lineRep compile ResultObjectSourceCode(handlers))
- }
- }
-
- lazy val resultSymbol = lineRep.resolvePathToSymbol(accessPath)
- def applyToResultMember[T](name: Name, f: Symbol => T) = exitingTyper(f(resultSymbol.info.nonPrivateDecl(name)))
-
- /* typeOf lookup with encoding */
- def lookupTypeOf(name: Name) = typeOf.getOrElse(name, typeOf(global.encode(name.toString)))
-
- private def typeMap[T](f: Type => T) =
- mapFrom[Name, Name, T](termNames ++ typeNames)(x => f(cleanMemberDecl(resultSymbol, x)))
-
- /** Types of variables defined by this request. */
- lazy val compilerTypeOf = typeMap[Type](x => x) withDefaultValue NoType
- /** String representations of same. */
- lazy val typeOf = typeMap[String](tp => exitingTyper(tp.toString))
-
- lazy val definedSymbols = (
- termNames.map(x => x -> applyToResultMember(x, x => x)) ++
- typeNames.map(x => x -> compilerTypeOf(x).typeSymbolDirect)
- ).toMap[Name, Symbol] withDefaultValue NoSymbol
-
- lazy val typesOfDefinedTerms = mapFrom[Name, Name, Type](termNames)(x => applyToResultMember(x, _.tpe))
-
- /** load and run the code using reflection */
- def loadAndRun: (String, Boolean) = {
- try { ("" + (lineRep call sessionNames.print), true) }
- catch { case ex: Throwable => (lineRep.bindError(ex), false) }
- }
-
- override def toString = "Request(line=%s, %s trees)".format(line, trees.size)
- }
-
- /** Returns the name of the most recent interpreter result.
- * Mostly this exists so you can conveniently invoke methods on
- * the previous result.
- */
- def mostRecentVar: String =
- if (mostRecentlyHandledTree.isEmpty) ""
- else "" + (mostRecentlyHandledTree.get match {
- case x: ValOrDefDef => x.name
- case Assign(Ident(name), _) => name
- case ModuleDef(_, name, _) => name
- case _ => naming.mostRecentVar
- })
-
- private var mostRecentWarnings: List[(global.Position, String)] = Nil
- def lastWarnings = mostRecentWarnings
-
- 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(javaMirror runtimeClass importToRu(sym).asClass)
- }
-
- def typeOfTerm(id: String): Type = symbolOfTerm(id).tpe
-
- def valueOfTerm(id: String): Option[Any] = exitingTyper {
- def value() = {
- val sym0 = symbolOfTerm(id)
- 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
- }
-
- try Some(value()) catch { case _: Exception => None }
- }
-
- /** 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 symbolOfIdent(id: String): Symbol = symbolOfType(id) orElse symbolOfTerm(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 =>
- clazz.supers find (!_.isScalaAnonymous) map { nonAnon =>
- (nonAnon, runtimeTypeOfTerm(id))
- }
- }
- }
-
- def runtimeTypeOfTerm(id: String): Type = {
- typeOfTerm(id) andAlso { tpe =>
- val clazz = classOfTerm(id) getOrElse { return NoType }
- val staticSym = tpe.typeSymbol
- val runtimeSym = getClassIfDefined(clazz.getName)
-
- if ((runtimeSym != NoSymbol) && (runtimeSym != staticSym) && (runtimeSym isSubClass staticSym))
- runtimeSym.info
- else NoType
- }
- }
-
- def cleanTypeAfterTyper(sym: => Symbol): Type = {
- exitingTyper(
- dealiasNonPublic(
- dropNullaryMethod(
- sym.tpe_*
- )
- )
- )
- }
- def cleanMemberDecl(owner: Symbol, member: Name): Type =
- cleanTypeAfterTyper(owner.info nonPrivateDecl member)
-
- object exprTyper extends {
- val repl: IMain.this.type = imain
- } with ExprTyper { }
-
- def parse(line: String): Option[List[Tree]] = exprTyper.parse(line)
-
- def symbolOfLine(code: String): Symbol =
- exprTyper.symbolOfLine(code)
-
- def typeOfExpression(expr: String, silent: Boolean = true): Type =
- exprTyper.typeOfExpression(expr, silent)
-
- 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)
- def definedSymbolList = prevRequestList flatMap (_.defines) filterNot (s => isInternalTermName(s.name))
-
- // Terms with user-given names (i.e. not res0 and not synthetic)
- def namedDefinedTerms = definedTerms filterNot (x => isUserVarName("" + x) || directlyBoundNames(x))
-
- private var _replScope: Scope = _
- private def resetReplScope() {
- _replScope = newScope
- }
- def replScope = {
- if (_replScope eq null)
- _replScope = newScope
-
- _replScope
- }
-
- private var executingRequest: Request = _
- private val prevRequests = mutable.ListBuffer[Request]()
- private val directlyBoundNames = mutable.Set[Name]()
-
- def allHandlers = prevRequestList flatMap (_.handlers)
- def lastRequest = if (prevRequests.isEmpty) null else prevRequests.last
- def prevRequestList = prevRequests.toList
- def importHandlers = allHandlers collect { case x: ImportHandler => x }
-
- def withoutUnwrapping(op: => Unit): Unit = {
- val saved = isettings.unwrapStrings
- isettings.unwrapStrings = false
- try op
- finally isettings.unwrapStrings = saved
- }
-
- def symbolDefString(sym: Symbol) = {
- TypeStrings.quieter(
- exitingTyper(sym.defString),
- sym.owner.name + ".this.",
- sym.owner.fullName + "."
- )
- }
-
- def showCodeIfDebugging(code: String) {
- /** Secret bookcase entrance for repl debuggers: end the line
- * with "// show" and see what's going on.
- */
- def isShow = code.lines exists (_.trim endsWith "// show")
- if (isReplDebug || isShow) {
- beSilentDuring(parse(code)) foreach { ts =>
- ts foreach { t =>
- withoutUnwrapping(echo(asCompactString(t)))
- }
- }
- }
- }
-
- // debugging
- def debugging[T](msg: String)(res: T) = {
- repldbg(msg + " " + res)
- res
- }
-}
-
-/** Utility methods for the Interpreter. */
-object IMain {
- // The two name forms this is catching are the two sides of this assignment:
- //
- // $line3.$read.$iw.$iw.Bippy =
- // $line3.$read$$iw$$iw$Bippy@4a6a00ca
- private def removeLineWrapper(s: String) = s.replaceAll("""\$line\d+[./]\$(read|eval|print)[$.]""", "")
- private def removeIWPackages(s: String) = s.replaceAll("""\$(iw|read|eval|print)[$.]""", "")
- def stripString(s: String) = removeIWPackages(removeLineWrapper(s))
-
- trait CodeAssembler[T] {
- def preamble: String
- def generate: T => String
- def postamble: String
-
- def apply(contributors: List[T]): String = stringFromWriter { code =>
- code println preamble
- contributors map generate foreach (code println _)
- code println postamble
- }
- }
-
- trait StrippingWriter {
- def isStripping: Boolean
- def stripImpl(str: String): String
- def strip(str: String): String = if (isStripping) stripImpl(str) else str
- }
- trait TruncatingWriter {
- def maxStringLength: Int
- def isTruncating: Boolean
- def truncate(str: String): String = {
- if (isTruncating && (maxStringLength != 0 && str.length > maxStringLength))
- (str take maxStringLength - 3) + "..."
- else str
- }
- }
- abstract class StrippingTruncatingWriter(out: JPrintWriter)
- extends JPrintWriter(out)
- with StrippingWriter
- with TruncatingWriter {
- self =>
-
- def clean(str: String): String = truncate(strip(str))
- override def write(str: String) = super.write(clean(str))
- }
- class ReplStrippingWriter(intp: IMain) extends StrippingTruncatingWriter(intp.out) {
- import intp._
- def maxStringLength = isettings.maxPrintString
- def isStripping = isettings.unwrapStrings
- def isTruncating = reporter.truncationOK
-
- def stripImpl(str: String): String = naming.unmangle(str)
- }
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/ISettings.scala b/src/compiler/scala/tools/nsc/interpreter/ISettings.scala
deleted file mode 100644
index 9541d08db1..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/ISettings.scala
+++ /dev/null
@@ -1,54 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Alexander Spoon
- */
-
-package scala.tools.nsc
-package interpreter
-
-/** Settings for the interpreter
- *
- * @version 1.0
- * @author Lex Spoon, 2007/3/24
- **/
-class ISettings(intp: IMain) {
- /** The maximum length of toString to use when printing the result
- * of an evaluation. 0 means no maximum. If a printout requires
- * more than this number of characters, then the printout is
- * truncated.
- */
- var maxPrintString = replProps.maxPrintString.option.getOrElse(800)
-
- /** The maximum number of completion candidates to print for tab
- * completion without requiring confirmation.
- */
- var maxAutoprintCompletion = 250
-
- /** String unwrapping can be disabled if it is causing issues.
- * Setting this to false means you will see Strings like "$iw.$iw.".
- */
- var unwrapStrings = true
-
- def deprecation_=(x: Boolean) = {
- val old = intp.settings.deprecation.value
- intp.settings.deprecation.value = x
- if (!old && x) println("Enabled -deprecation output.")
- else if (old && !x) println("Disabled -deprecation output.")
- }
- def deprecation: Boolean = intp.settings.deprecation.value
-
- def allSettings = Map[String, Any](
- "maxPrintString" -> maxPrintString,
- "maxAutoprintCompletion" -> maxAutoprintCompletion,
- "unwrapStrings" -> unwrapStrings,
- "deprecation" -> deprecation
- )
-
- private def allSettingsString =
- allSettings.toList sortBy (_._1) map { case (k, v) => " " + k + " = " + v + "\n" } mkString
-
- override def toString = """
- | ISettings {
- | %s
- | }""".stripMargin.format(allSettingsString)
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/Imports.scala b/src/compiler/scala/tools/nsc/interpreter/Imports.scala
deleted file mode 100644
index ff7bfd432c..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/Imports.scala
+++ /dev/null
@@ -1,181 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import scala.collection.{ mutable, immutable }
-
-trait Imports {
- self: IMain =>
-
- import global._
- import definitions.{ ObjectClass, ScalaPackage, JavaLangPackage, PredefModule }
- import memberHandlers._
-
- /** Synthetic import handlers for the language defined imports. */
- private def makeWildcardImportHandler(sym: Symbol): ImportHandler = {
- val hd :: tl = sym.fullName.split('.').toList map newTermName
- val tree = Import(
- tl.foldLeft(Ident(hd): Tree)((x, y) => Select(x, y)),
- ImportSelector.wildList
- )
- tree setSymbol sym
- new ImportHandler(tree)
- }
-
- /** Symbols whose contents are language-defined to be imported. */
- def languageWildcardSyms: List[Symbol] = List(JavaLangPackage, ScalaPackage, PredefModule)
- def languageWildcardHandlers = languageWildcardSyms map makeWildcardImportHandler
-
- def allImportedNames = importHandlers flatMap (_.importedNames)
-
- /** Types which have been wildcard imported, such as:
- * val x = "abc" ; import x._ // type java.lang.String
- * import java.lang.String._ // object java.lang.String
- *
- * Used by tab completion.
- *
- * XXX right now this gets import x._ and import java.lang.String._,
- * but doesn't figure out import String._. There's a lot of ad hoc
- * scope twiddling which should be swept away in favor of digging
- * into the compiler scopes.
- */
- def sessionWildcards: List[Type] = {
- importHandlers filter (_.importsWildcard) map (_.targetType) distinct
- }
-
- def languageSymbols = languageWildcardSyms flatMap membersAtPickler
- def sessionImportedSymbols = importHandlers flatMap (_.importedSymbols)
- def importedSymbols = languageSymbols ++ sessionImportedSymbols
- def importedTermSymbols = importedSymbols collect { case x: TermSymbol => x }
-
- /** Tuples of (source, imported symbols) in the order they were imported.
- */
- def importedSymbolsBySource: List[(Symbol, List[Symbol])] = {
- val lang = languageWildcardSyms map (sym => (sym, membersAtPickler(sym)))
- val session = importHandlers filter (_.targetType != NoType) map { mh =>
- (mh.targetType.typeSymbol, mh.importedSymbols)
- }
-
- lang ++ session
- }
- def implicitSymbolsBySource: List[(Symbol, List[Symbol])] = {
- importedSymbolsBySource map {
- case (k, vs) => (k, vs filter (_.isImplicit))
- } filterNot (_._2.isEmpty)
- }
-
- /** Compute imports that allow definitions from previous
- * requests to be visible in a new request. Returns
- * three pieces of related code:
- *
- * 1. An initial code fragment that should go before
- * the code of the new request.
- *
- * 2. A code fragment that should go after the code
- * of the new request.
- *
- * 3. An access path which can be traversed to access
- * any bindings inside code wrapped by #1 and #2 .
- *
- * The argument is a set of Names that need to be imported.
- *
- * Limitations: This method is not as precise as it could be.
- * (1) It does not process wildcard imports to see what exactly
- * they import.
- * (2) If it imports any names from a request, it imports all
- * of them, which is not really necessary.
- * (3) It imports multiple same-named implicits, but only the
- * last one imported is actually usable.
- */
- case class ComputedImports(prepend: String, append: String, access: String)
- protected def importsCode(wanted: Set[Name]): ComputedImports = {
- /** Narrow down the list of requests from which imports
- * should be taken. Removes requests which cannot contribute
- * useful imports for the specified set of wanted names.
- */
- case class ReqAndHandler(req: Request, handler: MemberHandler) { }
-
- def reqsToUse: List[ReqAndHandler] = {
- /** Loop through a list of MemberHandlers and select which ones to keep.
- * 'wanted' is the set of names that need to be imported.
- */
- def select(reqs: List[ReqAndHandler], wanted: Set[Name]): List[ReqAndHandler] = {
- // Single symbol imports might be implicits! See bug #1752. Rather than
- // try to finesse this, we will mimic all imports for now.
- def keepHandler(handler: MemberHandler) = handler match {
- case _: ImportHandler => true
- case x => x.definesImplicit || (x.definedNames exists wanted)
- }
-
- reqs match {
- case Nil => Nil
- case rh :: rest if !keepHandler(rh.handler) => select(rest, wanted)
- case rh :: rest =>
- import rh.handler._
- val newWanted = wanted ++ referencedNames -- definedNames -- importedNames
- rh :: select(rest, newWanted)
- }
- }
-
- /** Flatten the handlers out and pair each with the original request */
- select(allReqAndHandlers reverseMap { case (r, h) => ReqAndHandler(r, h) }, wanted).reverse
- }
-
- val code, trailingBraces, accessPath = new StringBuilder
- val currentImps = mutable.HashSet[Name]()
-
- // add code for a new object to hold some imports
- def addWrapper() {
- val impname = nme.INTERPRETER_IMPORT_WRAPPER
- code append "object %s {\n".format(impname)
- trailingBraces append "}\n"
- accessPath append ("." + impname)
- currentImps.clear()
- }
- def maybeWrap(names: Name*) = if (names exists currentImps) addWrapper()
- def wrapBeforeAndAfter[T](op: => T): T = {
- addWrapper()
- try op finally addWrapper()
- }
-
- // loop through previous requests, adding imports for each one
- 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
- }
- }
- }
- }
-
- ComputedImports(code.toString, trailingBraces.toString, accessPath.toString)
- }
-
- private def allReqAndHandlers =
- prevRequestList flatMap (req => req.handlers map (req -> _))
-
- private def membersAtPickler(sym: Symbol): List[Symbol] =
- enteringPickler(sym.info.nonPrivateMembers.toList)
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala b/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala
deleted file mode 100644
index 28ddf2939c..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala
+++ /dev/null
@@ -1,49 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Stepan Koltsov
- */
-
-package scala.tools.nsc
-package interpreter
-
-import java.io.IOException
-import session.History
-import InteractiveReader._
-import Properties.isMac
-
-/** Reads lines from an input stream */
-trait InteractiveReader {
- val interactive: Boolean
-
- def reset(): Unit
- def history: History
- def completion: Completion
- def redrawLine(): Unit
-
- def readYesOrNo(prompt: String, alt: => Boolean): Boolean = readOneKey(prompt) match {
- case 'y' => true
- case 'n' => false
- case _ => alt
- }
-
- protected def readOneLine(prompt: String): String
- protected def readOneKey(prompt: String): Int
-
- def readLine(prompt: String): String =
- // hack necessary for OSX jvm suspension because read calls are not restarted after SIGTSTP
- if (isMac) restartSysCalls(readOneLine(prompt), reset())
- else readOneLine(prompt)
-}
-
-object InteractiveReader {
- val msgEINTR = "Interrupted system call"
- def restartSysCalls[R](body: => R, reset: => Unit): R =
- try body catch {
- case e: IOException if e.getMessage == msgEINTR => reset ; body
- }
-
- def apply(): InteractiveReader = SimpleReader()
- @deprecated("Use `apply` instead.", "2.9.0")
- def createDefault(): InteractiveReader = apply() // used by sbt
-}
-
diff --git a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala b/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala
deleted file mode 100644
index 19fa562234..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala
+++ /dev/null
@@ -1,352 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import Completion._
-import scala.collection.mutable.ListBuffer
-import scala.reflect.internal.util.StringOps.longestCommonPrefix
-
-// REPL completor - queries supplied interpreter for valid
-// completions based on current contents of buffer.
-class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput {
- val global: intp.global.type = intp.global
- import global._
- import definitions.{ PredefModule, AnyClass, AnyRefClass, ScalaPackage, JavaLangPackage }
- import rootMirror.{ RootClass, getModuleIfDefined }
- type ExecResult = Any
- import intp.{ debugging }
-
- // verbosity goes up with consecutive tabs
- private var verbosity: Int = 0
- def resetVerbosity() = verbosity = 0
-
- def getSymbol(name: String, isModule: Boolean) = (
- if (isModule) getModuleIfDefined(name)
- else getModuleIfDefined(name)
- )
-
- trait CompilerCompletion {
- def tp: Type
- def effectiveTp = tp match {
- case MethodType(Nil, resType) => resType
- case NullaryMethodType(resType) => resType
- case _ => tp
- }
-
- // for some reason any's members don't show up in subclasses, which
- // we need so 5.<tab> offers asInstanceOf etc.
- private def anyMembers = AnyClass.tpe.nonPrivateMembers
- def anyRefMethodsToShow = Set("isInstanceOf", "asInstanceOf", "toString")
-
- def tos(sym: Symbol): String = sym.decodedName
- def memberNamed(s: String) = exitingTyper(effectiveTp member newTermName(s))
-
- // XXX we'd like to say "filterNot (_.isDeprecated)" but this causes the
- // compiler to crash for reasons not yet known.
- def members = exitingTyper((effectiveTp.nonPrivateMembers.toList ++ anyMembers) filter (_.isPublic))
- def methods = members.toList filter (_.isMethod)
- def packages = members.toList filter (_.isPackage)
- def aliases = members.toList filter (_.isAliasType)
-
- def memberNames = members map tos
- def methodNames = methods map tos
- def packageNames = packages map tos
- def aliasNames = aliases map tos
- }
-
- object NoTypeCompletion extends TypeMemberCompletion(NoType) {
- override def memberNamed(s: String) = NoSymbol
- override def members = Nil
- override def follow(s: String) = None
- override def alternativesFor(id: String) = Nil
- }
-
- object TypeMemberCompletion {
- def apply(tp: Type, runtimeType: Type, param: NamedParam): TypeMemberCompletion = {
- new TypeMemberCompletion(tp) {
- var upgraded = false
- lazy val upgrade = {
- intp rebind param
- intp.reporter.printMessage("\nRebinding stable value %s from %s to %s".format(param.name, tp, param.tpe))
- upgraded = true
- new TypeMemberCompletion(runtimeType)
- }
- override def completions(verbosity: Int) = {
- super.completions(verbosity) ++ (
- if (verbosity == 0) Nil
- else upgrade.completions(verbosity)
- )
- }
- override def follow(s: String) = super.follow(s) orElse {
- if (upgraded) upgrade.follow(s)
- else None
- }
- override def alternativesFor(id: String) = super.alternativesFor(id) ++ (
- if (upgraded) upgrade.alternativesFor(id)
- else Nil
- ) distinct
- }
- }
- def apply(tp: Type): TypeMemberCompletion = {
- if (tp eq NoType) NoTypeCompletion
- else if (tp.typeSymbol.isPackageClass) new PackageCompletion(tp)
- else new TypeMemberCompletion(tp)
- }
- def imported(tp: Type) = new ImportCompletion(tp)
- }
-
- class TypeMemberCompletion(val tp: Type) extends CompletionAware
- with CompilerCompletion {
- def excludeEndsWith: List[String] = Nil
- def excludeStartsWith: List[String] = List("<") // <byname>, <repeated>, etc.
- def excludeNames: List[String] = (anyref.methodNames filterNot anyRefMethodsToShow) :+ "_root_"
-
- def methodSignatureString(sym: Symbol) = {
- IMain stripString exitingTyper(new MethodSymbolOutput(sym).methodString())
- }
-
- def exclude(name: String): Boolean = (
- (name contains "$") ||
- (excludeNames contains name) ||
- (excludeEndsWith exists (name endsWith _)) ||
- (excludeStartsWith exists (name startsWith _))
- )
- def filtered(xs: List[String]) = xs filterNot exclude distinct
-
- def completions(verbosity: Int) =
- debugging(tp + " completions ==> ")(filtered(memberNames))
-
- override def follow(s: String): Option[CompletionAware] =
- debugging(tp + " -> '" + s + "' ==> ")(Some(TypeMemberCompletion(memberNamed(s).tpe)) filterNot (_ eq NoTypeCompletion))
-
- override def alternativesFor(id: String): List[String] =
- debugging(id + " alternatives ==> ") {
- val alts = members filter (x => x.isMethod && tos(x) == id) map methodSignatureString
-
- if (alts.nonEmpty) "" :: alts else Nil
- }
-
- override def toString = "%s (%d members)".format(tp, members.size)
- }
-
- class PackageCompletion(tp: Type) extends TypeMemberCompletion(tp) {
- override def excludeNames = anyref.methodNames
- }
-
- class LiteralCompletion(lit: Literal) extends TypeMemberCompletion(lit.value.tpe) {
- override def completions(verbosity: Int) = verbosity match {
- case 0 => filtered(memberNames)
- case _ => memberNames
- }
- }
-
- class ImportCompletion(tp: Type) extends TypeMemberCompletion(tp) {
- override def completions(verbosity: Int) = verbosity match {
- case 0 => filtered(members filterNot (_.isSetter) map tos)
- case _ => super.completions(verbosity)
- }
- }
-
- // not for completion but for excluding
- object anyref extends TypeMemberCompletion(AnyRefClass.tpe) { }
-
- // the unqualified vals/defs/etc visible in the repl
- object ids extends CompletionAware {
- override def completions(verbosity: Int) = intp.unqualifiedIds ++ List("classOf") //, "_root_")
- // now we use the compiler for everything.
- override def follow(id: String): Option[CompletionAware] = {
- if (!completions(0).contains(id))
- return None
-
- val tpe = intp typeOfExpression id
- if (tpe == NoType)
- return None
-
- def default = Some(TypeMemberCompletion(tpe))
-
- // only rebinding vals in power mode for now.
- if (!isReplPower) default
- else intp runtimeClassAndTypeOfTerm id match {
- case Some((clazz, runtimeType)) =>
- val sym = intp.symbolOfTerm(id)
- if (sym.isStable) {
- val param = new NamedParam.Untyped(id, intp valueOfTerm id getOrElse null)
- Some(TypeMemberCompletion(tpe, runtimeType, param))
- }
- else default
- case _ =>
- default
- }
- }
- override def toString = "<repl ids> (%s)".format(completions(0).size)
- }
-
- // user-issued wildcard imports like "import global._" or "import String._"
- private def imported = intp.sessionWildcards map TypeMemberCompletion.imported
-
- // literal Ints, Strings, etc.
- object literals extends CompletionAware {
- def simpleParse(code: String): Tree = newUnitParser(code).templateStats().last
- def completions(verbosity: Int) = Nil
-
- override def follow(id: String) = simpleParse(id) match {
- case x: Literal => Some(new LiteralCompletion(x))
- case _ => None
- }
- }
-
- // top level packages
- object rootClass extends TypeMemberCompletion(RootClass.tpe) {
- override def completions(verbosity: Int) = super.completions(verbosity) :+ "_root_"
- override def follow(id: String) = id match {
- case "_root_" => Some(this)
- case _ => super.follow(id)
- }
- }
- // members of Predef
- object predef extends TypeMemberCompletion(PredefModule.tpe) {
- override def excludeEndsWith = super.excludeEndsWith ++ List("Wrapper", "ArrayOps")
- override def excludeStartsWith = super.excludeStartsWith ++ List("wrap")
- override def excludeNames = anyref.methodNames
-
- override def exclude(name: String) = super.exclude(name) || (
- (name contains "2")
- )
-
- override def completions(verbosity: Int) = verbosity match {
- case 0 => Nil
- case _ => super.completions(verbosity)
- }
- }
- // members of scala.*
- object scalalang extends PackageCompletion(ScalaPackage.tpe) {
- def arityClasses = List("Product", "Tuple", "Function")
- def skipArity(name: String) = arityClasses exists (x => name != x && (name startsWith x))
- override def exclude(name: String) = super.exclude(name) || (
- skipArity(name)
- )
-
- override def completions(verbosity: Int) = verbosity match {
- case 0 => filtered(packageNames ++ aliasNames)
- case _ => super.completions(verbosity)
- }
- }
- // members of java.lang.*
- object javalang extends PackageCompletion(JavaLangPackage.tpe) {
- override lazy val excludeEndsWith = super.excludeEndsWith ++ List("Exception", "Error")
- override lazy val excludeStartsWith = super.excludeStartsWith ++ List("CharacterData")
-
- override def completions(verbosity: Int) = verbosity match {
- case 0 => filtered(packageNames)
- case _ => super.completions(verbosity)
- }
- }
-
- // the list of completion aware objects which should be consulted
- // for top level unqualified, it's too noisy to let much in.
- lazy val topLevelBase: List[CompletionAware] = List(ids, rootClass, predef, scalalang, javalang, literals)
- def topLevel = topLevelBase ++ imported
- def topLevelThreshold = 50
-
- // the first tier of top level objects (doesn't include file completion)
- def topLevelFor(parsed: Parsed): List[String] = {
- val buf = new ListBuffer[String]
- topLevel foreach { ca =>
- buf ++= (ca completionsFor parsed)
-
- if (buf.size > topLevelThreshold)
- return buf.toList.sorted
- }
- buf.toList
- }
-
- // the most recent result
- def lastResult = Forwarder(() => ids follow intp.mostRecentVar)
-
- def lastResultFor(parsed: Parsed) = {
- /** The logic is a little tortured right now because normally '.' is
- * ignored as a delimiter, but on .<tab> it needs to be propagated.
- */
- val xs = lastResult completionsFor parsed
- if (parsed.isEmpty) xs map ("." + _) else xs
- }
-
- def completer(): ScalaCompleter = new JLineTabCompletion
-
- /** This gets a little bit hairy. It's no small feat delegating everything
- * and also keeping track of exactly where the cursor is and where it's supposed
- * to end up. The alternatives mechanism is a little hacky: if there is an empty
- * string in the list of completions, that means we are expanding a unique
- * completion, so don't update the "last" buffer because it'll be wrong.
- */
- class JLineTabCompletion extends ScalaCompleter {
- // For recording the buffer on the last tab hit
- private var lastBuf: String = ""
- private var lastCursor: Int = -1
-
- // Does this represent two consecutive tabs?
- def isConsecutiveTabs(buf: String, cursor: Int) =
- cursor == lastCursor && buf == lastBuf
-
- // This is jline's entry point for completion.
- override def complete(buf: String, cursor: Int): Candidates = {
- verbosity = if (isConsecutiveTabs(buf, cursor)) verbosity + 1 else 0
- repldbg("\ncomplete(%s, %d) last = (%s, %d), verbosity: %s".format(buf, cursor, lastBuf, lastCursor, verbosity))
-
- // we don't try lower priority completions unless higher ones return no results.
- def tryCompletion(p: Parsed, completionFunction: Parsed => List[String]): Option[Candidates] = {
- val winners = completionFunction(p)
- if (winners.isEmpty)
- return None
- val newCursor =
- if (winners contains "") p.cursor
- else {
- val advance = longestCommonPrefix(winners)
- lastCursor = p.position + advance.length
- lastBuf = (buf take p.position) + advance
- repldbg("tryCompletion(%s, _) lastBuf = %s, lastCursor = %s, p.position = %s".format(
- p, lastBuf, lastCursor, p.position))
- p.position
- }
-
- Some(Candidates(newCursor, winners))
- }
-
- def mkDotted = Parsed.dotted(buf, cursor) withVerbosity verbosity
-
- // a single dot is special cased to completion on the previous result
- def lastResultCompletion =
- if (!looksLikeInvocation(buf)) None
- else tryCompletion(Parsed.dotted(buf drop 1, cursor), lastResultFor)
-
- def tryAll = (
- lastResultCompletion
- orElse tryCompletion(mkDotted, topLevelFor)
- getOrElse Candidates(cursor, Nil)
- )
-
- /**
- * This is the kickoff point for all manner of theoretically
- * possible compiler unhappiness. The fault may be here or
- * elsewhere, but we don't want to crash the repl regardless.
- * The compiler makes it impossible to avoid catching Throwable
- * with its unfortunate tendency to throw java.lang.Errors and
- * AssertionErrors as the hats drop. We take two swings at it
- * because there are some spots which like to throw an assertion
- * once, then work after that. Yeah, what can I say.
- */
- try tryAll
- catch { case ex: Throwable =>
- repldbg("Error: complete(%s, %s) provoked".format(buf, cursor) + ex)
- Candidates(cursor,
- if (isReplDebug) List("<error:" + ex + ">")
- else Nil
- )
- }
- }
- }
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala b/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala
deleted file mode 100644
index 5d41f1bbb4..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala
+++ /dev/null
@@ -1,68 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Stepan Koltsov
- */
-
-package scala.tools.nsc
-package interpreter
-
-import scala.tools.jline.console.ConsoleReader
-import scala.tools.jline.console.completer._
-import session._
-import Completion._
-
-/**
- * Reads from the console using JLine.
- */
-class JLineReader(_completion: => Completion) extends InteractiveReader {
- val interactive = true
- val consoleReader = new JLineConsoleReader()
-
- lazy val completion = _completion
- lazy val history: JLineHistory = JLineHistory()
-
- private def term = consoleReader.getTerminal()
- def reset() = term.reset()
-
- def scalaToJline(tc: ScalaCompleter): Completer = new Completer {
- def complete(_buf: String, cursor: Int, candidates: JList[CharSequence]): Int = {
- val buf = if (_buf == null) "" else _buf
- val Candidates(newCursor, newCandidates) = tc.complete(buf, cursor)
- newCandidates foreach (candidates add _)
- newCursor
- }
- }
-
- class JLineConsoleReader extends ConsoleReader with ConsoleReaderHelper {
- // working around protected/trait/java insufficiencies.
- def goBack(num: Int): Unit = back(num)
- if ((history: History) ne NoHistory)
- this setHistory history
-
- def readOneKey(prompt: String) = {
- this.print(prompt)
- this.flush()
- this.readVirtualKey()
- }
- def eraseLine() = consoleReader.resetPromptLine("", "", 0)
- def redrawLineAndFlush(): Unit = { flush() ; drawLine() ; flush() }
-
- // A hook for running code after the repl is done initializing.
- lazy val postInit: Unit = {
- this setBellEnabled false
-
- if (completion ne NoCompletion) {
- val argCompletor: ArgumentCompleter =
- new ArgumentCompleter(new JLineDelimiter, scalaToJline(completion.completer()))
- argCompletor setStrict false
-
- this addCompleter argCompletor
- this setAutoprintThreshold 400 // max completion candidates without warning
- }
- }
- }
-
- def redrawLine() = consoleReader.redrawLineAndFlush()
- def readOneLine(prompt: String) = consoleReader readLine prompt
- def readOneKey(prompt: String) = consoleReader readOneKey prompt
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/Logger.scala b/src/compiler/scala/tools/nsc/interpreter/Logger.scala
deleted file mode 100644
index 7407daf8d0..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/Logger.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-trait Logger {
- def isInfo: Boolean
- def isDebug: Boolean
- def isTrace: Boolean
- def out: JPrintWriter
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/LoopCommands.scala b/src/compiler/scala/tools/nsc/interpreter/LoopCommands.scala
deleted file mode 100644
index 4bba27b714..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/LoopCommands.scala
+++ /dev/null
@@ -1,86 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import scala.collection.{ mutable, immutable }
-import mutable.ListBuffer
-import scala.language.implicitConversions
-
-class ProcessResult(val line: String) {
- import scala.sys.process._
- private val buffer = new ListBuffer[String]
-
- val builder = Process(line)
- val logger = ProcessLogger(buffer += _)
- val exitCode = builder ! logger
- def lines = buffer.toList
-
- override def toString = "`%s` (%d lines, exit %d)".format(line, buffer.size, exitCode)
-}
-
-trait LoopCommands {
- protected def out: JPrintWriter
-
- // So outputs can be suppressed.
- def echoCommandMessage(msg: String): Unit = out println msg
-
- // a single interpreter command
- abstract class LoopCommand(val name: String, val help: String) extends (String => Result) {
- def usage: String = ""
- def usageMsg: String = ":" + name + (
- if (usage == "") "" else " " + usage
- )
- def apply(line: String): Result
-
- // called if no args are given
- def showUsage(): Result = {
- "usage is " + usageMsg
- Result(keepRunning = true, None)
- }
- }
- object LoopCommand {
- def nullary(name: String, help: String, f: () => Result): LoopCommand =
- new NullaryCmd(name, help, _ => f())
-
- def cmd(name: String, usage: String, help: String, f: String => Result): LoopCommand =
- if (usage == "") new NullaryCmd(name, help, f)
- else new LineCmd(name, usage, help, f)
- }
-
- class NullaryCmd(name: String, help: String, f: String => Result) extends LoopCommand(name, help) {
- def apply(line: String): Result = f(line)
- }
-
- class LineCmd(name: String, argWord: String, help: String, f: String => Result) extends LoopCommand(name, help) {
- override def usage = argWord
- def apply(line: String): Result = f(line)
- }
-
- class VarArgsCmd(name: String, argWord: String, help: String, f: List[String] => Result)
- extends LoopCommand(name, help) {
- override def usage = argWord
- def apply(line: String): Result = apply(words(line))
- def apply(args: List[String]) = f(args)
- }
-
- // the result of a single command
- case class Result(keepRunning: Boolean, lineToRecord: Option[String])
-
- object Result {
- // the default result means "keep running, and don't record that line"
- val default = Result(keepRunning = true, None)
-
- // most commands do not want to micromanage the Result, but they might want
- // to print something to the console, so we accomodate Unit and String returns.
- implicit def resultFromUnit(x: Unit): Result = default
- implicit def resultFromString(msg: String): Result = {
- echoCommandMessage(msg)
- default
- }
- }
-}
-
diff --git a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala
deleted file mode 100644
index 84a47311e2..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala
+++ /dev/null
@@ -1,219 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Martin Odersky
- */
-
-package scala.tools.nsc
-package interpreter
-
-import scala.collection.{ mutable, immutable }
-import scala.reflect.internal.Flags._
-import scala.language.implicitConversions
-
-trait MemberHandlers {
- val intp: IMain
-
- import intp.{ Request, global, naming }
- import global._
- import naming._
-
- private def codegenln(leadingPlus: Boolean, xs: String*): String = codegen(leadingPlus, (xs ++ Array("\n")): _*)
- private def codegenln(xs: String*): String = codegenln(true, xs: _*)
- private def codegen(leadingPlus: Boolean, xs: String*): String = {
- val front = if (leadingPlus) "+ " else ""
- front + (xs map string2codeQuoted mkString " + ")
- }
- private implicit def name2string(name: Name) = name.toString
-
- /** A traverser that finds all mentioned identifiers, i.e. things
- * that need to be imported. It might return extra names.
- */
- private class ImportVarsTraverser extends Traverser {
- val importVars = new mutable.HashSet[Name]()
-
- override def traverse(ast: Tree) = ast match {
- case Ident(name) =>
- // XXX this is obviously inadequate but it's going to require some effort
- // to get right.
- if (name.toString startsWith "x$") ()
- else importVars += name
- case _ => super.traverse(ast)
- }
- }
- private object ImportVarsTraverser {
- def apply(member: Tree) = {
- val ivt = new ImportVarsTraverser()
- ivt traverse member
- ivt.importVars.toList
- }
- }
-
- private def isTermMacro(ddef: DefDef): Boolean = ddef.mods.isMacro
-
- def chooseHandler(member: Tree): MemberHandler = member match {
- case member: DefDef if isTermMacro(member) => new TermMacroHandler(member)
- case member: DefDef => new DefHandler(member)
- case member: ValDef => new ValHandler(member)
- case member: ModuleDef => new ModuleHandler(member)
- case member: ClassDef => new ClassHandler(member)
- case member: TypeDef => new TypeAliasHandler(member)
- case member: Assign => new AssignHandler(member)
- case member: Import => new ImportHandler(member)
- case DocDef(_, documented) => chooseHandler(documented)
- case member => new GenericHandler(member)
- }
-
- sealed abstract class MemberDefHandler(override val member: MemberDef) extends MemberHandler(member) {
- override def name: Name = member.name
- def mods: Modifiers = member.mods
- def keyword = member.keyword
- def prettyName = name.decode
-
- override def definesImplicit = member.mods.isImplicit
- override def definesTerm: Option[TermName] = Some(name.toTermName) filter (_ => name.isTermName)
- override def definesType: Option[TypeName] = Some(name.toTypeName) filter (_ => name.isTypeName)
- override def definedSymbols = if (symbol eq NoSymbol) Nil else List(symbol)
- }
-
- /** Class to handle one member among all the members included
- * in a single interpreter request.
- */
- sealed abstract class MemberHandler(val member: Tree) {
- def name: Name = nme.NO_NAME
- def path = intp.originalPath(symbol)
- def symbol = if (member.symbol eq null) NoSymbol else member.symbol
- def definesImplicit = false
- def definesValue = false
-
- def definesTerm = Option.empty[TermName]
- def definesType = Option.empty[TypeName]
-
- lazy val referencedNames = ImportVarsTraverser(member)
- def importedNames = List[Name]()
- def definedNames = definesTerm.toList ++ definesType.toList
- def definedSymbols = List[Symbol]()
-
- def extraCodeToEvaluate(req: Request): String = ""
- def resultExtractionCode(req: Request): String = ""
-
- private def shortName = this.getClass.toString split '.' last
- override def toString = shortName + referencedNames.mkString(" (refs: ", ", ", ")")
- }
-
- class GenericHandler(member: Tree) extends MemberHandler(member)
-
- class ValHandler(member: ValDef) extends MemberDefHandler(member) {
- val maxStringElements = 1000 // no need to mkString billions of elements
- override def definesValue = true
-
- override def resultExtractionCode(req: Request): String = {
- val isInternal = isUserVarName(name) && req.lookupTypeOf(name) == "Unit"
- if (!mods.isPublic || isInternal) ""
- else {
- // if this is a lazy val we avoid evaluating it here
- val resultString =
- if (mods.isLazy) codegenln(false, "<lazy>")
- else any2stringOf(path, maxStringElements)
-
- val vidString =
- if (replProps.vids) s"""" + " @ " + "%%8x".format(System.identityHashCode($path)) + " """.trim
- else ""
-
- """ + "%s%s: %s = " + %s""".format(string2code(prettyName), vidString, string2code(req typeOf name), resultString)
- }
- }
- }
-
- class DefHandler(member: DefDef) extends MemberDefHandler(member) {
- override def definesValue = flattensToEmpty(member.vparamss) // true if 0-arity
- override def resultExtractionCode(req: Request) =
- if (mods.isPublic) codegenln(name, ": ", req.typeOf(name)) else ""
- }
-
- abstract class MacroHandler(member: DefDef) extends MemberDefHandler(member) {
- override def definesValue = false
- override def definesTerm: Option[TermName] = Some(name.toTermName)
- override def definesType: Option[TypeName] = None
- override def resultExtractionCode(req: Request) = if (mods.isPublic) codegenln(notification(req)) else ""
- def notification(req: Request): String
- }
-
- class TermMacroHandler(member: DefDef) extends MacroHandler(member) {
- def notification(req: Request) = s"defined term macro $name: ${req.typeOf(name)}"
- }
-
- class AssignHandler(member: Assign) extends MemberHandler(member) {
- val Assign(lhs, rhs) = member
- override lazy val name = newTermName(freshInternalVarName())
-
- override def definesTerm = Some(name)
- override def definesValue = true
- override def extraCodeToEvaluate(req: Request) =
- """val %s = %s""".format(name, lhs)
-
- /** Print out lhs instead of the generated varName */
- override def resultExtractionCode(req: Request) = {
- val lhsType = string2code(req lookupTypeOf name)
- val res = string2code(req fullPath name)
- """ + "%s: %s = " + %s + "\n" """.format(string2code(lhs.toString), lhsType, res) + "\n"
- }
- }
-
- class ModuleHandler(module: ModuleDef) extends MemberDefHandler(module) {
- override def definesTerm = Some(name.toTermName)
- override def definesValue = true
-
- override def resultExtractionCode(req: Request) = codegenln("defined object ", name)
- }
-
- class ClassHandler(member: ClassDef) extends MemberDefHandler(member) {
- override def definedSymbols = List(symbol, symbol.companionSymbol) filterNot (_ == NoSymbol)
- override def definesType = Some(name.toTypeName)
- override def definesTerm = Some(name.toTermName) filter (_ => mods.isCase)
-
- override def resultExtractionCode(req: Request) =
- codegenln("defined %s %s".format(keyword, name))
- }
-
- class TypeAliasHandler(member: TypeDef) extends MemberDefHandler(member) {
- private def isAlias = mods.isPublic && treeInfo.isAliasTypeDef(member)
- override def definesType = Some(name.toTypeName) filter (_ => isAlias)
-
- override def resultExtractionCode(req: Request) =
- codegenln("defined type alias ", name) + "\n"
- }
-
- class ImportHandler(imp: Import) extends MemberHandler(imp) {
- val Import(expr, selectors) = imp
- def targetType = intp.global.rootMirror.getModuleIfDefined("" + expr) match {
- case NoSymbol => intp.typeOfExpression("" + expr)
- case sym => sym.thisType
- }
- private def importableTargetMembers = importableMembers(targetType).toList
- // wildcard imports, e.g. import foo._
- private def selectorWild = selectors filter (_.name == nme.USCOREkw)
- // renamed imports, e.g. import foo.{ bar => baz }
- private def selectorRenames = selectors map (_.rename) filterNot (_ == null)
-
- /** Whether this import includes a wildcard import */
- val importsWildcard = selectorWild.nonEmpty
-
- def implicitSymbols = importedSymbols filter (_.isImplicit)
- def importedSymbols = individualSymbols ++ wildcardSymbols
-
- private val selectorNames = selectorRenames filterNot (_ == nme.USCOREkw) flatMap (_.bothNames) toSet
- lazy val individualSymbols: List[Symbol] = exitingTyper(importableTargetMembers filter (m => selectorNames(m.name)))
- lazy val wildcardSymbols: List[Symbol] = exitingTyper(if (importsWildcard) importableTargetMembers else Nil)
-
- /** Complete list of names imported by a wildcard */
- lazy val wildcardNames: List[Name] = wildcardSymbols map (_.name)
- lazy val individualNames: List[Name] = individualSymbols map (_.name)
-
- /** The names imported by this statement */
- override lazy val importedNames: List[Name] = wildcardNames ++ individualNames
- lazy val importsSymbolNamed: Set[String] = importedNames map (_.toString) toSet
-
- def importString = imp.toString
- override def resultExtractionCode(req: Request) = codegenln(importString) + "\n"
- }
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala b/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala
deleted file mode 100644
index 627a881cae..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala
+++ /dev/null
@@ -1,45 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import NamedParam._
-import scala.language.implicitConversions
-import scala.reflect.runtime.{universe => ru}
-import scala.reflect.{ClassTag, classTag}
-
-trait NamedParamCreator {
- protected def freshName: () => String
-
- def apply[T: ru.TypeTag : ClassTag](name: String, x: T): NamedParam = new Typed[T](name, x)
- def apply[T: ru.TypeTag : ClassTag](x: T): NamedParam = apply(freshName(), x)
- def clazz(name: String, x: Any): NamedParam = new Untyped(name, x)
-
- implicit def tuple[T: ru.TypeTag : ClassTag](pair: (String, T)): NamedParam = apply(pair._1, pair._2)
-}
-
-object NamedParam extends NamedParamCreator {
- class Typed[T: ru.TypeTag : ClassTag](val name: String, val value: T) extends NamedParam {
- val tpe = TypeStrings.fromTag[T]
- }
- class Untyped(val name: String, val value: Any) extends NamedParam {
- val tpe = TypeStrings.fromValue(value)
- }
-
- protected val freshName = {
- var counter = 0
- () => { counter += 1; "p" + counter }
- }
-}
-
-case class NamedParamClass(name: String, tpe: String, value: Any) extends NamedParam { }
-
-trait NamedParam {
- def name: String
- def tpe: String
- def value: Any
- override def toString = name + ": " + tpe
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/Naming.scala b/src/compiler/scala/tools/nsc/interpreter/Naming.scala
deleted file mode 100644
index 57f3675ada..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/Naming.scala
+++ /dev/null
@@ -1,105 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import scala.util.Properties.lineSeparator
-
-/** This is for name logic which is independent of the compiler (notice there's no Global.)
- * That includes at least generating, metaquoting, mangling, and unmangling.
- */
-trait Naming {
- def unmangle(str: String): String = {
- val ESC = '\u001b'
- val cleaned = removeIWPackages(removeLineWrapper(str))
- // Looking to exclude binary data which hoses the terminal, but
- // let through the subset of it we need, like whitespace and also
- // <ESC> for ansi codes.
- val binaryChars = cleaned count (ch => ch < 32 && !ch.isWhitespace && ch != ESC)
- // Lots of binary chars - translate all supposed whitespace into spaces
- // except supposed line endings, otherwise scrubbed lines run together
- if (binaryChars > 5) // more than one can count while holding a hamburger
- cleaned map {
- case c if lineSeparator contains c => c
- case c if c.isWhitespace => ' '
- case c if c < 32 => '?'
- case c => c
- }
- // Not lots - preserve whitespace and ESC
- else
- cleaned map (ch => if (ch.isWhitespace || ch == ESC) ch else if (ch < 32) '?' else ch)
- }
-
- // The two name forms this is catching are the two sides of this assignment:
- //
- // $line3.$read.$iw.$iw.Bippy =
- // $line3.$read$$iw$$iw$Bippy@4a6a00ca
-
- private def noMeta(s: String) = "\\Q" + s + "\\E"
- private lazy val lineRegex = {
- val sn = sessionNames
- val members = List(sn.read, sn.eval, sn.print) map noMeta mkString ("(?:", "|", ")")
- debugging("lineRegex")(noMeta(sn.line) + """\d+[./]""" + members + """[$.]""")
- }
-
- private def removeLineWrapper(s: String) = s.replaceAll(lineRegex, "")
- private def removeIWPackages(s: String) = s.replaceAll("""\$iw[$.]""", "")
-
- trait SessionNames {
- // All values are configurable by passing e.g. -Dscala.repl.name.read=XXX
- final def propOr(name: String): String = propOr(name, "$" + name)
- final def propOr(name: String, default: String): String =
- sys.props.getOrElse("scala.repl.name." + name, default)
-
- // Prefixes used in repl machinery. Default to $line, $read, etc.
- def line = propOr("line")
- def read = propOr("read")
- def eval = propOr("eval")
- def print = propOr("print")
- def result = propOr("result")
-
- // The prefix for unnamed results: by default res0, res1, etc.
- def res = propOr("res", "res") // INTERPRETER_VAR_PREFIX
- // Internal ones
- def ires = propOr("ires")
- }
- lazy val sessionNames: SessionNames = new SessionNames { }
-
- /** Generates names pre0, pre1, etc. via calls to apply method */
- class NameCreator(pre: String) {
- private var x = -1
- var mostRecent: String = ""
-
- def apply(): String = {
- x += 1
- mostRecent = pre + x
- mostRecent
- }
- def reset(): Unit = x = -1
- def didGenerate(name: String) =
- (name startsWith pre) && ((name drop pre.length) forall (_.isDigit))
- }
-
- private lazy val userVar = new NameCreator(sessionNames.res) // var name, like res0
- private lazy val internalVar = new NameCreator(sessionNames.ires) // internal var name, like $ires0
-
- def isUserVarName(name: String) = userVar didGenerate name
- def isInternalVarName(name: String) = internalVar didGenerate name
-
- val freshLineId = {
- var x = 0
- () => { x += 1 ; x }
- }
- def freshUserVarName() = userVar()
- def freshInternalVarName() = internalVar()
-
- def resetAllCreators() {
- userVar.reset()
- internalVar.reset()
- }
-
- def mostRecentVar = userVar.mostRecent
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/Parsed.scala b/src/compiler/scala/tools/nsc/interpreter/Parsed.scala
deleted file mode 100644
index 672a6fd28f..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/Parsed.scala
+++ /dev/null
@@ -1,60 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import util.returning
-
-/** One instance of a command buffer.
- */
-class Parsed private (
- val buffer: String,
- val cursor: Int,
- val delimited: Char => Boolean
-) extends Delimited {
- def isEmpty = args.isEmpty
- def isUnqualified = args.size == 1
- def isAtStart = cursor <= 0
-
- private var _verbosity = 0
-
- def verbosity = _verbosity
- def withVerbosity(v: Int): this.type = returning[this.type](this)(_ => _verbosity = v)
-
- def args = toArgs(buffer take cursor).toList
- def bufferHead = args.head
- def headLength = bufferHead.length + 1
- def bufferTail = new Parsed(buffer drop headLength, cursor - headLength, delimited) withVerbosity verbosity
-
- def prev = new Parsed(buffer, cursor - 1, delimited) withVerbosity verbosity
- def currentChar = buffer(cursor)
- def currentArg = args.last
- def position =
- if (isEmpty) 0
- else if (isLastDelimiter) cursor
- else cursor - currentArg.length
-
- def isFirstDelimiter = !isEmpty && isDelimiterChar(buffer.head)
- def isLastDelimiter = !isEmpty && isDelimiterChar(buffer.last)
-
- def isQuoted = false // TODO
- def isEscaped = !isAtStart && isEscapeChar(currentChar) && !isEscapeChar(prev.currentChar)
- def isDelimiter = !isQuoted && !isEscaped && isDelimiterChar(currentChar)
-
- override def toString = "Parsed(%s / %d)".format(buffer, cursor)
-}
-
-object Parsed {
- val DefaultDelimiters = "[]{},`; \t".toSet
-
- private def onull(s: String) = if (s == null) "" else s
-
- def apply(s: String, cursor: Int): Parsed = apply(onull(s), cursor, DefaultDelimiters)
- def apply(s: String, cursor: Int, delimited: Char => Boolean): Parsed =
- new Parsed(onull(s), cursor, delimited)
-
- def dotted(s: String, cursor: Int): Parsed = new Parsed(onull(s), cursor, _ == '.')
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/Pasted.scala b/src/compiler/scala/tools/nsc/interpreter/Pasted.scala
deleted file mode 100644
index f5db3d9e3a..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/Pasted.scala
+++ /dev/null
@@ -1,101 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-/** If it looks like they're pasting in a scala interpreter
- * transcript, remove all the formatting we inserted so we
- * can make some sense of it.
- *
- * Most of the interesting code in here is due to my goal of
- * "paste idempotence" i.e. the transcript resulting from pasting
- * a transcript should itself be pasteable and should achieve
- * the same result.
- */
-abstract class Pasted {
- def ContinueString: String
- def PromptString: String
- def interpret(line: String): Unit
-
- def matchesPrompt(line: String) = matchesString(line, PromptString)
- def matchesContinue(line: String) = matchesString(line, ContinueString)
- def running = isRunning
-
- private def matchesString(line: String, target: String): Boolean = (
- (line startsWith target) ||
- (line.nonEmpty && " \t".toSet(line.head) && matchesString(line.tail, target))
- )
- private def stripString(line: String, target: String) = line indexOf target match {
- case -1 => line
- case idx => line drop (idx + target.length)
- }
- private var isRunning = false
- private val resReference = """(?<!^)(res\d+)""".r
- private val resCreation = """^\s*(res\d+):.*""".r
- private val resAssign = """^val (res\d+).*""".r
-
- private class PasteAnalyzer(val lines: List[String]) {
- val referenced = lines flatMap (resReference findAllIn _.trim.stripPrefix("res")) toSet
- val cmds = lines reduceLeft append split PromptString filterNot (_.trim == "") toList
-
- /** If it's a prompt or continuation line, strip the formatting bits and
- * assemble the code. Otherwise ship it off to be analyzed for res references
- * and discarded.
- */
- def append(code: String, line: String): String =
- if (matchesPrompt(line)) code + "\n" + line
- else if (matchesContinue(line)) code + "\n" + stripString(line, ContinueString)
- else fixResRefs(code, line)
-
- /** If the line looks like
- * res15: Int
- *
- * and the additional conditions hold that:
- * 1) res15 is referenced from elsewhere in the transcript
- * 2) the preceding repl line is not "val res15 = ..." because that
- * indicates it has already been "val-ified" on a previous paste
- *
- * then we go back in time to the preceding scala> prompt and
- * rewrite the line containing <expr> as
- * val res15 = { <expr> }
- * and the rest as they say is rewritten history.
- *
- * In all other cases, discard the line.
- */
- def fixResRefs(code: String, line: String) = line match {
- case resCreation(resName) if referenced(resName) =>
- code.lastIndexOf(PromptString) match {
- case -1 => code
- case idx =>
- val (str1, str2) = code splitAt (idx + PromptString.length)
- str2 match {
- case resAssign(`resName`) => code
- case _ => "%sval %s = { %s }".format(str1, resName, str2)
- }
- }
- case _ => code
- }
-
- def run() {
- println("// Replaying %d commands from transcript.\n" format cmds.size)
- cmds foreach { cmd =>
- print(PromptString)
- interpret(cmd)
- }
- }
- }
-
- /** Commands start on lines beginning with "scala>" and each successive
- * line which begins with the continuation string is appended to that command.
- * Everything else is discarded. When the end of the transcript is spotted,
- * all the commands are replayed.
- */
- def apply(lines: TraversableOnce[String]) = {
- isRunning = true
- try new PasteAnalyzer(lines.toList) run()
- finally isRunning = false
- }
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/Phased.scala b/src/compiler/scala/tools/nsc/interpreter/Phased.scala
deleted file mode 100644
index f625124e70..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/Phased.scala
+++ /dev/null
@@ -1,143 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import scala.collection.immutable
-import scala.language.implicitConversions
-
-/** Mix this into an object and use it as a phasing
- * swiss army knife.
- */
-trait Phased {
- val global: Global
- import global._
-
- private var active: PhaseName = NoPhaseName
- private var multi: Seq[PhaseName] = Nil
-
- def get = active
- def set(phase: PhaseName): Boolean = phase match {
- case NoPhaseName => false
- case name => active = name ; true
- }
- def setMulti(phases: Seq[PhaseName]): Boolean = {
- if (phases contains NoPhaseName) false
- else {
- multi = phases
- true
- }
- }
-
- private def parsePhaseChange(str: String): Option[Int] = {
- if (str == "") Some(0)
- else if (str startsWith ".prev") parsePhaseChange(str drop 5) map (_ - 1)
- else if (str startsWith ".next") parsePhaseChange(str drop 5) map (_ + 1)
- else str.head match {
- case '+' | '-' =>
- val (num, rest) = str.tail.span(_.isDigit)
- val diff = if (str.head == '+') num.toInt else -num.toInt
- parsePhaseChange(rest) map (_ + diff)
- case _ =>
- None
- }
- }
-
- /** Takes a string like 4, typer+2, typer.next, etc.
- * and turns it into a PhaseName instance.
- */
- private def parseInternal(str: String): PhaseName = {
- if (str == "") NoPhaseName
- else if (str forall (_.isDigit)) PhaseName(str.toInt)
- else {
- val (name, rest) = str.toLowerCase span (_.isLetter)
- val start = PhaseName(name)
- val change = parsePhaseChange(rest)
-
- if (start.isEmpty || change.isEmpty) NoPhaseName
- else PhaseName(start.id + change.get)
- }
- }
- def parse(str: String): PhaseName =
- try parseInternal(str)
- catch { case _: Exception => NoPhaseName }
-
- def atCurrent[T](body: => T): T = enteringPhase(get)(body)
- def multi[T](body: => T): Seq[T] = multi map (ph => at(ph)(body))
-
- def at[T](ph: PhaseName)(body: => T): T = {
- val saved = get
- set(ph)
- try atCurrent(body)
- finally set(saved)
- }
- def atMulti[T](phs: Seq[PhaseName])(body: => T): Seq[T] = {
- val saved = multi
- setMulti(phs)
- try multi(body)
- finally setMulti(saved)
- }
-
- def atMap[T](phs: Seq[PhaseName])(body: => T): Seq[(PhaseName, T)] =
- phs zip atMulti(phs)(body)
-
- object PhaseName {
- implicit lazy val phaseNameOrdering: Ordering[PhaseName] = Ordering[Int] on (_.id)
-
- lazy val all = List(
- Parser, Namer, Packageobjects, Typer, Superaccessors, Pickler, Refchecks,
- Selectiveanf, Liftcode, Selectivecps, Uncurry, Tailcalls, Specialize,
- Explicitouter, Erasure, Lazyvals, Lambdalift, Constructors, Flatten, Mixin,
- Cleanup, Icode, Inliner, Closelim, Dce, Jvm, Terminal
- )
- lazy val nameMap = all.map(x => x.name -> x).toMap withDefaultValue NoPhaseName
- multi = all
-
- def apply(id: Int): PhaseName = all find (_.id == id) getOrElse NoPhaseName
- implicit def apply(s: String): PhaseName = nameMap(s)
- }
- sealed abstract class PhaseName {
- lazy val id = phase.id
- lazy val name = toString.toLowerCase
- def phase = currentRun.phaseNamed(name)
- def isEmpty = this eq NoPhaseName
- }
-
- case object Parser extends PhaseName
- case object Namer extends PhaseName
- case object Packageobjects extends PhaseName
- case object Typer extends PhaseName
- case object Superaccessors extends PhaseName
- case object Pickler extends PhaseName
- case object Refchecks extends PhaseName
- case object Selectiveanf extends PhaseName
- case object Liftcode extends PhaseName
- case object Selectivecps extends PhaseName
- case object Uncurry extends PhaseName
- case object Tailcalls extends PhaseName
- case object Specialize extends PhaseName
- case object Explicitouter extends PhaseName
- case object Erasure extends PhaseName
- case object Lazyvals extends PhaseName
- case object Lambdalift extends PhaseName
- case object Constructors extends PhaseName
- case object Flatten extends PhaseName
- case object Mixin extends PhaseName
- case object Cleanup extends PhaseName
- case object Icode extends PhaseName
- case object Inliner extends PhaseName
- case object Closelim extends PhaseName
- case object Dce extends PhaseName
- case object Jvm extends PhaseName
- case object Terminal extends PhaseName
- case object NoPhaseName extends PhaseName {
- override lazy val id = -1
- override lazy val name = phase.name
- override def phase = NoPhase
- }
-
- implicit def phaseEnumToPhase(name: PhaseName): Phase = name.phase
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/Power.scala b/src/compiler/scala/tools/nsc/interpreter/Power.scala
deleted file mode 100644
index e517a16b32..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/Power.scala
+++ /dev/null
@@ -1,326 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import scala.collection.{ mutable, immutable }
-import scala.util.matching.Regex
-import scala.io.Codec
-import java.net.{ URL, MalformedURLException }
-import io.{ Path }
-import scala.language.implicitConversions
-import scala.reflect.runtime.{universe => ru}
-import scala.reflect.{ClassTag, classTag}
-
-/** Collecting some power mode examples.
-
-scala> trait F[@specialized(Int) T] { def f: T = ??? }
-defined trait F
-
-scala> trait G[@specialized(Long, Int) T] extends F[T] { override def f: T = super.f }
-defined trait G
-
-scala> changesAfterEachPhase(intp("G").info.members filter (_.name.toString contains "super")) >
-Gained after 1/parser {
- method super$f
-}
-
-Gained after 12/specialize {
- method super$f$mcJ$sp
- method super$f$mcI$sp
-}
-
-Lost after 18/flatten {
- method super$f$mcJ$sp
- method super$f$mcI$sp
- method super$f
-}
-*/
-
-/** A class for methods to be injected into the intp in power mode.
- */
-class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, replVals: ReplValsImpl) {
- import intp.{ beQuietDuring, typeOfExpression, interpret, parse }
- import intp.global._
- import definitions.{ compilerTypeFromTag, compilerSymbolFromTag}
-
- abstract class SymSlurper {
- def isKeep(sym: Symbol): Boolean
- def isIgnore(sym: Symbol): Boolean
- def isRecur(sym: Symbol): Boolean
- def isFinished(): Boolean
-
- val keep = mutable.HashSet[Symbol]()
- val seen = mutable.HashSet[Symbol]()
- def processed = keep.size + seen.size
- def discarded = seen.size - keep.size
-
- def members(x: Symbol): List[Symbol] =
- if (x.rawInfo.isComplete) x.info.members.toList
- else Nil
-
- var lastCount = -1
- var pass = 0
- val unseenHistory = new mutable.ListBuffer[Int]
-
- def loop(todo: Set[Symbol]): Set[Symbol] = {
- pass += 1
- val (repeats, unseen) = todo partition seen
- unseenHistory += unseen.size
- if (settings.verbose.value) {
- println("%3d %s accumulated, %s discarded. This pass: %s unseen, %s repeats".format(
- pass, keep.size, discarded, unseen.size, repeats.size))
- }
- if (lastCount == processed || unseen.isEmpty || isFinished())
- return keep.toSet
-
- lastCount = processed
- keep ++= (unseen filter isKeep filterNot isIgnore)
- seen ++= unseen
- loop(unseen filter isRecur flatMap members)
- }
-
- def apply(sym: Symbol): Set[Symbol] = {
- keep.clear()
- seen.clear()
- loop(Set(sym))
- }
- }
-
- class PackageSlurper(packageClass: Symbol) extends SymSlurper {
- /** Looking for dwindling returns */
- def droppedEnough() = unseenHistory.size >= 4 && {
- unseenHistory takeRight 4 sliding 2 forall { it =>
- val List(a, b) = it.toList
- a > b
- }
- }
-
- def isRecur(sym: Symbol) = true
- def isIgnore(sym: Symbol) = sym.isAnonOrRefinementClass || (sym.name.toString contains "$mc")
- def isKeep(sym: Symbol) = sym.hasTransOwner(packageClass)
- def isFinished() = droppedEnough()
- def slurp() = {
- if (packageClass.isPackageClass)
- apply(packageClass)
- else {
- repldbg("Not a package class! " + packageClass)
- Set()
- }
- }
- }
-
- private def customBanner = replProps.powerBanner.option flatMap (f => io.File(f).safeSlurp())
- private def customInit = replProps.powerInitCode.option flatMap (f => io.File(f).safeSlurp())
-
- def banner = customBanner getOrElse """
- |** Power User mode enabled - BEEP WHIR GYVE **
- |** :phase has been set to 'typer'. **
- |** scala.tools.nsc._ has been imported **
- |** global._, definitions._ also imported **
- |** Try :help, :vals, power.<tab> **
- """.stripMargin.trim
-
- private def initImports = List(
- "scala.tools.nsc._",
- "scala.collection.JavaConverters._",
- "intp.global.{ error => _, _ }",
- "definitions.{ getClass => _, _ }",
- "power.rutil._",
- "replImplicits._",
- "treedsl.CODE._"
- )
-
- def init = customInit match {
- case Some(x) => x
- case _ => initImports.mkString("import ", ", ", "")
- }
-
- /** Starts up power mode and runs whatever is in init.
- */
- def unleash(): Unit = beQuietDuring {
- // 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.originalPath("$r") + "._")
- // And whatever else there is to do.
- init.lines foreach (intp interpret _)
- }
-
- trait LowPriorityInternalInfo {
- implicit def apply[T: ru.TypeTag : ClassTag] : InternalInfo[T] = new InternalInfo[T](None)
- }
- object InternalInfo extends LowPriorityInternalInfo { }
-
- /** Now dealing with the problem of acidentally calling a method on Type
- * when you're holding a Symbol and seeing the Symbol converted to the
- * type of Symbol rather than the type of the thing represented by the
- * symbol, by only implicitly installing one method, "?", and the rest
- * of the conveniences exist on that wrapper.
- */
- trait LowPriorityInternalInfoWrapper { }
- class InternalInfoWrapper[T: ru.TypeTag : ClassTag](value: Option[T] = None) {
- def ? : InternalInfo[T] = new InternalInfo[T](value)
- }
-
- /** Todos...
- * translate tag type arguments into applied types
- * customizable symbol filter (had to hardcode no-spec to reduce noise)
- */
- class InternalInfo[T](value: Option[T] = None)(implicit typeEvidence: ru.TypeTag[T], runtimeClassEvidence: ClassTag[T]) {
- private def isSpecialized(s: Symbol) = s.name.toString contains "$mc"
- private def isImplClass(s: Symbol) = s.name.toString endsWith "$class"
-
- /** Standard noise reduction filter. */
- def excludeMember(s: Symbol) = (
- isSpecialized(s)
- || isImplClass(s)
- || s.isAnonOrRefinementClass
- || s.isAnonymousFunction
- )
- def symbol = compilerSymbolFromTag(tag)
- def tpe = compilerTypeFromTag(tag)
- def members = membersUnabridged filterNot excludeMember
- def membersUnabridged = tpe.members.toList
- def pkg = symbol.enclosingPackage
- def tag = typeEvidence
- def runtimeClass = runtimeClassEvidence.runtimeClass
- def shortClass = runtimeClass.getName split "[$.]" last
- def baseClasses = tpe.baseClasses
-
- override def toString = value match {
- case Some(x) => "%s (%s)".format(x, shortClass)
- case _ => runtimeClass.getName
- }
- }
-
- trait LowPriorityPrettifier {
- implicit object AnyPrettifier extends Prettifier[Any] {
- def show(x: Any): Unit = prettify(x) foreach println
- def prettify(x: Any): TraversableOnce[String] = x match {
- case x: Name => List(x.decode)
- case Tuple2(k, v) => List(prettify(k).toIterator ++ Iterator("->") ++ prettify(v) mkString " ")
- case xs: Array[_] => xs.iterator flatMap prettify
- case xs: TraversableOnce[_] => xs flatMap prettify
- case x => List(Prettifier.stringOf(x))
- }
- }
- }
- object StringPrettifier extends Prettifier[String] {
- def show(x: String) = println(x)
- def prettify(x: String) = List(Prettifier stringOf x)
- }
- object Prettifier extends LowPriorityPrettifier {
- def stringOf(x: Any): String = scala.runtime.ScalaRunTime.stringOf(x)
- def default[T] = new Prettifier[T] {
- def prettify(x: T): TraversableOnce[String] = AnyPrettifier prettify x
- def show(x: T): Unit = AnyPrettifier show x
- }
- }
- trait Prettifier[T] {
- def show(x: T): Unit
- def prettify(x: T): TraversableOnce[String]
-
- def prettify(xs: TraversableOnce[T]): TraversableOnce[String] = xs flatMap (x => prettify(x))
- }
-
- abstract class PrettifierClass[T: Prettifier]() {
- val pretty = implicitly[Prettifier[T]]
- def value: Seq[T]
-
- def pp(f: Seq[T] => Seq[T]): Unit =
- pretty prettify f(value) foreach (StringPrettifier show _)
-
- def freq[U](p: T => U) = (value.toSeq groupBy p mapValues (_.size)).toList sortBy (-_._2) map (_.swap)
-
- def >>(implicit ord: Ordering[T]): Unit = pp(_.sorted)
- def >!(): Unit = pp(_.distinct)
- def >(): Unit = pp(identity)
- }
-
- class MultiPrettifierClass[T: Prettifier](val value: Seq[T]) extends PrettifierClass[T]() { }
- class SinglePrettifierClass[T: Prettifier](single: T) extends PrettifierClass[T]() {
- val value = List(single)
- }
-
- class RichReplString(s: String) {
- // make an url out of the string
- def u: URL = (
- if (s contains ":") new URL(s)
- else if (new JFile(s) exists) new JFile(s).toURI.toURL
- else new URL("http://" + s)
- )
- }
- class RichInputStream(in: InputStream)(implicit codec: Codec) {
- def bytes(): Array[Byte] = io.Streamable.bytes(in)
- def slurp(): String = io.Streamable.slurp(in)
- def <<(): String = slurp()
- }
- class RichReplURL(url: URL)(implicit codec: Codec) {
- def slurp(): String = io.Streamable.slurp(url)
- }
-
- trait Implicits1 {
- // fallback
- implicit def replPrinting[T](x: T)(implicit pretty: Prettifier[T] = Prettifier.default[T]) =
- new SinglePrettifierClass[T](x)
- }
- trait Implicits2 extends Implicits1 {
- class RichSymbol(sym: Symbol) {
- // convenient type application
- def apply(targs: Type*): Type = typeRef(NoPrefix, sym, targs.toList)
- }
- object symbolSubtypeOrdering extends Ordering[Symbol] {
- def compare(s1: Symbol, s2: Symbol) =
- if (s1 eq s2) 0
- else if (s1 isLess s2) -1
- else 1
- }
- implicit lazy val powerSymbolOrdering: Ordering[Symbol] = Ordering[Name] on (_.name)
- implicit lazy val powerTypeOrdering: Ordering[Type] = Ordering[Symbol] on (_.typeSymbol)
-
- implicit def replInternalInfo[T: ru.TypeTag : ClassTag](x: T): InternalInfoWrapper[T] = new InternalInfoWrapper[T](Some(x))
- implicit def replEnhancedStrings(s: String): RichReplString = new RichReplString(s)
- implicit def replMultiPrinting[T: Prettifier](xs: TraversableOnce[T]): MultiPrettifierClass[T] =
- new MultiPrettifierClass[T](xs.toSeq)
- implicit def replPrettifier[T] : Prettifier[T] = Prettifier.default[T]
- implicit def replTypeApplication(sym: Symbol): RichSymbol = new RichSymbol(sym)
-
- implicit def replInputStream(in: InputStream)(implicit codec: Codec) = new RichInputStream(in)
- implicit def replEnhancedURLs(url: URL)(implicit codec: Codec): RichReplURL = new RichReplURL(url)(codec)
- }
-
- trait ReplUtilities {
- def module[T: ru.TypeTag] = ru.typeOf[T].typeSymbol.suchThat(_.isPackage)
- def clazz[T: ru.TypeTag] = ru.typeOf[T].typeSymbol.suchThat(_.isClass)
- def info[T: ru.TypeTag : ClassTag] = InternalInfo[T]
- def ?[T: ru.TypeTag : ClassTag] = InternalInfo[T]
- def sanitize(s: String): String = sanitize(s.getBytes())
- def sanitize(s: Array[Byte]): String = (s map {
- case x if x.toChar.isControl => '?'
- case x => x.toChar
- }).mkString
-
- def strings(s: Seq[Byte]): List[String] = {
- if (s.length == 0) Nil
- else s dropWhile (_.toChar.isControl) span (x => !x.toChar.isControl) match {
- case (next, rest) => next.map(_.toChar).mkString :: strings(rest)
- }
- }
- }
-
- lazy val rutil: ReplUtilities = new ReplUtilities { }
- lazy val phased: Phased = new { val global: intp.global.type = intp.global } with Phased { }
-
- def unit(code: String) = newCompilationUnit(code)
- def trees(code: String) = parse(code) getOrElse Nil
-
- override def toString = s"""
- |** Power mode status **
- |Default phase: ${phased.get}
- |Names: ${intp.unqualifiedIds mkString " "}
- """.stripMargin
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplConfig.scala b/src/compiler/scala/tools/nsc/interpreter/ReplConfig.scala
deleted file mode 100644
index 3392ea0b5e..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/ReplConfig.scala
+++ /dev/null
@@ -1,49 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import scala.util.control.ControlThrowable
-import util.Exceptional.unwrap
-import util.stackTraceString
-
-trait ReplConfig {
- lazy val replProps = new ReplProps
-
- class TapMaker[T](x: T) {
- def tapDebug(msg: => String): T = tap(x => repldbg(parens(x)))
- def tap[U](f: T => U): T = {
- f(x)
- x
- }
- }
-
- private def parens(x: Any) = "(" + x + ")"
- private def echo(msg: => String) =
- try Console println msg
- catch { case x: AssertionError => Console.println("Assertion error printing debugging output: " + x) }
-
- private[nsc] def repldbg(msg: => String) = if (isReplDebug) echo(msg)
- private[nsc] def repltrace(msg: => String) = if (isReplTrace) echo(msg)
- private[nsc] def replinfo(msg: => String) = if (isReplInfo) echo(msg)
-
- private[nsc] def logAndDiscard[T](label: String, alt: => T): PartialFunction[Throwable, T] = {
- case t: ControlThrowable => throw t
- case t: Throwable =>
- repldbg(label + ": " + unwrap(t))
- repltrace(stackTraceString(unwrap(t)))
- alt
- }
- private[nsc] def substituteAndLog[T](label: String, alt: => T)(body: => T): T = {
- try body
- catch logAndDiscard(label, alt)
- }
-
- def isReplTrace: Boolean = replProps.trace
- def isReplDebug: Boolean = replProps.debug || isReplTrace
- def isReplInfo: Boolean = replProps.info || isReplDebug
- def isReplPower: Boolean = replProps.power
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplDir.scala b/src/compiler/scala/tools/nsc/interpreter/ReplDir.scala
deleted file mode 100644
index 5d386b47b7..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/ReplDir.scala
+++ /dev/null
@@ -1,48 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import io.VirtualDirectory
-import settings.MutableSettings
-import scala.reflect.io.{ AbstractFile, PlainDirectory, Directory }
-import scala.collection.generic.Clearable
-
-/** Directory to save .class files to. */
-trait ReplDir extends AbstractFile with Clearable { }
-
-private class ReplVirtualDir() extends VirtualDirectory("(memory)", None) with ReplDir { }
-private class ReplRealDir(dir: Directory) extends PlainDirectory(dir) with ReplDir {
- def clear() = {
- dir.deleteRecursively()
- dir.createDirectory()
- }
-}
-
-class ReplOutput(val dirSetting: MutableSettings#StringSetting) {
- // outdir for generated classfiles - may be in-memory (the default),
- // a generated temporary directory, or a specified outdir.
- val dir: ReplDir = (
- if (dirSetting.isDefault)
- new ReplVirtualDir()
- else if (dirSetting.value == "")
- new ReplRealDir(Directory.makeTemp("repl"))
- else
- new ReplRealDir(Directory(dirSetting.value))
- )
-
- // print the contents hierarchically
- def show(out: JPrintWriter) = {
- def pp(root: AbstractFile, indentLevel: Int) {
- val label = root.name
- val spaces = " " * indentLevel
- out.println(spaces + label)
- if (root.isDirectory)
- root.toList sortBy (_.name) foreach (x => pp(x, indentLevel + 1))
- }
- pp(dir, 0)
- }
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplGlobal.scala b/src/compiler/scala/tools/nsc/interpreter/ReplGlobal.scala
deleted file mode 100644
index 0eabd84234..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/ReplGlobal.scala
+++ /dev/null
@@ -1,56 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import typechecker.Analyzer
-
-/** A layer on top of Global so I can guarantee some extra
- * functionality for the repl. It doesn't do much yet.
- */
-trait ReplGlobal extends Global {
- // This exists mostly because using the reporter too early leads to deadlock.
- private def echo(msg: String) { Console println msg }
-
- override def abort(msg: String): Nothing = {
- echo("ReplGlobal.abort: " + msg)
- super.abort(msg)
- }
-
- override lazy val analyzer = new {
- val global: ReplGlobal.this.type = ReplGlobal.this
- } with Analyzer {
- override def newTyper(context: Context): Typer = new Typer(context) {
- override def typed(tree: Tree, mode: Mode, pt: Type): Tree = {
- val res = super.typed(tree, mode, pt)
- tree match {
- case Ident(name) if !tree.symbol.hasPackageFlag && !name.toString.startsWith("$") =>
- repldbg("typed %s: %s".format(name, res.tpe))
- case _ =>
- }
- res
- }
- }
- }
-
- object replPhase extends SubComponent {
- val global: ReplGlobal.this.type = ReplGlobal.this
- val phaseName = "repl"
- val runsAfter = List[String]("typer")
- val runsRightAfter = None
- def newPhase(_prev: Phase): StdPhase = new StdPhase(_prev) {
- def apply(unit: CompilationUnit) {
- repldbg("Running replPhase on " + unit.body)
- // newNamer(rootContext(unit)).enterSym(unit.body)
- }
- }
- }
-
- override protected def computePhaseDescriptors: List[SubComponent] = {
- addToPhasesSet(replPhase, "repl")
- super.computePhaseDescriptors
- }
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplProps.scala b/src/compiler/scala/tools/nsc/interpreter/ReplProps.scala
deleted file mode 100644
index 2364918494..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/ReplProps.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import scala.sys._
-import Prop._
-
-class ReplProps {
- private def bool(name: String) = BooleanProp.keyExists(name)
- private def int(name: String) = IntProp(name)
-
- val info = bool("scala.repl.info")
- val debug = bool("scala.repl.debug")
- val trace = bool("scala.repl.trace")
- val power = bool("scala.repl.power")
-
- val replAutorunCode = Prop[JFile]("scala.repl.autoruncode")
- val powerInitCode = Prop[JFile]("scala.repl.power.initcode")
- val powerBanner = Prop[JFile]("scala.repl.power.banner")
-
- val vids = bool("scala.repl.vids")
- val maxPrintString = int("scala.repl.maxprintstring")
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplReporter.scala b/src/compiler/scala/tools/nsc/interpreter/ReplReporter.scala
deleted file mode 100644
index b20166d070..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/ReplReporter.scala
+++ /dev/null
@@ -1,34 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2002-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import reporters._
-import IMain._
-
-/** Like ReplGlobal, a layer for ensuring extra functionality.
- */
-class ReplReporter(intp: IMain) extends ConsoleReporter(intp.settings, Console.in, new ReplStrippingWriter(intp)) {
- def printUntruncatedMessage(msg: String) = withoutTruncating(printMessage(msg))
-
- override def printMessage(msg: String) {
- // Avoiding deadlock if the compiler starts logging before
- // the lazy val is complete.
- if (intp.isInitializeComplete) {
- if (intp.totalSilence) {
- if (isReplTrace)
- super.printMessage("[silent] " + msg)
- }
- else super.printMessage(msg)
- }
- else Console.println("[init] " + msg)
- }
-
- override def displayPrompt() {
- if (intp.totalSilence) ()
- else super.displayPrompt()
- }
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplStrings.scala b/src/compiler/scala/tools/nsc/interpreter/ReplStrings.scala
deleted file mode 100644
index 08472bbc64..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/ReplStrings.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import scala.reflect.internal.Chars
-
-trait ReplStrings {
- /** Convert a string into code that can recreate the string.
- * This requires replacing all special characters by escape
- * codes. It does not add the surrounding " marks. */
- def string2code(str: String): String = {
- val res = new StringBuilder
- for (c <- str) c match {
- case '"' | '\'' | '\\' => res += '\\' ; res += c
- case _ if c.isControl => res ++= Chars.char2uescape(c)
- case _ => res += c
- }
- res.toString
- }
-
- def string2codeQuoted(str: String) =
- "\"" + string2code(str) + "\""
-
- def any2stringOf(x: Any, maxlen: Int) =
- "scala.runtime.ScalaRunTime.replStringOf(%s, %s)".format(x, maxlen)
-
- def words(s: String) = s.trim split "\\s+" filterNot (_ == "") toList
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala b/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala
deleted file mode 100644
index ea100b25f2..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala
+++ /dev/null
@@ -1,82 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import scala.language.implicitConversions
-import scala.reflect.api.{Universe => ApiUniverse}
-import scala.reflect.runtime.{universe => ru}
-
-/** A class which the repl utilizes to expose predefined objects.
- * The base implementation is empty; the standard repl implementation
- * is StdReplVals.
- */
-abstract class ReplVals { }
-
-class StdReplVals(final val r: ILoop) extends ReplVals {
- final lazy val repl = r
- final lazy val intp = r.intp
- final lazy val power = r.power
- final lazy val reader = r.in
- final lazy val vals = this
- final lazy val global: intp.global.type = intp.global
- final lazy val isettings = intp.isettings
- final lazy val completion = reader.completion
- final lazy val history = reader.history
- final lazy val phased = power.phased
- final lazy val analyzer = global.analyzer
-
- object treedsl extends { val global: intp.global.type = intp.global } with ast.TreeDSL { }
-
- final lazy val typer = analyzer.newTyper(
- analyzer.rootContext(
- power.unit("").asInstanceOf[analyzer.global.CompilationUnit]
- )
- )
- def lastRequest = intp.lastRequest
-
- class ReplImplicits extends power.Implicits2 {
- import intp.global._
-
- private val tagFn = ReplVals.mkCompilerTypeFromTag[intp.global.type](global)
- implicit def mkCompilerTypeFromTag(sym: Symbol) = tagFn(sym)
- }
-
- final lazy val replImplicits = new ReplImplicits
-
- def typed[T <: analyzer.global.Tree](tree: T): T = typer.typed(tree).asInstanceOf[T]
-}
-
-object ReplVals {
- /** Latest attempt to work around the challenge of foo.global.Type
- * not being seen as the same type as bar.global.Type even though
- * the globals are the same. Dependent method types to the rescue.
- */
- def mkCompilerTypeFromTag[T <: Global](global: T) = {
- import global._
-
- /** We can't use definitions.compilerTypeFromTag directly because we're passing
- * it to map and the compiler refuses to perform eta expansion on a method
- * with a dependent return type. (Can this be relaxed?) To get around this
- * I have this forwarder which widens the type and then cast the result back
- * to the dependent type.
- */
- def compilerTypeFromTag(t: ApiUniverse # WeakTypeTag[_]): Global#Type =
- definitions.compilerTypeFromTag(t)
-
- class AppliedTypeFromTags(sym: Symbol) {
- def apply[M](implicit m1: ru.TypeTag[M]): Type =
- if (sym eq NoSymbol) NoType
- else appliedType(sym, compilerTypeFromTag(m1).asInstanceOf[Type])
-
- def apply[M1, M2](implicit m1: ru.TypeTag[M1], m2: ru.TypeTag[M2]): Type =
- if (sym eq NoSymbol) NoType
- else appliedType(sym, compilerTypeFromTag(m1).asInstanceOf[Type], compilerTypeFromTag(m2).asInstanceOf[Type])
- }
-
- (sym: Symbol) => new AppliedTypeFromTags(sym)
- }
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/Results.scala b/src/compiler/scala/tools/nsc/interpreter/Results.scala
deleted file mode 100644
index e400906a58..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/Results.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Martin Odersky
- */
-
-package scala.tools.nsc
-package interpreter
-
-object Results {
- /** A result from the Interpreter interpreting one line of input. */
- abstract sealed class Result
-
- /** The line was interpreted successfully. */
- case object Success extends Result
-
- /** The line was erroneous in some way. */
- case object Error extends Result
-
- /** The input was incomplete. The caller should request more input.
- */
- case object Incomplete extends Result
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/RichClass.scala b/src/compiler/scala/tools/nsc/interpreter/RichClass.scala
deleted file mode 100644
index 36cdf65510..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/RichClass.scala
+++ /dev/null
@@ -1,36 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import scala.reflect.{ ClassTag, classTag }
-
-class RichClass[T](val clazz: Class[T]) {
- def toTag: ClassTag[T] = ClassTag[T](clazz)
-
- // Sadly isAnonymousClass does not return true for scala anonymous
- // classes because our naming scheme is not doing well against the
- // jvm's many assumptions.
- def isScalaAnonymous = (
- try clazz.isAnonymousClass || (clazz.getName contains "$anon$")
- catch { case _: java.lang.InternalError => false } // good ol' "Malformed class name"
- )
-
- def supertags: List[ClassTag[_]] = supers map (_.toTag)
- def superNames: List[String] = supers map (_.getName)
- def interfaces: List[JClass] = supers filter (_.isInterface)
-
- def hasAncestorName(f: String => Boolean) = superNames exists f
- def hasAncestor(f: JClass => Boolean) = supers exists f
-
- def supers: List[JClass] = {
- def loop(x: JClass): List[JClass] = x.getSuperclass match {
- case null => List(x)
- case sc => x :: (x.getInterfaces.toList flatMap loop) ++ loop(sc)
- }
- loop(clazz).distinct
- }
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala b/src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala
deleted file mode 100644
index 2d0917d91f..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala
+++ /dev/null
@@ -1,40 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Stepan Koltsov
- */
-
-package scala.tools.nsc
-package interpreter
-
-import java.io.{ BufferedReader }
-import session.NoHistory
-
-/** Reads using standard JDK API */
-class SimpleReader(
- in: BufferedReader,
- out: JPrintWriter,
- val interactive: Boolean)
-extends InteractiveReader
-{
- val history = NoHistory
- val completion = NoCompletion
-
- def reset() = ()
- def redrawLine() = ()
- def readOneLine(prompt: String): String = {
- if (interactive) {
- out.print(prompt)
- out.flush()
- }
- in.readLine()
- }
- def readOneKey(prompt: String) = sys.error("No char-based input in SimpleReader")
-}
-
-object SimpleReader {
- def defaultIn = Console.in
- def defaultOut = new JPrintWriter(Console.out)
-
- def apply(in: BufferedReader = defaultIn, out: JPrintWriter = defaultOut, interactive: Boolean = true): SimpleReader =
- new SimpleReader(in, out, interactive)
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/package.scala b/src/compiler/scala/tools/nsc/interpreter/package.scala
deleted file mode 100644
index 52a085080b..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/package.scala
+++ /dev/null
@@ -1,157 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-
-import scala.language.implicitConversions
-import scala.reflect.{ classTag, ClassTag }
-import scala.reflect.runtime.{ universe => ru }
-import scala.reflect.{ClassTag, classTag}
-import scala.reflect.api.{Mirror, TypeCreator, Universe => ApiUniverse}
-
-/** The main REPL related classes and values are as follows.
- * In addition to standard compiler classes Global and Settings, there are:
- *
- * History: an interface for session history.
- * Completion: an interface for tab completion.
- * ILoop (formerly InterpreterLoop): The umbrella class for a session.
- * IMain (formerly Interpreter): Handles the evolving state of the session
- * and handles submitting code to the compiler and handling the output.
- * InteractiveReader: how ILoop obtains input.
- * History: an interface for session history.
- * Completion: an interface for tab completion.
- * Power: a repository for more advanced/experimental features.
- *
- * ILoop contains { in: InteractiveReader, intp: IMain, settings: Settings, power: Power }
- * InteractiveReader contains { history: History, completion: Completion }
- * IMain contains { global: Global }
- */
-package object interpreter extends ReplConfig with ReplStrings {
- type JFile = java.io.File
- type JClass = java.lang.Class[_]
- type JList[T] = java.util.List[T]
- type JCollection[T] = java.util.Collection[T]
- type JPrintWriter = java.io.PrintWriter
- type InputStream = java.io.InputStream
- type OutputStream = java.io.OutputStream
-
- val IR = Results
-
- implicit def postfixOps = scala.language.postfixOps // make all postfix ops in this package compile without warning
-
- private[interpreter] implicit def javaCharSeqCollectionToScala(xs: JCollection[_ <: CharSequence]): List[String] = {
- import scala.collection.JavaConverters._
- xs.asScala.toList map ("" + _)
- }
-
- private[nsc] implicit def enrichClass[T](clazz: Class[T]) = new RichClass[T](clazz)
- private[nsc] implicit def enrichAnyRefWithTap[T](x: T) = new TapMaker(x)
- private[nsc] def debugging[T](msg: String)(x: T) = x.tapDebug(msg)
-
- private val ourClassloader = getClass.getClassLoader
-
- def staticTypeTag[T: ClassTag]: ru.TypeTag[T] = ru.TypeTag[T](
- ru.runtimeMirror(ourClassloader),
- new TypeCreator {
- def apply[U <: ApiUniverse with Singleton](m: Mirror[U]): U # Type =
- m.staticClass(classTag[T].runtimeClass.getName).toTypeConstructor.asInstanceOf[U # Type]
- })
-
- /** This class serves to trick the compiler into treating a var
- * (intp, in ILoop) as a stable identifier.
- */
- implicit class IMainOps(val intp: IMain) {
- import intp._
- import global.{ reporter => _, _ }
- import definitions._
-
- protected def echo(msg: String) = {
- Console.out println msg
- Console.out.flush()
- }
-
- def implicitsCommand(line: String): String = {
- def p(x: Any) = intp.reporter.printMessage("" + x)
-
- // If an argument is given, only show a source with that
- // in its name somewhere.
- val args = line split "\\s+"
- val filtered = intp.implicitSymbolsBySource filter {
- case (source, syms) =>
- (args contains "-v") || {
- if (line == "") (source.fullName.toString != "scala.Predef")
- else (args exists (source.name.toString contains _))
- }
- }
-
- if (filtered.isEmpty)
- return "No implicits have been imported other than those in Predef."
-
- filtered foreach {
- case (source, syms) =>
- p("/* " + syms.size + " implicit members imported from " + source.fullName + " */")
-
- // This groups the members by where the symbol is defined
- val byOwner = syms groupBy (_.owner)
- val sortedOwners = byOwner.toList sortBy { case (owner, _) => exitingTyper(source.info.baseClasses indexOf owner) }
-
- sortedOwners foreach {
- case (owner, members) =>
- // Within each owner, we cluster results based on the final result type
- // if there are more than a couple, and sort each cluster based on name.
- // This is really just trying to make the 100 or so implicits imported
- // by default into something readable.
- val memberGroups: List[List[Symbol]] = {
- val groups = members groupBy (_.tpe.finalResultType) toList
- val (big, small) = groups partition (_._2.size > 3)
- val xss = (
- (big sortBy (_._1.toString) map (_._2)) :+
- (small flatMap (_._2))
- )
-
- xss map (xs => xs sortBy (_.name.toString))
- }
-
- val ownerMessage = if (owner == source) " defined in " else " inherited from "
- p(" /* " + members.size + ownerMessage + owner.fullName + " */")
-
- memberGroups foreach { group =>
- group foreach (s => p(" " + intp.symbolDefString(s)))
- p("")
- }
- }
- p("")
- }
- ""
- }
-
- /** TODO -
- * -n normalize
- * -l label with case class parameter names
- * -c complete - leave nothing out
- */
- def typeCommandInternal(expr: String, verbose: Boolean): Unit =
- symbolOfLine(expr) andAlso (echoTypeSignature(_, verbose))
-
- def printAfterTyper(msg: => String) =
- reporter printUntruncatedMessage exitingTyper(msg)
-
- private def replInfo(sym: Symbol) =
- if (sym.isAccessor) dropNullaryMethod(sym.info) else sym.info
-
- def echoTypeStructure(sym: Symbol) =
- printAfterTyper("" + deconstruct.show(replInfo(sym)))
-
- def echoTypeSignature(sym: Symbol, verbose: Boolean) = {
- if (verbose) echo("// Type signature")
- printAfterTyper("" + replInfo(sym))
-
- if (verbose) {
- echo("\n// Internal Type structure")
- echoTypeStructure(sym)
- }
- }
- }
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/session/FileBackedHistory.scala b/src/compiler/scala/tools/nsc/interpreter/session/FileBackedHistory.scala
deleted file mode 100644
index dddfb1b8f6..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/session/FileBackedHistory.scala
+++ /dev/null
@@ -1,84 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-package session
-
-import scala.tools.nsc.io._
-import FileBackedHistory._
-
-/** TODO: file locking.
- */
-trait FileBackedHistory extends JLineHistory with JPersistentHistory {
- def maxSize: Int
- protected lazy val historyFile: File = defaultFile
- private var isPersistent = true
-
- locally {
- load()
- }
-
- def withoutSaving[T](op: => T): T = {
- val saved = isPersistent
- isPersistent = false
- try op
- finally isPersistent = saved
- }
- def addLineToFile(item: CharSequence): Unit = {
- if (isPersistent)
- append(item + "\n")
- }
-
- /** Overwrites the history file with the current memory. */
- protected def sync(): Unit = {
- val lines = asStrings map (_ + "\n")
- historyFile.writeAll(lines: _*)
- }
- /** Append one or more lines to the history file. */
- protected def append(lines: String*): Unit = {
- historyFile.appendAll(lines: _*)
- }
-
- def load(): Unit = {
- if (!historyFile.canRead)
- historyFile.createFile()
-
- val lines: IndexedSeq[String] = {
- try historyFile.lines().toIndexedSeq
- catch {
- // It seems that control characters in the history file combined
- // with the default codec can lead to nio spewing exceptions. Rather
- // than abandon hope we'll try to read it as ISO-8859-1
- case _: Exception =>
- try historyFile.lines("ISO-8859-1").toIndexedSeq
- catch { case _: Exception => Vector() }
- }
- }
-
- repldbg("Loading " + lines.size + " into history.")
-
- // avoid writing to the history file
- withoutSaving(lines takeRight maxSize foreach add)
- // truncate the history file if it's too big.
- if (lines.size > maxSize) {
- repldbg("File exceeds maximum size: truncating to " + maxSize + " entries.")
- sync()
- }
- moveToEnd()
- }
-
- def flush(): Unit = ()
- def purge(): Unit = historyFile.truncate()
-}
-
-object FileBackedHistory {
- // val ContinuationChar = '\003'
- // val ContinuationNL: String = Array('\003', '\n').mkString
- import Properties.userHome
-
- def defaultFileName = ".scala_history"
- def defaultFile: File = File(Path(userHome) / defaultFileName)
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/session/History.scala b/src/compiler/scala/tools/nsc/interpreter/session/History.scala
deleted file mode 100644
index 794d41adc7..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/session/History.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-package session
-
-/** An implementation-agnostic history interface which makes no
- * reference to the jline classes. Very sparse right now.
- */
-trait History {
- def asStrings: List[String]
- def index: Int
- def size: Int
-}
-object NoHistory extends History {
- def asStrings = Nil
- def index = 0
- def size = 0
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/session/JLineHistory.scala b/src/compiler/scala/tools/nsc/interpreter/session/JLineHistory.scala
deleted file mode 100644
index 18e0ee7c85..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/session/JLineHistory.scala
+++ /dev/null
@@ -1,49 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-package session
-
-/** A straight scalification of the jline interface which mixes
- * in the sparse jline-independent one too.
- */
-trait JLineHistory extends JHistory with History {
- def size: Int
- def isEmpty: Boolean
- def index: Int
- def clear(): Unit
- def get(index: Int): CharSequence
- def add(line: CharSequence): Unit
- def replace(item: CharSequence): Unit
-
- def entries(index: Int): JListIterator[JEntry]
- def entries(): JListIterator[JEntry]
- def iterator: JIterator[JEntry]
-
- def current(): CharSequence
- def previous(): Boolean
- def next(): Boolean
- def moveToFirst(): Boolean
- def moveToLast(): Boolean
- def moveTo(index: Int): Boolean
- def moveToEnd(): Unit
-}
-
-object JLineHistory {
- class JLineFileHistory extends SimpleHistory with FileBackedHistory {
- override def add(item: CharSequence): Unit = {
- if (!isEmpty && last == item)
- repldbg("Ignoring duplicate entry '" + item + "'")
- else {
- super.add(item)
- addLineToFile(item)
- }
- }
- override def toString = "History(size = " + size + ", index = " + index + ")"
- }
-
- def apply(): JLineHistory = try new JLineFileHistory catch { case x: Exception => new SimpleHistory() }
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/session/SimpleHistory.scala b/src/compiler/scala/tools/nsc/interpreter/session/SimpleHistory.scala
deleted file mode 100644
index 89998e438a..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/session/SimpleHistory.scala
+++ /dev/null
@@ -1,58 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-package session
-
-import scala.collection.mutable.{ Buffer, ListBuffer }
-import scala.collection.JavaConverters._
-
-class SimpleHistory extends JLineHistory {
- private var _index: Int = 0
- private val buf: Buffer[String] = new ListBuffer[String]
- private def toEntries(): Seq[JEntry] = buf.zipWithIndex map { case (x, i) => Entry(i, x) }
- private def setTo(num: Int) = { _index = num ; true }
- private def minusOne = { _index -= 1 ; true }
- private def plusOne = { _index += 1 ; true }
- private def lastIndex = size - 1
- private def fail(msg: String): String = {
- repldbg("Internal error in history(size %d, index %d): %s".format(
- size, index, msg)
- )
- ""
- }
-
- case class Entry(index: Int, value: CharSequence) extends JEntry {
- override def toString = value
- }
-
- def maxSize: Int = 2500
- def last = if (isEmpty) fail("last") else buf.last
-
- def size = buf.size
- def index = _index
- def isEmpty = buf.isEmpty
- def clear() = buf.clear()
- def get(idx: Int): CharSequence = buf(idx)
- def add(item: CharSequence): Unit = buf += item
- def replace(item: CharSequence): Unit = {
- buf trimEnd 1
- add(item)
- }
- def entries(idx: Int): JListIterator[JEntry] = toEntries().asJava.listIterator(idx)
- def entries(): JListIterator[JEntry] = toEntries().asJava.listIterator()
- def iterator: JIterator[JEntry] = toEntries().iterator.asJava
-
- def current() = if (index >= 0 && index < buf.size) buf(index) else fail("current()")
- def previous() = (index > 0) && minusOne
- def next() = (index <= lastIndex) && plusOne
- def moveToFirst() = (size > 0) && (index != 0) && setTo(0)
- def moveToLast() = (size > 0) && (index < lastIndex) && setTo(lastIndex)
- def moveTo(idx: Int) = (idx > 0) && (idx <= lastIndex) && setTo(idx)
- def moveToEnd(): Unit = setTo(size)
-
- def asStrings = buf.toList
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/session/package.scala b/src/compiler/scala/tools/nsc/interpreter/session/package.scala
deleted file mode 100644
index c62cf21151..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/session/package.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-import scala.language.implicitConversions
-
-/** Files having to do with the state of a repl session:
- * lines of text entered, types and terms defined, etc.
- */
-package object session {
- type JIterator[T] = java.util.Iterator[T]
- type JListIterator[T] = java.util.ListIterator[T]
-
- type JEntry = scala.tools.jline.console.history.History.Entry
- type JHistory = scala.tools.jline.console.history.History
- type JMemoryHistory = scala.tools.jline.console.history.MemoryHistory
- type JPersistentHistory = scala.tools.jline.console.history.PersistentHistory
-
- private[interpreter] implicit def charSequenceFix(x: CharSequence): String = x.toString
-}
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index 2aee9bd4bc..9469113238 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -188,7 +188,6 @@ trait ScalaSettings extends AbsScalaSettings
val Ypmatdebug = BooleanSetting("-Ypmat-debug", "Trace all pattern matcher activity.")
val Yposdebug = BooleanSetting("-Ypos-debug", "Trace position validation.")
val Yreifydebug = BooleanSetting("-Yreify-debug", "Trace reification.")
- val Yrepldebug = BooleanSetting("-Yrepl-debug", "Trace all repl activity.") andThen (interpreter.replProps.debug setValue _)
val Ytyperdebug = BooleanSetting("-Ytyper-debug", "Trace all type assignments.")
val Ypatmatdebug = BooleanSetting("-Ypatmat-debug", "Trace pattern matching translation.")
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index 1693bdbc8c..91ebd798e1 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -43,8 +43,15 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
import definitions._
import treeInfo.{isRepeatedParamType => _, _}
import MacrosStats._
+
def globalSettings = global.settings
+ protected def findMacroClassLoader(): ClassLoader = {
+ val classpath = global.classPath.asURLs
+ macroLogVerbose("macro classloader: initializing from -cp: %s".format(classpath))
+ ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader)
+ }
+
/** `MacroImplBinding` and its companion module are responsible for
* serialization/deserialization of macro def -> impl bindings.
*
@@ -474,21 +481,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
* Loads classes from from -cp (aka the library classpath).
* Is also capable of detecting REPL and reusing its classloader.
*/
- lazy val macroClassloader: ClassLoader = {
- val classpath = global.classPath.asURLs
- macroLogVerbose("macro classloader: initializing from -cp: %s".format(classpath))
- val loader = ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader)
-
- // a heuristic to detect the REPL
- if (global.settings.exposeEmptyPackage.value) {
- macroLogVerbose("macro classloader: initializing from a REPL classloader: %s".format(global.classPath.asURLs))
- import scala.tools.nsc.interpreter._
- val virtualDirectory = global.settings.outputDirs.getSingleOutput.get
- new AbstractFileClassLoader(virtualDirectory, loader) {}
- } else {
- loader
- }
- }
+ lazy val macroClassloader: ClassLoader = findMacroClassLoader()
/** Produces a function that can be used to invoke macro implementation for a given macro definition:
* 1) Looks up macro implementation symbol in this universe.
diff --git a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala b/src/compiler/scala/tools/nsc/typechecker/TypeStrings.scala
index 3ecd3b9ae4..65a3fedbd2 100644
--- a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TypeStrings.scala
@@ -4,7 +4,7 @@
*/
package scala.tools.nsc
-package interpreter
+package typechecker
import java.lang.{ reflect => r }
import r.TypeVariable
@@ -12,7 +12,6 @@ import scala.reflect.NameTransformer
import NameTransformer._
import scala.reflect.runtime.{universe => ru}
import scala.reflect.{ClassTag, classTag}
-import typechecker.DestructureTypes
/** A more principled system for turning types into strings.
*/
@@ -53,8 +52,7 @@ trait StructuredTypeStrings extends DestructureTypes {
private def shortClass(x: Any) = {
if (settings.debug.value) {
val name = (x.getClass.getName split '.').last
- val isAnon = name.reverse takeWhile (_ != '$') forall (_.isDigit)
- val str = if (isAnon) name else (name split '$').last
+ val str = if (TypeStrings.isAnonClass(x.getClass)) name else (name split '$').last
" // " + str
}
@@ -152,11 +150,11 @@ trait StructuredTypeStrings extends DestructureTypes {
* "definition" is when you want strings like
*/
trait TypeStrings {
+ private type JClass = java.lang.Class[_]
private val ObjectClass = classOf[java.lang.Object]
private val primitives = Set[String]("byte", "char", "short", "int", "long", "float", "double", "boolean", "void")
private val primitiveMap = primitives.toList map { x =>
val key = x match {
- case "void" => "Void"
case "int" => "Integer"
case "char" => "Character"
case s => s.capitalize
@@ -169,6 +167,11 @@ trait TypeStrings {
("java.lang." + key) -> ("scala." + value)
} toMap
+ def isAnonClass(cl: Class[_]) = {
+ val xs = cl.getName.reverse takeWhile (_ != '$')
+ xs.nonEmpty && xs.forall(_.isDigit)
+ }
+
def scalaName(s: String): String = {
if (s endsWith MODULE_SUFFIX_STRING) s.init + ".type"
else if (s == "void") "scala.Unit"
@@ -178,17 +181,16 @@ trait TypeStrings {
// Trying to put humpty dumpty back together again.
def scalaName(clazz: JClass): String = {
val name = clazz.getName
- val isAnon = clazz.isScalaAnonymous
val enclClass = clazz.getEnclosingClass
def enclPre = enclClass.getName + MODULE_SUFFIX_STRING
def enclMatch = name startsWith enclPre
scalaName(
- if (enclClass == null || isAnon || !enclMatch) name
+ if (enclClass == null || isAnonClass(clazz) || !enclMatch) name
else enclClass.getName + "." + (name stripPrefix enclPre)
)
}
- def anyClass(x: Any): JClass = if (x == null) null else x.getClass
+ def anyClass(x: Any): JClass = if (x == null) null else x.getClass
private def brackets(tps: String*): String =
if (tps.isEmpty) ""
diff --git a/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala b/src/compiler/scala/tools/nsc/util/AbstractFileClassLoader.scala
index e909cd945d..7aef87f387 100644
--- a/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala
+++ b/src/compiler/scala/tools/nsc/util/AbstractFileClassLoader.scala
@@ -3,10 +3,9 @@
*/
package scala.tools.nsc
-package interpreter
+package util
import scala.tools.nsc.io.AbstractFile
-import util.ScalaClassLoader
import java.net.{ URL, URLConnection, URLStreamHandler }
import scala.collection.{ mutable, immutable }
@@ -78,7 +77,7 @@ class AbstractFileClassLoader(val root: AbstractFile, parent: ClassLoader)
case null => super.classBytes(name)
case file => file.toByteArray
}
- override def findClass(name: String): JClass = {
+ override def findClass(name: String): Class[_] = {
val bytes = classBytes(name)
if (bytes.length == 0)
throw new ClassNotFoundException(name)
diff --git a/src/compiler/scala/tools/nsc/util/ShowPickled.scala b/src/compiler/scala/tools/nsc/util/ShowPickled.scala
index 4bc393bd0b..f91e94471a 100644
--- a/src/compiler/scala/tools/nsc/util/ShowPickled.scala
+++ b/src/compiler/scala/tools/nsc/util/ShowPickled.scala
@@ -13,7 +13,6 @@ import java.lang.Float.intBitsToFloat
import java.lang.Double.longBitsToDouble
import scala.reflect.internal.{Flags, Names}
import scala.reflect.internal.pickling.{ PickleBuffer, PickleFormat }
-import interpreter.ByteCode.scalaSigBytesForPath
object ShowPickled extends Names {
import PickleFormat._
@@ -272,7 +271,6 @@ object ShowPickled extends Names {
}
def fromFile(path: String) = fromBytes(io.File(path).toByteArray())
- def fromName(name: String) = fromBytes(scalaSigBytesForPath(name) getOrElse Array())
def fromBytes(data: => Array[Byte]): Option[PickleBuffer] =
try Some(new PickleBuffer(data, 0, data.length))
catch { case _: Exception => None }
@@ -287,7 +285,7 @@ object ShowPickled extends Names {
def main(args: Array[String]) {
args foreach { arg =>
- (fromFile(arg) orElse fromName(arg)) match {
+ fromFile(arg) match {
case Some(pb) => show(arg + ":", pb)
case _ => Console.println("Cannot read " + arg)
}