diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala | 4 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala | 9 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/interpreter/ILoop.scala | 104 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/interpreter/IMain.scala | 62 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/interpreter/ReplConfig.scala | 18 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala | 19 | ||||
-rw-r--r-- | src/compiler/scala/tools/util/Javap.scala | 22 | ||||
-rw-r--r-- | test/files/jvm/interpreter.check | 2 | ||||
-rw-r--r-- | test/files/run/repl-reset.check | 57 | ||||
-rw-r--r-- | test/files/run/repl-reset.scala | 18 |
11 files changed, 243 insertions, 74 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala index 5b6e37e4fe..70aa8ff54e 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala @@ -10,7 +10,7 @@ import ch.epfl.lamp.fjbg._ import java.io.{ DataOutputStream, OutputStream, File => JFile } import scala.tools.nsc.io._ import scala.tools.nsc.util.ScalaClassLoader -import scala.tools.util.Javap +import scala.tools.util.JavapClass import java.util.jar.{ JarEntry, JarOutputStream, Attributes } import Attributes.Name @@ -67,7 +67,7 @@ trait BytecodeWriters { def emitJavap(bytes: Array[Byte], javapFile: io.File) { val pw = javapFile.printWriter() - val javap = new Javap(ScalaClassLoader.appLoader, pw) { + val javap = new JavapClass(ScalaClassLoader.appLoader, pw) { override def findBytes(path: String): Array[Byte] = bytes } diff --git a/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala b/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala index c79728d0b1..3bc4e1cbe1 100644 --- a/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala +++ b/src/compiler/scala/tools/nsc/interpreter/AbstractFileClassLoader.scala @@ -20,11 +20,6 @@ class AbstractFileClassLoader(root: AbstractFile, parent: ClassLoader) with ScalaClassLoader { // private val defined = mutable.Map[String, Class[_]]() - private def cllog(msg: => String) { - if (trace) - println("[" + classLoaderUniqId + "] " + msg) - } - override protected def trace = sys.props contains "scala.debug.classloader" @@ -57,12 +52,12 @@ class AbstractFileClassLoader(root: AbstractFile, parent: ClassLoader) case file => file.toByteArray } override def loadClass(name: String, resolve: Boolean) = { - cllog("load " + name + ".") + classLoaderLog("load " + name + ".") super.loadClass(name, resolve) } override def findClass(name: String): JClass = { val bytes = classBytes(name) - cllog("find %s: %s".format(name, + classLoaderLog("find %s: %s".format(name, if (bytes.isEmpty) "failed." else bytes.size + " bytes." )) diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala index cc06987dc4..a355e19ff9 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala @@ -19,6 +19,8 @@ import util.{ ClassPath, Exceptional, stringFromWriter, stringFromStream } import interpreter._ import io.{ File, Sources } import scala.reflect.NameTransformer._ +import util.ScalaClassLoader._ +import scala.tools.util._ /** The Scala interactive shell. It provides a read-eval-print loop * around the Interpreter class. @@ -82,13 +84,23 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) /** Record a command for replay should the user request a :replay */ def addReplay(cmd: String) = replayCommandStack ::= cmd + def savingReplayStack[T](body: => T): T = { + val saved = replayCommandStack + try body + finally replayCommandStack = saved + } + def savingReader[T](body: => T): T = { + val saved = in + try body + finally in = saved + } + /** Close the interpreter and set the var to null. */ def closeInterpreter() { if (intp ne null) { - intp.close + intp.close() intp = null removeSigIntHandler() - Thread.currentThread.setContextClassLoader(originalClassLoader) } } @@ -228,6 +240,8 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) nullary("power", "enable power user mode", powerCmd), nullary("quit", "exit the interpreter", () => Result(false, None)), nullary("replay", "reset execution and replay all previous commands", replay), + nullary("reset", "reset the repl to its initial state, forgetting all session entries", resetCommand), + // nullary("reset", "reset the interpreter, forgetting session values but retaining session types", replay), shCommand, nullary("silent", "disable/enable automatic printing of results", verbosity), cmd("type", "<expr>", "display the type of an expression without evaluating it", typeCommand), @@ -359,7 +373,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } } - protected def newJavap() = new Javap(intp.classLoader, new IMain.ReplStrippingWriter(intp)) { + protected def newJavap() = new JavapClass(intp.classLoader, new IMain.ReplStrippingWriter(intp)) { override def tryClass(path: String): Array[Byte] = { val hd :: rest = path split '.' toList; // If there are dots in the name, the first segment is the @@ -387,9 +401,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } } } - private lazy val javap = - try newJavap() - catch { case _: Exception => null } + private lazy val javap = substituteAndLog[Javap]("javap", NoJavap)(newJavap()) // Still todo: modules. private def typeCommand(line: String): Result = { @@ -505,7 +517,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) |[y/n] """.trim.stripMargin - private val crashRecovery: PartialFunction[Throwable, Unit] = { + private val crashRecovery: PartialFunction[Throwable, Boolean] = { case ex: Throwable => if (settings.YrichExes.value) { val sources = implicitly[Sources] @@ -529,6 +541,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) if (fn()) replay() else echo("\nAbandoning crashed session.") } + true } /** The main read-eval-print loop for the repl. It calls @@ -553,39 +566,56 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) case _ => true } } - - while (true) { - try if (!processLine(readOneLine())) return - catch crashRecovery + def innerLoop() { + if ( try processLine(readOneLine()) catch crashRecovery ) + innerLoop() } + innerLoop() } /** interpret all lines from a specified file */ def interpretAllFrom(file: File) { - val oldIn = in - val oldReplay = replayCommandStack - - try file applyReader { reader => - in = SimpleReader(reader, out, false) - echo("Loading " + file + "...") - loop() - } - finally { - in = oldIn - replayCommandStack = oldReplay + savingReader { + savingReplayStack { + file applyReader { reader => + in = SimpleReader(reader, out, false) + echo("Loading " + file + "...") + loop() + } + } } } - /** create a new interpreter and replay all commands so far */ + /** create a new interpreter and replay the given commands */ def replay() { - closeInterpreter() - createInterpreter() - for (cmd <- replayCommands) { + reset() + if (replayCommandStack.isEmpty) + echo("Nothing to replay.") + else for (cmd <- replayCommands) { echo("Replaying: " + cmd) // flush because maybe cmd will have its own output command(cmd) echo("") } } + def resetCommand() { + echo("Resetting interpreter state.") + if (replayCommandStack.nonEmpty) { + echo("Forgetting this session history:\n") + replayCommands foreach echo + echo("") + replayCommandStack = Nil + } + if (intp.namedDefinedTerms.nonEmpty) + echo("Forgetting all expression results and named terms: " + intp.namedDefinedTerms.mkString(", ")) + if (intp.definedTypes.nonEmpty) + echo("Forgetting defined types: " + intp.definedTypes.mkString(", ")) + + reset() + } + def reset() { + intp.reset() + unleashAndSetPhase() + } /** fork a shell and run a command */ lazy val shCommand = new LoopCommand("sh", "run a shell command (result is implicitly => List[String])") { @@ -632,10 +662,20 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } def enablePowerMode(isDuringInit: Boolean) = { replProps.power setValue true - power.unleash() - intp.beSilentDuring(phaseCommand("typer")) - if (isDuringInit) asyncMessage(power.banner) - else echo(power.banner) + unleashAndSetPhase() + asyncEcho(isDuringInit, power.banner) + } + private def unleashAndSetPhase() { + if (isReplPower) { + power.unleash() + // Set the phase to "typer" + intp beSilentDuring phaseCommand("typer") + } + } + + def asyncEcho(async: Boolean, msg: => String) { + if (async) asyncMessage(msg) + else echo(msg) } def verbosity() = { @@ -792,7 +832,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) SimpleReader() } } - def process(settings: Settings): Boolean = { + def process(settings: Settings): Boolean = savingContextLoader { this.settings = settings createInterpreter() @@ -925,7 +965,7 @@ object ILoop { if (assertion) break[T](args.toList) // start a repl, binding supplied args - def break[T: Manifest](args: List[NamedParam]): Unit = { + def break[T: Manifest](args: List[NamedParam]): Unit = savingContextLoader { val msg = if (args.isEmpty) "" else " Binding " + args.size + " value%s.".format( if (args.size == 1) "" else "s" ) diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala b/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala index 6ebe3f7362..2f02748e8f 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala @@ -61,7 +61,7 @@ trait ILoopInit { } } protected def removeSigIntHandler() { - SignalManager("INT") = null + squashAndLog("removeSigIntHandler")(SignalManager("INT") = null) } private val initLock = new java.util.concurrent.locks.ReentrantLock() diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala index ff6100e9e8..a7fb15124a 100644 --- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala +++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala @@ -226,14 +226,6 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends def quietRun[T](code: String) = beQuietDuring(interpret(code)) - private def logAndDiscard[T](label: String, alt: => T): PartialFunction[Throwable, T] = { - case t => - repldbg(label + ": " + unwrap(t)) - repltrace(util.stackTraceString(unwrap(t))) - - alt - } - /** whether to bind the lastException variable */ private var bindExceptions = true /** takes AnyRef because it may be binding a Throwable or an Exceptional */ @@ -242,7 +234,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends bindExceptions = false try beQuietDuring(body) - catch logAndDiscard("bindLastException", alt) + catch logAndDiscard("withLastExceptionLock", alt) finally bindExceptions = true } @@ -310,6 +302,9 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends else new URLClassLoader(compilerClasspath, parentClassLoader) new AbstractFileClassLoader(virtualDirectory, parent) { + private[IMain] var traceClassLoading = isReplTrace + override protected def trace = traceClassLoading + /** Overridden here to try translating a simple name to the generated * class name if the original attempt fails. This method is used by * getResourceAsStream as well as findClass. @@ -638,6 +633,14 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends interpret(line) } } + def directBind(name: String, boundType: String, value: Any): IR.Result = { + val result = bind(name, boundType, value) + if (result == IR.Success) + directlyBoundNames += name + result + } + def directBind(p: NamedParam): IR.Result = directBind(p.name, p.tpe, p.value) + def directBind[T: Manifest](name: String, value: T): IR.Result = directBind((name, value)) def rebind(p: NamedParam): IR.Result = { val name = p.name @@ -661,10 +664,13 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends /** Reset this interpreter, forgetting all user-specified requests. */ def reset() { - virtualDirectory.clear() + clearExecutionWrapper() resetClassLoader() resetAllCreators() prevRequests.clear() + referencedNameMap.clear() + definedNameMap.clear() + virtualDirectory.clear() } /** This instance is no longer needed, so release any resources @@ -711,14 +717,14 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends withLastExceptionLock[String]({ if (opt.richExes) { val ex = new LineExceptional(unwrapped) - bind[Exceptional]("lastException", ex) + directBind[Exceptional]("lastException", ex) ex.contextHead + "\n(access lastException for the full trace)" } else { - bind[Throwable]("lastException", unwrapped) + directBind[Throwable]("lastException", unwrapped) util.stackTraceString(unwrapped) } - }, "" + unwrapped) + }, util.stackTraceString(unwrapped)) } // TODO: split it out into a package object and a regular @@ -732,8 +738,14 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends def evalPath = pathTo(evalName) def printPath = pathTo(printName) - def call(name: String, args: Any*): AnyRef = - evalMethod(name).invoke(evalClass, args.map(_.asInstanceOf[AnyRef]): _*) + def call(name: String, args: Any*): AnyRef = { + val m = evalMethod(name) + repldbg("Invoking: " + m) + if (args.nonEmpty) + repldbg(" with args: " + args.mkString(", ")) + + m.invoke(evalClass, args.map(_.asInstanceOf[AnyRef]): _*) + } def callEither(name: String, args: Any*): Either[Throwable, AnyRef] = try Right(call(name, args: _*)) @@ -1093,6 +1105,9 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends def definedTypes = onlyTypes(allDefinedNames) def definedSymbols = prevRequests.toSet flatMap ((x: Request) => x.definedSymbols.values) + // Terms with user-given names (i.e. not res0 and not synthetic) + def namedDefinedTerms = definedTerms filterNot (x => isUserVarName("" + x) || directlyBoundNames(x)) + private def findName(name: Name) = definedSymbols find (_.name == name) private def missingOpt(op: => Symbol): Option[Symbol] = @@ -1127,14 +1142,15 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends } /** the previous requests this interpreter has processed */ - private lazy val prevRequests = mutable.ListBuffer[Request]() - private lazy val referencedNameMap = mutable.Map[Name, Request]() - private lazy val definedNameMap = mutable.Map[Name, Request]() - protected def prevRequestList = prevRequests.toList - private def allHandlers = prevRequestList flatMap (_.handlers) - def allSeenTypes = prevRequestList flatMap (_.typeOf.values.toList) distinct - def allImplicits = allHandlers filter (_.definesImplicit) flatMap (_.definedNames) - def importHandlers = allHandlers collect { case x: ImportHandler => x } + private lazy val prevRequests = mutable.ListBuffer[Request]() + private lazy val referencedNameMap = mutable.Map[Name, Request]() + private lazy val definedNameMap = mutable.Map[Name, Request]() + private lazy val directlyBoundNames = mutable.Set[Name]() + protected def prevRequestList = prevRequests.toList + private def allHandlers = prevRequestList flatMap (_.handlers) + def allSeenTypes = prevRequestList flatMap (_.typeOf.values.toList) distinct + def allImplicits = allHandlers filter (_.definesImplicit) flatMap (_.definedNames) + def importHandlers = allHandlers collect { case x: ImportHandler => x } def visibleTermNames: List[Name] = definedTerms ++ importedTerms distinct diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplConfig.scala b/src/compiler/scala/tools/nsc/interpreter/ReplConfig.scala index c4a77e9630..8c589eba60 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ReplConfig.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ReplConfig.scala @@ -6,6 +6,9 @@ package scala.tools.nsc package interpreter +import util.Exceptional.unwrap +import util.stackTraceString + trait ReplConfig { lazy val replProps = new ReplProps @@ -28,6 +31,21 @@ trait ReplConfig { private[nsc] def repltrace(msg: => String) = if (isReplTrace) echo(msg) private[nsc] def replinfo(msg: => String) = if (isReplInfo) echo(msg) + private[nsc] def logAndDiscard[T](label: String, alt: => T): PartialFunction[Throwable, T] = { + case t => + repldbg(label + ": " + unwrap(t)) + repltrace(stackTraceString(unwrap(t))) + alt + } + private[nsc] def substituteAndLog[T](alt: => T)(body: => T): T = + substituteAndLog("" + alt, alt)(body) + private[nsc] def substituteAndLog[T](label: String, alt: => T)(body: => T): T = { + try body + catch logAndDiscard(label, alt) + } + private[nsc] def squashAndLog(label: String)(body: => Unit): Unit = + substituteAndLog(label, ())(body) + def isReplTrace: Boolean = replProps.trace def isReplDebug: Boolean = replProps.debug || isReplTrace def isReplInfo: Boolean = replProps.info || isReplDebug diff --git a/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala b/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala index 74a56fbc2c..952b1e4dd2 100644 --- a/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala +++ b/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala @@ -26,7 +26,11 @@ trait HasClassPath { trait ScalaClassLoader extends JClassLoader { /** Override to see classloader activity traced */ protected def trace: Boolean = false - val classLoaderUniqId = "Cl#" + System.identityHashCode(this) + protected lazy val classLoaderUniqueId = "Cl#" + System.identityHashCode(this) + protected def classLoaderLog(msg: => String) { + if (trace) + Console.err.println("[" + classLoaderUniqueId + "] " + msg) + } /** Executing an action with this classloader as context classloader */ def asContext[T](action: => T): T = { @@ -51,13 +55,13 @@ trait ScalaClassLoader extends JClassLoader { override def findClass(name: String) = { val result = super.findClass(name) - // if (trace) println("findClass(%s) = %s".format(name, result)) + classLoaderLog("findClass(%s) = %s".format(name, result)) result } override def loadClass(name: String, resolve: Boolean) = { val result = super.loadClass(name, resolve) - // if (trace) println("loadClass(%s, %s) = %s".format(name, resolve, result)) + classLoaderLog("loadClass(%s, %s) = %s".format(name, resolve, result)) result } @@ -94,7 +98,7 @@ trait ScalaClassLoader extends JClassLoader { case null => Nil case p => p.loaderChain }) - override def toString = classLoaderUniqId + override def toString = classLoaderUniqueId } /** Methods for obtaining various classloaders. @@ -146,6 +150,11 @@ object ScalaClassLoader { } def setContext(cl: JClassLoader) = Thread.currentThread.setContextClassLoader(cl) + def savingContextLoader[T](body: => T): T = { + val saved = contextLoader + try body + finally setContext(saved) + } class URLClassLoader(urls: Seq[URL], parent: JClassLoader) extends JURLClassLoader(urls.toArray, parent) @@ -162,7 +171,7 @@ object ScalaClassLoader { classloaderURLs :+= url super.addURL(url) } - def toLongString = urls.mkString("URLClassLoader(id=" + classLoaderUniqId + "\n ", "\n ", "\n)\n") + def toLongString = urls.mkString("URLClassLoader(id=" + classLoaderUniqueId + "\n ", "\n ", "\n)\n") } def fromURLs(urls: Seq[URL], parent: ClassLoader = null): URLClassLoader = diff --git a/src/compiler/scala/tools/util/Javap.scala b/src/compiler/scala/tools/util/Javap.scala index 94de5588dd..0c359a2619 100644 --- a/src/compiler/scala/tools/util/Javap.scala +++ b/src/compiler/scala/tools/util/Javap.scala @@ -13,10 +13,26 @@ import java.io.{ InputStream, PrintWriter, ByteArrayInputStream, FileNotFoundExc import scala.tools.nsc.io.{ File, NullPrintStream } import Javap._ -class Javap( +trait Javap { + def loader: ScalaClassLoader + def printWriter: PrintWriter + def apply(args: Seq[String]): List[JpResult] + def tryFile(path: String): Option[Array[Byte]] + def tryClass(path: String): Array[Byte] +} + +object NoJavap extends Javap { + def loader: ScalaClassLoader = getClass.getClassLoader + def printWriter: PrintWriter = new PrintWriter(System.err, true) + def apply(args: Seq[String]): List[JpResult] = Nil + def tryFile(path: String): Option[Array[Byte]] = None + def tryClass(path: String): Array[Byte] = Array() +} + +class JavapClass( val loader: ScalaClassLoader = ScalaClassLoader.appLoader, val printWriter: PrintWriter = new PrintWriter(System.out, true) -) { +) extends Javap { lazy val parser = new JpOptions @@ -87,7 +103,7 @@ object Javap { type FakePrinter = AnyRef def apply(path: String): Unit = apply(Seq(path)) - def apply(args: Seq[String]): Unit = new Javap() apply args foreach (_.show()) + def apply(args: Seq[String]): Unit = new JavapClass() apply args foreach (_.show()) sealed trait JpResult { type ResultType diff --git a/test/files/jvm/interpreter.check b/test/files/jvm/interpreter.check index 607e2bcaff..196a769a17 100644 --- a/test/files/jvm/interpreter.check +++ b/test/files/jvm/interpreter.check @@ -369,7 +369,7 @@ scala> scala> plusOne: (x: Int)Int res0: Int = 6 -res1: String = after reset +res0: String = after reset <console>:8: error: not found: value plusOne plusOne(5) // should be undefined now ^ diff --git a/test/files/run/repl-reset.check b/test/files/run/repl-reset.check new file mode 100644 index 0000000000..652948c63b --- /dev/null +++ b/test/files/run/repl-reset.check @@ -0,0 +1,57 @@ +Type in expressions to have them evaluated. +Type :help for more information. + +scala> + +scala> val x1 = 1 +x1: Int = 1 + +scala> val x2 = 2 +x2: Int = 2 + +scala> val x3 = 3 +x3: Int = 3 + +scala> case class BippyBungus() +defined class BippyBungus + +scala> x1 + x2 + x3 +res0: Int = 6 + +scala> :reset +Resetting interpreter state. +Forgetting this session history: + +val x1 = 1 +val x2 = 2 +val x3 = 3 +case class BippyBungus() +x1 + x2 + x3 + +Forgetting all expression results and named terms: BippyBungus, x1, x2, x3 +Forgetting defined types: BippyBungus + +scala> x1 + x2 + x3 +<console>:8: error: not found: value x1 + x1 + x2 + x3 + ^ + +scala> val x1 = 4 +x1: Int = 4 + +scala> new BippyBungus +<console>:8: error: not found: type BippyBungus + new BippyBungus + ^ + +scala> class BippyBungus() { def f = 5 } +defined class BippyBungus + +scala> { new BippyBungus ; x1 } +res2: Int = 4 + +scala> :javap BippyBungus +Compiled from "<console>"public class BippyBungus extends java.lang.Object implements scala.ScalaObject{ public int f(); public BippyBungus();} +scala> + +scala> diff --git a/test/files/run/repl-reset.scala b/test/files/run/repl-reset.scala new file mode 100644 index 0000000000..95cc48b942 --- /dev/null +++ b/test/files/run/repl-reset.scala @@ -0,0 +1,18 @@ +import scala.tools.partest.ReplTest + +object Test extends ReplTest { + def code = """ + |val x1 = 1 + |val x2 = 2 + |val x3 = 3 + |case class BippyBungus() + |x1 + x2 + x3 + |:reset + |x1 + x2 + x3 + |val x1 = 4 + |new BippyBungus + |class BippyBungus() { def f = 5 } + |{ new BippyBungus ; x1 } + |:javap BippyBungus + """.stripMargin +} |