summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLex Spoon <lex@lexspoon.org>2006-05-15 15:41:31 +0000
committerLex Spoon <lex@lexspoon.org>2006-05-15 15:41:31 +0000
commit5911c61bf58fd0d1acbd65028ea56c0aeaec7dae (patch)
treebb7aa7b57c25bfb1b8f182e6426b4df1c0682440
parent5d3c21e6c7695bf4f77eb701df799a4cf33434ad (diff)
downloadscala-5911c61bf58fd0d1acbd65028ea56c0aeaec7dae.tar.gz
scala-5911c61bf58fd0d1acbd65028ea56c0aeaec7dae.tar.bz2
scala-5911c61bf58fd0d1acbd65028ea56c0aeaec7dae.zip
added compileString() and bind()
-rw-r--r--src/compiler/scala/tools/nsc/Interpreter.scala69
1 files changed, 66 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/Interpreter.scala b/src/compiler/scala/tools/nsc/Interpreter.scala
index ec21c5c45a..64945ce5f2 100644
--- a/src/compiler/scala/tools/nsc/Interpreter.scala
+++ b/src/compiler/scala/tools/nsc/Interpreter.scala
@@ -93,7 +93,7 @@ class Interpreter(val settings: Settings, reporter: Reporter, out: PrintWriter)
The main disadvantage is:
- Objects, classes, and methods cannot be rebound. Instead, definitions
- shadow the old ones, and old code objects to refer to the old
+ shadow the old ones, and old code objects refer to the old
definitions.
*/
private val classLoader = {
@@ -173,7 +173,7 @@ class Interpreter(val settings: Settings, reporter: Reporter, out: PrintWriter)
}
/** Compile one source file */
- def compile(filename: String): Unit = {
+ def compileFile(filename: String): Unit = {
val jfile = new File(filename)
if(!jfile.exists) {
reporter.error(null, "no such file: " + filename)
@@ -183,6 +183,15 @@ class Interpreter(val settings: Settings, reporter: Reporter, out: PrintWriter)
cr.compileSources(List(new SourceFile(PlainFile.fromFile(jfile))))
}
+ /** Compile a string. Returns true if there are no
+ * compilation errors, or false otherwise. */
+ def compileString(code: String): Boolean = {
+ val cr = new compiler.Run
+ reporter.reset
+ cr.compileSources(List(new SourceFile("<script>", code.toCharArray)))
+ return (reporter.errors == 0)
+ }
+
/** build a request from the user. "tree" is "line" after being parsed */
private def buildRequest(trees: List[Tree], line: String, lineName: String): Request = {
trees match {
@@ -247,6 +256,61 @@ class Interpreter(val settings: Settings, reporter: Reporter, out: PrintWriter)
succeeded
}
+ /** A counter used for numbering objects created by bind() */
+ private var binderNum = 0
+
+ /** Bind a specified name to a specified value. The name may
+ * later be used by expressions passed to interpret
+ */
+ def bind(name: String, boundType: String, value: Any) = {
+ // XXX check that name is a valid variable name */
+ val binderName = "binder" + binderNum
+ binderNum = binderNum + 1
+ /*
+ /** Find a narrow Scala type for the specified object */
+ def scalaType(obj: Any): String =
+ obj match {
+ case ary:scala.runtime.BoxedArray => { //XXX what if obj is actually a non-boxed array??
+ val elementType =
+ if(ary.length == 0)
+ "Nothing" // XXX this might not work; what should be done?
+ else
+ scalaType(ary(0))
+ "Array[" + elementType + "]"
+ }
+ case _:Boolean => "Boolean"
+ case _:Byte => "Byte"
+ case _:Char => "Char"
+ case _:Double => "Double"
+ case _:Float => "Float"
+ case _:Int => "Int"
+ case _:Long => "Long"
+ case _:Short => "Short"
+ case obj:AnyRef => obj.getClass.getName
+ }
+ val boundType = scalaType(value)
+ */
+ compileString(
+ "object " + binderName +
+ "{ var value: " + boundType + " = _; " +
+ " def set(x: Any) = value=x.asInstanceOf[" + boundType + "]; }")
+
+ val binderObject =
+ Class.forName(binderName, true, classLoader)
+ val setterMethod =
+ (binderObject
+ .getDeclaredMethods
+ .toList
+ .find(meth => meth.getName == "set")
+ .get)
+ var argsHolder: Array[Any] = null // XXX this roundabout approach is to try and make sure the value is boxed
+ argsHolder = List(value).toArray
+ setterMethod.invoke(null, argsHolder.asInstanceOf[Array[Object]])
+
+
+ interpret("val " + name + " = " + binderName + ".value")
+ }
+
/** Delete a directory tree recursively. Use with care! */
private def deleteRecursively(path: File): Unit = {
path match {
@@ -547,5 +611,4 @@ class Interpreter(val settings: Settings, reporter: Reporter, out: PrintWriter)
code.println("+ \"" + line + "\"")
}
}
-
}