Macro Code Execution
In the Function Macros section we mentioned that Ryna has a code generation pattern that executes code. Since its complexity is far from the rest, we will dedicate this section to explaining how it works.
Syntax
The syntax of this pattern is simple:
{| inner_pattern |}
You can put any macro pattern you want inside those braces and the resulting text will be interpreted as Ryna code. The generated code
will execute normally, even importing libraries if necessary, but you will have access to a special function
not available otherwise: the emit
function.
This funtion, which takes as a parameter a single String
, will send that string to a buffer that will accumulate everything emited
throughout the execution of the code. After the execution ends, the buffer will be appended to the code generated by the macro. This is
essentially the same as procedural macros in Rust.
Examples
Lets see a basic example that creates the expression 1 + 1
. In order to do this you do not need compile time code execution, but it will allow us to
illustrate how they work. You could use the following:
syntax expr one_plus_one from "Example" {
{| emit("1 + 1") |}
}
// Use it like this ...
print(Example);
// ... which compiles to this
print(1 + 1);
Of course, this is not very interesting because this macro has no interaction with the pattern that was matched. This can be changed easily by using different inner patterns, so let's make a more complex example:
syntax expr n_plus_m from Arg(1{d}, a) "plus" Arg(1{d}, a) {
{|
let a = "$a";
let b = "$b";
emit(*a);
emit(" + ");
emit(*b);
|}
}
// Use it like this ...
print(7plus32);
// ... which compiles to this
print(7 + 32);
As you can imagine, this opens up possibilities a lot when using macros, since you can even import libraries inside them. You can see an extreme example where you embed an esoteric language inside Ryna using these macro patterns in the Learn by example section.