#init

#init allows you to define procedures that run before the main in your program. This allows you to do simple set ups and initialization before main is reached.

#init must be followed by a compile-time known procedure with the type signature, () -> void.

#init () {
	println("In #init procedure!");
}

main :: () {
	println("In main!");
}

// Output:
// In #init procedure!
// In main!

You are guaranteed that the runtime has been fully initialized before any #init procedure is invoked. This way, you know that printing and heap allocations will work from #init procedures.

Ordering with #after

The order of #init procedure is undefined and unstable if you change your program. However, by using the #after directive, you can specify a dependency of an #init procedure that is guaranteed to be executed before the procedure in question.

global_map: Map(str, i32);

// Bind the #init statement to a symbol.
prepare_map :: #init () {
	global_map = make(Map(str, i32));
}

populate_map :: #init #after prepare_map () {
	global_map->put("A", 1);
	global_map->put("B", 2);
	global_map->put("C", 3);
}

In this example, prepare_map is guaranteed to be run before populate_map because of the #after directive on populate_map.

You can specify as many #after directives as you want on a single #init procedure.

#init
	#after A
	#after B
	#after C
() {
	// ...
}

In this example, the #init procedures A, B and C will be run before this #init procedure.