summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/Interpreter.scala90
-rw-r--r--src/compiler/scala/tools/nsc/InterpreterLoop.scala173
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Completion.scala31
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/History.scala1
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala42
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/JLineReader.scala25
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/NamedParam.scala31
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Power.scala28
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala6
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolTable.scala2
11 files changed, 226 insertions, 205 deletions
diff --git a/src/compiler/scala/tools/nsc/Interpreter.scala b/src/compiler/scala/tools/nsc/Interpreter.scala
index 8cbc904947..d5a9e80326 100644
--- a/src/compiler/scala/tools/nsc/Interpreter.scala
+++ b/src/compiler/scala/tools/nsc/Interpreter.scala
@@ -157,28 +157,23 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
}
/** the public, go through the future compiler */
- lazy val compiler: Global = {
+ lazy val global: Global = {
initialize()
// blocks until it is ; false means catastrophic failure
if (_isInitialized()) _compiler
else null
}
+ @deprecated("Use `global` for access to the compiler instance.")
+ lazy val compiler = global
- import compiler.{ Traverser, CompilationUnit, Symbol, Name, TermName, TypeName, Type, TypeRef, NullaryMethodType }
- import compiler.{
- Tree, TermTree, ValOrDefDef, ValDef, DefDef, Assign, ClassDef,
- ModuleDef, Ident, BackQuotedIdent, Select, TypeDef, Import, MemberDef, DocDef,
- ImportSelector, EmptyTree, NoType }
- import compiler.{ opt, nme, newTermName, newTypeName }
+ import global._
+ import definitions.{ EmptyPackage, getMember }
import nme.{
INTERPRETER_VAR_PREFIX, INTERPRETER_SYNTHVAR_PREFIX, INTERPRETER_LINE_PREFIX,
INTERPRETER_IMPORT_WRAPPER, INTERPRETER_WRAPPER_SUFFIX, USCOREkw
}
- import compiler.definitions
- import definitions.{ EmptyPackage, getMember }
-
/** Temporarily be quiet */
def beQuietDuring[T](operation: => T): T = {
val wasPrinting = printResults
@@ -194,6 +189,8 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
finally totalSilence = saved
}
+ def quietRun[T](code: String) = beQuietDuring(interpret(code))
+
/** whether to bind the lastException variable */
private var bindLastException = true
@@ -530,7 +527,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
def simpleParse(code: String): List[Tree] = {
reporter.reset
val unit = new CompilationUnit(new BatchSourceFile("<console>", code))
- val scanner = new compiler.syntaxAnalyzer.UnitParser(unit)
+ val scanner = new syntaxAnalyzer.UnitParser(unit)
scanner.templateStatSeq(false)._2
}
@@ -555,7 +552,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
*/
def compileSources(sources: SourceFile*): Boolean = {
reporter.reset
- new compiler.Run() compileSources sources.toList
+ new Run() compileSources sources.toList
!reporter.hasErrors
}
@@ -572,11 +569,11 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
if (code.lines exists (_.trim endsWith "// show")) {
Console println code
parse(code) match {
- case Some(trees) => trees foreach (t => DBG(compiler.asCompactString(t)))
+ case Some(trees) => trees foreach (t => DBG(asCompactString(t)))
case _ => DBG("Parse error:\n\n" + code)
}
}
- val run = new compiler.Run()
+ val run = new Run()
run.compileSources(List(new BatchSourceFile(label, code)))
run
}
@@ -655,7 +652,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
else IR.Error
}
- if (compiler == null) IR.Error
+ if (global == null) IR.Error
else requestFromLine(line, synthetic) match {
case Left(result) => result
case Right(req) =>
@@ -669,6 +666,9 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
/** A name creator used for objects created by <code>bind()</code>. */
private lazy val newBinder = new NameCreator("binder")
+ def bind[T](p: NamedParam[T]): IR.Result =
+ bind(p.name, p.tpe, p.value)
+
def bindToType[T: ClassManifest](name: String, value: T): IR.Result =
bind(name, classManifest[T].erasure.getName, value)
@@ -837,7 +837,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
private class TypeAliasHandler(typeDef: TypeDef) extends MemberHandler(typeDef) {
lazy val TypeDef(mods, name, _, _) = typeDef
- def isAlias() = mods.isPublic && compiler.treeInfo.isAliasTypeDef(typeDef)
+ def isAlias() = mods.isPublic && treeInfo.isAliasTypeDef(typeDef)
override lazy val boundNames = if (isAlias) List(name) else Nil
override def resultExtractionCode(req: Request, code: PrintWriter) =
@@ -1015,7 +1015,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
!reporter.hasErrors
}
- def afterTyper[T](op: => T): T = compiler.atPhase(objRun.typerPhase.next)(op)
+ def afterTyper[T](op: => T): T = atPhase(objRun.typerPhase.next)(op)
/** The outermost wrapper object */
lazy val outerResObjSym: Symbol = getMember(EmptyPackage, newTermName(objectName))
@@ -1029,7 +1029,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
}
/* typeOf lookup with encoding */
- def lookupTypeOf(name: Name) = typeOf.getOrElse(name, typeOf(compiler encode name))
+ def lookupTypeOf(name: Name) = typeOf.getOrElse(name, typeOf(global.encode(name)))
def simpleNameOfType(name: TypeName) = (compilerTypeOf get name) map (_.typeSymbol.simpleName)
private def typeMap[T](f: Type => T): Map[Name, T] = {
@@ -1124,7 +1124,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
private def requestForIdent(line: String): Option[Request] = requestForName(newTermName(line))
// XXX literals.
- def stringToCompilerType(id: String): compiler.Type = {
+ def stringToCompilerType(id: String): Type = {
// if it's a recognized identifier, the type of that; otherwise treat the
// String like a value (e.g. scala.collection.Map) .
def findType = typeForIdent(id) match {
@@ -1284,7 +1284,6 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
/** Utility methods for the Interpreter. */
object Interpreter {
-
import scala.collection.generic.CanBuildFrom
def partialFlatMap[A, B, CC[X] <: Traversable[X]]
(coll: CC[A])
@@ -1298,57 +1297,6 @@ object Interpreter {
b.result
}
- object DebugParam {
- implicit def tuple2debugparam[T](x: (String, T))(implicit m: Manifest[T]): DebugParam[T] =
- DebugParam(x._1, x._2)
-
- implicit def any2debugparam[T](x: T)(implicit m: Manifest[T]): DebugParam[T] =
- DebugParam("p" + getCount(), x)
-
- private var counter = 0
- def getCount() = { counter += 1; counter }
- }
- case class DebugParam[T](name: String, param: T)(implicit m: Manifest[T]) {
- val manifest = m
- val typeStr = {
- val str = manifest.toString
- // I'm sure there are more to be discovered...
- val regexp1 = """(.*?)\[(.*)\]""".r
- val regexp2str = """.*\.type#"""
- val regexp2 = (regexp2str + """(.*)""").r
-
- (str.replaceAll("""\n""", "")) match {
- case regexp1(clazz, typeArgs) => "%s[%s]".format(clazz, typeArgs.replaceAll(regexp2str, ""))
- case regexp2(clazz) => clazz
- case _ => str
- }
- }
- }
- // provide the enclosing type T
- // in order to set up the interpreter's classpath and parent class loader properly
- def breakIf[T: Manifest](assertion: => Boolean, args: DebugParam[_]*): Unit =
- if (assertion) break[T](args.toList)
-
- // start a repl, binding supplied args
- def break[T: Manifest](args: List[DebugParam[_]]): Unit = {
- val intLoop = new InterpreterLoop
- intLoop.settings = new Settings(Console.println)
- intLoop.settings.embeddedDefaults[T]
- intLoop.createInterpreter
- intLoop.in = InteractiveReader.createDefault(intLoop.interpreter)
-
- // rebind exit so people don't accidentally call sys.exit by way of predef
- intLoop.interpreter.beQuietDuring {
- intLoop.interpreter.interpret("""def exit = println("Type :quit to resume program execution.")""")
- for (p <- args) {
- intLoop.interpreter.bind(p.name, p.typeStr, p.param)
- Console println "%s: %s".format(p.name, p.typeStr)
- }
- }
- intLoop.repl()
- intLoop.closeInterpreter
- }
-
def codegenln(leadingPlus: Boolean, xs: String*): String = codegen(leadingPlus, (xs ++ Array("\n")): _*)
def codegenln(xs: String*): String = codegenln(true, xs: _*)
diff --git a/src/compiler/scala/tools/nsc/InterpreterLoop.scala b/src/compiler/scala/tools/nsc/InterpreterLoop.scala
index 32391ba2ba..6bb9428528 100644
--- a/src/compiler/scala/tools/nsc/InterpreterLoop.scala
+++ b/src/compiler/scala/tools/nsc/InterpreterLoop.scala
@@ -94,16 +94,14 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
def this(in0: BufferedReader, out: PrintWriter) = this(Some(in0), out)
def this() = this(None, new PrintWriter(Console.out))
- /** The input stream from which commands come, set by main() */
- var in: InteractiveReader = _
+ var in: InteractiveReader = _ // the input stream from which commands come
+ var settings: Settings = _
+ var intp: Interpreter = _
+ var power: Power = _
/** The context class loader at the time this object was created */
protected val originalClassLoader = Thread.currentThread.getContextClassLoader
- var settings: Settings = _ // set by main()
- var interpreter: Interpreter = _ // set by createInterpreter()
- var replPower: Power = _
-
// classpath entries added via :cp
var addedClasspath: String = ""
@@ -130,10 +128,10 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
}
ignoring(classOf[Exception]) {
SignalManager("INT") = {
- if (interpreter == null)
+ if (intp == null)
onExit()
- else if (interpreter.lineManager.running)
- interpreter.lineManager.cancel()
+ else if (intp.lineManager.running)
+ intp.lineManager.cancel()
else if (in.currentLine != "") {
// non-empty buffer, so make them hit ctrl-C a second time
SignalManager("INT") = onExit()
@@ -146,10 +144,10 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
/** Close the interpreter and set the var to null. */
def closeInterpreter() {
- if (interpreter ne null) {
- interpreter.close
- interpreter = null
- replPower = null
+ if (intp ne null) {
+ intp.close
+ intp = null
+ power = null
Thread.currentThread.setContextClassLoader(originalClassLoader)
}
}
@@ -159,7 +157,7 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
if (addedClasspath != "")
settings.classpath append addedClasspath
- interpreter = new Interpreter(settings, out) {
+ intp = new Interpreter(settings, out) {
override protected def createLineManager() = new Line.Manager {
override def onRunaway(line: Line[_]): Unit = {
val template = """
@@ -176,9 +174,9 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
override protected def parentClassLoader =
settings.explicitParentLoader.getOrElse( classOf[InterpreterLoop].getClassLoader )
}
- interpreter.setContextClassLoader()
+ intp.setContextClassLoader()
installSigIntHandler()
- // interpreter.quietBind("settings", "scala.tools.nsc.InterpreterSettings", interpreter.isettings)
+ // intp.quietBind("settings", "scala.tools.nsc.InterpreterSettings", intp.isettings)
}
/** print a friendly help message */
@@ -203,12 +201,14 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
}
/** Show the history */
- def printHistory(xs: List[String]) {
+ def printHistory(xs: List[String]): Result = {
+ if (in.history eq History.Empty)
+ return "No history available."
+
val defaultLines = 20
- val h = in.history getOrElse { return println("No history available.") }
- val current = h.index
+ val current = in.history.index
val count = try xs.head.toInt catch { case _: Exception => defaultLines }
- val lines = in.historyList takeRight count
+ val lines = in.history.asList takeRight count
val offset = current - lines.size + 1
for ((line, index) <- lines.zipWithIndex)
@@ -217,21 +217,20 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
/** Some print conveniences */
def println(x: Any) = out println x
- def plush(x: Any) = { out print x ; out.flush() }
+ def plush(x: Any) = { out print x ; out.flush() }
def plushln(x: Any) = { out println x ; out.flush() }
/** Search the history */
def searchHistory(_cmdline: String) {
val cmdline = _cmdline.toLowerCase
- val h = in.history getOrElse { return println("No history available.") }
- val offset = h.index - h.size + 1
+ val offset = in.history.index - in.history.size + 1
- for ((line, index) <- h.asStrings.zipWithIndex ; if line.toLowerCase contains cmdline)
+ for ((line, index) <- in.history.asStrings.zipWithIndex ; if line.toLowerCase contains cmdline)
println("%d %s".format(index + offset, line))
}
/** Prompt to print when awaiting input */
- val prompt = Properties.shellPromptString
+ def prompt = Properties.shellPromptString
/** Standard commands **/
val standardCommands: List[Command] = {
@@ -252,18 +251,18 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
/** Power user commands */
val powerCommands: List[Command] = {
List(
- NoArgs("dump", "displays a view of the interpreter's internal state", replPower.toString _),
+ NoArgs("dump", "displays a view of the interpreter's internal state", power.toString _),
LineArg("phase", "set the implicit phase for power commands", phaseCommand),
LineArg("symfilter", "change the filter for symbol printing", symfilterCmd)
)
}
private def symfilterCmd(line: String): Result = {
if (line == "") {
- replPower.vars.symfilter set "_ => true"
+ power.vars.symfilter set "_ => true"
"Remove symbol filter."
}
else {
- replPower.vars.symfilter set line
+ power.vars.symfilter set line
"Set symbol filter to '" + line + "'."
}
}
@@ -271,7 +270,7 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
val name = _name.toLowerCase
// This line crashes us in TreeGen:
//
- // if (interpreter.power.phased set name) "..."
+ // if (intp.power.phased set name) "..."
//
// Exception in thread "main" java.lang.AssertionError: assertion failed: ._7.type
// at scala.Predef$.assert(Predef.scala:99)
@@ -281,7 +280,7 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
// at scala.tools.nsc.ast.TreeGen.mkAttributedStableRef(TreeGen.scala:143)
//
// But it works like so, type annotated.
- val x: Phased = replPower.phased
+ val x: Phased = power.phased
if (name == "") "Active phase is '" + x.get + "'"
else if (x set name) "Active phase is now '" + name + "'"
else "'" + name + "' does not appear to be a valid phase."
@@ -289,15 +288,15 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
/** Available commands */
def commands: List[Command] = standardCommands ++ (
- if (replPower == null) Nil
+ if (power == null) Nil
else powerCommands
)
- /** The main read-eval-print loop for the interpreter. It calls
+ /** The main read-eval-print loop for the repl. It calls
* command() for each line of input, and stops when
* command() returns false.
*/
- def repl() {
+ def loop() {
def readOneLine() = {
out.flush
in readLine prompt
@@ -311,11 +310,6 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
case _ => true
}
- if (sys.props contains PowerProperty) {
- plushln("Starting in power mode, one moment...\n")
- powerCmd()
- }
-
while (processLine(readOneLine)) { }
}
@@ -327,7 +321,7 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
try file applyReader { reader =>
in = new SimpleReader(reader, out, false)
plushln("Loading " + file + "...")
- repl()
+ loop()
}
finally {
in = oldIn
@@ -348,10 +342,10 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
/** fork a shell and run a command */
def runShellCmd(cmd: String) {
- interpreter.beQuietDuring { interpreter.interpret("import _root_.scala.sys.process._") }
+ intp.beQuietDuring { intp.interpret("import _root_.scala.sys.process._") }
val xs = Process(cmd).lines
if (xs.nonEmpty)
- interpreter.bind("stdout", "scala.Stream[String]", xs)
+ intp.bind("stdout", "scala.Stream[String]", xs)
}
def withFile(filename: String)(action: File => Unit) {
@@ -381,28 +375,21 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
else out.println("The path '" + f + "' doesn't seem to exist.")
}
- def completions(arg: String): Unit = {
- val comp = in.completion getOrElse { return println("Completion unavailable.") }
- val xs = comp completions arg
-
- injectAndName(xs)
- }
-
def powerCmd(): Result = {
- if (replPower != null)
+ if (power != null)
return "Already in power mode."
- replPower = new Power(interpreter) { }
- replPower.unleash()
- injectOne("history", in.historyList)
- in.completion foreach (x => injectOne("completion", x))
+ power = new Power(intp) { }
+ power.unleash()
+ injectOne("history", in.history.asList)
+ injectOne("completion", in.completion)
- replPower.banner
+ power.banner
}
def verbosity() = {
- val old = interpreter.printResults
- interpreter.printResults = !old
+ val old = intp.printResults
+ intp.printResults = !old
out.println("Switched " + (if (old) "off" else "on") + " result printing.")
}
@@ -419,7 +406,7 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
// not a command
if (!line.startsWith(":")) {
// Notice failure to create compiler
- if (interpreter.compiler == null) return Result(false, None)
+ if (intp.global == null) return Result(false, None)
else return Result(true, interpretStartingWith(line))
}
@@ -507,7 +494,7 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
for (PasteCommand(cmd, trailing) <- xs) {
out.flush()
def runCode(code: String, extraLines: List[String]) {
- (interpreter interpret code) match {
+ (intp interpret code) match {
case IR.Incomplete if extraLines.nonEmpty =>
runCode(code + "\n" + extraLines.head, extraLines.tail)
case _ => ()
@@ -528,9 +515,9 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
*/
def interpretStartingWith(code: String): Option[String] = {
// signal completion non-completion input has been received
- in.completion foreach (_.resetVerbosity())
+ in.completion.resetVerbosity()
- def reallyInterpret = interpreter.interpret(code) match {
+ def reallyInterpret = intp.interpret(code) match {
case IR.Error => None
case IR.Success => Some(code)
case IR.Incomplete =>
@@ -544,7 +531,7 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
// 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.
- interpreter.compileString(code)
+ intp.compileString(code)
None
case line => interpretStartingWith(code + "\n" + line)
@@ -566,13 +553,13 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
interpretAsPastedTranscript(List(code))
None
}
- else if (Completion.looksLikeInvocation(code) && interpreter.mostRecentVar != "") {
- interpretStartingWith(interpreter.mostRecentVar + code)
+ else if (Completion.looksLikeInvocation(code) && intp.mostRecentVar != "") {
+ interpretStartingWith(intp.mostRecentVar + code)
}
else {
- if (interpreter.isParseable(code)) reallyInterpret
+ if (intp.isParseable(code)) reallyInterpret
else {
- val res = in.completion flatMap (_ execute code) map injectAndName
+ val res = (in.completion execute code) map injectAndName
if (res.isDefined) None // completion took responsibility, so do not parse
else reallyInterpret // we know it will fail, this is to show the error
}
@@ -601,14 +588,16 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
case None =>
// the interpreter is passed as an argument to expose tab completion info
if (settings.Xnojline.value || Properties.isEmacsShell) new SimpleReader
- else if (settings.noCompletion.value) InteractiveReader.createDefault()
- else InteractiveReader.createDefault(interpreter)
+ else InteractiveReader(
+ if (settings.noCompletion.value) Completion.Empty
+ else Completion(intp)
+ )
}
loadFiles(settings)
try {
// it is broken on startup; go ahead and exit
- if (interpreter.reporter.hasErrors) return
+ if (intp.reporter.hasErrors) return
printWelcome()
@@ -617,8 +606,12 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
// our best to look ready. Ideally the user will spend a
// couple seconds saying "wow, it starts so fast!" and by the time
// they type a command the compiler is ready to roll.
- interpreter.initialize()
- repl()
+ intp.initialize()
+ if (sys.props contains PowerProperty) {
+ plushln("Starting in power mode, one moment...\n")
+ powerCmd()
+ }
+ loop()
}
finally closeInterpreter()
}
@@ -640,20 +633,20 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
}
def inject[T: ClassManifest](name: String, value: T): (String, String) = {
- interpreter.bind[T](name, value)
+ intp.bind[T](name, value)
(name, objName(value))
}
// injects one value into the repl; returns pair of name and class
def injectOne(name: String, obj: Any): (String, String) = {
val className = objName(obj)
- interpreter.quietBind(name, className, obj)
+ intp.quietBind(name, className, obj)
(name, className)
}
def injectAndName(obj: Any): (String, String) = {
- val name = interpreter.getVarName
+ val name = intp.getVarName
val className = objName(obj)
- interpreter.bind(name, className, obj)
+ intp.bind(name, className, obj)
(name, className)
}
@@ -685,3 +678,35 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
}
}
}
+
+object InterpreterLoop {
+ implicit def loopToInterpreter(repl: InterpreterLoop): Interpreter = repl.intp
+
+ // provide the enclosing type T
+ // in order to set up the interpreter's classpath and parent class loader properly
+ def breakIf[T: Manifest](assertion: => Boolean, args: NamedParam[_]*): Unit =
+ if (assertion) break[T](args.toList)
+
+ // start a repl, binding supplied args
+ def break[T: Manifest](args: List[NamedParam[_]]): Unit = {
+ val msg = if (args.isEmpty) "" else " Binding " + args.size + " value%s.".format(
+ if (args.size == 1) "" else "s"
+ )
+ Console.println("Debug repl starting." + msg)
+ val repl = new InterpreterLoop {
+ override def prompt = "\ndebug> "
+ }
+ repl.settings = new Settings(Console println _)
+ repl.settings.embeddedDefaults[T]
+ repl.createInterpreter()
+ repl.in = InteractiveReader(repl)
+
+ // rebind exit so people don't accidentally call sys.exit by way of predef
+ repl.quietRun("""def exit = println("Type :quit to resume program execution.")""")
+ args foreach (p => repl.bind(p.name, p.tpe, p.value))
+ repl.loop()
+
+ Console.println("\nDebug repl exiting.")
+ repl.closeInterpreter()
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/interpreter/Completion.scala b/src/compiler/scala/tools/nsc/interpreter/Completion.scala
index c10a3f64e8..04a1a4014a 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Completion.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/Completion.scala
@@ -13,6 +13,14 @@ import java.util.{ List => JList }
import util.returning
object Completion {
+ object Empty extends Completion {
+ def resetVerbosity() = ()
+ def execute(line: String) = None
+ def completer() = new NullCompleter
+ }
+
+ def apply(repl: Interpreter): Completion = new CompletionImpl(repl)
+
def looksLikeInvocation(code: String) = (
(code != null)
&& (code startsWith ".")
@@ -33,9 +41,19 @@ object Completion {
}
import Completion._
+trait Completion {
+ def resetVerbosity(): Unit
+ def execute(line: String): Option[Any]
+ def completer(): Completer
+}
+
// REPL completor - queries supplied interpreter for valid
// completions based on current contents of buffer.
-class Completion(val repl: Interpreter) extends CompletionOutput {
+class CompletionImpl(val repl: Interpreter) extends Completion with CompletionOutput {
+ val global: repl.global.type = repl.global
+ import global._
+ import definitions.{ PredefModule, RootClass, AnyClass, AnyRefClass, ScalaPackage, JavaLangPackage }
+
// verbosity goes up with consecutive tabs
private var verbosity: Int = 0
def resetVerbosity() = verbosity = 0
@@ -44,10 +62,6 @@ class Completion(val repl: Interpreter) extends CompletionOutput {
def DBG(msg: => Any) = if (isCompletionDebug) println(msg.toString)
def debugging[T](msg: String): T => T = (res: T) => returning[T](res)(x => DBG(msg + x))
- lazy val global: repl.compiler.type = repl.compiler
- import global._
- import definitions.{ PredefModule, RootClass, AnyClass, AnyRefClass, ScalaPackage, JavaLangPackage }
-
// XXX not yet used.
lazy val dottedPaths = {
def walk(tp: Type): scala.List[Symbol] = {
@@ -284,12 +298,7 @@ class Completion(val repl: Interpreter) extends CompletionOutput {
def completions(buf: String): List[String] =
topLevelFor(Parsed.dotted(buf + ".", buf.length + 1))
- // jline's entry point
- lazy val jline: ArgumentCompleter = {
- val c = new ArgumentCompleter(new JLineDelimiter, new JLineCompletion)
- c setStrict false
- c
- }
+ def completer() = new JLineCompletion
/** 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
diff --git a/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala b/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala
index 5167e3c4c5..047acdf701 100644
--- a/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala
@@ -12,7 +12,7 @@ package interpreter
* as is also in progress with error messages.
*/
trait CompletionOutput {
- self: Completion =>
+ self: CompletionImpl =>
import global._
import definitions.{ NothingClass, AnyClass, isTupleTypeOrSubtype, isFunctionType, isRepeatedParamType }
diff --git a/src/compiler/scala/tools/nsc/interpreter/History.scala b/src/compiler/scala/tools/nsc/interpreter/History.scala
index a90627a07b..da91a55365 100644
--- a/src/compiler/scala/tools/nsc/interpreter/History.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/History.scala
@@ -31,6 +31,7 @@ class History(val jhistory: JHistory) {
}
object History {
+ val Empty: History = null
val ScalaHistoryFile = ".scala_history"
def apply(): History = new History(
diff --git a/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala b/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala
index f58c6f038a..f094aab104 100644
--- a/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala
@@ -13,11 +13,15 @@ import InteractiveReader._
/** Reads lines from an input stream */
trait InteractiveReader {
-
- protected def readOneLine(prompt: String): String
val interactive: Boolean
- def init(): Unit = ()
- def reset(): Unit = ()
+ protected def readOneLine(prompt: String): String
+
+ def history: History
+ def completion: Completion
+
+ def init(): Unit
+ def reset(): Unit
+
def redrawLine(): Unit = ()
def currentLine = "" // the current buffer contents, if available
@@ -30,13 +34,6 @@ trait InteractiveReader {
catching(handler) { readOneLine(prompt) }
}
- // override if history is available
- def history: Option[History] = None
- def historyList = history map (_.asList) getOrElse Nil
-
- // override if completion is available
- def completion: Option[Completion] = None
-
// hack necessary for OSX jvm suspension because read calls are not restarted after SIGTSTP
private def restartSystemCall(e: Exception): Boolean =
Properties.isMac && (e.getMessage == msgEINTR)
@@ -44,17 +41,14 @@ trait InteractiveReader {
object InteractiveReader {
val msgEINTR = "Interrupted system call"
- def createDefault(): InteractiveReader = createDefault(null)
-
- /** Create an interactive reader. Uses <code>JLineReader</code> if the
- * library is available, but otherwise uses a <code>SimpleReader</code>.
- */
- def createDefault(interpreter: Interpreter): InteractiveReader =
- try new JLineReader(interpreter)
- catch {
- case e @ (_: Exception | _: NoClassDefFoundError) =>
- // println("Failed to create JLineReader(%s): %s".format(interpreter, e))
- new SimpleReader
- }
-}
+ def apply(): InteractiveReader = new SimpleReader
+ def apply(repl: Interpreter): InteractiveReader = apply(Completion(repl))
+ def apply(comp: Completion): InteractiveReader = {
+ try new JLineReader(comp)
+ catch { case e @ (_: Exception | _: NoClassDefFoundError) => apply() }
+ }
+
+ @deprecated("Use `apply` instead") def createDefault(repl: Interpreter): InteractiveReader = apply(repl)
+ @deprecated("Use `apply` instead") def createDefault(comp: Completion): InteractiveReader = apply(comp)
+}
diff --git a/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala b/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala
index a61c06f821..8f42305bcb 100644
--- a/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala
@@ -11,25 +11,32 @@ import scala.tools.jline.console.ConsoleReader
import scala.tools.jline.console.completer._
/** Reads from the console using JLine */
-class JLineReader(interpreter: Interpreter) extends InteractiveReader {
- def this() = this(null)
+class JLineReader(val completion: Completion) extends InteractiveReader {
+ lazy val history = History()
+
+ def reset() = consoleReader.getTerminal().reset()
+ def init() = consoleReader.getTerminal().init()
- override lazy val history = Some(History())
- override lazy val completion = Option(interpreter) map (x => new Completion(x))
- override def reset() = consoleReader.getTerminal().reset()
- override def init() = consoleReader.getTerminal().init()
override def redrawLine() = {
consoleReader.flush()
consoleReader.drawLine()
consoleReader.flush()
}
+ def argCompletor: ArgumentCompleter = {
+ val c = new ArgumentCompleter(new JLineDelimiter, completion.completer())
+ c setStrict false
+ c
+ }
+
val consoleReader = {
val r = new ConsoleReader()
r setBellEnabled false
- history foreach { r setHistory _.jhistory }
- completion foreach { c =>
- r addCompleter c.jline
+ if (history ne History.Empty)
+ r setHistory history.jhistory
+
+ if (completion ne Completion.Empty) {
+ r addCompleter argCompletor
r setAutoprintThreshold 250 // max completion candidates without warning
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala b/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala
new file mode 100644
index 0000000000..62255b2aaf
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala
@@ -0,0 +1,31 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools.nsc
+package interpreter
+
+object NamedParam {
+ def apply[T: Manifest](name: String, x: T): NamedParam[T] = new NamedParam[T](name, x)
+ def apply[T: Manifest](x: T): NamedParam[T] = apply(getParamName(), x)
+
+ implicit def fromValue[T: Manifest](x: T) = apply(x)
+ implicit def fromNameAndValue[T: Manifest](name: String, x: T) = apply(name, x)
+ implicit def fromTuple[T: Manifest](pair: (String, T)) = apply(pair._1, pair._2)
+
+ private val getParamName = {
+ var counter = 0
+ () => { counter += 1; "p" + counter }
+ }
+}
+
+class NamedParam[T: Manifest](val name: String, val value: T) {
+ val clazz = manifest[T].erasure.getName
+ val tparams = manifest[T].typeArguments match {
+ case Nil => ""
+ case xs => xs.mkString("[", ", ", "]")
+ }
+ val tpe = clazz + tparams
+ override def toString = name + ": " + tpe
+}
diff --git a/src/compiler/scala/tools/nsc/interpreter/Power.scala b/src/compiler/scala/tools/nsc/interpreter/Power.scala
index ac8f08ec80..9cd6619c2d 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Power.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/Power.scala
@@ -10,14 +10,14 @@ import scala.collection.{ mutable, immutable }
import mutable.{ HashMap }
import scala.tools.nsc.util.{ NoPosition, BatchSourceFile }
-/** A class for methods to be injected into the repl in power mode.
+/** A class for methods to be injected into the intp in power mode.
*/
-class Power(repl: Interpreter) {
- val global: repl.compiler.type = repl.compiler
+class Power(intp: Interpreter) {
+ val global: intp.global.type = intp.global
import global._
import definitions.{ getMember, getModule, getClass => getCompilerClass }
- import repl.{ beQuietDuring, interpret, parse }
+ import intp.{ beQuietDuring, interpret, parse }
object phased extends Phased {
val global: Power.this.global.type = Power.this.global
@@ -29,7 +29,7 @@ class Power(repl: Interpreter) {
def set(code: String) = interpret(path + ".value = " + code)
def get: T = value
- override def toString = "repl." + path + ".value = \"" + code + "\""
+ override def toString = "intp." + path + ".value = \"" + code + "\""
}
object vars {
@@ -40,16 +40,17 @@ class Power(repl: Interpreter) {
}
def banner = """
- |** Power User mode enabled - BEEP BOOP **
+ |** Power User mode enabled - BEEP BOOP WHIR **
|** scala.tools.nsc._ has been imported **
- |** New vals! Try repl, global, power **
+ |** global._ and definitions._ also imported **
+ |** New vals! Try repl, intp, global, power **
|** New cmds! :help to discover them **
|** New defs! Type power.<tab> to reveal **
""".stripMargin.trim
def init = """
|import scala.tools.nsc._
- |val global: repl.compiler.type = repl.compiler
+ |val global: intp.global.type = intp.global
|import global._
|import definitions._
|import power.{ phased, show, clazz, module }
@@ -59,8 +60,9 @@ class Power(repl: Interpreter) {
*/
def unleash(): Unit = {
def f = {
- repl.bind[Interpreter]("repl", repl)
- repl.bind[Power]("power", this)
+ intp.bind[InterpreterLoop]("repl", this)
+ intp.bind[Interpreter]("intp", intp)
+ intp.bind[Power]("power", this)
init split '\n' foreach interpret
}
if (isReplDebug) f
@@ -122,7 +124,7 @@ class Power(repl: Interpreter) {
run.units.toList map (_.body)
}
def mkTypedTree(code: String) = mkTypedTrees(code).head
- def mkType(id: String): Type = repl.stringToCompilerType(id)
+ def mkType(id: String): Type = intp.stringToCompilerType(id)
override def toString = """
|** Power mode status **
@@ -131,7 +133,7 @@ class Power(repl: Interpreter) {
|Identifiers: %s
""".stripMargin.format(
phased.get,
- repl.allreferencedNames mkString " ",
- repl.unqualifiedIds mkString " "
+ intp.allreferencedNames mkString " ",
+ intp.unqualifiedIds mkString " "
)
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala b/src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala
index fa1c1d1b43..a28fb9c5fe 100644
--- a/src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala
@@ -18,7 +18,11 @@ extends InteractiveReader {
def this() = this(Console.in, new PrintWriter(Console.out), true)
def this(in: File, out: PrintWriter, interactive: Boolean) = this(in.bufferedReader(), out, interactive)
- def close() = in.close()
+ lazy val history = History.Empty
+ lazy val completion = Completion.Empty
+
+ def init() = ()
+ def reset() = ()
def readOneLine(prompt: String): String = {
if (interactive) {
out.print(prompt)
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
index 61371c5ef8..60387c8335 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
@@ -102,7 +102,7 @@ abstract class SymbolTable extends reflect.generic.Universe
/** Break into repl debugger if assertion is true */
// def breakIf(assertion: => Boolean, args: Any*): Unit =
// if (assertion)
- // Interpreter.break(args.toList)
+ // InterpreterLoop.break(args.toList)
/** The set of all installed infotransformers */
var infoTransformers = new InfoTransformer {