summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2009-03-10 18:13:58 +0000
committerPaul Phillips <paulp@improving.org>2009-03-10 18:13:58 +0000
commit4ccece5f6e31b83fa9067a533d743d6cd6c8fe4a (patch)
tree91dffb4230948e313ff3c66cdebcf5f1f48c5bb2 /src
parentf085ff3942af6773e3ebd6d071e425921830e5d7 (diff)
downloadscala-4ccece5f6e31b83fa9067a533d743d6cd6c8fe4a.tar.gz
scala-4ccece5f6e31b83fa9067a533d743d6cd6c8fe4a.tar.bz2
scala-4ccece5f6e31b83fa9067a533d743d6cd6c8fe4a.zip
Adds debugger-like capabilities to repl.
with -Ydebugger, then calls to breakIf(assertion, arg1, arg2, ...) will drop out to a repl if assertion proves true. This is very primitive at present and will improve.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/Interpreter.scala19
-rw-r--r--src/compiler/scala/tools/nsc/InterpreterLoop.scala20
-rw-r--r--src/compiler/scala/tools/nsc/Settings.scala1
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolTable.scala5
5 files changed, 46 insertions, 1 deletions
diff --git a/src/compiler/scala/tools/nsc/Interpreter.scala b/src/compiler/scala/tools/nsc/Interpreter.scala
index df14417565..78ac10b021 100644
--- a/src/compiler/scala/tools/nsc/Interpreter.scala
+++ b/src/compiler/scala/tools/nsc/Interpreter.scala
@@ -888,6 +888,25 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
/** Utility methods for the Interpreter. */
object Interpreter {
+ def breakIf(assertion: => Boolean, args: Any*): Unit =
+ if (assertion) break(args.toList)
+
+ // start a repl binding supplied args to p1, p2, etc.
+ def break(args: List[Any]): Unit = {
+ val intLoop = new InterpreterLoop
+ intLoop.settings = new Settings(Console.println)
+ intLoop.createInterpreter
+ intLoop.in = InteractiveReader.createDefault(intLoop.interpreter)
+
+ // rebind exit so people don't accidentally call System.exit by way of predef
+ intLoop.interpreter.beQuietDuring {
+ intLoop.interpreter.interpret("""def exit = println("Type :quit to resume program execution.")""")
+ println(intLoop.inject(args))
+ }
+ intLoop.repl()
+ intLoop.closeInterpreter
+ }
+
/** Delete a directory tree recursively. Use with care! */
private[nsc] def deleteRecursively(path: File): Unit =
if (path.exists) {
diff --git a/src/compiler/scala/tools/nsc/InterpreterLoop.scala b/src/compiler/scala/tools/nsc/InterpreterLoop.scala
index 796fb4bbf9..ea387b39dc 100644
--- a/src/compiler/scala/tools/nsc/InterpreterLoop.scala
+++ b/src/compiler/scala/tools/nsc/InterpreterLoop.scala
@@ -352,6 +352,26 @@ class InterpreterLoop(in0: Option[BufferedReader], out: PrintWriter) {
}
}
+ // injects one value into the repl; returns pair of name and class
+ def injectOne(name: String, obj: Any): Tuple2[String, String] = {
+ val className = obj.asInstanceOf[AnyRef].getClass.getName
+ interpreter.bind(name, className, obj)
+ (name, className)
+ }
+
+ // injects list of values into the repl; returns summary string
+ def inject(args: List[Any]): String = {
+ val strs =
+ for ((arg, i) <- args.zipWithIndex) yield {
+ val varName = "p" + (i + 1)
+ val (vname, vtype) = injectOne(varName, arg)
+ vname + ": " + vtype
+ }
+
+ if (strs.size == 0) "Set no variables."
+ else "Variables set:\n" + strs.mkString("\n")
+ }
+
/** process command-line arguments and do as they request */
def main(args: Array[String]) {
def error1(msg: String) = out println ("scala: " + msg)
diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala
index e1d40df66d..53fb2e014d 100644
--- a/src/compiler/scala/tools/nsc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/Settings.scala
@@ -137,6 +137,7 @@ class Settings(error: String => Unit) {
val Xcloselim = BooleanSetting ("-Yclosure-elim", "Perform closure elimination")
val Xcodebase = StringSetting ("-Ycodebase", "codebase", "Specify the URL containing the Scala libraries", "").hideToIDE
val debug = BooleanSetting ("-Ydebug", "Output debugging messages").hideToIDE
+ val debugger = BooleanSetting ("-Ydebugger", "Enable interactive debugger").hideToIDE
val Xdce = BooleanSetting ("-Ydead-code", "Perform dead code elimination")
val Xdetach = BooleanSetting ("-Ydetach", "Perform detaching of remote closures")
// val doc = BooleanSetting ("-Ydoc", "Generate documentation").hideToIDE
diff --git a/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala b/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala
index 4ae04b76ee..9cc23381f0 100644
--- a/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala
@@ -42,7 +42,7 @@ object InteractiveReader {
try {
new JLineReader(interpreter)
} catch {
- case e: Exception => new SimpleReader
+ case _: Exception | _: NoClassDefFoundError => new SimpleReader
}
}
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
index c735bb246c..090d534f3a 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
@@ -110,6 +110,11 @@ abstract class SymbolTable extends Names
}
}
+ /** Break into repl debugger if assertion is true and debugging enabled */
+ def breakIf(assertion: => Boolean, args: Any*): Unit =
+ if (settings.debugger.value && assertion)
+ Interpreter.break(args.toList)
+
/** The set of all installed infotransformers */
var infoTransformers = new InfoTransformer {
val pid = NoPhase.id