First off, please forgive me if my title doesn't make sense - my vocabulary for asking my question is currently a bit limited!
I've found a surprising error in SOMns's implementation of object literals, which arises when an object literal inherits from the class of another object literal that is declared in a different scope. In particular, the error with the current SOMns implementation is that the initialization expressions of the inherited object literal's class resolve:
- in the activation enclosing the inheritor (the subclass so to speak), instead of
- resolving in the activation enclosing the declaration of the inheritee (the superclass so to speak).
I'm hoping that someone here might be able to help me understand what the expected behaviour is for Newspeak - if we can get that far I'd be happy to attempt fixing the SOMns error.
Let me start by giving a little bit of context on how I found the error. I'm currently using SOMns to interpret programs written in Grace. To do this, I translate Grace AST into the SOMns equivalent. In particular, I've modeled Grace's objects using SOMns's object literals (this works fine), but I found the error when trying to model Grace's inheritance semantics. Let me start with a simplified example of the Grace program I was using when I found the error:
```
1. class A (name') {
2. def name = name'
3. }
4.
5. def x = object {
6. var obj := inherit A('Alice')
8. }
```
In Grace, we have an equality rule that says that classes are equivalent to methods that tail return an object, so the class in the program above is syntactic sugar for:
```
1. method A (name') {
2. return object {
3. def name = name'
4. }
5. }
6.
7. def x = object {
8. var obj := inherit A('Alice')
10. }
```
Note that the initialization expression of the inherited object (see line 3) reads an argument belonging to the activation in which the inherited object is declared in. With line 3 noted, let me present the Newspeak program that would result from my AST translator (note that the `objL Superclass (...)(...)` is the syntax SOMns uses for object literals).
```
1. class Example usingPlatform: platform = Value (
2. | private ClassMirror = platform mirrors ClassMirror. |
3. )(
4.
5. public A: namePrime = (
6. ^ objL (| public name = namePrime. |)()
7. )
8.
9. public getSuper = (
11. | obj |
12. obj:: A: 'Alice'.
13. ^ (ClassMirror reflecting: obj) classObject
14. )
15.
16. public main: args = (
17. | obj |
18. obj:: objL getSuper ()().
19. (obj name) println.
20. ^ 0
21. )
22. )
So, as you can see to get the superclass for our object (line 18), I first invoke the method `A:` to get the inherited object (line 12) and then reflect on to return its class (lines 13). Again, be careful to note that the superclass contains an initialization expression that refers to the activation enclosing the inherited object's declaration (line 6).
The surprising error is that our object (line 18) ends up with the slot `name` set to `args` (as in, the array of arguments given to the main method)! Why: the `name =` expression says to set name to the first argument of the enclosing activation, and unfortunately the enclosing activation when SOMns invokes the constructor is `main`. Consequently, `name` is set to args. Stefan and I have both verified this to be true, unfortunately.
Intuitively, I would guess that the `name =` expression somehow eagerly evaluated to `namePrime` and somehow store that information in the class. However, doing so would require adding state (about the object) to the class, which seems like a bad idea. So, finally my question - what behaviour should I expect from the Newspeak program above?
One more apology for being a bit long-winded, I hope the question I'm asking makes sense - looking forward to any further discussion!