Modules

Compiler

moduleSource

Available on macOS, Linux, Windows, Wasm

#import "Compiler";

The metaprogramming API: create and drive builds ("workspaces") from compile-time code, read and edit the program as syntax trees, and listen to what the compiler does.

Example↗
#run {
    w := compiler_create_workspace("demo");
    options := get_build_options(w);
    options.output_type = .NO_OUTPUT;
    set_build_options(options, w);
    add_build_string("value :: 47; main :: () {}", w);

    compiler_begin_intercept(w);
    while true {
        message := compiler_wait_for_message();
        if message.kind == .COMPLETE break;
    }
    compiler_end_intercept(w);
}

main :: () {}

Procedures#

Helpers#

(build_options: *C.Build_Options, type: C.Optimization_Type, preserve_debug_info := true)

Sets the options that go with an optimization level: bounds and cast checks, the LLVM optimization settings, inlining and so on. preserve_debug_info keeps or drops debug information.

options: Build_Options;
set_optimization(*options, .OPTIMIZED);
assert(options.array_bounds_check == .OFF);
set_optimization(*options, .DEBUG);
assert(options.array_bounds_check == .ON);
↗
(input_name: string) -> (basename: string, path: string)

Splits a file path into its name without the extension and its folder (with the trailing slash).

name, folder := get_basename_and_path("src/lib/parser.jai");
assert(name == "parser" && folder == "src/lib/");
↗
(info: *Type_Info, base_name: string, first_call := true) -> bool

True if the struct info is, or starts with a #as using member that is, a struct called base_name.

Workspace#

(w: Workspace = -1) -> string

Returns the name of workspace w; the default is the workspace running the code.

(filename: string, w: Workspace, loc := #caller_location)

Adds the source file filename to workspace w, as if it were passed on the command line.

#import "File";

#run {
    path := tprint("%/extra.jai", #filepath);
    write_entire_file(path, "extra :: 1;");
    w := compiler_create_workspace("from file");
    options := get_build_options(w);
    options.output_type = .NO_OUTPUT;
    set_build_options(options, w);
    add_build_file(path, w);
}

main :: () {}

Doesn't run in the browser (skipped on wasm).

(data: string, w: Workspace, code := #code,null, loc := #caller_location)
(data: string, w: Workspace, message: *Message, loc := #caller_location)

Adds the source text data to workspace w. Pass code to compile it in the scope that code was written in, so it can see that scope's names.

#run {
    w := compiler_create_workspace("strings");
    options := get_build_options(w);
    options.output_type = .NO_OUTPUT;
    set_build_options(options, w);
    add_build_string("answer :: 42; main :: () {}", w);
}

main :: () {}
↗
(message: string, loc := #caller_location, mode := Report.ERROR)
(filename: string, line_number: s64, character_number: s64, error_text: string, mode := Report.ERROR)

Reports a problem at loc (by default the call site). The default mode, .ERROR, fails the build once the current step ends; .WARNING and .INFO only print.

#run compiler_report("heads up", mode = .INFO);

main :: () {}
↗
() -> [] string

Returns the arguments of the command line the compiler was started with, so a build script can read its own options.

(w: Workspace, host_module_name: string, import_name: string, replacement_name: string)

Makes #import "import_name" inside host_module_name load replacement_name instead. Use it from a message handler to swap in another version of a module.

(node: *Code_Node, code_to_copy_scope_from: Code = #code,null) -> Code

Turns the node node back into a Code value you can insert with #insert. code_to_copy_scope_from says which scope the new code is read in.

(ti: *Type_Info) -> Type

Returns the Type that goes with a Type_Info pointer.

(w: Workspace = -1) -> [] *Type_Info

Returns the Type_Info of every type in workspace w.

() -> *Message

Blocks until the compiler has a message for an intercepted workspace, and returns it. Check kind and cast to the matching Message_* type. The last message of a build is .COMPLETE.

#run {
    w := compiler_create_workspace("messages");
    options := get_build_options(w);
    options.output_type = .NO_OUTPUT;
    set_build_options(options, w);
    add_build_string("main :: () {}", w);

    compiler_begin_intercept(w);
    files := 0;
    while true {
        message := compiler_wait_for_message();
        if message.kind == .FILE files += 1;
        if message.kind == .COMPLETE break;
    }
    compiler_end_intercept(w);
    assert(files > 0);
}

main :: () {}
↗
(section_name: string, characteristics := Data_Segment_Characteristics.READ | .WRITE, alignment: s32 = 16, w: Workspace = -1) -> (segment: *Data_Segment, actual_segment_will_be_created: bool)

Asks for a named data segment in the program being built. Returns it and whether the compiler will really create it on this target.

(w: Workspace = -1) -> Runtime_Info

Returns the type table and the global data layout of workspace w. Used by tools that read a program's memory.

Types#

:: enum_flags

What a custom data segment allows: reading, writing, executing, and whether it starts zeroed.

READ
WRITE
EXECUTE
ZEROED
:: enum

Which segment add_global_data puts data in: one of the built-in ones, or USER_SEGMENT for one you added.

WRITABLE
WRITABLE_NO_RESET
READ_ONLY
BSS
USER_SEGMENT
:: struct

One segment of the global data: what kind it is (zeroed, writable, read-only, ...) and its bytes.

segment_tag: enum u16 { BSS :: 0; DATA :: 1; RDATA :: 2; NO_RESET :: 3; USER :: 5; }
data: [] u8
:: struct

Every setting of a build: what to produce (output_type), where to write it, the checks to compile in, the optimizer and the backend. Get a copy with get_build_options, change it, and apply it with set_build_options. set_optimization fills in the fields that go with an optimization level.

output_type: := Output_Type.EXECUTABLE
Commonly_Propagated: struct { write_added_strings := true; runtime_storageless_type_info := false; shorten_filenames_in_error_messages := false; use_visual_studio_message_format := false; use_natvis_compatible_types := false; minimum_os_version: Os_Version; lazy_foreign_function_lookups := false; disable_redzone := false; enable_bytecode_inliner := true; enable_bytecode_deduplication := true; stack_trace := true; use_ansi_color := true; interactive_bytecode_debugger := false; debug_for_expansions := false; enable_frame_pointers := true; runtime_support_definitions: enum u8 { AUTO; ENTRY_POINT_AND_INIT; ONLY_INIT; OMIT; } = .AUTO; backtrace_on_crash: enum u8 { OFF; ON; } = .ON; array_bounds_check: enum u8 { OFF; ON; ALWAYS; } = .ON; cast_bounds_check: enum u8 { OFF; NONFATAL; FATAL; } = .FATAL; null_pointer_check: enum u8 { OFF; ON; } = .ON; arithmetic_overflow_check: enum u8 { OFF; NONFATAL; FATAL; } = .OFF; dead_code_elimination: enum u8 { NONE; ALL; MODULES_ONLY; } = .MODULES_ONLY; max_bytecode_instructions_for_inlined_initializer: s32 = 8; context_size_max: s32 = 4096; prevent_compile_time_calls_from_runtime := false; info_flags: enum_flags u32 { POLYMORPH_MATCH :: 0x1; POLYMORPH_DEDUPLICATE :: 0x2; } text_output_flags: enum_flags u32 { OUTPUT_LINK_LINE :: 0x1; OUTPUT_TIMING_INFO :: 0x2; } = xx 3; os_target := OS; cpu_target := CPU; backend: enum u32 { X64; LLVM; } = .LLVM; machine_options: [MACHINE_OPTIONS_SIZE] u8; emit_debug_info: enum u32 { NONE :: 0; DWARF :: 1; CODEVIEW :: 2; DEFAULT :: 3; } = .DEFAULT; maximum_polymorph_depth := 100; maximum_array_count_before_compile_time_returns_are_not_reflected_in_ast := 5000; x64_options: X64_Options; llvm_options: Llvm_Options; }
output_executable_name: string
output_path: string
intermediate_path: string
entry_point_name: string
compile_time_command_line: [] string
append_executable_filename_extension: := true
use_custom_link_command: := false
temporary_storage_size: s32
import_path: [] string
additional_linker_arguments: [] string
user_data_u64: u64
user_data_string: string
user_data_pointer: *void
user_data_pointer_size: s32
options: Build_Options;
assert(options.output_type == .EXECUTABLE);
options.output_type = .NO_OUTPUT;
options.array_bounds_check = .OFF;
↗
:: struct

The build options that can still change while a build is running. Apply them with set_build_options_dc.

do_output: := true
write_added_strings: := true
append_executable_filename_extension: := true
interactive_bytecode_debugger: := false
append_linker_arguments: [] string
output_executable_name: string
output_path: string
:: struct

Settings for the LLVM backend: optimization levels, inlining, vectorization, and what intermediate output to keep.

bitcode_optimization_setting: Llvm_Bitcode_Optimization_Setting
machine_code_optimization_setting: Llvm_Machine_Code_Optimization_Setting
function_sections: bool
enable_tail_calls: := false
enable_loop_unrolling: := false
enable_slp_vectorization: := false
enable_loop_vectorization: := false
preserve_debug_info: := true
merge_functions: := false
disable_inlining: := true
disable_mem2reg: := false
enable_split_modules: := true
output_bitcode_before_optimizations: := false
output_llvm_ir_before_optimizations: := false
output_bitcode: := false
output_llvm_ir: := false
target_system_triple: string
target_system_cpu: string
target_system_features: string
command_line: [] string
:: enum

An optimization preset for set_optimization, from DEBUG to VERY_OPTIMIZED, plus two that favor size.

DEBUG
VERY_DEBUG
OPTIMIZED
VERY_OPTIMIZED
OPTIMIZED_SMALL
OPTIMIZED_VERY_SMALL
:: struct

Settings for the built-in x64 backend.

use_dlls: := false
enable_register_allocation: := false
enable_unix_runtime_frame_information: := true
:: enum_flags

Which kinds of typechecked code compiler_begin_intercept should leave out of its messages, and which performance reports to send.

SKIP_EXPRESSIONS_WITHOUT_NOTES
SKIP_DECLARATIONS
SKIP_PROCEDURE_HEADERS
SKIP_PROCEDURE_BODIES
SKIP_STRUCTS
SKIP_OTHERS
SKIP_ALL
DO_PERFORMANCE_REPORT_POLYMORPHS
DO_PERFORMANCE_REPORT_RUNS
:: struct

The start of every compiler message. kind says which Message_* type it really is; cast to that type to read the rest. workspace is the build it belongs to.

kind: enum u8 { UNINITIALIZED :: 0; FILE; IMPORT; FAILED_IMPORT; PHASE; TYPECHECKED; COMPLETE; DEBUG_DUMP; ERROR; PERFORMANCE_REPORT; }
workspace: Workspace
:: struct

The last message of a build. error_code says whether it worked.

error_code: enum u8 { NONE :: 0; COMPILATION_FAILED :: 1; COMPILER_SHUTDOWN :: 2; }
:: struct

A source file was loaded, with its full path and the import it belongs to.

fully_pathed_filename: string
enclosing_import: *Message_Import
from_a_string: bool
:: struct

A module was imported, with its name, path and kind.

module_type: enum u8 { UNINITIALIZED :: 0; PRELOAD :: 1; RUNTIME_SUPPORT :: 2; MAIN_PROGRAM :: 3; FILE :: 4; }
module_name: string
fully_pathed_filename: string
:: struct

The build reached a stage, such as all source being parsed or the executable being written.

phase: enum u32 { ALL_SOURCE_CODE_PARSED :: 0; TYPECHECKED_ALL_WE_CAN :: 1; ALL_TARGET_CODE_BUILT :: 2; PRE_WRITE_EXECUTABLE :: 3; POST_WRITE_EXECUTABLE :: 4; READY_FOR_CUSTOM_LINK_COMMAND :: 5; }
executable_name: string
executable_write_failed: := false
linker_exit_code: s32
num_items_waiting_to_typecheck: s32
compiler_generated_object_files: [] string
support_object_files: [] string
system_libraries: [] string
user_libraries: [] string
:: enum

How serious a compiler_report is. ERROR fails the build; the others only print.

ERROR
ERROR_CONTINUABLE
WARNING
INFO
:: struct

A { ... } block: its statements and the declarations it makes.

base: Code_Node
parent: *Code_Block
block_type: enum s32 { UNINITIALIZED :: 0; IMPERATIVE :: 1; DATA_DECLARATIONS :: 2; ARGUMENTS :: 3; RETURNS :: 4; STRUCT_ARGUMENTS :: 5; CONSTANTS :: 6; }
block_flags: enum u32 { NO_ARRAY_BOUNDS_CHECK :: 0x1; NO_ARITHMETIC_OVERFLOW_CHECK :: 0x2; }
belongs_to_struct: *Code_Struct
members: [] *Code_Scope_Entry
statements: [] *Code_Node
owning_statement: *Code_Node
:: struct

A cast, explicit or inserted by the compiler, with the type it converts to.

base: Code_Node
expression: *Code_Node
cast_flags: enum_flags u32 { IS_IMPLICIT :: 0x1; IS_POINTER_DEREFERENCE :: 0x2; IS_AUTO :: 0x4; NO_BOUNDS_CHECK :: 0x8; TRUNCATE :: 0x10; AS :: 0x20; ISA :: 0x40; FORCE :: 0x80; VERY_FORCE :: 0x100; HAS_FUNCTION_SYNTAX :: 0x800; HAS_POSTFIX_SYNTAX :: 0x1000; }
:: struct

A declaration: a variable, constant, parameter or procedure name, with its type, value, notes and flags.

expression: *Code_Node
flags: enum_flags u32 { IS_CONSTANT :: 0x1; IS_MARKED_AS_AS :: 0x2; IS_MARKED_AS_DISCARD :: 0x4; IS_ITERATOR :: 0x10; NO_RESET :: 0x40; IS_UNINITIALIZED :: 0x80; COMES_FROM_ASM :: 0x100; IS_IMPORTED :: 0x200; AUTO_VALUE_BAKE :: 0x4000; AUTO_VALUE_BAKE_IS_REQUIRED :: 0x8000; IS_OVERLAY :: 0x1_0000; PROGRAM_EXPORT :: 0x2_0000; ELSEWHERE :: 0x4_0000; SCOPE_FILE :: 0x8_0000; IS_GLOBAL :: 0x10_0000; HAS_SCOPE_MODIFIER :: 0x20_0000; }
alignment_expression: *Code_Node
notes: [] *Code_Note
program_export_name: string
:: struct

A #code expression, whose body becomes a Code value.

base: Code_Node
expression: *Code_Node
code_flags: enum u32 { IMPLICITLY_GENERATED :: 0x1; NULL :: 0x2; TYPED :: 0x8; }
:: struct

A #library directive naming a native library.

base: Code_Node
name: string
library_flags: enum u32 { IS_SYSTEM_LIBRARY :: 0x1; DYNAMIC_LIBRARY_UNAVAILABLE :: 0x2; STATIC_LIBRARY_UNAVAILABLE :: 0x4; LINK_ALWAYS :: 0x8; }
:: struct

A #load directive: the file it names and its resolved path.

base: Code_Node
short_name: string
fully_pathed_filename: string
loaded_string: string
load_flags: s32
:: struct

A #run directive and the procedure it runs.

base: Code_Node
flags: enum u32 { ASSERTION :: 0x1; STALLABLE :: 0x2; SYNTACTICALLY_IMPLICIT :: 0x4; HAS_IMPLICIT_RETURN_TYPES :: 0x8; }
assertion_string: string
:: struct

A #scope_export, #scope_file or #scope_module directive.

base: Code_Node
scope_type: enum u32 { EXPORT :: 0; FILE :: 1; INTERNAL :: 2; }
:: struct

An enum definition: its members, notes and whether it is a flags or complete enum.

base: Code_Node
internal_type_inst: *Code_Type_Instantiation
internal_type: *Type_Info
external_type: *Type_Info_Enum
block: *Code_Block
notes: [] *Code_Note
marked_as_complete: := false
marked_as_specified: := false
is_flags: := false
:: struct

A type_of, is_constant or #code_of query about an expression.

base: Code_Node
query_kind: enum u32 { TYPE_OF :: 0; IS_CONSTANT :: 1; CODE_OF :: 2; }
expression_to_query: *Code_Node
:: struct

A for loop: what it iterates, its body and its it and it_index names.

base: Code_Node
iteration_expression: *Code_Node
iteration_expression_right: *Code_Node
block: *Code_Block
ident_it: *Code_Ident
ident_it_index: *Code_Ident
ident_decl: *Code_Declaration
index_decl: *Code_Declaration
want_replacement_for_expansion: *Code_Node
want_pointer_expression: *Code_Node
want_reverse_expression: *Code_Node
macro_expansion_procedure_call: *Code_Procedure_Call
for_flags: For_Flags
:: struct

A name, and the declaration it resolved to.

base: Code_Node
name: string
resolved_declaration: *Code_Declaration
flags: enum_flags u32 { DEFINES_POLYMORPH_VARIABLE :: 0x01; IS_RHS_OF_DOT_DEREFERENCE :: 0x02; RESOLVES_ONLY_SHALLOWLY :: 0x04; GENERATED_BY_OPERATOR_OVERLOAD :: 0x08; DO_NOT_RESOLVE_DUE_TO_PARSER :: 0x10; CAN_RESOLVE_TO_REG :: 0x20; HAS_SCOPE_MODIFIER :: 0x40; }
:: struct

An if or ifx, including a #if and an if == switch.

base: Code_Node
condition: *Code_Node
then_block: *Code_Block
else_block: *Code_Block
if_flags: enum_flags u16 { IS_SWITCH_STATEMENT :: 0x1; IS_IFX :: 0x2; IS_STATIC :: 0x4; MARKED_AS_COMPLETE :: 0x8; }
static_if_flags: enum_flags u16 { EVALUATED_AS_TRUE :: 0x1; }
static_if_accepted_case: *Code_Case
:: struct

A literal: a number, string, boolean, array, struct, pointer or type. value_type says which, and the matching union member holds the value.

base: Code_Node
value_type: enum s16 { UNINITIALIZED :: 0; NUMBER :: 1; STRING :: 2; BOOLEAN :: 3; ARRAY :: 6; STRUCT :: 7; POINTER :: 8; TYPE_INFO :: 9; }
values: union { _string: string; _float64: float64; _s64: s64; _u64: u64; struct_literal_info: *Code_Struct_Literal_Info; array_literal_info: *Code_Array_Literal_Info; pointer_literal_info: *Code_Pointer_Literal_Info; type_info_literal_defn: *Code_Type_Definition; }
value_flags: enum_flags u32 { IS_A_NUMBER :: 0x1; HEX :: 0x2; FLOAT :: 0x4; BINARY :: 0x20; MINUS_SIGN :: 0x40; HERE_STRING :: 0x80; DEFAULTS_TO_FLOAT64 :: 0x100; REQUIRES_FLOAT64 :: 0x200; }
:: struct

The list of extra arguments a call passes to a variadic procedure.

base: Code_Node
element_type: *Type_Info
expressions: [] *Code_Node
is_for_non_native_calling_convention: bool
:: struct

The part every syntax node shares: its kind, where it is in the source, its type once checked and flags. Cast a node to the Code_* type that matches its kind to read the rest.

location: Location
kind: := Kind.UNINITIALIZED
node_flags: enum u32 { EXPRESSION_IS_SPREAD :: 0x1; NO_ARRAY_BOUNDS_CHECK :: 0x2; ALLOWED_BY_CONTEXT :: 0x4; STATEMENT_IS_DEFERRED :: 0x8; IS_PARENTHESIZED :: 0x10; CREATED_BY_DESUGARING :: 0x100; EXPRESSION_IS_DEPRECATED :: 0x8000_0000 }
type: *Type_Info
serial: s64
:: struct

A @note attached to a declaration, procedure or struct.

base: Code_Node
text: string
note_flags: u32
:: struct

The details of a pointer constant: the symbol or literal it points into, and an offset.

data_pointer: *u8
pointer_literal_type: enum u8 { GLOBAL_SYMBOL :: 0; STRING_OR_ARRAY_LITERAL_DATA_POINTER :: 1; CONSTANT_VALUE :: 2; }
offset_from_symbol: s64
:: struct

A procedure's declaration: name, parameters, return values, notes and flags such as MACRO or POLYMORPHIC.

base: Code_Node
constants_block: *Code_Block
arguments: [] *Code_Declaration
returns: [] *Code_Declaration
parameter_usings: [] *Code_Using
name: string
foreign_function_name: string
library_identifier: *Code_Ident
deprecation_string: string
polymorph_source_header: *Code_Procedure_Header
modify_directives: [] *Code_Directive_Modify
body_or_null: *Code_Procedure_Body
procedure_flags: enum_flags u32 { ELSEWHERE :: 0x1; COMPILE_TIME_ONLY :: 0x2; POLYMORPHIC :: 0x4; COMPILER_GENERATED :: 0x8; DEBUG_DUMP :: 0x10; C_CALL :: 0x20; TYPE_ONLY :: 0x40; INTRINSIC :: 0x80; DEPRECATED :: 0x100; SYNTACTICALLY_MARKED_AS_NO_CONTEXT :: 0x200; QUICK :: 0x400; QUICK_IN_BLOCK_FORM :: 0x800; CPP_METHOD :: 0x1000; NO_CALL :: 0x2000; MACRO :: 0x4000; NO_DEBUG :: 0x8000; ENTRY_POINT :: 0x1_0000; HAS_IMPLICIT_RETURN_VALUE :: 0x2_0000; SYMMETRIC :: 0x4_0000; CPP_RETURN_TYPE_IS_NON_POD :: 0x8_0000; ENTRY_POINT_HOOK :: 0x10_0000; SYNTACTICALLY_MARKED_AS_COMPILE_TIME :: 0x20_0000; SYNTACTICALLY_MARKED_AS_COMPILER :: 0x40_0000; SYNTACTICALLY_MARKED_AS_INLINE_YES :: 0x100_0000; SYNTACTICALLY_MARKED_AS_INLINE_NO :: 0x200_0000; INITIALIZER :: 0x400_0000; }
notes: [] *Code_Note
:: struct

A type as written in source, such as *[] int, and the Type_Info it resolved to.

base: Code_Node
result: *Type_Info
type_valued_expression: *Code_Node
must_implement: *Code_Node
type_directive_target: *Code_Type_Instantiation
array_element_type: *Code_Type_Instantiation
array_dimension: *Code_Node
inst_flags: enum_flags u32 { VARARGS :: 0x1; RESIZABLE :: 0x2; TYPE_OF_PROCEDURE :: 0x4; TYPE_DIRECTIVE :: 0x8; TYPE_DIRECTIVE_DISTINCT :: 0x10; TYPE_DIRECTIVE_ISA :: 0x20; ARRAY_VIEW :: 0x40; INTERFACE :: 0x80; }
:: struct

A using statement or parameter.

base: Code_Node
expression: *Code_Node
filter_type: enum u8 { NONE :: 0; ONLY :: 1; EXCEPT :: 2; MAP :: 3; }
filter_expression: *Code_Node
no_parameters: := false
:: enum

An operator that has no single-character name. Single-character operators use their character, as in cast(Operator_Type) #char "+".

IS_EQUAL
IS_NOT_EQUAL
LOGICAL_AND
LOGICAL_OR
LESS_OR_EQUAL
GREATER_OR_EQUAL
SHIFT_LEFT
SHIFT_RIGHT
ROTATE_LEFT
ROTATE_RIGHT
PLUS_ASSIGN
MINUS_ASSIGN
TIMES_ASSIGN
DIV_ASSIGN
MOD_ASSIGN
SHIFT_LEFT_ASSIGN
SHIFT_RIGHT_ASSIGN
ROTATE_LEFT_ASSIGN
ROTATE_RIGHT_ASSIGN
BITWISE_AND_ASSIGN
BITWISE_OR_ASSIGN
BITWISE_XOR_ASSIGN
LOGICAL_AND_ASSIGN
LOGICAL_OR_ASSIGN
POINTER_DEREFERENCE
POSTFIX_DEREFERENCE
ARRAY_SUBSCRIPT
:: struct

How many calls and instructions the compile-time interpreter ran, and how many were inlined.

num_calls_inlined: s64
num_calls_total: s64
num_instructions_inlined: s64
num_instructions_total: s64
:: struct

A plugin for a metaprogram. Fill in the procedures you care about and the compiler calls them: init once, message for every compiler message, finish at the end. workspace is the build it works on.

workspace: Workspace
init: (p: *Metaprogram_Plugin, options: [] string) -> bool
before_intercept: (p: *Metaprogram_Plugin, flags: *Intercept_Flags)
add_source: (p: *Metaprogram_Plugin)
message: (p: *Metaprogram_Plugin, message: *Message)
finish: (p: *Metaprogram_Plugin)
shutdown: (p: *Metaprogram_Plugin)
log_help: (p: *Metaprogram_Plugin)
communication_proc: (p: *Metaprogram_Plugin, key: string, value: string) -> bool
plugin: Metaprogram_Plugin;
plugin.message = (p: *Metaprogram_Plugin, message: *Message) {};
assert(plugin.init == null);
↗
:: struct

Counts of the polymorphic procedures the compiler instantiated, and from where.

num_solves_invoked: s64
num_solves_used: s64
reported: := false
records: [] Record
:: struct

How long the compile-time interpreter spent running code, inlining and generating bytecode.

run_directives: float64
bytecode_inlining: float64
bytecode_generating: float64

Constants#