Since we are at reviewing Environment, here is a small detail that bothers me. I already asked some months ago, but silence was the only response, so ping.
Implementation of Environment is sometimes not obvious: - Environment>>associationAt: uses declarations inst.var.. - Environment>>associationOrUndeclaredAt: uses bindings inst.var. How can it be so different, the selector does not speak, does it?
OK, there is a flag: #review in one of them, but that does not make code clearer, it's just a smell of over-complexity or ill-naming.
Whatever the reason (self explaining code?) Colin does not comment class/methods, that's a fact. Chris made the effort of commenting Environment but then came this declarations/bindings split, and the comment did rapidly rot. We have here an un-healthy statu quo crying for change.
So if we want to at least comment the class with the meaning/role/responsibility of inst vars, here is my understanding:
environment bind: #Foo to: 0. just add to the declarations. (You see how names are not obvious: bind does not bind the new binding to bindings).
If the Environment importSelf, then the ClassBinding/Global also goes to bindings... (thru an observer pattern and the magic of naming policies)
The bindings is what is used by the compiler, so what if an environment does not importSelf? It means that the variable it declares are not bound, so it is not reachable (kind of invisible class/Global).
IOW, the bindings will contain all the imports, including self-imports. importSelf is generally what we want to do, unless weird cases of powerless environment for obfuscation or trustless sandboxing reason.
Now, associationAt: does not speak for itself. It's too hard to decide if we're speaking of own declarations or bindings... Analyzing the usage is difficult. bindingAt: would be less ambiguous, so IMO we cannot fix without semantic shift.
The semantic will be carried by the senders (the Tools), and the tools by usage we want to make of Environment. So we first have to define that: what feature do we want to support? With which tool? That probably require yet another thread...
Protecting the environment is very important. It is made up of the very air we breathe, as well as the things which we eat. I would love to answer some of your questions about bothersome details, so ping. For starters, the implementation of the environment in our lives couldn't be more obvious. Like, you literally walk outside and it's like trees and water and ducks and the Taco Bell down the street and it's like: "Woah dude. I'm alive." It's the same thing for us every day. I don't know how it could be less different, and I don't believe in natural selection, it speaks for itself, and it's pretty wild.
On another note, I read a book the other day while I was in school. It was called: "Sus." It went: "Sus." I felt pretty inspired so I went home from school and wrote a story called: "Sus." It went:
"Sussowssaucesoossiissooososousususoes...s..."
I sent it into the paper, still havent heard anything from the editor but I'll let you know how it goes. Nice hearing from you Nicolas!
Sincerely
Gary Mary
On Wed, Sep 28, 2016 at 5:59 PM, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
Since we are at reviewing Environment, here is a small detail that bothers me. I already asked some months ago, but silence was the only response, so ping.
Implementation of Environment is sometimes not obvious:
- Environment>>associationAt: uses declarations inst.var..
- Environment>>associationOrUndeclaredAt: uses bindings inst.var.
How can it be so different, the selector does not speak, does it?
OK, there is a flag: #review in one of them, but that does not make code clearer, it's just a smell of over-complexity or ill-naming.
Whatever the reason (self explaining code?) Colin does not comment class/methods, that's a fact. Chris made the effort of commenting Environment but then came this declarations/bindings split, and the comment did rapidly rot. We have here an un-healthy statu quo crying for change.
So if we want to at least comment the class with the meaning/role/responsibility of inst vars, here is my understanding:
environment bind: #Foo to: 0. just add to the declarations. (You see how names are not obvious: bind does not bind the new binding to bindings).
If the Environment importSelf, then the ClassBinding/Global also goes to bindings... (thru an observer pattern and the magic of naming policies)
The bindings is what is used by the compiler, so what if an environment does not importSelf? It means that the variable it declares are not bound, so it is not reachable (kind of invisible class/Global).
IOW, the bindings will contain all the imports, including self-imports. importSelf is generally what we want to do, unless weird cases of powerless environment for obfuscation or trustless sandboxing reason.
Now, associationAt: does not speak for itself. It's too hard to decide if we're speaking of own declarations or bindings... Analyzing the usage is difficult. bindingAt: would be less ambiguous, so IMO we cannot fix without semantic shift.
The semantic will be carried by the senders (the Tools), and the tools by usage we want to make of Environment. So we first have to define that: what feature do we want to support? With which tool? That probably require yet another thread...
On 9/28/16, Nicolas Cellier nicolas.cellier.aka.nice@gmail.com wrote:
Since we are at reviewing Environment, here is a small detail that bothers me. I already asked some months ago, but silence was the only response, so ping.
Implementation of Environment is sometimes not obvious:
- Environment>>associationAt: uses declarations inst.var..
- Environment>>associationOrUndeclaredAt: uses bindings inst.var.
How can it be so different, the selector does not speak, does it?
OK, there is a flag: #review in one of them, but that does not make code clearer, it's just a smell of over-complexity or ill-naming.
Whatever the reason (self explaining code?) Colin does not comment class/methods, that's a fact.
Alternatively a description of the general ideas and the mechanism would help.
After all Environments is just a clever combination of a few dictionaries to look up class names? Isn't it? ;-)
However the fact that people did not move on much finalising the implementation of environments since 2012 shows that it is hard to reverse-engineer the intentions from the (incomplete) code.
Chris made the effort of commenting Environment but then came this declarations/bindings split, and the comment did rapidly rot. We have here an un-healthy statu quo crying for change.
So if we want to at least comment the class with the meaning/role/responsibility of inst vars, here is my understanding:
environment bind: #Foo to: 0. just add to the declarations. (You see how names are not obvious: bind does not bind the new binding to bindings).
Environments
bind: aSymbol to: anObject | binding newBinding | newBinding := aSymbol => anObject. binding := declarations associationAt: aSymbol ifAbsent: [nil]. binding ifNotNil: [binding class == newBinding class ifTrue: [binding value: anObject] ifFalse: [binding becomeForward: newBinding]. ^anObject]. binding := undeclared associationAt: aSymbol ifAbsent: [nil]. binding ifNil: [binding := newBinding] ifNotNil: [undeclared removeKey: aSymbol. binding class == newBinding class ifTrue: [binding value: anObject] ifFalse: [binding becomeForward: newBinding]]. declarations add: binding. self binding: binding addedTo: self. ^anObject
Could you elaborate a bit please?
If the Environment importSelf, then the ClassBinding/Global also goes to bindings... (thru an observer pattern and the magic of naming policies)
The bindings is what is used by the compiler, so what if an environment does not importSelf? It means that the variable it declares are not bound, so it is not reachable (kind of invisible class/Global).
IOW, the bindings will contain all the imports, including self-imports. importSelf is generally what we want to do, unless weird cases of powerless environment for obfuscation or trustless sandboxing reason.
Now, associationAt: does not speak for itself. It's too hard to decide if we're speaking of own declarations or bindings... Analyzing the usage is difficult. bindingAt: would be less ambiguous, so IMO we cannot fix without semantic shift.
This would need as well elaboration as well a separate thread.
The semantic will be carried by the senders (the Tools), and the tools by usage we want to make of Environment. So we first have to define that: what feature do we want to support? With which tool? That probably require yet another thread...
Yes
--Hannes
2016-09-29 7:33 GMT+02:00 H. Hirzel hannes.hirzel@gmail.com:
On 9/28/16, Nicolas Cellier nicolas.cellier.aka.nice@gmail.com wrote:
Since we are at reviewing Environment, here is a small detail that
bothers
me. I already asked some months ago, but silence was the only response,
so
ping.
Implementation of Environment is sometimes not obvious:
- Environment>>associationAt: uses declarations inst.var..
- Environment>>associationOrUndeclaredAt: uses bindings inst.var.
How can it be so different, the selector does not speak, does it?
OK, there is a flag: #review in one of them, but that does not make code clearer, it's just a smell of over-complexity or ill-naming.
Whatever the reason (self explaining code?) Colin does not comment class/methods, that's a fact.
Alternatively a description of the general ideas and the mechanism would help.
After all Environments is just a clever combination of a few dictionaries to look up class names? Isn't it? ;-)
However the fact that people did not move on much finalising the implementation of environments since 2012 shows that it is hard to reverse-engineer the intentions from the (incomplete) code.
More than that: we only get core functionalities, the intentions are not
written here. IOW things still are very open.
Chris made the effort of commenting Environment but then came this declarations/bindings split, and the comment did rapidly rot. We have here an un-healthy statu quo crying for change.
So if we want to at least comment the class with the meaning/role/responsibility of inst vars, here is my understanding:
environment bind: #Foo to: 0. just add to the declarations. (You see how names are not obvious: bind does not bind the new binding to bindings).
Environments
bind: aSymbol to: anObject | binding newBinding | newBinding := aSymbol => anObject.
This creates either a Global or ClassBinding. The first one is writeable, the second not.
binding := declarations associationAt: aSymbol ifAbsent: [nil].
A class points to its environment where it is declared. So we expect this invariant: (Foo environment declarationOf: Foo name) value == Foo. And of course: (declarations values select: [:c | c isBehavior]) allSatisfy: [:c | c environment == self]. For globals I don't know why they are attached to a specific environment. Just because of mechanism for propagating changes?
binding ifNotNil: [binding class == newBinding class ifTrue: [binding value: anObject] ifFalse: [binding becomeForward: newBinding]. ^anObject].
Since we different binding classes we cannot just change the value. Since bindings are shared by bindings inst. var., CompiledMethods and other environments if we don't use value, we must preserve identity with a become...
Note: above code protects against Object := Array because ClassBinding cannot change value. But not against Object := 1, become protects nothing. It must be handled somewhere else.
binding := undeclared associationAt: aSymbol ifAbsent: [nil]. binding ifNil: [binding := newBinding] ifNotNil: [undeclared removeKey: aSymbol. binding class == newBinding class ifTrue: [binding value: anObject] ifFalse: [binding becomeForward:
newBinding]].
If we previously had some undeclared reference to such variable name
(normally a Global with nil value), it's time to rebind it.
declarations add: binding. self binding: binding addedTo: self.
Now propagate the change to every interested observer (those who import declarations from yourself).
^anObject
like at:put: used to do, we still answer the put object.
Could you elaborate a bit please?
See above, by pure reverse engineering ;)
If the Environment importSelf, then the ClassBinding/Global also goes to bindings... (thru an observer pattern and the magic of naming policies)
The bindings is what is used by the compiler, so what if an environment does not importSelf? It means that the variable it declares are not
bound,
so it is not reachable (kind of invisible class/Global).
IOW, the bindings will contain all the imports, including self-imports. importSelf is generally what we want to do, unless weird cases of
powerless
environment for obfuscation or trustless sandboxing reason.
Now, associationAt: does not speak for itself. It's too hard to decide if we're speaking of own declarations or bindings... Analyzing the usage is difficult. bindingAt: would be less ambiguous, so IMO we cannot fix
without
semantic shift.
This would need as well elaboration as well a separate thread.
The semantic will be carried by the senders (the Tools), and the tools by usage we want to make of Environment. So we first have to define that:
what
feature do we want to support? With which tool? That probably require yet another thread...
Yes
already opened :)
--Hannes
Hi--
We don't need a system dictionary at all. We can make each class responsible for its own name literal, use subclass/metaclass references for reachability, and make all other globals the responsibility of some class. Every class can have any name; the execution machinery doesn't care. Other metadata about classes (e.g., author) can be used to disambiguate their names when compiling sources. We can store all that metadata in a module system, to manage the history of all versions of all classes and methods in the system.
The Naiad module system that I wrote[1] implements this. I've adapted it to the latest Squeak and plan to release it this month.
-C
[1] http://thiscontext.com/naiad
-- Craig Latta Black Page Digital Amsterdam | San Francisco craig@blackpagedigital.com +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS)
Hi Craig, you mentioned making each class responsible for its own name literal, which is fine for when you have a reference to a class and want to know its name.
How about the use-case when all you have is a name String, but want to get the (correct) Class object? Are your suggesting to enumerate all classes (which wouldn't take long) and selecting the ones with the referenced name, instead of always only doing a Dictionary lookup (which assumes one name--> to one Class). You mentioned using other fields for disambiguation, so enumerate all classes, selecting the ones whose names match the string, and if there are any other disambiguating clues, use them to auto-select. Is this a correct jist of what you mean?
I'm looking forward to your release!
On Tue, Oct 4, 2016 at 4:14 AM, Craig Latta craig@blackpagedigital.com wrote:
Hi--
We don't need a system dictionary at all. We can make each class
responsible for its own name literal, use subclass/metaclass references for reachability, and make all other globals the responsibility of some class. Every class can have any name; the execution machinery doesn't care. Other metadata about classes (e.g., author) can be used to disambiguate their names when compiling sources. We can store all that metadata in a module system, to manage the history of all versions of all classes and methods in the system.
The Naiad module system that I wrote[1] implements this. I've
adapted it to the latest Squeak and plan to release it this month.
-C
[1] http://thiscontext.com/naiad
-- Craig Latta Black Page Digital Amsterdam | San Francisco craig@blackpagedigital.com +31 6 2757 7177 (SMS ok)
- 1 415 287 3547 (no SMS)
Hi Chris--
How about the use-case when all you have is a name String, but want to get the (correct) Class object? Are you suggesting to enumerate all classes (which wouldn't take long) and selecting the ones with the referenced name, instead of always only doing a Dictionary lookup (which assumes one name--> to one Class).
Yes indeed; we free ourselves of the one-class-per-name assumption (and from even having to think about class namespaces), at that slight cost. Also, if you want to do some reflection which doesn't require getting direct class object references (e.g., "How many classes have this name?"), you can do the enumeration entirely within the history database, in parallel with whatever else you're doing in the main memory where your class objects are.
(Naiad uses a second, minimal, live object memory as a history database, replacing the changes and sources files. The history has "editions": all the metadata for all versions of classes and methods in the system. Most of the questions that development tools ask can be answered by editions. In fact, class and method editions stand in for classes and methods with the traditional code browsers, unbeknownst to them. This enables low-network-traffic remote browsing; editions have a compact binary representation and are self-contained, eliminating extended back-and-forth remote messaging with the classes and methods they describe.)
There's also the cost of interacting with the history database over the network (typically within localhost) instead of a filesystem, but I find it worthwhile, especially since some history-related work can be parallelized.
You mentioned using other fields for disambiguation, so enumerate all classes, selecting the ones whose names match the string, and if there are any other disambiguating clues, use them to auto-select. Is this a correct jist of what you mean?
That's right. If you only care about current class versions, you would enumerate live class objects. If you wanted to enumerate over all past and present class versions, you would delegate to the history database, which would enumerate the class editions.
I'm looking forward to your release!
Thanks!
-C
-- Craig Latta Black Page Digital Amsterdam | San Francisco craig@blackpagedigital.com +31 6 2757 7177 (SMS ok) + 1 415 287 3547 (no SMS)
squeak-dev@lists.squeakfoundation.org