#insert directive

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;
  }
}
1 Like