summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/interactive/REPL.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2011-11-10 18:15:35 +0000
committerMartin Odersky <odersky@gmail.com>2011-11-10 18:15:35 +0000
commita38f03ba966907c2996944bf1e82f51760c661d9 (patch)
tree794b00408c93b9557c430f5bc00913401c220db4 /src/compiler/scala/tools/nsc/interactive/REPL.scala
parent5d6844e9b6f95b0476f26ac7fe2f28d0831f6384 (diff)
downloadscala-a38f03ba966907c2996944bf1e82f51760c661d9.tar.gz
scala-a38f03ba966907c2996944bf1e82f51760c661d9.tar.bz2
scala-a38f03ba966907c2996944bf1e82f51760c661d9.zip
More refinements for the scratchpad.
Diffstat (limited to 'src/compiler/scala/tools/nsc/interactive/REPL.scala')
-rw-r--r--src/compiler/scala/tools/nsc/interactive/REPL.scala119
1 files changed, 91 insertions, 28 deletions
diff --git a/src/compiler/scala/tools/nsc/interactive/REPL.scala b/src/compiler/scala/tools/nsc/interactive/REPL.scala
index ea30ce2516..81d4faa36e 100644
--- a/src/compiler/scala/tools/nsc/interactive/REPL.scala
+++ b/src/compiler/scala/tools/nsc/interactive/REPL.scala
@@ -12,6 +12,7 @@ import scala.tools.nsc.ast._
import scala.tools.nsc.reporters._
import scala.tools.nsc.io._
import scala.tools.nsc.scratchpad.{Executor, SourceInserter}
+import scala.tools.nsc.interpreter.AbstractFileClassLoader
import java.io.{File, FileWriter}
/** Interface of interactive compiler to a client such as an IDE
@@ -118,34 +119,84 @@ object REPL {
show(structureResult)
}
- /** This is the method for implement worksheet functionality
+ /** Write instrumented source file to disk.
+ * @param iFullName The full name of the first top-level object in source
+ * @param iContents An Array[Char] containing the instrumented source
+ * @return The name of the instrumented source file
*/
- def instrument(source: SourceFile, line: Int): Option[Array[Char]] = {
+ def writeInstrumented(iFullName: String, iContents: Array[Char]): String = {
+ val iSimpleName = iFullName drop ((iFullName lastIndexOf '.') + 1)
+ val iSourceName = iSimpleName + "$instrumented.scala"
+ val ifile = new FileWriter(iSourceName)
+ ifile.write(iContents)
+ ifile.close()
+ iSourceName
+ }
+
+ /** Compile instrumented source file
+ * @param iSourceName The name of the instrumented source file
+ * @param arguments Further argumenrs to pass to the compiler
+ * @return Optionallu, if no -d option is given, the virtual directory
+ * contained the generated bytecode classes
+ */
+ def compileInstrumented(iSourceName: String, arguments: List[String]): Option[AbstractFile] = {
+ println("compiling "+iSourceName)
+ val command = new CompilerCommand(iSourceName :: arguments, reporter.error(scala.tools.nsc.util.NoPosition, _))
+ val virtualDirectoryOpt =
+ if (arguments contains "-d")
+ None
+ else {
+ val vdir = new VirtualDirectory("(memory)", None)
+ command.settings.outputDirs setSingleOutput vdir
+ Some(vdir)
+ }
+ val compiler = new scala.tools.nsc.Global(command.settings, reporter)
+ val run = new compiler.Run()
+ println("compiling: "+command.files)
+ run compile command.files
+ virtualDirectoryOpt
+ }
+
+ /** Run instrumented bytecode file
+ * @param vdir Optionally, the virtual directory containing the generated bytecode classes
+ * @param iFullName The full name of the generated object
+ * @param stripped The contents original source file without any right hand column comments.
+ * @return The generated file content containing original source in the left column
+ * and outputs in the right column
+ */
+ def runInstrumented(vdirOpt: Option[AbstractFile], iFullName: String, stripped: Array[Char]): Array[Char] = {
+ val defaultClassLoader = getClass.getClassLoader
+ val classLoader = vdirOpt match {
+ case Some(vdir) => new AbstractFileClassLoader(vdir, defaultClassLoader)
+ case None => defaultClassLoader
+ }
+ println("running "+iFullName)
+ val si = new SourceInserter(stripped)
+ Executor.execute(iFullName, si, classLoader)
+ println("done")
+ si.currentContents
+ }
+
+ /** The method for implementing worksheet functionality.
+ * @param arguments a file name, followed by optional command line arguments that are passed
+ * to the compiler that processes the instrumented source.
+ * @param line A line number that controls uop to which line results should be produced
+ * If line = -1, results are produced for all expressions in the worksheet.
+ * @return The generated file content containing original source in the left column
+ * and outputs in the right column, or None if the presentation compiler
+ * does not respond to askInstrumented.
+ */
+ def instrument(arguments: List[String], line: Int): Option[Array[Char]] = {
+ val source = toSourceFile(arguments.head)
// strip right hand side comment column and any trailing spaces from all lines
val strippedSource = new BatchSourceFile(source.file, SourceInserter.stripRight(source.content))
comp.askReload(List(strippedSource), reloadResult)
- // todo: Display strippedSource in place of source
comp.askInstrumented(strippedSource, line, instrumentedResult)
- using(instrumentedResult) { case (iFullName, iContents) =>
- // iFullName: The full name of the first top-level object in source
- // iContents: An Array[Char] containing the instrumented source
- // Create a file from iContents so that it can be compiled
- // The name here is <simple name of object>+"$instrumented.scala", but
- // it could be anything.
- val iSimpleName = iFullName drop ((iFullName lastIndexOf '.') + 1)
- val iSourceName = iSimpleName + "$instrumented.scala"
- val ifile = new FileWriter(iSourceName)
- ifile.write(iContents)
- ifile.close()
- println("compiling "+iSourceName)
- // Compile instrumented source
- scala.tools.nsc.Main.process(Array(iSourceName, "-verbose", "-d", "/classes"))
- // Run instrumented source, inserting all output into stripped source
- println("running "+iFullName)
- val si = new SourceInserter(strippedSource.content)
- Executor.execute(iFullName, si)
- println("done")
- si.currentContents
+ using(instrumentedResult) {
+ case (iFullName, iContents) =>
+ val iSourceName = writeInstrumented(iFullName, iContents)
+ val vdirOpt = compileInstrumented(iSourceName, arguments.tail)
+ runInstrumented(vdirOpt, iFullName, strippedSource.content)
}
}
@@ -170,17 +221,29 @@ object REPL {
doComplete(makePos(file, off1, off2))
case List("complete", file, off1) =>
doComplete(makePos(file, off1, off1))
- case List("instrument", file) =>
- println(instrument(toSourceFile(file), -1).map(_.mkString))
- case List("instrument", file, line) =>
- println(instrument(toSourceFile(file), line.toInt).map(_.mkString))
+ case "instrument" :: arguments =>
+ println(instrument(arguments, -1).map(_.mkString))
+ case "instrumentTo" :: line :: arguments =>
+ println(instrument(arguments, line.toInt).map(_.mkString))
case List("quit") =>
comp.askShutdown()
exit(1) // Don't use sys yet as this has to run on 2.8.2 also.
case List("structure", file) =>
doStructure(file)
case _ =>
- println("unrecongized command")
+ print("""Available commands:
+ | reload <file_1> ... <file_n>
+ | reloadAndAskType <file> <sleep-ms>
+ | typed <file>
+ | typeat <file> <start-pos> <end-pos>
+ | typeat <file> <pos>
+ | complete <file> <start-pos> <end-pos>
+ | compile <file> <pos>
+ | instrument <file> <arg>*
+ | instrumentTo <line-num> <file> <arg>*
+ | structure <file>
+ | quit
+ |""".stripMargin)
}
}
}