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

Interpreter / Compiler inconsistent #321

Closed
scabug opened this issue Dec 28, 2007 · 7 comments
Closed

Interpreter / Compiler inconsistent #321

scabug opened this issue Dec 28, 2007 · 7 comments

Comments

@scabug
Copy link

scabug commented Dec 28, 2007

When working through Scala By Example, I found an inconsistency in the interpreter vs. the compiler. If I have the following file ('IntSet.scala')

trait IntSet {
    def incl(x: Int): IntSet
    def contains(x: Int): Boolean
}

class EmptySet extends IntSet {
    def contains(x: Int): Boolean = false
    def incl(x: Int): IntSet = 
        new NonEmptySet(x, new EmptySet, new EmptySet)
}

class NonEmptySet(elem: Int, left: IntSet, right: IntSet) extends IntSet {
    def contains(x: Int): Boolean =
        if (x < elem) left contains x
        else if (x > elem) right contains x
        else true
    def incl(x: Int): IntSet = 
        if (x < elem) 
            new NonEmptySet(elem, left incl x, right)
        else if (x > elem) 
            new NonEmptySet(elem, left, right incl x)
        else this
}

object Exec {
    def main(args: Array[String]) {
        var x: IntSet = new EmptySet
        x = x incl 5
        x = x incl 4
        println(x contains 4)
        println(x contains 3)
    }
}

and run 'scala', then at the interpreter type ':load IntSet.scala' I get the following errors:

scala> :load IntSet.scala
Loading IntSet.scala...
defined trait IntSet
<console>:8: error: type mismatch;
 found   : EmptySet
 required: IntSet
               new NonEmptySet(x, new EmptySet, new EmptySet)
                                  ^
<console>:8: error: type mismatch;
 found   : EmptySet
 required: IntSet
               new NonEmptySet(x, new EmptySet, new EmptySet)
                                                ^
<console>:8: error: type mismatch;
 found   : NonEmptySet
 required: IntSet
               new NonEmptySet(x, new EmptySet, new EmptySet)
               ^
defined class NonEmptySet
<console>:7: error: type mismatch;
 found   : EmptySet
 required: IntSet
               var x: IntSet = new EmptySet
                               ^

However, if I compile and then run with 'scalac IntSet.scala' and 'scala Exec', I get

...>scala Exec
true
false

As expected.

The two should have uniform semantics. An acceptably typed input to the compiler should be acceptably typed to the interpreter and REPL.

@scabug
Copy link
Author

scabug commented Dec 28, 2007

Imported From: https://issues.scala-lang.org/browse/SI-321?orig=1
Reporter: David Hogarty (flyingsymbols)
Attachments:

  • IntSet.scala (created on Dec 28, 2007 4:47:09 AM UTC, 896 bytes)

@scabug
Copy link
Author

scabug commented Dec 28, 2007

David Hogarty (flyingsymbols) said:
Referenced code file

@scabug
Copy link
Author

scabug commented Dec 29, 2007

Ville Aine (heap) said:
Replying to [ticket:321 flyingsymbols]:

At least on 2.6.1-final, the initial error message is different:

$$ scala
Welcome to Scala version 2.6.1-final.
Type in expressions to have them evaluated.
Type :help for more information.

scala> :l IntSet.scala
Loading IntSet.scala...
defined trait IntSet
<console>:8: error: not found: type NonEmptySet
               new NonEmptySet(x, new EmptySet, new EmptySet)
                   ^
defined class NonEmptySet
<console>:7: error: not found: type EmptySet
               var x: IntSet = new EmptySet
                                   ^

If IntSet.scala is now :loaded again, then we'll see the type mismatch errors
from the original report.

The reason for the first error is that that IntSet, EmptySet and NonEmptySet
are each compiled separately, as if you would have typed each of them on a
separate line in the interpreter. Or in other words, the reason for the "not
found: NonEmptySet" error is that scala hasn't had the chance to see the
definition of NonEmptySet yet.

The second "not found" error follows from the first one: as the interpreter
could not define EmptySet, it naturally cannot find it later on either.

Now, the type mismatch errors are somewhat more involved. When the interpreter
compiles a chunk of code, it actually wraps the code inside multiple nested
objects:

object line2$$object {
object $$iw{
object $$iw{
       trait IntSet {
           def incl(x: Int): IntSet
           def contains(x: Int): Boolean
       }

}
}

And when a line references something that was defined in one of the previous
lines, that something is imported from the last(?) line object defining it:

object line3$$object {
object $$iw{
import line2$$object.$$iw.$$iw.IntSet;
object $$iw{
       class EmptySet extends IntSet {
           def contains(x: Int): Boolean = false
           def incl(x: Int): IntSet = 
               new NonEmptySet(x, new EmptySet, new EmptySet)
       }

}
}

;}

When IntSet.scala is :loaded for the second time, IntSet trait is first
defined inside line7$$object, and then for EmptySet:

object line8$$object {
object $$iw{
import line4$$object.$$iw.$$iw.NonEmptySet;
import line7$$object.$$iw.$$iw.IntSet;
object $$iw{
       class EmptySet extends IntSet {
[...]

So, EmpySet.incl ought to return line7$$object.$$iw.$$iw.IntSet but it
actually returns line4$$object.$$iw.$$iw.NonEmptySet that extends
line2$$object.$$iw.$$iw.IntSet, which is clearly a type error. The type errors
regarding NonEmptySet constructor parameters are caused by a similar thing,
just the other way around.

@scabug
Copy link
Author

scabug commented Feb 4, 2008

Geoffrey Alan Washburn (washburn) said:
As noted by heap, the interpreter reads inputs sequentially and therefore
it is not possible to use forward references like this.

@scabug
Copy link
Author

scabug commented Jan 14, 2009

@odersky said:
Milestone 2.7.0 deleted

@scabug
Copy link
Author

scabug commented Mar 15, 2009

Edwin Fuquen (ed5) said:
This obviously isn't critical but it is a pain when trying to play with anything more then trivial on the interpreter, so I think it at least deserves an enhancement status?

@scabug
Copy link
Author

scabug commented May 27, 2012

@retronym said (edited on May 27, 2012 7:59:33 PM UTC):
Shall we say that :paste mode is sufficient for this sort of thing, and :load can retain its current semantics?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant