Notes are a way to tag a struct
, function
, or struct member
. Notes are represented as strings. This tag will show up in a metaprogram. In the metaprogram, you can use the note to do special metaprogramming such custom program typechecking and modifying the executable based on the metaprogram. Notes in Jai are represented as strings
, and unlike Java or C#, are not structured (but structured notes may be added in the future).
Here is a simple metaprogram that finds all the functions tagged @note
and creates a main
function that calls all functions tagged @note
in alphabetical order.
Metaprogram build.jai
:
#run {
w := compiler_create_workspace();
options := get_build_options(w);
options.output_executable_name = "exe";
set_build_options(options, w);
compiler_begin_intercept(w);
add_build_file("main.jai", w);
// find all functions tagged @note, sort all functions alphabetically,
// and call all functions in alphabetical order from a generated "main"
functions: [..] string;
gen_code := false;
while true {
message := compiler_wait_for_message();
if !message break;
if message.kind == {
case .TYPECHECKED;
typechecked := cast(*Message_Typechecked) message;
for decl: typechecked.declarations {
if equal(decl.expression.name , "main") {
continue;
}
for note: decl.expression.notes {
if equal(note.text, "note") {
array_add(*functions, copy_string(decl.expression.name));
}
}
}
case .PHASE;
phase := cast(*Message_Phase) message;
if gen_code == false && phase.phase == .TYPECHECKED_ALL_WE_CAN {
code := generate_code();
add_build_string(code, w);
gen_code = true;
}
case .COMPLETE;
break;
}
}
compiler_end_intercept(w);
set_build_options_dc(.{do_output=false});
generate_code :: () -> string #expand {
bubble_sort(functions, compare);
builder: String_Builder;
append(*builder, "main :: () {\n");
for func: functions {
print_to_builder(*builder, " %1();\n", func);
}
append(*builder, "}\n");
return builder_to_string(*builder);
}
}
#import "Compiler";
#import "String";
#import "Basic";
#import "Sort";
The main program main.jai
:
apple :: () {
print("apple\n");
} @note
bannana :: () {
print("bannana\n");
} @note
cherry :: () {
print("cherry\n");
} @note
dog :: () {
print("dog\n");
} @note
elephant :: () {
print("elephant\n");
} @note
#import "Basic";
// create the main() function using the metaprogram.
When you hit jai build.jai
followed by running the executable, you should get the following output:
apple
bannana
cherry
dog
elephant