The #insert
directive inserts a code or a piece of code represented as a string into the program.
a := 0;
b := 0;
#insert "c := a + b;"; // insert the code as a string
my_code :: #string END_STRING
a += 100;
b += 100;
c += 1000;
END_STRING;
#insert my_code; // insert the multi-line string as a piece of code
#insert
directives work with structs. As you can see in this example, #insert
is being used on an anonymous function that outputs a string to generate code.
SOA :: struct(T: Type, count: int) {
#insert -> string {
t_info := type_info(T);
builder: String_Builder;
defer free_buffers(*builder);
for fields: t_info.members {
print_to_builder(*builder, " %1: [%2] type_of(T.%1);\n", fields.name, count);
}
result := builder_to_string(*builder);
return result;
}
}
Multiple inserts can be run recursively inside #insert
. In the unroll_for_loop
example below, the #insert
directive has an #insert
that recursively runs for code being inserted.
unroll_for_loop :: (a: int, b: int, body: Code) #expand {
#insert -> string {
builder: String_Builder;
print_to_builder(*builder, "{\n");
print_to_builder(*builder, "`it: int;\n");
for i: a..b {
print_to_builder(*builder, "it = %;\n", i);
print_to_builder(*builder, "#insert body;\n");
}
print_to_builder(*builder, "}\n");
return builder_to_string(*builder);
}
}
unroll_for_loop(0, 10, #code {
print("%\n", it);
});
#insert_internal
directive
#insert_internal
directive functions exactly like #insert
, except it also allows code to access variables in the local scope. Here is an example that uses #insert_internal
to insert a comparison code into a bubble sort. The inserted code acts like a comparison function, except without the drawbacks of function pointer callback performance cost.
arr: [10] int;
for i: 0..9
arr[i] = random_get() % 100;
bubble_sort(arr, #code (a < b));
print("%\n", arr);
bubble_sort :: (arr: [] $T, compare_code: Code) #expand {
while true {
TF := true;
for i: 1..arr.count-1 {
a := arr[i-1];
b := arr[i];
if !(#insert_internal compare_code) {
t := arr[i];
arr[i] = arr[i-1];
arr[i-1] = t;
TF = false;
}
}
if TF break;
}
}