diff options
author | Paul Phillips <paulp@improving.org> | 2013-03-10 17:17:58 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-03-11 20:07:24 -0700 |
commit | 48cc8b47fcadaa187026ca0422178c9094e4b412 (patch) | |
tree | 32f3cce4559030e3088741390024c19eb5110bbe /src/repl/scala/tools/nsc/interpreter/ExprTyper.scala | |
parent | 1b6297f642877dcc7edcd704a5d3cf99a12e54b8 (diff) | |
download | scala-48cc8b47fcadaa187026ca0422178c9094e4b412.tar.gz scala-48cc8b47fcadaa187026ca0422178c9094e4b412.tar.bz2 scala-48cc8b47fcadaa187026ca0422178c9094e4b412.zip |
Modularized the repl.
Following in the footsteps of scaladoc and interactive.
The interpreter sources move into src/repl, and are given
a separate build target. As with the others, at present
they are still packaged into scala-compiler.jar.
A summary of changes:
- repl requires use of ReplGlobal (this was already implied)
- macro code's repl-specific classloader hack pulled into overridable
method and overridden in ReplGlobal
- removed -Ygen-javap option to eliminate backend's dependency on javap
- removed -Yrepl-debug option (can still be enabled with -Dscala.repl.debug)
- pushed javap code into src/repl so javax.tools dependency can bee
weakened to the repl only
- removed some "show pickled" related code which hasn't worked right
in a while and isn't the right way to do it anymore anyway. Will
return to fix showPickled and provide it with some tests.
Diffstat (limited to 'src/repl/scala/tools/nsc/interpreter/ExprTyper.scala')
-rw-r--r-- | src/repl/scala/tools/nsc/interpreter/ExprTyper.scala | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala b/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala new file mode 100644 index 0000000000..9edd54b939 --- /dev/null +++ b/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala @@ -0,0 +1,99 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2013 LAMP/EPFL + * @author Paul Phillips + */ + +package scala.tools.nsc +package interpreter + +import scala.tools.nsc.ast.parser.Tokens.EOF + +trait ExprTyper { + val repl: IMain + + import repl._ + import global.{ reporter => _, Import => _, _ } + import definitions._ + 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() + // Typing it with a lazy val would give us the right type, but runs + // into compiler bugs with things like existentials, so we compile it + // behind a def and strip the NullaryMethodType which wraps the expr. + val line = "def " + name + " = " + code + + interpretSynthetic(line) match { + case IR.Success => + val sym0 = symbolOfTerm(name) + // drop NullaryMethodType + sym0.cloneSymbol setInfo exitingTyper(sym0.info.finalResultType) + case _ => NoSymbol + } + } + def asDefn(): Symbol = { + val old = repl.definedSymbolList.toSet + + interpretSynthetic(code) match { + case IR.Success => + repl.definedSymbolList filterNot old match { + case Nil => NoSymbol + case sym :: Nil => sym + case syms => NoSymbol.newOverloaded(NoPrefix, syms) + } + case _ => NoSymbol + } + } + def asError(): Symbol = { + interpretSynthetic(code) + NoSymbol + } + beSilentDuring(asExpr()) orElse beSilentDuring(asDefn()) orElse asError() + } + + private var typeOfExpressionDepth = 0 + def typeOfExpression(expr: String, silent: Boolean = true): Type = { + if (typeOfExpressionDepth > 2) { + repldbg("Terminating typeOfExpression recursion for expression: " + expr) + return NoType + } + typeOfExpressionDepth += 1 + // Don't presently have a good way to suppress undesirable success output + // while letting errors through, so it is first trying it silently: if there + // is an error, and errors are desired, then it re-evaluates non-silently + // to induce the error message. + try beSilentDuring(symbolOfLine(expr).tpe) match { + case NoType if !silent => symbolOfLine(expr).tpe // generate error + case tpe => tpe + } + finally typeOfExpressionDepth -= 1 + } +} |