Skip to content

Commit 0de79e4

Browse files
committed
Embryonic but functioning JSR223 support
1 parent fb0e3bc commit 0de79e4

File tree

5 files changed

+95
-1
lines changed

5 files changed

+95
-1
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dotty.tools.repl.ScriptEngine$Factory

compiler/src/dotty/tools/repl/Rendering.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ private[repl] class Rendering(parentClassLoader: Option[ClassLoader] = None) {
2626
private[this] var myClassLoader: ClassLoader = _
2727

2828
/** Class loader used to load compiled code */
29-
private[this] def classLoader()(implicit ctx: Context) =
29+
private[repl] def classLoader()(implicit ctx: Context) =
3030
if (myClassLoader != null) myClassLoader
3131
else {
3232
val parent = parentClassLoader.getOrElse {
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package dotty.tools
2+
package repl
3+
4+
import java.io.{Reader, StringWriter};
5+
import javax.script.{AbstractScriptEngine, Bindings, ScriptContext, ScriptEngine => JScriptEngine, ScriptEngineFactory, ScriptException, SimpleBindings}
6+
7+
/** A JSR 223 (Scripting API) compatible wrapper around the REPL for improved
8+
* interoperability with software that support it.
9+
*
10+
* @param factory the script engine factory
11+
*/
12+
class ScriptEngine(factory: ScriptEngine.Factory) extends AbstractScriptEngine {
13+
val driver = factory.driver
14+
val rendering = new Rendering
15+
var state: State = driver.initialState
16+
17+
def getFactory(): ScriptEngineFactory = factory
18+
19+
def createBindings: Bindings = new SimpleBindings
20+
21+
/* Evaluate with the given context. */
22+
@throws[ScriptException]
23+
def eval(script: String, context: ScriptContext): Object = {
24+
val vid = state.valIndex
25+
state = driver.run(script)(state)
26+
val oid = state.objectIndex
27+
Class.forName(s"rs$$line$$$oid", true, rendering.classLoader()(state.context))
28+
.getDeclaredMethods.find(_.getName == s"res$vid")
29+
.map(_.invoke(null))
30+
.getOrElse(null)
31+
}
32+
33+
@throws[ScriptException]
34+
def eval(reader: Reader, context: ScriptContext): Object = eval(stringFromReader(reader), context)
35+
36+
def stringFromReader(reader: Reader) = {
37+
val writer = new StringWriter()
38+
var c = reader.read()
39+
while(c != -1) {
40+
writer.write(c)
41+
c = reader.read()
42+
}
43+
reader.close()
44+
writer.toString()
45+
}
46+
}
47+
48+
object ScriptEngine {
49+
import java.util.Arrays.asList
50+
import scala.util.Properties.versionString
51+
52+
class Factory extends ScriptEngineFactory {
53+
val driver = new ReplDriver(Array("-usejavacp", "-color:never"), Console.out, None);
54+
55+
def getEngineName() = "Scala REPL"
56+
def getEngineVersion() = "3.0"
57+
def getExtensions() = asList("scala")
58+
def getLanguageName() = "Scala"
59+
def getLanguageVersion() = versionString
60+
def getMimeTypes() = asList("application/x-scala")
61+
def getNames() = asList("scala")
62+
63+
def getMethodCallSyntax(obj: String, m: String, args: String*): String = null
64+
65+
def getOutputStatement(toDisplay: String): String = null
66+
67+
def getParameter(key: String): Object = key match {
68+
case JScriptEngine.ENGINE => getEngineName
69+
case JScriptEngine.ENGINE_VERSION => getEngineVersion
70+
case JScriptEngine.LANGUAGE => getLanguageName
71+
case JScriptEngine.LANGUAGE_VERSION => getLanguageVersion
72+
case JScriptEngine.NAME => getNames.get(0)
73+
case _ => null
74+
}
75+
76+
def getProgram(statements: String*): String = null
77+
78+
def getScriptEngine: JScriptEngine = {
79+
new ScriptEngine(this)
80+
}
81+
}
82+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
val res0: Int = 42
2+
3+
42
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
object Test {
2+
def main(args: Array[String]): Unit = {
3+
val m = new javax.script.ScriptEngineManager(getClass().getClassLoader())
4+
val e = m.getEngineByName("scala")
5+
println(e.eval("42"))
6+
}
7+
}
8+

0 commit comments

Comments
 (0)