diff options
6 files changed, 36 insertions, 42 deletions
diff --git a/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala b/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala index e79fc310bb..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, _.templateStatsCompat()) - } - - /** 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 3a71930383..5b3f64afca 100644 --- a/src/repl/scala/tools/nsc/interpreter/IMain.scala +++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala @@ -446,9 +446,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 +466,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 +479,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 @@ -1096,7 +1097,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) @@ -1155,10 +1173,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 _ => } } } diff --git a/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala b/src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala index 8c5162d788..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).templateStatsCompat().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) } |