Last days I play with idea of compile time evaluation without special language support.
For example in Dolphin Smalltalk there is special syntax for this:
##(100 factorial)
Factorial will be evaluated at method compilation time and result will be saved as literal. And this precomputed value will be used during method execution.
In Pharo we can do this without special syntax. Thank's to powerful reflection system which called Reflectivity. It allows reflection on the level of AST nodes with different kind of transformations.
With Reflectivity we could substitute particular expression with result when method will be executed first time. It is a bit different than compile time evaluation. But after first method execution it will be same: precomputed value of expression will be stored and used as regular literal.
And now magic:
100 factorial asMethodConst
I was quite impressed when I realize that this approach could work. First I tried to use blocks but it was completely not needed:
Object>>asMethodConst
| constNode link |
constNode := thisContext sender sourceNodeExecuted.
link := MetaLink new
metaObject: self;
control: #instead.
constNode link: link.
^self
#asMethodConst will be executed on result of expression. Trick here is that constNode is "message send" ast-node where receiver is target expression. Metalink with control #instead will substitute it as whole and receiver will not be executed anymore.
Wondering how little code is required. It will be available in Pharo soon (18768).
For example in Dolphin Smalltalk there is special syntax for this:
##(100 factorial)
Factorial will be evaluated at method compilation time and result will be saved as literal. And this precomputed value will be used during method execution.
In Pharo we can do this without special syntax. Thank's to powerful reflection system which called Reflectivity. It allows reflection on the level of AST nodes with different kind of transformations.
With Reflectivity we could substitute particular expression with result when method will be executed first time. It is a bit different than compile time evaluation. But after first method execution it will be same: precomputed value of expression will be stored and used as regular literal.
And now magic:
100 factorial asMethodConst
I was quite impressed when I realize that this approach could work. First I tried to use blocks but it was completely not needed:
Object>>asMethodConst
| constNode link |
constNode := thisContext sender sourceNodeExecuted.
link := MetaLink new
metaObject: self;
control: #instead.
constNode link: link.
^self
#asMethodConst will be executed on result of expression. Trick here is that constNode is "message send" ast-node where receiver is target expression. Metalink with control #instead will substitute it as whole and receiver will not be executed anymore.
Wondering how little code is required. It will be available in Pharo soon (18768).
What is `const` in return?
ОтветитьУдалитьit should be ^self. Thanks
Удалить