summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLex Spoon <lex@lexspoon.org>2008-02-18 21:22:08 +0000
committerLex Spoon <lex@lexspoon.org>2008-02-18 21:22:08 +0000
commit41dc7225084c735f0306e0ebb1a9da0fbd9886ff (patch)
tree071a5737f9f871bc8b5769584cdf5327ada971bc
parent1769b68a6d41010aebcd76d240c1a74166a99419 (diff)
downloadscala-41dc7225084c735f0306e0ebb1a9da0fbd9886ff.tar.gz
scala-41dc7225084c735f0306e0ebb1a9da0fbd9886ff.tar.bz2
scala-41dc7225084c735f0306e0ebb1a9da0fbd9886ff.zip
Generalizes the allowed inputs to the interpret...
Generalizes the allowed inputs to the interpreter to be any combination of phrases that can be placed inside a template. Instead of having one "request" object try to understand the entire combination of phrases, the code now uses multiple "member handlers" for each request, one member handler for each phrase.
-rw-r--r--src/compiler/scala/tools/nsc/Interpreter.scala512
-rw-r--r--src/compiler/scala/tools/nsc/symtab/StdNames.scala1
-rw-r--r--test/files/run/interpreter.check22
-rw-r--r--test/files/run/interpreter.scala8
4 files changed, 269 insertions, 274 deletions
diff --git a/src/compiler/scala/tools/nsc/Interpreter.scala b/src/compiler/scala/tools/nsc/Interpreter.scala
index be954205f2..1833ff1065 100644
--- a/src/compiler/scala/tools/nsc/Interpreter.scala
+++ b/src/compiler/scala/tools/nsc/Interpreter.scala
@@ -10,6 +10,7 @@ import java.io.{File, PrintWriter, StringWriter, Writer}
import java.lang.{Class, ClassLoader}
import java.net.{URL, URLClassLoader}
+import scala.collection.immutable.ListSet
import scala.collection.mutable
import scala.collection.mutable.{ListBuffer, HashSet, ArrayBuffer}
@@ -78,6 +79,8 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
import compiler.CompilationUnit
import compiler.{Symbol,Name,Type}
import compiler.nme
+ import compiler.newTermName
+ import compiler.nme.{INTERPRETER_VAR_PREFIX, INTERPRETER_SYNTHVAR_PREFIX}
import Interpreter.string2code
/** construct an interpreter that reports to Console */
@@ -181,9 +184,27 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
private def newVarName() = {
val num = nextVarNameNo
nextVarNameNo += 1
- compiler.nme.INTERPRETER_VAR_PREFIX + num
+ INTERPRETER_VAR_PREFIX + num
}
+ /** next internal variable number to use */
+ private var nextInternalVarNo = 0
+
+ /** allocate a fresh internal variable name */
+ private def newInternalVarName() = {
+ val num = nextVarNameNo
+ nextVarNameNo += 1
+ INTERPRETER_SYNTHVAR_PREFIX + num
+ }
+
+
+ /** Check if a name looks like it was generated by newVarName */
+ private def isGeneratedVarName(name: String): Boolean =
+ name.startsWith(INTERPRETER_VAR_PREFIX) && {
+ val suffix = name.drop(INTERPRETER_VAR_PREFIX.length)
+ suffix.forall(_.isDigit)
+ }
+
/** generate a string using a routine that wants to write on a stream */
private def stringFrom(writer: PrintWriter => Unit): String = {
@@ -259,34 +280,31 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
* should be taken. Removes requests which cannot contribute
* useful imports for the specified set of wanted names.
*/
- def reqsToUse: List[Request] = {
- /** Loop through the requests in reverse and select
+ def reqsToUse: List[(Request,MemberHandler)] = {
+ /** Loop through a list of MemberHandlers and select
* which ones to keep. 'wanted' is the set of
* names that need to be imported, and
* 'shadowed' is the list of names useless to import
* because a later request will re-import it anyway.
*/
- def select(reqs: List[Request], wanted: Set[Name]): List[Request] = {
+ def select(reqs: List[(Request,MemberHandler)], wanted: Set[Name]):
+ List[(Request,MemberHandler)] = {
reqs match {
case Nil => Nil
- case req::rest =>
- val keepit = req.definesImplicit || (req match {
- case req:ImportReq =>
- req.importsWildcard ||
- req.importedNames.exists(wanted.contains)
- case _ =>
- req.boundNames.exists(wanted.contains)
- })
+ case (req,handler)::rest =>
+ val keepit =
+ (handler.definesImplicit ||
+ handler.importsWildcard ||
+ handler.importedNames.exists(wanted.contains(_)) ||
+ handler.boundNames.exists(wanted.contains(_)))
val newWanted =
if (keepit) {
- req match {
- case req:ImportReq =>
- wanted -- req.importedNames ++ req.usedNames
-
- case _ => wanted -- req.boundNames
- }
+ (wanted
+ ++ handler.usedNames
+ -- handler.boundNames
+ -- handler.importedNames)
} else {
wanted
}
@@ -294,13 +312,18 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
val restToKeep = select(rest, newWanted)
if(keepit)
- req :: restToKeep
+ (req,handler) :: restToKeep
else
restToKeep
}
}
- select(prevRequests.toList.reverse, wanted).reverse
+ val rhpairs = for {
+ req <- prevRequests.toList.reverse
+ handler <- req.handlers
+ } yield (req, handler)
+
+ select(rhpairs, wanted).reverse
}
val code = new StringBuffer
@@ -321,40 +344,37 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
// loop through previous requests, adding imports
// for each one
- for (req <- reqsToUse) {
- req match {
- case req:ImportReq =>
+ for ((req,handler) <- reqsToUse) {
// If the user entered an import, then just use it
// add an import wrapping level if the import might
// conflict with some other import
- if(req.importsWildcard ||
- currentImps.exists(req.importedNames.contains))
+ if(handler.importsWildcard ||
+ currentImps.exists(handler.importedNames.contains))
if(!currentImps.isEmpty)
addWrapper()
- code.append(req.line + ";\n")
+ if (handler.member.isInstanceOf[Import])
+ code.append(handler.member.toString + ";\n")
// give wildcard imports a import wrapper all to their own
- if(req.importsWildcard)
+ if(handler.importsWildcard)
addWrapper()
else
- currentImps ++= req.importedNames
+ currentImps ++= handler.importedNames
- case req =>
// For other requests, import each bound variable.
// import them explicitly instead of with _, so that
// ambiguity errors will not be generated. Also, quote
// the name of the variable, so that we don't need to
// handle quoting keywords separately.
- for (imv <- req.boundNames) {
+ for (imv <- handler.boundNames) {
if (currentImps.contains(imv))
addWrapper()
code.append("import ")
code.append(req.objectName + req.accessPath + ".`" + imv + "`;\n")
currentImps += imv
}
- }
}
addWrapper() // Add one extra wrapper, to prevent warnings
@@ -411,26 +431,20 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
* after being parsed.
*/
private def buildRequest(trees: List[Tree], line: String, lineName: String): Request =
- trees match {
- /* This case for assignments is more specialized than desirable: it only
- handles assignments to an identifier. It would be better to support
- arbitrary paths being assigned, but that is technically difficult
- because of the way objectSourceCode and resultObjectSourceCode are
- implemented in class Request. */
- case List(Assign(Ident(lhs), _)) =>
- new AssignReq(lhs, line, lineName)
- case _ if trees.forall(t => t.isInstanceOf[ValOrDefDef]) =>
- new DefReq(line, lineName)
- case List(_:TermTree) | List(_:Ident) | List(_:Select) =>
- new ExprReq(line, lineName)
- case List(_:ModuleDef) => new ModuleReq(line, lineName)
- case List(_:ClassDef) => new ClassReq(line, lineName)
- case List(t:TypeDef) if compiler.treeInfo.isAliasTypeDef(t) =>
- new TypeAliasReq(line, lineName)
- case List(_:Import) => new ImportReq(line, lineName)
- case _ =>
- reporter.error(null, "That kind of statement combination is not supported by the interpreter.")
- null
+ new Request(line, lineName)
+
+ private def chooseHandler(member: Tree): Option[MemberHandler] =
+ member match {
+ case member: DefDef =>
+ Some(new DefHandler(member))
+ case member: ValDef =>
+ Some(new ValHandler(member))
+ case member@Assign(Ident(_), _) => Some(new AssignHandler(member))
+ case member: ModuleDef => Some(new ModuleHandler(member))
+ case member: ClassDef => Some(new ClassHandler(member))
+ case member: TypeDef => Some(new TypeAliasHandler(member))
+ case member: Import => Some(new ImportHandler(member))
+ case _ => None
}
/** <p>
@@ -458,6 +472,19 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
case Some(trees) => trees
}
+ trees match {
+ case List(_:Assign) => ()
+
+ case List(_:TermTree) | List(_:Ident) | List(_:Select) =>
+ // Treat a single bare expression specially.
+ // This is necessary due to it being hard to modify
+ // code at a textual level, and it being hard to
+ // submit an AST to the compiler.
+ return interpret("val "+newVarName()+" = \n"+line)
+
+ case _ => ()
+ }
+
val lineName = newLineName
// figure out what kind of request
@@ -472,10 +499,6 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
if (printResults || !succeeded) {
// print the result
out.print(clean(interpreterResultString))
-
- // print out types of functions; they are not printed in the
- // request printout
- out.print(clean(req.defTypesSummary))
}
// book-keeping
@@ -556,94 +579,178 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
}
- /** One line of code submitted by the user for interpretation */
- private abstract class Request(val line: String, val lineName: String) {
- val trees = parse(line) match {
- case Some(ts) => ts
- case None => Nil
+ /** Class to handle one member among all the members included
+ * in a single interpreter request.
+ */
+ private sealed abstract class MemberHandler(val member: Tree) {
+ val usedNames: List[Name] = {
+ val ivt = new ImportVarsTraverser(boundNames)
+ ivt.traverseTrees(List(member))
+ ivt.importVars.toList
}
+ val boundNames: List[Name] = Nil
+ def valAndVarNames: List[Name] = Nil
+ def defNames: List[Name] = Nil
+ val importsWildcard = false
+ val importedNames: Seq[Name] = Nil
+ val definesImplicit =
+ member match {
+ case tree:MemberDef =>
+ tree.mods.hasFlag(symtab.Flags.IMPLICIT)
+ case _ => false
+ }
- /** name to use for the object that will compute "line" */
- def objectName = lineName + compiler.nme.INTERPRETER_WRAPPER_SUFFIX
+ def extraCodeToEvaluate(req: Request, code: PrintWriter) { }
+ def resultExtractionCode(req: Request, code: PrintWriter) { }
+ }
- /** name of the object that retrieves the result from the above object */
- def resultObjectName = "RequestResult$" + objectName
+ private class ValHandler(member: ValDef) extends MemberHandler(member) {
+ override val boundNames = List(member.name)
+ override def valAndVarNames = boundNames
- /** whether the trees need a variable name, as opposed to standing
- alone */
- val needsVarName: Boolean = false
+ override def resultExtractionCode(req: Request, code: PrintWriter) {
+ val vname = member.name
+ if (member.mods.isPublic &&
+ !(isGeneratedVarName(vname) &&
+ req.typeOf(compiler.encode(vname)) == "Unit"))
+ {
+ code.print(" + \"" + vname + ": " +
+ string2code(req.typeOf(vname)) +
+ " = \" + " +
+ " (if(" +
+ req.fullPath(vname) +
+ ".asInstanceOf[AnyRef] != null) " +
+ " ((if(" +
+ req.fullPath(vname) +
+ ".toString.contains('\\n')) " +
+ " \"\\n\" else \"\") + " +
+ req.fullPath(vname) + ".toString + \"\\n\") else \"null\\n\") ")
+ }
+ }
+ }
- /** A cache for the chosen variable name, if one has been calculated */
- var varNameCache: Option[String] = None
+ private class DefHandler(defDef: DefDef) extends MemberHandler(defDef) {
+ override val boundNames = List(defDef.name)
+ override def defNames = boundNames
- /** A computed variable name, if one is needed */
- def varName = varNameCache match {
- case None =>
- varNameCache = Some(newVarName)
- varNameCache.get
- case Some(name) =>
- name
+ override def resultExtractionCode(req: Request, code: PrintWriter) {
+ if (defDef.mods.isPublic)
+ code.print("+\""+string2code(defDef.name)+": "+
+ string2code(req.typeOf(defDef.name))+"\\n\"")
}
+ }
- /** list of methods defined */
- val defNames =
- for (DefDef(mods, name, _, _, _, _) <- trees if mods.isPublic)
- yield name
+ private class AssignHandler(member: Assign) extends MemberHandler(member) {
+ val lhs = member. lhs.asInstanceOf[Ident] // an unfortunate limitation
- /** list of val's and var's defined */
- val valAndVarNames = {
- val baseNames =
- for (ValDef(mods, name, _, _) <- trees if mods.isPublic)
- yield name
+ val helperName = newTermName(newInternalVarName())
+ override val valAndVarNames = List(helperName)
- if (needsVarName)
- compiler.encode(varName) :: baseNames // add a var name
- else
- baseNames
+ override def extraCodeToEvaluate(req: Request, code: PrintWriter) {
+ code.println("val "+helperName+" = "+member.lhs+";")
}
- /** list of modules defined */
- val moduleNames = {
- val explicit =
- for (ModuleDef(mods, name, _) <- trees if mods.isPublic)
- yield name
- val caseClasses =
- for {val ClassDef(mods, name, _, _) <- trees
- mods.isPublic
- mods.hasFlag(Flags.CASE)}
- yield name.toTermName
- explicit ::: caseClasses
+ /** Print out lhs instead of the generated varName */
+ override def resultExtractionCode(req: Request, code: PrintWriter) {
+ code.print(" + \"" + lhs + ": " +
+ string2code(req.typeOf(compiler.encode(helperName))) +
+ " = \" + " +
+ string2code(req.fullPath(helperName))
+ + " + \"\\n\"")
}
+ }
+
+ private class ModuleHandler(module: ModuleDef) extends MemberHandler(module) {
+ override val boundNames = List(module.name)
- /** list of classes defined */
- val classNames =
- for (ClassDef(mods, name, _, _) <- trees if mods.isPublic)
- yield name
+ override def resultExtractionCode(req: Request, code: PrintWriter) {
+ code.println(" + \"defined module " +
+ string2code(module.name)
+ + "\\n\"")
+ }
+ }
- /** list of type aliases defined */
- val typeNames =
- for (t @ TypeDef(mods, name, _, _) <- trees
- if mods.isPublic && compiler.treeInfo.isAliasTypeDef(t))
- yield name
+ private class ClassHandler(classdef: ClassDef)
+ extends MemberHandler(classdef)
+ {
+ override val boundNames =
+ List(classdef.name) :::
+ (if (classdef.mods.hasFlag(Flags.CASE))
+ List(classdef.name.toTermName)
+ else
+ Nil)
- /** all (public) names defined by these statements */
- val boundNames =
- defNames ::: valAndVarNames ::: moduleNames ::: classNames ::: typeNames
+ // TODO: MemberDef.keyword does not include "trait";
+ // otherwise it could be used here
+ def keyword: String =
+ if (classdef.mods.isTrait) "trait" else "class"
- /** list of names used by this expression */
- val usedNames: List[Name] = {
- val ivt = new ImportVarsTraverser(boundNames)
- ivt.traverseTrees(trees)
- ivt.importVars.toList
+ override def resultExtractionCode(req: Request, code: PrintWriter) {
+ code.print(
+ " + \"defined " +
+ keyword +
+ " " +
+ string2code(classdef.name) +
+ "\\n\"")
}
+ }
+
+ private class TypeAliasHandler(typeDef: TypeDef)
+ extends MemberHandler(typeDef)
+ {
+ override val boundNames =
+ if (typeDef.mods.isPublic && compiler.treeInfo.isAliasTypeDef(typeDef))
+ List(typeDef.name)
+ else
+ Nil
+
+ override def resultExtractionCode(req: Request, code: PrintWriter) {
+ code.println(" + \"defined type alias " +
+ string2code(typeDef.name) + "\\n\"")
+ }
+ }
+
+ private class ImportHandler(imp: Import) extends MemberHandler(imp) {
+ override def resultExtractionCode(req: Request, code: PrintWriter) {
+ code.println("+ \"" + imp.toString + "\\n\"")
+ }
+
+ /** Whether this import includes a wildcard import */
+ override val importsWildcard =
+ imp.selectors.map(_._1).contains(nme.USCOREkw)
+
+ /** The individual names imported by this statement */
+ override val importedNames: Seq[Name] =
+ for {
+ val (_,sel) <- imp.selectors
+ sel != null
+ sel != nme.USCOREkw
+ val name <- List(sel.toTypeName, sel.toTermName)
+ }
+ yield name
+ }
- /** Whether this request defines an implicit. */
- def definesImplicit = trees.exists {
- case tree:MemberDef =>
- tree.mods.hasFlag(symtab.Flags.IMPLICIT)
- case _ => false
+ /** One line of code submitted by the user for interpretation */
+ private class Request(val line: String, val lineName: String) {
+ val trees = parse(line) match {
+ case Some(ts) => ts
+ case None => Nil
}
+ /** name to use for the object that will compute "line" */
+ def objectName = lineName + compiler.nme.INTERPRETER_WRAPPER_SUFFIX
+
+ /** name of the object that retrieves the result from the above object */
+ def resultObjectName = "RequestResult$" + objectName
+
+ val handlers: List[MemberHandler] = trees.flatMap(chooseHandler(_))
+
+ /** all (public) names defined by these statements */
+ val boundNames = (ListSet() ++ handlers.flatMap(_.boundNames)).toList
+
+ /** list of names used by this expression */
+ val usedNames: List[Name] = handlers.flatMap(_.usedNames)
+
def myImportsCode = importsCode(Set.empty ++ usedNames)
/** Code to append to objectName to access anything that
@@ -671,12 +778,10 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
code.print(importsPreamble)
- // the variable to compute, if any
- if (needsVarName)
- code.println(" val " + varName + " = ")
-
code.println(indentCode(toCompute))
+ handlers.foreach(_.extraCodeToEvaluate(this,code))
+
code.println(importsTrailer)
//end the wrapper object
@@ -694,28 +799,13 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
code.println("object " + resultObjectName)
code.println("{ val result: String = {")
code.println(objectName + accessPath + ";") // evaluate the object, to make sure its constructor is run
- code.print("\"\"") // print an initial empty string, so later code can
+ code.print("(\"\"") // print an initial empty string, so later code can
// uniformly be: + morestuff
- resultExtractionCode(code)
- code.println("}")
+ handlers.foreach(_.resultExtractionCode(this, code))
+ code.println("\n)}")
code.println(";}")
})
- def resultExtractionCode(code: PrintWriter) {
- for (vname <- valAndVarNames) {
- code.print(" + \"" + vname + ": " +
- string2code(typeOf(vname)) +
- " = \" + " +
- " (if(" +
- fullPath(vname) +
- ".asInstanceOf[AnyRef] != null) " +
- " ((if(" +
- fullPath(vname) +
- ".toString.contains('\\n')) " +
- " \"\\n\" else \"\") + " +
- fullPath(vname) + ".toString + \"\\n\") else \"null\\n\") ")
- }
- }
/** Compile the object file. Returns whether the compilation succeeded.
* If all goes well, the "types" map is computed. */
@@ -750,11 +840,14 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
* @return ...
*/
def findTypes(objRun: compiler.Run): Map[Name, String] = {
+ def valAndVarNames = handlers.flatMap(_.valAndVarNames)
+ def defNames = handlers.flatMap(_.defNames)
+
def getTypes(names: List[Name], nameMap: Name=>Name): Map[Name, String] = {
/** the outermost wrapper object */
val outerResObjSym: Symbol =
compiler.definitions.getMember(compiler.definitions.EmptyPackage,
- compiler.newTermName(objectName))
+ newTermName(objectName))
/** the innermost object inside the wrapper, found by
* following accessPath into the outer one. */
@@ -762,7 +855,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
(accessPath.split("\\.")).foldLeft(outerResObjSym)((sym,name) =>
if(name == "") sym else
compiler.atPhase(objRun.typerPhase.next) {
- sym.info.member(compiler.newTermName(name)) })
+ sym.info.member(newTermName(name)) })
names.foldLeft(Map.empty[Name,String])((map, name) => {
val rawType =
@@ -802,139 +895,14 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
(stringFrom(str => orig.printStackTrace(str)), false)
}
}
-
- /** return a summary of the defined methods */
- def defTypesSummary: String =
- stringFrom(summ => {
- for (methname <- defNames)
- summ.println("" + methname + ": " +
- string2code(typeOf(methname)))
- })
- }
-
- /** A sequence of definition's. val's, var's, def's. */
- private class DefReq(line: String, lineName: String)
- extends Request(line, lineName)
-
- /** Assignment of a single variable: lhs = exp */
- private class AssignReq(val lhs: Name, line: String, lineName: String)
- extends Request(line, lineName) {
- override val needsVarName = true
-
- /** Perform the assignment, and then return the new value */
- override def toCompute = "{\n" + line + "\n;\n" + lhs + "\n}"
-
- /** Print out lhs instead of the generated varName */
- override def resultExtractionCode(code: PrintWriter) {
- code.print(" + \"" + lhs + ": " +
- string2code(typeOf(compiler.encode(varName))) +
- " = \" + " +
- string2code(fullPath(varName))
- + " + \"\\n\"")
-// override def resultExtractionCode(code: PrintWriter) {
-// {wrapperObj; lhs}
-// }
- }
}
- /** A single expression */
- private class ExprReq(line: String, lineName: String)
- extends Request(line, lineName) {
- override val needsVarName = true
-
- /** Skip the printout if the expression has type Unit */
- override def resultExtractionCode(code: PrintWriter) {
- if (typeOf(compiler.encode(varName)) != "Unit")
- super.resultExtractionCode(code)
- }
- }
-
- /** A module definition */
- private class ModuleReq(line: String, lineName: String)
- extends Request(line, lineName) {
- def moduleName = trees match {
- case List(ModuleDef(_, name, _)) => name
- }
- override def resultExtractionCode(code: PrintWriter) {
- super.resultExtractionCode(code)
- code.println(" + \"defined module " +
- string2code(moduleName)
- + "\\n\"")
- }
- }
-
- /** A class definition */
- private class ClassReq(line: String, lineName: String)
- extends Request(line, lineName) {
- def newClassName = trees match {
- case List(ClassDef(_, name, _, _)) => name
- }
-
- def classdef = trees.head.asInstanceOf[ClassDef]
-
- // TODO: MemberDef.keyword does not include "trait";
- // otherwise it could be used here
- def keyword: String =
- if (classdef.mods.isTrait) "trait" else "class"
-
- override def resultExtractionCode(code: PrintWriter) {
- super.resultExtractionCode(code)
- code.print(
- " + \"defined " +
- keyword +
- " " +
- string2code(newClassName) +
- "\\n\"")
- }
- }
-
- /** a type alias */
- private class TypeAliasReq(line: String, lineName: String)
- extends Request(line, lineName) {
- def newTypeName = trees match {
- case List(TypeDef(_, name, _, _)) => name
- }
-
- override def resultExtractionCode(code: PrintWriter) {
- super.resultExtractionCode(code)
- code.println(" + \"defined type alias " + newTypeName + "\\n\"")
- }
- }
-
- /** an import */
- private class ImportReq(line: String, lineName: String)
- extends Request(line, lineName) {
- override val boundNames = Nil
- override def resultExtractionCode(code: PrintWriter) {
- code.println("+ \"" + trees.head.toString + "\\n\"")
- }
-
- /** Whether this import includes a wildcard import */
- def importsWildcard =
- trees.exists {
- case Import(_, selectors) =>
- selectors.map(_._1).contains(nme.USCOREkw)
- case _ => false
- }
-
- /** The individual names imported by this statement */
- def importedNames: Seq[Name] =
- for {
- val Import(_, selectors) <- trees
- val (_,sel) <- selectors
- sel != null
- sel != nme.USCOREkw
- val name <- List(sel.toTypeName, sel.toTermName)
- }
- yield name
- }
-}
-
class NewLinePrintWriter(out: Writer, autoFlush: Boolean)
extends PrintWriter(out, autoFlush) {
def this(out: Writer) = this(out, false)
override def println() { print("\n"); flush() }
}
+}
/** Utility methods for the Interpreter. */
object Interpreter {
diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
index 70597eb5db..9403280384 100644
--- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala
+++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
@@ -78,6 +78,7 @@ trait StdNames {
val INTERPRETER_LINE_PREFIX = "line"
val INTERPRETER_VAR_PREFIX = "res"
val INTERPRETER_IMPORT_WRAPPER = "$iw"
+ val INTERPRETER_SYNTHVAR_PREFIX = "synthvar$"
def LOCAL(clazz: Symbol) = newTermName(LOCALDUMMY_PREFIX_STRING + clazz.name+">")
def TUPLE_FIELD(index: Int) = newTermName(TUPLE_FIELD_PREFIX_STRING + index)
diff --git a/test/files/run/interpreter.check b/test/files/run/interpreter.check
index 7623eb2fbc..1bb6c28486 100644
--- a/test/files/run/interpreter.check
+++ b/test/files/run/interpreter.check
@@ -27,6 +27,11 @@ scala> <console>:5: error: type mismatch;
scala> defined trait PointlessTrait
+scala> x: Int = 2
+y: Int = 3
+
+scala> hello
+
scala>
scala>
scala> defined class Foo
@@ -151,7 +156,7 @@ scala> <console>:1: error: identifier expected but integer literal found.
scala>
scala>
scala>
-scala> | | | | res2: scala.xml.Elem =
+scala> | | | | res3: scala.xml.Elem =
<a>
<b d="dd" c="c"></b></a>
@@ -161,7 +166,7 @@ scala> | | | |
scala>
scala>
scala>
-scala> | | | res3: java.lang.String =
+scala> | | | res4: java.lang.String =
hello
there
@@ -177,3 +182,16 @@ scala> x: Int = 1
scala>
scala>
+scala> defined class Exp
+defined class Fact
+defined class Term
+
+scala> | | <console>:15: warning: match is not exhaustive!
+missing combination Term
+
+ def f(e: Exp) = e match { // non-exhaustive warning here
+ ^
+f: (Exp)Int
+
+scala>
+scala>
diff --git a/test/files/run/interpreter.scala b/test/files/run/interpreter.scala
index 5ad9953857..b239b253cf 100644
--- a/test/files/run/interpreter.scala
+++ b/test/files/run/interpreter.scala
@@ -19,6 +19,8 @@ type anotherint = Int
val four: anotherint = 4
val bogus: anotherint = "hello"
trait PointlessTrait
+val (x,y) = (2,3)
+println("hello")
// implicit conversions
case class Foo(n: int)
@@ -111,6 +113,12 @@ there
def `match` = 1
val x = `match`
+// multiple classes defined on one line
+sealed class Exp; class Fact extends Exp; class Term extends Exp
+def f(e: Exp) = e match {{ // non-exhaustive warning here
+ case _:Fact => 3
+}}
+
</code>.text
/** A writer that skips the first line of text. The first