Smalltalk code generation
Marcus Denker
denker at iam.unibe.ch
Sat Oct 8 08:19:58 UTC 2005
Am 08.10.2005 um 05:47 schrieb Mariano Montone:
> Hi Alexandre, sorry for not answering before, I hadn't noticed the
> message.
>
> The problem is that I have a code generation visitor traversing the
> AST. I need to generate different parts of the method from
> different methods of the visitor. I don't see how your approach may
> fit, that's why I need to implement it this way.
>
Yes, then you don't want to deal with text, for sure. One way to do
it is to visit your AST and build up a refactoring browser AST. The
new compiler
(see project NewCompiler on SqueakSource) then can generate bytecode
from that. (Or you can use the standard Squeak AST for that, but
this is far from fun to use...)
Another way to do it is to reuse just the back-end of the new compiler:
Generate directly bytecode from your AST. This saved you from doing
the conversion to the Squeak AST, thus it's faster and you are not bound
to Smalltalk semantics, that is, you can encode controlflow with
jumps directly as you like, thus generating quite nice code for your
language.
The backend is IRBuilder: It's a kind of a "symbolic assembler" for
Squeak Bytecode.
Here's a simple example:
iRMethod := IRBuilder new
numRargs: 1;
addTemps: #(self); "receiver and args declarations"
pushLiteral: 1;
returnTop;
ir.
aCompiledMethod := iRMethod compiledMethod.
So for your AST visitor, you make one IRBuilder, put it in an instVar
of the visitor and then just call methods on it while
traversing the tree. IRBuilder has support for symbolic jumps, a test
showing this:
ir := IRBuilder new
numRargs: 2;
addTemps: #(self a z); "rcvr, arg, & extra temp (not
used here)"
pushTemp: #self;
pushInstVar: 2;
pushTemp: #a;
send: #>;
jumpAheadTo: #else if: false;
pushLiteral: 'yes';
returnTop;
jumpAheadTarget: #else;
pushLiteral: 'no';
returnTop;
ir.
cm := ir compiledMethod.
self assert: (cm isKindOf: CompiledMethod).
self assert: (cm valueWithReceiver: self arguments: #(1)) =
'yes' .
self assert: (cm valueWithReceiver: self arguments: #(3)) =
'no' .
^cm
There are some examples in the IRBuilderTest method (e.g. for how to
do blocks).
Of course there are downsides: For a complete system you need to take
care of debugging (a it more difficult,
but it should be doable. The debugger just needs a mapping bytecode--
>text that your compiler/decompiler need to
build up). And you need to keep in mind that the code generated will
not be decompilable by the smalltalk decompiler,
If you need a decompiler, then do your own that then will decompile
directly to your AST.
One problem: It's not yet all to easy to get it in installed, the
new compiler requires the
latest 3.9a with AST and methodAnnotations (from http://
www.iam.unibe.ch/~denker/temp/CMAnnotations.zip).
This will be fixed soon.
Marcus
More information about the Squeak-dev
mailing list
|