Skip to content

Commit

Permalink
SI-7933 REPL javax.script eval is cached result
Browse files Browse the repository at this point in the history
The problem is that the repl underneath the script engine evaluates input to
val res0..resN, so it is a one shot operation. To allow repetition,
compile(script) now returns a CompiledScript object whose eval method can be
called any number of times.
  • Loading branch information
rjolly committed Jan 31, 2014
1 parent 8f6f403 commit 9dfac45
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 36 deletions.
13 changes: 12 additions & 1 deletion src/compiler/scala/tools/nsc/util/package.scala
Expand Up @@ -7,7 +7,7 @@ package scala
package tools
package nsc

import java.io.{ OutputStream, PrintStream, ByteArrayOutputStream, PrintWriter, StringWriter }
import java.io.{ OutputStream, PrintStream, ByteArrayOutputStream, PrintWriter, StringWriter, Reader }

package object util {
// forwarder for old code that builds against 2.9 and 2.10
Expand Down Expand Up @@ -46,6 +46,17 @@ package object util {
(result, ts2 filterNot (ts1 contains _))
}

def stringFromReader(reader: Reader) = {
val writer = new StringWriter()
var c = reader.read()
while(c != -1) {
writer.write(c)
c = reader.read()
}
reader.close()
writer.toString()
}

/** Generate a string using a routine that wants to write on a stream. */
def stringFromWriter(writer: PrintWriter => Unit): String = {
val stringWriter = new StringWriter()
Expand Down
27 changes: 10 additions & 17 deletions src/repl/scala/tools/nsc/interpreter/IMain.scala
Expand Up @@ -18,7 +18,7 @@ import scala.reflect.internal.util.{ BatchSourceFile, SourceFile }
import scala.tools.util.PathResolver
import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.typechecker.{ TypeStrings, StructuredTypeStrings }
import scala.tools.nsc.util.{ ScalaClassLoader, stringFromWriter, StackTraceOps }
import scala.tools.nsc.util.{ ScalaClassLoader, stringFromReader, stringFromWriter, StackTraceOps }
import scala.tools.nsc.util.Exceptional.unwrap
import javax.script.{AbstractScriptEngine, Bindings, ScriptContext, ScriptEngine, ScriptEngineFactory, ScriptException, CompiledScript, Compilable}

Expand Down Expand Up @@ -534,8 +534,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set

var code = ""
var bound = false
@throws[ScriptException]
def compile(script: String): CompiledScript = {
def compiled(script: String): CompiledScript = {
if (!bound) {
quietBind("engine" -> this.asInstanceOf[ScriptEngine])
bound = true
Expand All @@ -562,18 +561,6 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
}
}

@throws[ScriptException]
def compile(reader: java.io.Reader): CompiledScript = {
val writer = new java.io.StringWriter()
var c = reader.read()
while(c != -1) {
writer.write(c)
c = reader.read()
}
reader.close()
compile(writer.toString())
}

private class WrappedRequest(val req: Request) extends CompiledScript {
var recorded = false

Expand Down Expand Up @@ -1014,10 +1001,16 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
}

@throws[ScriptException]
def eval(script: String, context: ScriptContext): Object = compile(script).eval(context)
def compile(script: String): CompiledScript = eval("new javax.script.CompiledScript { def eval(context: javax.script.ScriptContext): Object = { " + script + " }.asInstanceOf[Object]; def getEngine: javax.script.ScriptEngine = engine }").asInstanceOf[CompiledScript]

@throws[ScriptException]
def compile(reader: java.io.Reader): CompiledScript = compile(stringFromReader(reader))

@throws[ScriptException]
def eval(script: String, context: ScriptContext): Object = compiled(script).eval(context)

@throws[ScriptException]
def eval(reader: java.io.Reader, context: ScriptContext): Object = compile(reader).eval(context)
def eval(reader: java.io.Reader, context: ScriptContext): Object = eval(stringFromReader(reader), context)

override def finalize = close

Expand Down
18 changes: 0 additions & 18 deletions test/disabled/run/t7843-jsr223-service.scala

This file was deleted.

File renamed without changes.
8 changes: 8 additions & 0 deletions test/files/run/t7843-jsr223-service.scala
@@ -0,0 +1,8 @@
import scala.tools.nsc.interpreter.IMain

object Test extends App {
val engine = new IMain.Factory getScriptEngine()
engine.asInstanceOf[IMain].settings.usejavacp.value = true
engine put ("n", 10)
engine eval "1 to n.asInstanceOf[Int] foreach print"
}
2 changes: 2 additions & 0 deletions test/files/run/t7933.check
@@ -0,0 +1,2 @@
hello
hello
11 changes: 11 additions & 0 deletions test/files/run/t7933.scala
@@ -0,0 +1,11 @@
import scala.tools.nsc.interpreter.IMain

object Test extends App {
val engine = new IMain.Factory getScriptEngine()
engine.asInstanceOf[IMain].settings.usejavacp.value = true
val res2 = engine.asInstanceOf[javax.script.Compilable]
res2 compile "8" eval()
val res5 = res2 compile """println("hello") ; 8"""
res5 eval()
res5 eval()
}

0 comments on commit 9dfac45

Please sign in to comment.