Macros
Table of Contents
Declaration
MacroDecl = "macro" identifier "(" ParameterList ")" MacroBody "end" ; MacroBody = { ( identifier | TemplateStmt ) ";" } ; TemplateStmt = LineTemplateStmt | BlockTemplateStmt ; LineTemplateStmt = "$" TemplateContent ; BlockTemplateStmt = "!!" { TemplateContent } "!!" ;
TemplateContent
is a bit more complex: it essentially is normal lapyst sourcecode but with one addition: everywhere a TemplateInterpolation
can be placed.
TemplateInterpolation = "{{" identifier "}}" ;
A TemplateInterpolation
itself is just used to inject a variable’s value inside the template.
macro declare_method(ident name, type ret) $ dec {{ret}} {{name}}(); end macro make_method(ident name, type ret, expr value) !! def {{ret}} {{name}}() return {{value}} end !! end
Types
TODO: document this |
@macro_context
annotation
TODO: maybe rework this a bit |
This annotation can give your macro extra information where the macro itself can be used.
@macro_context{ in=[ :shape ] } macro attr_reader(ident name) type = context.getField(name).getType(); !! def {{type}} !{{name}} return self.{{name}} end !! end
It’s only has the attribute in
which accepts an array of symbols.
These symbols can be:
:shape :function :method :namespace :global :constructor
The context
TODO: expand more on the context |
In each macro, the context
variable holds the context in which the macro is currently being evaluated. With this, you have read access to all definitions / declarations in this context until the point of the macro call.
@macro_context{ in=[ :shape ] } macro attr_reader(ident name) type = context.getField(name).getType(); end
This line querys the current context (a shape) for an specific field. From this field it then retrieves the type of that field. |