diff options
author | Lex Spoon <lex@lexspoon.org> | 2006-05-15 15:41:31 +0000 |
---|---|---|
committer | Lex Spoon <lex@lexspoon.org> | 2006-05-15 15:41:31 +0000 |
commit | 5911c61bf58fd0d1acbd65028ea56c0aeaec7dae (patch) | |
tree | bb7aa7b57c25bfb1b8f182e6426b4df1c0682440 | |
parent | 5d3c21e6c7695bf4f77eb701df799a4cf33434ad (diff) | |
download | scala-5911c61bf58fd0d1acbd65028ea56c0aeaec7dae.tar.gz scala-5911c61bf58fd0d1acbd65028ea56c0aeaec7dae.tar.bz2 scala-5911c61bf58fd0d1acbd65028ea56c0aeaec7dae.zip |
added compileString() and bind()
-rw-r--r-- | src/compiler/scala/tools/nsc/Interpreter.scala | 69 |
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 + "\"") } } - } |