Scala Programming Language
  1. Scala Programming Language
  2. SI-4899

valueOfTerm method of scala.tools.nsc.interpreter.IMain broken in 2.9.1 RC2

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: Scala 2.9.1
    • Fix Version/s: Scala 2.9.0-1
    • Component/s: Repl / Interpreter
    • Labels:
      None
    • Environment:

      Scala 2.9.1.RC2 running on Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_26 on openSUSE 11.4

      Description

      The valueOfTerm method of scala.tools.nsc.interpreter.IMain seems to be broken in 2.9.1 RC2, whereas it works as expected in 2.9.0.1. See transcripts from both versions below.

                          1. 2.9.1.RC2 ##############

      Welcome to Scala version 2.9.1.RC2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_26).
      Type in expressions to have them evaluated.
      Type :help for more information.

      scala> val n = new scala.tools.nsc.interpreter.IMain()
      n: scala.tools.nsc.interpreter.IMain = scala.tools.nsc.interpreter.IMain@f4f7a86

      scala> n.interpret("val a = 2+3")
      a: Int = 5
      res0: scala.tools.nsc.interpreter.package.IR.Result = Success

      scala> n.valueOfTerm("a") == Some(5) // Should be true!
      res1: Boolean = false

                          1. 2.9.0.1 ##############

      Welcome to Scala version 2.9.0.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_26).
      Type in expressions to have them evaluated.
      Type :help for more information.

      scala> val n = new scala.tools.nsc.interpreter.IMain()
      n: scala.tools.nsc.interpreter.IMain = scala.tools.nsc.interpreter.IMain@34ae19a

      scala> n.interpret("val a = 2+3")
      a: Int = 5
      res0: scala.tools.nsc.interpreter.Results.Result = Success

      scala> n.valueOfTerm("a") == Some(5) // Is true, as it should be
      res1: Boolean = true

        Activity

        Hide
        Eugene Yokota added a comment -

        I'm still seeing this with 2.9.1.final. Why is the Fix Version/s set to Scala 2.9.0-1?

        Show
        Eugene Yokota added a comment - I'm still seeing this with 2.9.1.final. Why is the Fix Version/s set to Scala 2.9.0-1?
        Hide
        Sebastien Riou added a comment -

        Similar thing here, with 2.9.1.final:
        Welcome to Scala version 2.9.1.final (Java HotSpot(TM) Server VM, Java 1.6.0_24).
        Type in expressions to have them evaluated.
        Type :help for more information.

        scala> val n = new scala.tools.nsc.interpreter.IMain()
        n: scala.tools.nsc.interpreter.IMain = scala.tools.nsc.interpreter.IMain@5c18ff

        scala> n.interpret("val r=1")
        r: Int = 1
        res0: scala.tools.nsc.interpreter.package.IR.Result = Success

        scala> n.valueOfTerm("r")
        res1: Option[AnyRef] = None

        How to get the value of r then ???

        Show
        Sebastien Riou added a comment - Similar thing here, with 2.9.1.final: Welcome to Scala version 2.9.1.final (Java HotSpot(TM) Server VM, Java 1.6.0_24). Type in expressions to have them evaluated. Type :help for more information. scala> val n = new scala.tools.nsc.interpreter.IMain() n: scala.tools.nsc.interpreter.IMain = scala.tools.nsc.interpreter.IMain@5c18ff scala> n.interpret("val r=1") r: Int = 1 res0: scala.tools.nsc.interpreter.package.IR.Result = Success scala> n.valueOfTerm("r") res1: Option [AnyRef] = None How to get the value of r then ???
        Hide
        Zach Cox added a comment -

        I see this too with 2.9.1.final:

        Welcome to Scala version 2.9.1.final (OpenJDK 64-Bit Server VM, Java 1.6.0_20).
        Type in expressions to have them evaluated.
        Type :help for more information.
        
        scala> val n = new scala.tools.nsc.interpreter.IMain()
        n: scala.tools.nsc.interpreter.IMain = scala.tools.nsc.interpreter.IMain@3f6a5d72
        
        scala>  n.interpret("val r=1")
        r: Int = 1
        res0: scala.tools.nsc.interpreter.package.IR.Result = Success
        
        scala> n.valueOfTerm("r")
        res1: Option[AnyRef] = None
        

        The underlying cause of this is that ReadEvalPrint.call throws an exception if you try to access the evaluated value:

        Welcome to Scala version 2.9.1.final (OpenJDK 64-Bit Server VM, Java 1.6.0_20).
        Type in expressions to have them evaluated.
        Type :help for more information.
        
        scala> import scala.tools.nsc.interpreter._
        import scala.tools.nsc.interpreter._
        
        scala> class MyIMain extends IMain {
             | def lastRequest = prevRequestList.last
             | }
        defined class MyIMain
        
        scala> val n = new MyIMain()
        n: MyIMain = MyIMain@1483ce25
        
        scala> n.interpret("val a = 1")
        import scala.tools.nsc.interpreter._
        res0: scala.tools.nsc.interpreter.package.IR.Result = Success
        
        scala> val r = n.lastRequest
        r: n.Request = Request(line=val a = 1, 1 trees)
        
        scala> r.lineRep.call(r.lineRep.evalName)
        java.lang.RuntimeException: Internal error: eval object class $line1.$eval, 
        
        	at scala.sys.package$.error(package.scala:27)
        	at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.evalMethod(IMain.scala:750)
        	at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704)
        	at .<init>(<console>:14)
        	at .<clinit>(<console>)
        	at .<init>(<console>:11)
        	at .<clinit>(<console>)
        	at $print(<console>)
        	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        	at java.lang.reflect.Method.invoke(Method.java:616)
        	at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704)
        	at scala.tools.nsc.interpreter.IMain$Request$$anonfun$14.apply(IMain.scala:920)
        	at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:43)
        	at scala.tools.nsc.io.package$$anon$2.run(package.scala:25)
        	at java.lang.Thread.run(Thread.java:636)
        

        IMain.valueOfTerm ultimately calls ReadEvalPrint.callEither which swallows that exception and eventually a None bubbles up and gets returned. I haven't done any more digging as to why that exception is thrown, will report more details if I find them.

        Are there any known workarounds for this? We're embedding the Scala REPL and trying to customize the Print stage to dump the contents of any eval'ed collection or iterator in Gremlin and this bug is impeding progress.

        Show
        Zach Cox added a comment - I see this too with 2.9.1.final: Welcome to Scala version 2.9.1.final (OpenJDK 64-Bit Server VM, Java 1.6.0_20). Type in expressions to have them evaluated. Type :help for more information. scala> val n = new scala.tools.nsc.interpreter.IMain() n: scala.tools.nsc.interpreter.IMain = scala.tools.nsc.interpreter.IMain@3f6a5d72 scala> n.interpret("val r=1") r: Int = 1 res0: scala.tools.nsc.interpreter.package.IR.Result = Success scala> n.valueOfTerm("r") res1: Option[AnyRef] = None The underlying cause of this is that ReadEvalPrint.call throws an exception if you try to access the evaluated value: Welcome to Scala version 2.9.1.final (OpenJDK 64-Bit Server VM, Java 1.6.0_20). Type in expressions to have them evaluated. Type :help for more information. scala> import scala.tools.nsc.interpreter._ import scala.tools.nsc.interpreter._ scala> class MyIMain extends IMain { | def lastRequest = prevRequestList.last | } defined class MyIMain scala> val n = new MyIMain() n: MyIMain = MyIMain@1483ce25 scala> n.interpret("val a = 1") import scala.tools.nsc.interpreter._ res0: scala.tools.nsc.interpreter.package.IR.Result = Success scala> val r = n.lastRequest r: n.Request = Request(line=val a = 1, 1 trees) scala> r.lineRep.call(r.lineRep.evalName) java.lang.RuntimeException: Internal error: eval object class $line1.$eval, at scala.sys.package$.error(package.scala:27) at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.evalMethod(IMain.scala:750) at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704) at .<init>(<console>:14) at .<clinit>(<console>) at .<init>(<console>:11) at .<clinit>(<console>) at $print(<console>) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:616) at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704) at scala.tools.nsc.interpreter.IMain$Request$$anonfun$14.apply(IMain.scala:920) at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:43) at scala.tools.nsc.io.package$$anon$2.run(package.scala:25) at java.lang.Thread.run(Thread.java:636) IMain.valueOfTerm ultimately calls ReadEvalPrint.callEither which swallows that exception and eventually a None bubbles up and gets returned. I haven't done any more digging as to why that exception is thrown, will report more details if I find them. Are there any known workarounds for this? We're embedding the Scala REPL and trying to customize the Print stage to dump the contents of any eval'ed collection or iterator in Gremlin and this bug is impeding progress.
        Hide
        Sebastien Riou added a comment -

        In my case, I reverted to 2.9.0.1 to get things going...

        Show
        Sebastien Riou added a comment - In my case, I reverted to 2.9.0.1 to get things going...
        Hide
        Wiktor Macura added a comment - - edited

        Hi!

        It seems that the problem is that r.lineRep.evalName returns $eval. If we call r.lineRep.call("$result") directly we get the results as expected:

        object IMainSpecs extends Specification {
          "IMain" should {
            "give term value" in {
              System.setProperty("settings.usejavacp.value", "true")
              val settings = new Settings()
              settings.embeddedDefaults[UXPad]
              settings.processArgumentString("-usejavacp")
        
              class MyIMain extends IMain(settings) {
                def lastRequest = prevRequestList.last
              }
        
              val n = new MyIMain()
              n.interpret("val a = 1")
        
              val r = n.lastRequest
              r.lineRep.call("$result").must_== (1)
            }
          }
        }
        
        Show
        Wiktor Macura added a comment - - edited Hi! It seems that the problem is that r.lineRep.evalName returns $eval . If we call r.lineRep.call("$result") directly we get the results as expected: object IMainSpecs extends Specification { "IMain" should { "give term value" in { System.setProperty("settings.usejavacp.value", "true") val settings = new Settings() settings.embeddedDefaults[UXPad] settings.processArgumentString("-usejavacp") class MyIMain extends IMain(settings) { def lastRequest = prevRequestList.last } val n = new MyIMain() n.interpret("val a = 1") val r = n.lastRequest r.lineRep.call("$result").must_== (1) } } }
        Hide
        Zach Cox added a comment -

        Wiktor - are you using Scala 2.9.1? What exactly is UXPad?

        If I run your code (excluding the UXPad line) in the REPL I end up with null instead of 1:

        scala> r.lineRep.call("$result")
        res4: AnyRef = null
        

        If I run your Specification using sbt test then I get this exception on the n.interpret() line:

        Exception in thread "Thread-10" java.lang.Error: typeConstructor inapplicable for <none>
        	at scala.tools.nsc.symtab.SymbolTable.abort(SymbolTable.scala:34)
        	at scala.tools.nsc.symtab.Symbols$Symbol.typeConstructor(Symbols.scala:877)
        	at scala.tools.nsc.symtab.Definitions$definitions$.scala$tools$nsc$symtab$Definitions$definitions$$booltype(Definitions.scala:157)
        	at scala.tools.nsc.symtab.Definitions$definitions$.init(Definitions.scala:814)
        	at scala.tools.nsc.Global$Run.<init>(Global.scala:697)
        	at scala.tools.nsc.interpreter.IMain.scala$tools$nsc$interpreter$IMain$$_initialize(IMain.scala:114)
        	at scala.tools.nsc.interpreter.IMain$$anonfun$initialize$1.apply$mcZ$sp(IMain.scala:127)
        	at scala.tools.nsc.interpreter.IMain$$anonfun$initialize$2.apply(IMain.scala:126)
        	at scala.tools.nsc.interpreter.IMain$$anonfun$initialize$2.apply(IMain.scala:126)
        	at scala.concurrent.ThreadRunner$$anon$2$$anonfun$run$2.apply(ThreadRunner.scala:45)
        	at scala.concurrent.ThreadRunner.scala$concurrent$ThreadRunner$$tryCatch(ThreadRunner.scala:31)
        	at scala.concurrent.ThreadRunner$$anon$2.run(ThreadRunner.scala:45)
        	at java.lang.Thread.run(Thread.java:636)
        

        Could you please provide more details about the environment in which that test passes for you?

        Show
        Zach Cox added a comment - Wiktor - are you using Scala 2.9.1? What exactly is UXPad? If I run your code (excluding the UXPad line) in the REPL I end up with null instead of 1: scala> r.lineRep.call("$result") res4: AnyRef = null If I run your Specification using sbt test then I get this exception on the n.interpret() line: Exception in thread "Thread-10" java.lang.Error: typeConstructor inapplicable for <none> at scala.tools.nsc.symtab.SymbolTable.abort(SymbolTable.scala:34) at scala.tools.nsc.symtab.Symbols$Symbol.typeConstructor(Symbols.scala:877) at scala.tools.nsc.symtab.Definitions$definitions$.scala$tools$nsc$symtab$Definitions$definitions$$booltype(Definitions.scala:157) at scala.tools.nsc.symtab.Definitions$definitions$.init(Definitions.scala:814) at scala.tools.nsc.Global$Run.<init>(Global.scala:697) at scala.tools.nsc.interpreter.IMain.scala$tools$nsc$interpreter$IMain$$_initialize(IMain.scala:114) at scala.tools.nsc.interpreter.IMain$$anonfun$initialize$1.apply$mcZ$sp(IMain.scala:127) at scala.tools.nsc.interpreter.IMain$$anonfun$initialize$2.apply(IMain.scala:126) at scala.tools.nsc.interpreter.IMain$$anonfun$initialize$2.apply(IMain.scala:126) at scala.concurrent.ThreadRunner$$anon$2$$anonfun$run$2.apply(ThreadRunner.scala:45) at scala.concurrent.ThreadRunner.scala$concurrent$ThreadRunner$$tryCatch(ThreadRunner.scala:31) at scala.concurrent.ThreadRunner$$anon$2.run(ThreadRunner.scala:45) at java.lang.Thread.run(Thread.java:636) Could you please provide more details about the environment in which that test passes for you?
        Hide
        Wiktor Macura added a comment - - edited

        ((I finally found the preview button; my apologies.))

        Yes, sorry. I should have extracted the minimal test case:

        import tools.nsc.interpreter.IMain
        import tools.nsc.Settings
        
        val settings = new Settings()
        
        class MyIMain extends IMain() {
          def lastRequest = prevRequestList.last
        }
        
        val n = new MyIMain()
        n.interpret("val a = 123")
        
        val r = n.lastRequest
        println(r.lineRep.call("$result"))
        

        Running:

        [wiktor@wiktorair1 Documents]# scala -version
        Scala code runner version 2.9.1.final -- Copyright 2002-2011, LAMP/EPFL
        
        [wiktor@wiktorair1 Documents]# scala Test.scala 
        a: Int = 123
        123
        

        This is on OS X, if it matters.

        Show
        Wiktor Macura added a comment - - edited ((I finally found the preview button; my apologies.)) Yes, sorry. I should have extracted the minimal test case: import tools.nsc.interpreter.IMain import tools.nsc.Settings val settings = new Settings() class MyIMain extends IMain() { def lastRequest = prevRequestList.last } val n = new MyIMain() n.interpret("val a = 123") val r = n.lastRequest println(r.lineRep.call("$result")) Running: [wiktor@wiktorair1 Documents]# scala -version Scala code runner version 2.9.1.final -- Copyright 2002-2011, LAMP/EPFL [wiktor@wiktorair1 Documents]# scala Test.scala a: Int = 123 123 This is on OS X, if it matters.
        Hide
        Zach Cox added a comment -

        Thanks Wiktor! I did get that to work in a standalone source file (but not on the REPL - maybe some problem using an interpreter inside an interpreter...). And I'm on Ubuntu.

        I made it even a bit more minimal:

        class MyIMain extends tools.nsc.interpreter.IMain {
          def lastRequest = prevRequestList.last
        }
        
        val n = new MyIMain()
        n.interpret("val a = 123")
        
        println(n.lastRequest.lineRep.call("$result"))
        
        Show
        Zach Cox added a comment - Thanks Wiktor! I did get that to work in a standalone source file (but not on the REPL - maybe some problem using an interpreter inside an interpreter...). And I'm on Ubuntu. I made it even a bit more minimal: class MyIMain extends tools.nsc.interpreter.IMain { def lastRequest = prevRequestList.last } val n = new MyIMain() n.interpret("val a = 123") println(n.lastRequest.lineRep.call("$result"))
        Hide
        Commit Message Bot added a comment -

        (extempore in r25848) Fixing valueOfTerm in the repl.

        Impressed at the amount of ticket traffic for an unadvertised internal
        method. All the more reason to work toward that support repl API.
        Don't worry, it'll come. Closes SI-4899, no review.

        Show
        Commit Message Bot added a comment - (extempore in r25848 ) Fixing valueOfTerm in the repl. Impressed at the amount of ticket traffic for an unadvertised internal method. All the more reason to work toward that support repl API. Don't worry, it'll come. Closes SI-4899 , no review.

          People

          • Assignee:
            Paul Phillips
            Reporter:
            David B. Dahl
          • Votes:
            6 Vote for this issue
            Watchers:
            11 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development