diff options
author | Paul Phillips <paulp@improving.org> | 2009-03-10 18:13:58 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2009-03-10 18:13:58 +0000 |
commit | 4ccece5f6e31b83fa9067a533d743d6cd6c8fe4a (patch) | |
tree | 91dffb4230948e313ff3c66cdebcf5f1f48c5bb2 /src | |
parent | f085ff3942af6773e3ebd6d071e425921830e5d7 (diff) | |
download | scala-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')
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 |