Class variables only bound in methods following them
| Project: | GNU Smalltalk |
| Component: | VM |
| Category: | bug |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | postponed |
Might be by design, but it's confusing… I suppose the first B resolves to a non-existent global ?
Object subclass: Fail [
a [ stdout << 'a:' << B; nl ]
B := 'hi there'.
c [ stdout << 'c:' << B; nl ]
]
st> Fail new a; c
a:nil
c:hi there
a Fail
st>
Updates
I agree that it's confusing, but "stealing" a binding from Undeclared would not be possible for two reasons:
- you risk introducing a binding from one class to another
- you cannot handle the case in which two different classes have the same undeclared variable, and then the variable turns out to be a class variable only in one of the two.
The way to fix this would be to give a warning upon defining the class variable if the variable can be found in Undeclared. Usually the naming conventions for globals and class variables are different enough that it should not give many false positives.
What about going through the class definition for class variables first, then compile the methods? So at least inside the A subclass: B [ … ] block, the compiler would only "Undeclare" only what's really not there.
That would mean you have to keep potentially the entire class in memory, right? Right now the parse tree of GNU Smalltalk is never deeper than a method.
Indeed. I'm thinking like in pure file-based languages where you want to organize the file arbitrarily and use lexical scope. I'm not entirely clear how variable pools are resolved in other Smalltalks anyway. Here class variables just seemed like a nice way to emulate constants for synopsis, help text, and so on :)
| Status: | active | » invalid |
> Here class variables just seemed like a nice way to emulate constants for synopsis, help text, and so on :)
Yes, you just have to place them before they're used. :-)
Ruby and Python behave like this too, I think it is safe to declare this invalid.
Thanks for raising the point anyway!
| Status: | invalid | » active |
Actually, ruby behaves like I want:
def hello
puts HELLO
end
# calling hello would fail here
HELLO = "Hello, world!"
hello()
the variable is bound like it should even if the reference is before the declaration (well actually it's declared when it's first seen in the method), but of course if you evaluate it before it's been initialized, then you get an exception.
| Status: | active | » postponed |
Given that Ruby is also a bit inconsistent, I'll leave the bug in the database, but I don't plan about working on it anytime soon.
