Structure of objects and execution (with effects on visu
Jerome.Garcia at wj.com
Sat Oct 24 00:01:03 UTC 1998
Sorry to butt into this conversation so quickly but I just have to
excitedly express my support for the idea that ParseTrees should be
dominant. I have thought so since my days as project leader of the
COBOL compiler development project at CDC in the early 80's. I then
kept thinking "Why can't I get rid of all this text, focus on the
parse trees and give the programmer a GUI to edit the parse trees?".
Of course, no self respecting COBOL programmer would have gone for
If I remember correctly, Prograph felt a little like what I wanted
from the GUI but not quite correct.
Since I don't know enough about the innards of Squeak to comment
intellegently on most of Daniel's discussion, I will quiet down now
but keep my fingers crossed.
Jerome E. Garcia
jegarcia at adventurousmind.com
______________________________ Reply Separator _________________________________
Subject: Structure of objects and execution (with effects on visual p
Author: Daniel Vainsencher <danielv at netvision.net.il> at INTERNET
Date: 10/23/98 10:47 PM
remember the idea of replacing CompiledMethods in MethodDictionaries
More thoughts on that direction.
There are three main representation of executable stuff, AFAIK.
They differ in three main aspects - structure, human useability, machine
Text - freeform, human readable, not directly executable.
ParseTree - structure represents code semantics, not human readable but
can be reasonably represented, requires only a little context to be
CompiledMethod - a VM datastructure that specifies execution, not human
readable at all and hard to access via messages, but directly executable
If we look at Squeak, two of the three form are clearly dominant, and
much more visible to the user - the first and the third.
The user directly edits Texts all the time, and can find CompiledMethods
by inspecting any class.
ParseTrees are mere shadows, temporary constructs built by the Compiler,
and thrown away.
(if you're not sure I'm right about this, in a standard distribution
CompiledMethod allInstances size => ~13,000
MethodNode (the root of ParseTrees) allInstances size => ~1 )
The point I'll make is that this is all wrong. ParseTrees should be
dominant, the others mere shadows.
I'll propose some changes, and ask some feasibilty questions.
1. Text is not really a very good way for users to program.
It's true, it is superficially easy (the UI is the same like working
with simple, non executable text).
But right now, it doesn't give much information back. Decorated Text
(eg, format with left-shift held), which can include more information,
is rare in the system right now, and doesn't give much more.
Graphical ways of visualizing program execution might be more useful
even than Decorated Text. But that's not the point - the point is that
Decorated Text and Visualization of the program are manufactured from a
ParseTree. One might say, they are simply alternative ways to render
or specify a ParseTree.
So why is so much focus on the source code, and so little on the
2. On the system side, one might call CompiledMethods a premature
(though great at the time) optimization. The direction of
and JIT compilers is to give us more efficient ways to represent code.
In addition, we find that we sometimes want to modify the execution
We already have a system simulator, and we've seen we might want to
stretch that in other directions - reversible debugging, for example.
What am I proposing? make classes have dictionaries of selector ->
ParseTree (Concretely, MethodNode, or we might choose to wrap it) pairs.
At runtime, the ParseTree can be dynamically decorated by other
selector -> ExecutingDecorator-> ParseTree
where the decorator will only take over functions it does better
(execution). Note that this would make it easy to experiment with lots
for example, to setup a fast-compiler/optimizing-compiler pair like in
3. If we already make execution much more transparent, implementing
extensions like MethodWrappers and such should become much easier.
Refactoring operations become quite natural, as does having a ParseTree
"reattach" - bind itself to a new class, instead of it's old context. So
aClass when: aSelector do: aBlock
aBlock reattachToClass: self
self atSelector: aSelector putCode: aBlock.
becomes pretty easy. To me that suggests that blocks also stay mere
ParseTrees until they're used, but then that's only natural...
Possible problems -
The size of the ParseTree representation - bytecode is pretty small,
but we can keep rarely used trees compressed, and open them on access.
Efficiency of dynamic translation - if we have a method cache, and we
keep that always equiped with directly executable code, we probably will
not have a problem. Self worked using something like this, though I'm
not sure what their intermediate representation was like.
What do you think?
I'd like to try to do a simple version of this (that simply converts
MethodNodes to CompiledMethods). Do you have tips on navigation in the
code for dispatch and such?
More information about the Squeak-dev