Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

REPL handles assignment ops like Assign #10728

Open
wants to merge 2 commits into
base: 2.13.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 13 additions & 13 deletions src/repl/scala/tools/nsc/interpreter/IMain.scala
Expand Up @@ -19,9 +19,9 @@ import java.net.URL
import scala.collection.mutable, mutable.ListBuffer
import scala.language.implicitConversions
import scala.reflect.{ClassTag, classTag}
import scala.reflect.internal.{FatalError, Flags, MissingRequirementError, NoPhase, Precedence}
import scala.reflect.internal.util.ScalaClassLoader.URLClassLoader
import scala.reflect.internal.util.{AbstractFileClassLoader, BatchSourceFile, ListOfNil, Position, ReplBatchSourceFile, SourceFile}
import scala.reflect.internal.{FatalError, Flags, MissingRequirementError, NoPhase}
import scala.reflect.runtime.{universe => ru}
import scala.tools.nsc.{Global, Settings}
import scala.tools.nsc.interpreter.Results.{Error, Incomplete, Result, Success}
Expand Down Expand Up @@ -621,16 +621,14 @@ class IMain(val settings: Settings, parentClassLoaderOverride: Option[ClassLoade
override lazy val power = new Power(this, new StdReplVals(this))(tagOfStdReplVals, classTag[StdReplVals])

/** Here is where we:
*
* 1) Read some source code, and put it in the "read" object.
* 2) Evaluate the read object, and put the result in the "eval" object.
* 3) Create a String for human consumption, and put it in the "print" object.
*
* Read! Eval! Print! Some of that not yet centralized here.
*/
class ReadEvalPrint(val lineId: Int) {
def this() = this(freshLineId())

*
* 1) Read some source code, and put it in the "read" object.
* 2) Evaluate the read object, and put the result in the "eval" object.
* 3) Create a String for human consumption, and put it in the "print" object.
*
* Read! Eval! Print! Some of that not yet centralized here.
*/
class ReadEvalPrint(val lineId: Int = freshLineId()) {
val packageName = sessionNames.packageName(lineId)
val readName = sessionNames.read
val evalName = sessionNames.eval
Expand Down Expand Up @@ -813,6 +811,7 @@ class IMain(val settings: Settings, parentClassLoaderOverride: Option[ClassLoade
case init :+ tree =>
def loop(scrut: Tree): Tree = scrut match {
case _: Assign => tree
case Apply(Select(_, op), _) if Precedence(op.decoded).level == 0 => tree
case _: RefTree | _: TermTree => storeInVal(tree)
case Annotated(_, arg) => loop(arg)
case _ => tree
Expand All @@ -823,7 +822,7 @@ class IMain(val settings: Settings, parentClassLoaderOverride: Option[ClassLoade
}

/** handlers for each tree in this request */
val handlers: List[MemberHandler] = trees map (memberHandlers chooseHandler _)
val handlers: List[MemberHandler] = trees.map(memberHandlers.chooseHandler(_))
val definesValueClass = handlers.exists(_.definesValueClass)

val isClassBased = IMain.this.isClassBased && !definesValueClass
Expand Down Expand Up @@ -967,7 +966,8 @@ class IMain(val settings: Settings, parentClassLoaderOverride: Option[ClassLoade


/** Compile the object file. Returns whether the compilation succeeded.
* If all goes well, the "types" map is computed. */
* If all goes well, the "types" map is computed.
*/
def compile: Boolean = {

// compile the object containing the user's code
Expand Down
16 changes: 13 additions & 3 deletions src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala
Expand Up @@ -15,6 +15,7 @@ package scala.tools.nsc.interpreter
import scala.language.implicitConversions

import scala.collection.mutable
import scala.reflect.internal.Precedence

trait MemberHandlers {
val intp: IMain
Expand Down Expand Up @@ -77,7 +78,9 @@ trait MemberHandlers {
case member: ModuleDef => new ModuleHandler(member)
case member: ClassDef => new ClassHandler(member)
case member: TypeDef => new TypeAliasHandler(member)
case member: Assign => new AssignHandler(member)
case member: Assign => AssignHandler(member)
case member @ Apply(Select(_, op), _)
if Precedence(op.decoded).level == 0 => AssignHandler(member)
case member: Import => new ImportHandler(member.duplicate) // duplicate because the same tree will be type checked (which loses info)
case DocDef(_, documented) => chooseHandler(documented)
case member => new GenericHandler(member)
Expand Down Expand Up @@ -175,9 +178,16 @@ trait MemberHandlers {
def notification(req: Request) = s"def ${req.defTypeOf(name)}"
}

class AssignHandler(member: Assign) extends MemberHandler(member) {
class AssignHandler private (member: Tree, lhs: Tree) extends MemberHandler(member) {
override def resultExtractionCode(req: Request) =
codegenln(s"// mutated ${member.lhs}")
codegenln(s"// mutated $lhs")
}
object AssignHandler {
def apply(member: Assign) = new AssignHandler(member, member.lhs)
def apply(member: Apply) = member match {
case Apply(Select(qual, op), _) if Precedence(op.decoded).level == 0 => new AssignHandler(member, qual)
case _ => new GenericHandler(member)
}
}

class ModuleHandler(module: ModuleDef) extends MemberDefHandler(module) {
Expand Down
14 changes: 7 additions & 7 deletions test/files/run/repl-assign.check
@@ -1,14 +1,14 @@

scala> var x = 10
var x: Int = 10
scala> var x = 42
var x: Int = 42

scala> var y = 11
var y: Int = 11
scala> x = 17
// mutated x

scala> x = 12
scala> x += 10
// mutated x

scala> y = 13
// mutated y
scala> x
val res0: Int = 27

scala> :quit
12 changes: 3 additions & 9 deletions test/files/run/repl-assign.scala
@@ -1,10 +1,4 @@
import scala.tools.partest.ReplTest

object Test extends ReplTest {
def code = """
var x = 10
var y = 11
x = 12
y = 13
"""
}
import scala.tools.partest.SessionTest

object Test extends SessionTest
30 changes: 1 addition & 29 deletions test/files/run/t8935-object.scala
@@ -1,31 +1,3 @@
import scala.tools.partest.SessionTest

import scala.tools.nsc.Settings

object Test extends SessionTest {
/* future
override def transformSettings(s: Settings): Settings = {
//s.YreplWrap.value = "object"
s
}
*/
override def session =
"""
scala> 41+1
res0: Int = 42

scala> $intp.valueOfTerm($intp.mostRecentVar)
res1: Option[Any] = Some(42)

scala> val i = 17 ; 64
i: Int = 17
res2: Int = 64

scala> $intp.valueOfTerm($intp.mostRecentVar)
res3: Option[Any] = Some(64)

scala> $intp.valueOfTerm("i")
res4: Option[Any] = Some(17)

scala> :quit"""
}
object Test extends SessionTest