summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLex Spoon <lex@lexspoon.org>2007-03-24 16:13:01 +0000
committerLex Spoon <lex@lexspoon.org>2007-03-24 16:13:01 +0000
commit5752dd02e21bcc05cc3120bc05686856272b898f (patch)
tree8ab4739703ad22ff6fb8167d260697daadda08de /src
parent78e8d1aef2aeb544630f8c87186448f5709ac6f0 (diff)
downloadscala-5752dd02e21bcc05cc3120bc05686856272b898f.tar.gz
scala-5752dd02e21bcc05cc3120bc05686856272b898f.tar.bz2
scala-5752dd02e21bcc05cc3120bc05686856272b898f.zip
- added user-accessible settings for the interp...
- added user-accessible settings for the interpreter - truncate each line of interpreter output to a user-settable length - generate variables like "unnamed123" instead of "line123" - only increment the number for generated variables when one is generated, not for every line submitted to the interpreter
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/Interpreter.scala68
-rw-r--r--src/compiler/scala/tools/nsc/InterpreterLoop.scala35
-rw-r--r--src/compiler/scala/tools/nsc/InterpreterSettings.scala20
3 files changed, 96 insertions, 27 deletions
diff --git a/src/compiler/scala/tools/nsc/Interpreter.scala b/src/compiler/scala/tools/nsc/Interpreter.scala
index c66590c359..331e63108c 100644
--- a/src/compiler/scala/tools/nsc/Interpreter.scala
+++ b/src/compiler/scala/tools/nsc/Interpreter.scala
@@ -93,6 +93,9 @@ class Interpreter(val settings: Settings, reporter: Reporter, out: PrintWriter)
}
}
+ /** interpreter settings */
+ val isettings = new InterpreterSettings
+
/** directory to save .class files to */
val classfilePath = File.createTempFile("scalaint", "")
classfilePath.delete // the file is created as a file; make it a directory
@@ -148,10 +151,20 @@ class Interpreter(val settings: Settings, reporter: Reporter, out: PrintWriter)
private def newLineName = {
val num = nextLineNo
nextLineNo = nextLineNo + 1
- (compiler.nme.INTERPRETER_LINE_PREFIX +
- (if (num>=0) num.toString else "_neg" + (-num).toString))
+ compiler.nme.INTERPRETER_LINE_PREFIX + num
+ }
+
+ /** next result variable number to use */
+ private var nextVarNameNo = 0
+
+ /** allocate a fresh variable name */
+ private def newVarName() = {
+ val num = nextVarNameNo
+ nextVarNameNo = nextVarNameNo + 1
+ "unnamed" + num
}
+
/** import statements that should be used for submitted code */
private def importLines: List[String] =
for {
@@ -174,6 +187,23 @@ class Interpreter(val settings: Settings, reporter: Reporter, out: PrintWriter)
stringWriter.toString
}
+ /** Truncate a string if it is longer than settings.maxPrintString */
+ private def truncPrintString(str: String): String = {
+ val maxpr = isettings.maxPrintString
+
+ if(maxpr <= 0)
+ return str
+
+ if(str.length <= maxpr)
+ return str
+
+ val trailer = "..."
+ if(maxpr >= trailer.length+1)
+ return str.substring(0, maxpr-3) + trailer
+
+ return str.substring(0, maxpr)
+ }
+
/** Parse a line into a sequence of trees. Returns None if the input
* is incomplete. */
private def parse(line: String): Option[List[Tree]] = {
@@ -286,7 +316,7 @@ class Interpreter(val settings: Settings, reporter: Reporter, out: PrintWriter)
if (printResults || !succeeded) {
// print the result
- out.print(interpreterResultString)
+ out.print(truncPrintString(interpreterResultString))
// print out types of functions; they are not printed in the
// request printout
@@ -337,18 +367,6 @@ class Interpreter(val settings: Settings, reporter: Reporter, out: PrintWriter)
}
- /** Make a dry run in order to fill caches. This is useful
- * for interactive interpreters so that the interpreter responds
- * quickly to the first user-supplied query.
- */
- def prime: Unit =
- if(prevRequests.isEmpty)
- beQuietDuring {
- nextLineNo = -1 // cosmetic: make the first user-requested line
- // be number 0
- interpret("0")
- }
-
/** <p>
* This instance is no longer needed, so release any resources
* it is using.
@@ -386,7 +404,19 @@ class Interpreter(val settings: Settings, reporter: Reporter, out: PrintWriter)
/** whether the trees need a variable name, as opposed to standing
alone */
- def needsVarName: Boolean = false
+ val needsVarName: Boolean = false
+
+ /** A cache for the chosen variable name, if one has been calculated */
+ var varNameCache: Option[String] = None
+
+ /** A computed variable name, if one is needed */
+ def varName =
+ varNameCache match {
+ case None =>
+ varNameCache = Some(newVarName)
+ varNameCache.get
+ case Some(name) => name
+ }
/** list of methods defined */
val defNames =
@@ -404,7 +434,7 @@ class Interpreter(val settings: Settings, reporter: Reporter, out: PrintWriter)
} yield name
if (needsVarName)
- compiler.encode(lineName) :: baseNames // add a var name
+ compiler.encode(varName) :: baseNames // add a var name
else
baseNames
}
@@ -467,7 +497,7 @@ class Interpreter(val settings: Settings, reporter: Reporter, out: PrintWriter)
// the line of code to compute
if (needsVarName)
- code.println(" val " + lineName + " = " + line)
+ code.println(" val " + varName + " = " + line)
else
code.println(" " + line)
@@ -652,7 +682,7 @@ class Interpreter(val settings: Settings, reporter: Reporter, out: PrintWriter)
override val boundNames = Nil
override val usedNames = Nil
override def resultExtractionCode(code: PrintWriter): Unit = {
- code.println("+ \"" + line + "\"")
+ code.println("+ \"" + trees.head.toString + "\"")
}
}
}
diff --git a/src/compiler/scala/tools/nsc/InterpreterLoop.scala b/src/compiler/scala/tools/nsc/InterpreterLoop.scala
index a353c2b3e8..a8c26c4a79 100644
--- a/src/compiler/scala/tools/nsc/InterpreterLoop.scala
+++ b/src/compiler/scala/tools/nsc/InterpreterLoop.scala
@@ -36,6 +36,7 @@ class InterpreterLoop(in0: BufferedReader, out: PrintWriter) {
var settings: Settings = _ // set by main()
var interpreter: Interpreter = null // set by createInterpreter()
+ def isettings = interpreter.isettings
/** A reverse list of commands to replay if the user
* requests a :replay */
@@ -72,6 +73,17 @@ class InterpreterLoop(in0: BufferedReader, out: PrintWriter) {
}
}
+ /** Bind the settings so that evaluated code can modiy them */
+ def bindSettings() {
+ interpreter.beQuietDuring {
+ interpreter.bind(
+ "settings",
+ "scala.tools.nsc.InterpreterSettings",
+ isettings)
+ }
+ }
+
+
/** print a friendly help message */
def printHelp {
out.println("This is an interpreter for Scala.")
@@ -89,21 +101,28 @@ class InterpreterLoop(in0: BufferedReader, out: PrintWriter) {
out.println("Type :help for more information.")
}
- /** The main read-eval-print loop for the interpereter. It calls
+ /** The main read-eval-print loop for the interpreter. It calls
* <code>command()</code> for each line of input, and stops when
* <code>command()</code> returns <code>false</code>.
*/
- def repl {
- var firstTime = true
+ def repl() {
+ var first = true
while (true) {
if (interactive) {
out.print("\nscala> ")
out.flush
- if (firstTime) {
- interpreter.prime
- firstTime = false
- }
}
+ if(first) {
+ /* For some reason, the first interpreted command always takes
+ * a second or two. So, wait until the welcome message
+ * has been printed before calling bindSettings. That way,
+ * the user can read the welcome message while this
+ * command executes.
+ */
+ bindSettings()
+ first = false
+ }
+
var line = in.readLine()
if (line eq null)
return () // assumes null means EOF
@@ -145,7 +164,7 @@ class InterpreterLoop(in0: BufferedReader, out: PrintWriter) {
}
/** create a new interpreter and replay all commands so far */
- def replay {
+ def replay() {
closeInterpreter
createInterpreter
for (val cmd <- replayCommands) {
diff --git a/src/compiler/scala/tools/nsc/InterpreterSettings.scala b/src/compiler/scala/tools/nsc/InterpreterSettings.scala
new file mode 100644
index 0000000000..7e5d0a5cc4
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/InterpreterSettings.scala
@@ -0,0 +1,20 @@
+package scala.tools.nsc
+
+/** Settings for the interpreter */
+class InterpreterSettings {
+ /** A list of paths where :load should look */
+ var loadPath = List(".", "/home/lex/tmp") // XXX remove tmp, just for testing
+
+ /** 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 = 390
+
+ override def toString =
+ "InterpreterSettings {\n" +
+// " loadPath = " + loadPath + "\n" +
+ " maxPrintString = " + maxPrintString + "\n" +
+ "}"
+}