Login  Register

Re: AST Transformation Techniques

Posted by hogoww on Nov 18, 2020; 8:07am
URL: https://forum.world.st/AST-Transformation-Techniques-tp5124771p5124785.html

Indeed !

I'm going to show you a simplified example here, hopefully it'll be understandable.
Bit of context, I'm generating code for visitors, from a Famix metamodel.

    body := [ :anInstance | ] asPlainCodeBC.

    collections do:[:propertyName|
        body add: [:anInstance|
            anInstance propertyName
                ifNotNil:[:aCollection| aCollection
                    do:[:aMember| aMember acceptVisitor: self ]
]]
            withArguments: {#aCollection -> propertyName . #aMember -> propertyName asAnInstance } asDictionary ].
   
    singleElements do:[:propertyName|
        body add: [:anInstance| anInstance propertyName
                    ifNotNil:[:aPropertyName| aPropertyName acceptVisitor: self ] ]
            withArguments: {#aPropertyName -> propertyName asAnInstance } asDictionary ].

We first declare a block that we can concatenate stuff too, then we add others blocks to it.
In this loop, we have to visit every objects in collections for an instance variable of a class.
So we have to add a block per collection to go through.

The actual block that will be added to the resulting block.
Replacements for *this* block.
(Note about this one, I do not remember well, buit I think that you can use one scope per block added, it is copied when the block is added, so you can modify the variables)

The second part is exactly the same as the first one, but for instance variables that do not have to be iterate over.
If you understood the first one, you'll understand the second one !
Otherwise the second one might be able to help you with the first one !

And an example of generated code:

visitStructureDefinition: aStructureDefinition
    aStructureDefinition members
        ifNotNil:
            [ :members | members do: [ :aMembers | aMembers acceptVisitor: self ] ].
    aStructureDefinition declaration
        ifNotNil: [ :aDeclaration | aDeclaration acceptVisitor: self ]

This is an indexable object, a collection.
So we want to visit each objects contained in it.
This is a non indexable object, so we send the visitMessage.
The visit method for this type will take care of visiting its slots properly
.

Note that I initially went with #+, but #, makes as much or more sense ! :)


Pierre

On 18/11/2020 08:42, Hernán Morales Durand wrote:

I took a simple ish example, but we can do more advanced stuff, like concatenating blocks.


This is something which I've been expecting and trying to find some time to do myself.
Just to be clear, you mean something like:

[ :arg1 | arg1 + 0 ] , [ :arg2 | arg2 + 7 ]

which would give:
[ :arg1 :arg2 |
    arg1 + 0.
    arg2 + 7 ]

Did I understand well?

 Thanks for this report!

Cheers,

Hernán

You can find more example in the following project in which I use PlainPharoCode exclusively to generate my code: https://github.com/hogoww/C-AST.
(In the ASTCGenerator class)
(You will need a moose image).

I hope you find this interesting !

Have a nice day !

Pierre.