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
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.
Free forum by Nabble | Edit this page |