summaryrefslogtreecommitdiff
path: root/src/repl
diff options
context:
space:
mode:
Diffstat (limited to 'src/repl')
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ExprTyper.scala26
-rw-r--r--src/repl/scala/tools/nsc/interpreter/IMain.scala117
-rw-r--r--src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala4
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Power.scala2
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Results.scala2
-rw-r--r--src/repl/scala/tools/nsc/interpreter/package.scala4
6 files changed, 71 insertions, 84 deletions
diff --git a/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala b/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala
index 9353215e1e..6406dacc24 100644
--- a/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala
@@ -16,32 +16,6 @@ trait ExprTyper {
import syntaxAnalyzer.UnitParser
import naming.freshInternalVarName
- object codeParser {
- val global: repl.global.type = repl.global
- def applyRule[T](code: String, rule: UnitParser => T): T = {
- reporter.reset()
- val scanner = newUnitParser(code)
- val result = rule(scanner)
-
- if (!reporter.hasErrors)
- scanner.accept(EOF)
-
- result
- }
- def stmts(code: String) = applyRule(code, _.templateStats())
- }
-
- /** Parse a line into a sequence of trees. Returns None if the input is incomplete. */
- def parse(line: String): Option[List[Tree]] = debugging(s"""parse("$line")""") {
- var isIncomplete = false
- reporter.withIncompleteHandler((_, _) => isIncomplete = true) {
- val trees = codeParser.stmts(line)
- if (reporter.hasErrors) Some(Nil)
- else if (isIncomplete) None
- else Some(trees)
- }
- }
-
def symbolOfLine(code: String): Symbol = {
def asExpr(): Symbol = {
val name = freshInternalVarName()
diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala
index b35f71aeef..ae318697ec 100644
--- a/src/repl/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala
@@ -7,30 +7,23 @@ package scala
package tools.nsc
package interpreter
-import Predef.{ println => _, _ }
-import util.stringFromWriter
-import scala.reflect.internal.util._
-import java.net.URL
-import scala.sys.BooleanProp
-import scala.tools.nsc.io.AbstractFile
-import reporters._
+import scala.language.implicitConversions
+
+import scala.collection.mutable
+
+import scala.concurrent.{ Future, ExecutionContext }
+
+import scala.reflect.runtime.{ universe => ru }
+import scala.reflect.{ BeanProperty, ClassTag, classTag }
+import scala.reflect.internal.util.{ BatchSourceFile, SourceFile }
+
import scala.tools.util.PathResolver
-import scala.tools.nsc.util.ScalaClassLoader
+import scala.tools.nsc.io.AbstractFile
import scala.tools.nsc.typechecker.{ TypeStrings, StructuredTypeStrings }
-import ScalaClassLoader.URLClassLoader
+import scala.tools.nsc.util.{ ScalaClassLoader, stringFromWriter }
import scala.tools.nsc.util.Exceptional.unwrap
-import scala.collection.{ mutable, immutable }
-import scala.reflect.BeanProperty
-import scala.util.Properties.versionString
+
import javax.script.{AbstractScriptEngine, Bindings, ScriptContext, ScriptEngine, ScriptEngineFactory, ScriptException, CompiledScript, Compilable}
-import java.io.{ StringWriter, Reader }
-import java.util.Arrays
-import IMain._
-import java.util.concurrent.Future
-import scala.reflect.runtime.{ universe => ru }
-import scala.reflect.{ ClassTag, classTag }
-import StdReplTags._
-import scala.language.implicitConversions
/** An interpreter for Scala code.
*
@@ -92,7 +85,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
private var _classLoader: util.AbstractFileClassLoader = null // active classloader
private val _compiler: ReplGlobal = newCompiler(settings, reporter) // our private compiler
- def compilerClasspath: Seq[URL] = (
+ def compilerClasspath: Seq[java.net.URL] = (
if (isInitializeComplete) global.classPath.asURLs
else new PathResolver(settings).result.asURLs // the compiler's classpath
)
@@ -142,10 +135,8 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
def initialize(postInitSignal: => Unit) {
synchronized {
if (_isInitialized == null) {
- _isInitialized = io.spawn {
- try _initialize()
- finally postInitSignal
- }
+ _isInitialized =
+ Future(try _initialize() finally postInitSignal)(ExecutionContext.global)
}
}
}
@@ -241,7 +232,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
lazy val isettings = new ISettings(this)
/** Instantiate a compiler. Overridable. */
- protected def newCompiler(settings: Settings, reporter: Reporter): ReplGlobal = {
+ protected def newCompiler(settings: Settings, reporter: reporters.Reporter): ReplGlobal = {
settings.outputDirs setSingleOutput replOutput.dir
settings.exposeEmptyPackage.value = true
new Global(settings, reporter) with ReplGlobal { override def toString: String = "<global>" }
@@ -334,7 +325,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
private def makeClassLoader(): util.AbstractFileClassLoader =
new TranslatingClassLoader(parentClassLoader match {
case null => ScalaClassLoader fromURLs compilerClasspath
- case p => new URLClassLoader(compilerClasspath, p)
+ case p => new ScalaClassLoader.URLClassLoader(compilerClasspath, p)
})
// Set the current Java "context" class loader to this interpreter's class loader
@@ -446,9 +437,9 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
private def requestFromLine(line: String, synthetic: Boolean): Either[IR.Result, Request] = {
val content = indentCode(line)
val trees = parse(content) match {
- case None => return Left(IR.Incomplete)
- case Some(Nil) => return Left(IR.Error) // parse error or empty input
- case Some(trees) => trees
+ case parse.Incomplete => return Left(IR.Incomplete)
+ case parse.Error => return Left(IR.Error)
+ case parse.Success(trees) => trees
}
repltrace(
trees map (t => {
@@ -466,7 +457,8 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
// If the last tree is a bare expression, pinpoint where it begins using the
// AST node position and snap the line off there. Rewrite the code embodied
// by the last tree as a ValDef instead, so we can access the value.
- trees.last match {
+ val last = trees.lastOption.getOrElse(EmptyTree)
+ last match {
case _:Assign => // we don't want to include assignments
case _:TermTree | _:Ident | _:Select => // ... but do want other unnamed terms.
val varName = if (synthetic) freshInternalVarName() else freshUserVarName()
@@ -478,7 +470,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
if (trees.size == 1) "val " + varName + " =\n" + content
else {
// The position of the last tree
- val lastpos0 = earliestPosition(trees.last)
+ val lastpos0 = earliestPosition(last)
// Oh boy, the parser throws away parens so "(2+2)" is mispositioned,
// with increasingly hard to decipher positions as we move on to "() => 5",
// (x: Int) => x + 1, and more. So I abandon attempts to finesse and just
@@ -554,7 +546,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
var code = ""
var bound = false
- @throws(classOf[ScriptException])
+ @throws[ScriptException]
def compile(script: String): CompiledScript = {
if (!bound) {
quietBind("engine" -> this.asInstanceOf[ScriptEngine])
@@ -582,9 +574,9 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
}
}
- @throws(classOf[ScriptException])
- def compile(reader: Reader): CompiledScript = {
- val writer = new StringWriter()
+ @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)
@@ -604,7 +596,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
* escape. We could have wrapped runtime exceptions just like other
* exceptions in ScriptException, this is a choice.
*/
- @throws(classOf[ScriptException])
+ @throws[ScriptException]
def eval(context: ScriptContext): Object = {
val result = req.lineRep.evalEither match {
case Left(e: RuntimeException) => throw e
@@ -737,7 +729,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
val unwrapped = unwrap(t)
withLastExceptionLock[String]({
- directBind[Throwable]("lastException", unwrapped)(tagOfThrowable, classTag[Throwable])
+ directBind[Throwable]("lastException", unwrapped)(StdReplTags.tagOfThrowable, classTag[Throwable])
util.stackTraceString(unwrapped)
}, util.stackTraceString(unwrapped))
}
@@ -873,7 +865,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
def fullPath(vname: String) = s"${lineRep.readPath}$accessPath.`$vname`"
/** generate the source code for the object that computes this request */
- private object ObjectSourceCode extends CodeAssembler[MemberHandler] {
+ private object ObjectSourceCode extends IMain.CodeAssembler[MemberHandler] {
def path = originalPath("$intp")
def envLines = {
if (!isReplPower) Nil // power mode only for now
@@ -896,7 +888,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
val generate = (m: MemberHandler) => m extraCodeToEvaluate Request.this
}
- private object ResultObjectSourceCode extends CodeAssembler[MemberHandler] {
+ private object ResultObjectSourceCode extends IMain.CodeAssembler[MemberHandler] {
/** We only want to generate this code when the result
* is a value which can be referred to as-is.
*/
@@ -995,11 +987,11 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
}
}
- @throws(classOf[ScriptException])
+ @throws[ScriptException]
def eval(script: String, context: ScriptContext): Object = compile(script).eval(context)
- @throws(classOf[ScriptException])
- def eval(reader: Reader, context: ScriptContext): Object = compile(reader).eval(context)
+ @throws[ScriptException]
+ def eval(reader: java.io.Reader, context: ScriptContext): Object = compile(reader).eval(context)
override def finalize = close
@@ -1098,7 +1090,24 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
val repl: IMain.this.type = imain
} with ExprTyper { }
- def parse(line: String): Option[List[Tree]] = exprTyper.parse(line)
+ /** Parse a line into and return parsing result (error, incomplete or success with list of trees) */
+ object parse {
+ abstract sealed class Result
+ case object Error extends Result
+ case object Incomplete extends Result
+ case class Success(trees: List[Tree]) extends Result
+
+ def apply(line: String): Result = debugging(s"""parse("$line")""") {
+ var isIncomplete = false
+ reporter.withIncompleteHandler((_, _) => isIncomplete = true) {
+ reporter.reset()
+ val trees = newUnitParser(line).parseStats()
+ if (reporter.hasErrors) Error
+ else if (isIncomplete) Incomplete
+ else Success(trees)
+ }
+ }
+ }
def symbolOfLine(code: String): Symbol =
exprTyper.symbolOfLine(code)
@@ -1157,10 +1166,12 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
*/
def isShow = code.lines exists (_.trim endsWith "// show")
if (isReplDebug || isShow) {
- beSilentDuring(parse(code)) foreach { ts =>
- ts foreach { t =>
- withoutUnwrapping(echo(asCompactString(t)))
- }
+ beSilentDuring(parse(code)) match {
+ case parse.Success(ts) =>
+ ts foreach { t =>
+ withoutUnwrapping(echo(asCompactString(t)))
+ }
+ case _ =>
}
}
}
@@ -1174,6 +1185,8 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set
/** Utility methods for the Interpreter. */
object IMain {
+ import java.util.Arrays.{ asList => asJavaList }
+
class Factory extends ScriptEngineFactory {
@BeanProperty
val engineName = "Scala Interpreter"
@@ -1182,21 +1195,21 @@ object IMain {
val engineVersion = "1.0"
@BeanProperty
- val extensions: JList[String] = Arrays.asList("scala")
+ val extensions: JList[String] = asJavaList("scala")
@BeanProperty
val languageName = "Scala"
@BeanProperty
- val languageVersion = versionString
+ val languageVersion = scala.util.Properties.versionString
def getMethodCallSyntax(obj: String, m: String, args: String*): String = null
@BeanProperty
- val mimeTypes: JList[String] = Arrays.asList("application/x-scala")
+ val mimeTypes: JList[String] = asJavaList("application/x-scala")
@BeanProperty
- val names: JList[String] = Arrays.asList("scala")
+ val names: JList[String] = asJavaList("scala")
def getOutputStatement(toDisplay: String): String = null
diff --git a/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala b/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala
index 8b8b668c9f..61db8d1748 100644
--- a/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala
+++ b/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala
@@ -190,10 +190,10 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput
// literal Ints, Strings, etc.
object literals extends CompletionAware {
- def simpleParse(code: String): Tree = newUnitParser(code).templateStats().last
+ def simpleParse(code: String): Option[Tree] = newUnitParser(code).parseStats().lastOption
def completions(verbosity: Int) = Nil
- override def follow(id: String) = simpleParse(id) match {
+ override def follow(id: String) = simpleParse(id).flatMap {
case x: Literal => Some(new LiteralCompletion(x))
case _ => None
}
diff --git a/src/repl/scala/tools/nsc/interpreter/Power.scala b/src/repl/scala/tools/nsc/interpreter/Power.scala
index da6d271a68..f69a5b487d 100644
--- a/src/repl/scala/tools/nsc/interpreter/Power.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Power.scala
@@ -316,7 +316,7 @@ class Power[ReplValsImpl <: ReplVals : ru.TypeTag: ClassTag](val intp: IMain, re
lazy val phased: Phased = new { val global: intp.global.type = intp.global } with Phased { }
def unit(code: String) = newCompilationUnit(code)
- def trees(code: String) = parse(code) getOrElse Nil
+ def trees(code: String) = parse(code) match { case parse.Success(trees) => trees; case _ => Nil }
override def toString = s"""
|** Power mode status **
diff --git a/src/repl/scala/tools/nsc/interpreter/Results.scala b/src/repl/scala/tools/nsc/interpreter/Results.scala
index e400906a58..a4e1e25cbb 100644
--- a/src/repl/scala/tools/nsc/interpreter/Results.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Results.scala
@@ -19,4 +19,4 @@ object Results {
/** The input was incomplete. The caller should request more input.
*/
case object Incomplete extends Result
-}
+} \ No newline at end of file
diff --git a/src/repl/scala/tools/nsc/interpreter/package.scala b/src/repl/scala/tools/nsc/interpreter/package.scala
index f82c38f5e7..5dc9b65436 100644
--- a/src/repl/scala/tools/nsc/interpreter/package.scala
+++ b/src/repl/scala/tools/nsc/interpreter/package.scala
@@ -145,8 +145,8 @@ package object interpreter extends ReplConfig with ReplStrings {
case sym: TypeSymbol => Some(sym)
case _ => None
}
- (typeFromTypeString orElse typeFromNameTreatedAsTerm orElse typeFromFullName orElse typeOfTerm) foreach { sym =>
- val (kind, tpe) = exitingTyper {
+ (typeFromTypeString orElse typeFromNameTreatedAsTerm orElse typeFromFullName orElse typeOfTerm) foreach { sym =>
+ val (kind, tpe) = exitingTyper {
val tpe = sym.tpeHK
(intp.global.inferKind(NoPrefix)(tpe, sym.owner), tpe)
}