我正在使用scala.tools.nsc.Interpreter执行scala代码片段当代码片段正确时,一切都很好,但是当它有错误时,我的代码无法找到并愉快地继续.我想获得一个异常或方法来调用以获取解释器在上次评估期间发生的任何错误.
我的代码:
import scala.tools.nsc.Interpreter
import scala.tools.nsc.Settings
object RuntimeEval {
def main(args: Array[String]): Unit = {
var msg = "fail"
val eval = new RuntimeEval
msg = eval.eval(msg,"\"success\"")
println(msg)
var anInt = 0
while(true){
println("Enter an integer")
val userInput = Console.readLine
anInt = eval.eval(anInt,userInput)
println("-->"+anInt)
println
}
}
}
class ResContainer(var value: Any)
class RuntimeEval {
val settings = new Settings
settings.classpath.value = System.getProperty("java.class.path")
val interp = new Interpreter(settings)
def eval[A <: Any](obj: A, expression: String): A={
val res = new ResContainer(obj)
interp.beQuietDuring {
interp.bind("res", res.getClass.getCanonicalName, res)
interp.interpret("res.value = "+expression)
}
val info = obj match{
case x: AnyRef => "expected type: \n"+x.getClass.getCanonicalName+"\n"
case _ => "expected type is not an AnyRef\n"
}
res.value match{
case x: A => x
case x: AnyRef => error("unexpected result type, "+info+"result type:\n"+x.getClass.getCanonicalName)
case _ => error("unexpected result type, "+info+"result type is not an AnyRef")
}
}
}
Run Code Online (Sandbox Code Playgroud)
问题的一个例子:
success
Enter an integer
9/12
-->0
Enter an integer
9/0
java.lang.ArithmeticException: / by zero
at .<init>(<console>:6)
at .<clinit>(<console>)
at RequestResult$.<init>(<console>:5)
at RequestResult$.<clinit>(<console>)
at RequestResult$scala_repl_result(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$17.apply(Interpreter.scala:988)
at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$17.apply(Interpreter.scala:988)
at scala.util.control.Exception$Catch.apply(Exception.scala:79)
at scala...-->0
Enter an integer
9/4
-->2
Enter an integer
Run Code Online (Sandbox Code Playgroud)
ArithmeticException发生在解释器内部,然后它似乎什么也没有返回,所以我的代码得到了与之前的操作相同的结果,0.如何捕获这个?
interpretInterpreter 的方法返回一个结果值,指示代码是否可以成功解释.从而:
interp.beQuietDuring {
interp.bind("res", res.getClass.getCanonicalName, res)
interp.interpret("res.value = "+expression)
} match {
case Results.Error => error( ... )
case Results.Incomplete => error( ... )
case Results.Success => res.value
}
Run Code Online (Sandbox Code Playgroud)
还有两件事:你不需要"res"为每一个绑定eval,一旦你初始化解释器就应该这样做.另外,请注意有一种方法mostRecentVar,因此您可以完全取消结果绑定.以下是Scala 2.9的示例(与2.8相同,但不是Interpreter您使用IMain):
import tools.nsc.interpreter.{IMain, Results}
import sys.error
val interp = new IMain()
def eval( expression: String ) : AnyRef =
interp.interpret( expression ) match {
case Results.Error => error( "Failed" )
case Results.Incomplete => error( "Incomplete" )
case Results.Success => interp.valueOfTerm( interp.mostRecentVar )
.getOrElse( error( "No result" ))
}
Run Code Online (Sandbox Code Playgroud)
测试:
scala> val x = eval( "1 + 2" )
res0: Int = 3
x: AnyRef = 3
Run Code Online (Sandbox Code Playgroud)