Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use JSR-223 to get Scala interpreter in sbt console?

In the sbt console, sbt version 0.13.5, Scala version 2.11.1, I can get javax.script.ScriptEngine for Scala:

scala> val engine = new javax.script.ScriptEngineManager().getEngineByName("scala")
engine: javax.script.ScriptEngine = scala.tools.nsc.interpreter.IMain@bf78a9

However, I can't use it:

scala> engine.eval("3")
[init] error: error while loading Object, Missing dependency 'object scala in compiler mirror', required by /usr/lib/jvm/java-7-openjdk-i386/jre/lib/rt.jar(java/lang/Object.class)

Failed to initialize compiler: object scala in compiler mirror not found.
** Note that as of 2.8 scala does not assume use of the java classpath.
** For the old behavior pass -usejavacp to scala, or if using a Settings
** object programatically, settings.usejavacp.value = true.
scala.reflect.internal.MissingRequirementError: object scala in compiler mirror not found.
  at ...

According to the SBT FAQ, I am supposed to do some magic with a Settings, and then pass it into my Interpreter's constructor. However, I'm not directly creating an Interpreter (and it's not even clear if I'm indirectly creating it, as the engine object is an IMain).

Is there some way for the Scala ScriptEngine to work on the SBT console?

like image 424
Dan Getz Avatar asked May 30 '14 18:05

Dan Getz


1 Answers

You can cast your engine to scala.tools.nsc.interpreter.IMain, which will give you an access to the settings. Then you can use embeddedDefaults to set a classpath as it was mentioned in the FAQ. Just do it before call to the eval method.

val engine = new javax.script.ScriptEngineManager().getEngineByName("scala")
val settings = engine.asInstanceOf[scala.tools.nsc.interpreter.IMain].settings
// MyScalaClass is just any class in your project
settings.embeddedDefaults[MyScalaClass]

Given that you should be able to run eval, e.g.

scala> engine.eval("10")
res3: Object = 10

The reason is more or less explained in the gist linked from the FAQ. Basically, when creating an interpreter using getEngineByName("scala"), the java.class.path is used and it contains only sbt-launch.jar. Using the trick with embeddedDefaults sets the class path to the correct value (you can check the settings before and after a call to the embeddedDefaults).

like image 162
lpiepiora Avatar answered Nov 01 '22 01:11

lpiepiora