Skip to content

Commit ace3584

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

File tree

5 files changed

+98
-1
lines changed

5 files changed

+98
-1
lines changed

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

+1-1
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 {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
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+
class ScriptEngine(factory: ScriptEngine.Factory) extends AbstractScriptEngine {
8+
val driver = factory.driver
9+
val rendering = new Rendering
10+
var state: State = driver.initialState
11+
12+
def getFactory(): ScriptEngineFactory = factory
13+
14+
def createBindings: Bindings = new SimpleBindings
15+
16+
/* Evaluate with the given context. */
17+
@throws[ScriptException]
18+
def eval(script: String, context: ScriptContext): Object = {
19+
val vid = state.valIndex
20+
state = driver.run(script)(state)
21+
val oid = state.objectIndex
22+
Class.forName(s"rs$$line$$$oid", true, rendering.classLoader()(state.context))
23+
.getDeclaredMethods.find(_.getName == s"res$vid")
24+
.map(_.invoke(null))
25+
.getOrElse(null)
26+
}
27+
28+
@throws[ScriptException]
29+
def eval(reader: Reader, context: ScriptContext): Object = eval(stringFromReader(reader), context)
30+
31+
def stringFromReader(reader: Reader) = {
32+
val writer = new StringWriter()
33+
var c = reader.read()
34+
while(c != -1) {
35+
writer.write(c)
36+
c = reader.read()
37+
}
38+
reader.close()
39+
writer.toString()
40+
}
41+
}
42+
43+
object ScriptEngine {
44+
import java.util.Arrays.asList
45+
import scala.util.Properties.versionString
46+
47+
class Factory extends ScriptEngineFactory {
48+
val driver = new ReplDriver(Array("-usejavacp"), Console.out, None);
49+
50+
def getEngineName() = "Scala REPL"
51+
def getEngineVersion() = "3.0"
52+
def getExtensions() = asList("scala")
53+
def getLanguageName() = "Scala"
54+
def getLanguageVersion() = versionString
55+
def getMimeTypes() = asList("application/x-scala")
56+
def getNames() = asList("scala")
57+
58+
def getMethodCallSyntax(obj: String, m: String, args: String*): String = null
59+
60+
def getOutputStatement(toDisplay: String): String = null
61+
62+
def getParameter(key: String): Object = key match {
63+
case JScriptEngine.ENGINE => getEngineName
64+
case JScriptEngine.ENGINE_VERSION => getEngineVersion
65+
case JScriptEngine.LANGUAGE => getLanguageName
66+
case JScriptEngine.LANGUAGE_VERSION => getLanguageVersion
67+
case JScriptEngine.NAME => getNames.get(0)
68+
case _ => null
69+
}
70+
71+
def getProgram(statements: String*): String = null
72+
73+
def getScriptEngine: JScriptEngine = {
74+
new ScriptEngine(this)
75+
}
76+
}
77+
}

project/Build.scala

+7
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,13 @@ object Build {
553553
Seq(file)
554554
}.taskValue,
555555

556+
// Generate the ScriptEngineFactory service definition
557+
resourceGenerators in Compile += Def.task {
558+
val f = (resourceManaged in Compile).value / "META-INF" / "services" / "javax.script.ScriptEngineFactory"
559+
IO.write(f, "dotty.tools.repl.ScriptEngine$Factory\n")
560+
Seq(f)
561+
}.taskValue,
562+
556563
// get libraries onboard
557564
libraryDependencies ++= Seq(
558565
"org.scala-lang.modules" % "scala-asm" % "6.0.0-scala-1", // used by the backend
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
val res0: Int = 42
2+
3+
42
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
object Test {
2+
def main(args: Array[String]): Unit = {
3+
// val m = new javax.script.ScriptEngineManager()
4+
// val e = m.getEngineByName("scala")
5+
val f = new dotty.tools.repl.ScriptEngine.Factory()
6+
val e = f.getScriptEngine()
7+
println(e.eval("42"))
8+
}
9+
}
10+

0 commit comments

Comments
 (0)