import "@std/mem" import "@std/arraylist" import "@std/enummap" SourceId :: distinct usize #! borrows a source path and text owned by the compilation or caller. Source :: struct { path []u8 text []u8 } Span :: struct { start u32 end u32 source SourceId = SourceId(0) } DiagnosticId :: distinct u32 no_diagnostic :: maxval!(DiagnosticId) Code :: enum { invalid_character float_must_end_with_digit unterminated_string unexpected_token duplicate_name unknown_name expected_type type_not_value invalid_void_type type_mismatch invalid_operand integer_division not_callable argument_count_mismatch cannot_infer_type missing_return return_type_mismatch condition_not_bool invalid_assignment_target break_outside_loop continue_outside_loop invalid_range_bound invalid_for_iterable range_value_not_supported range_pointer_capture range_index_capture invalid_array_length array_length_mismatch invalid_array_element_type array_size_overflow invalid_index_type not_indexable invalid_index_assignment index_out_of_bounds unknown_field duplicate_field missing_field tuple_arity_mismatch not_record recursive_record invalid_record_field_type missing_entry invalid_entry literal_out_of_range inexact_integer_literal invalid_escape read_before_initialization write_before_initialization initialization_cycle integer_overflow import_cycle invalid_import_path package_unavailable namespace_not_value not_namespace invalid_import_alias invalid_enum_backing invalid_enum_value enum_context_required invalid_distinct_backing invalid_union_tag union_initializer_count invalid_match_subject invalid_match_pattern duplicate_match_pattern non_exhaustive_match unreachable_match_arm invalid_match_capture inactive_union_field invalid_pointer_type invalid_address_operand invalid_dereference invalid_pointer_assignment invalid_pointer_access null_unwrap invalid_slice_bounds sentinel_mismatch overlapping_memory_copy unsupported_foreign_call invalid_fallible_type invalid_sum_type invalid_fallible_operand try_outside_fallible incompatible_propagated_error catch_type_mismatch errdefer_outside_fallible cleanup_control_flow comptime_argument_required cannot_infer_generic specialization_cycle specialization_limit comptime_execution_limit } Diagnostic :: struct { code Code span Span } #! owns diagnostic storage and retains its allocator; release with deinit. Store :: struct { list arraylist.ArrayList(Diagnostic) } CapacityError :: enum { diagnostic_limit_reached, storage_limit_reached } #! retains `allocator` for added diagnostics; the caller owns the returned Store. init proc(allocator mem.Allocator) Store { return Store{ list = arraylist.init(allocator) } } #! releases diagnostic storage with the retained allocator. deinit proc(store @mut Store) void { arraylist.deinit(&store.list) } #! allocates from the retained allocator; the returned ID is valid until deinit. add proc(store @mut Store, code Code, span Span) DiagnosticId ! (mem.AllocError | CapacityError) { if (store.list.items.len >= usize(no_diagnostic)) return .diagnostic_limit_reached id :: DiagnosticId(store.list.items.len) try arraylist.append(&store.list, Diagnostic{ code = code, span = span }) return id } get proc(store @Store, id DiagnosticId) ?Diagnostic { if (usize(id) >= store.list.items.len) return null return store.list.items[usize(id)] } count proc(store @Store) usize { return store.list.items.len } #! constructed at compile time so missing entries fail compilation; message bytes live for the process lifetime. messages :: $enummap.init(Code, []u8, { invalid_character = "invalid character", float_must_end_with_digit = "float literal must end with a digit", unterminated_string = "unterminated string literal", unexpected_token = "unexpected token", duplicate_name = "duplicate name or forbidden shadowing", unknown_name = "unknown name", expected_type = "annotation must name a type", type_not_value = "type name cannot be used as a value", invalid_void_type = "void cannot be stored or used as a parameter type", type_mismatch = "incompatible value type", invalid_operand = "operator requires compatible operand types", integer_division = "division requires float operands", not_callable = "value is not callable", argument_count_mismatch = "argument count does not match the function signature", cannot_infer_type = "cannot infer a type without a type anchor", missing_return = "nonvoid function can finish without returning a value", return_type_mismatch = "return does not match the function result type", condition_not_bool = "condition must have type bool", invalid_assignment_target = "assignment requires a mutable local binding", break_outside_loop = "break requires an enclosing loop", continue_outside_loop = "continue requires an enclosing loop", invalid_range_bound = "range bounds must have compatible integer types", invalid_for_iterable = "for-loop iteration currently requires a direct integer range", range_value_not_supported = "first-class range values are not implemented", range_pointer_capture = "range loops do not support pointer captures", range_index_capture = "range loops do not support index captures", invalid_array_length = "array length must be a nonnegative supported compile-time integer", array_length_mismatch = "array literal length does not match its type", invalid_array_element_type = "array element annotations require a supported concrete value type", array_size_overflow = "array storage size exceeds the supported address space", invalid_index_type = "array index must have type usize", not_indexable = "indexing is currently implemented for fixed arrays only", invalid_index_assignment = "indexed assignment requires a writable array element", index_out_of_bounds = "index out of bounds", unknown_field = "record has no such field", duplicate_field = "record field is specified more than once", missing_field = "record initializer is missing a required field", tuple_arity_mismatch = "tuple initializer arity does not match its type", not_record = "field selection requires a record or tuple", recursive_record = "record has a recursive by-value layout", invalid_record_field_type = "record fields require a concrete value type", missing_entry = "program requires a main function", invalid_entry = "main must be a function with no parameters", literal_out_of_range = "numeric literal is outside its runtime type's range", inexact_integer_literal = "integer literal is not exactly representable as float; use a floating literal to allow rounding", invalid_escape = "invalid string escape", read_before_initialization = "local value was read before initialization", write_before_initialization = "local value was assigned before initialization", initialization_cycle = "global initialization cycle", integer_overflow = "integer arithmetic overflow", import_cycle = "package import cycle", invalid_import_path = "invalid import path", package_unavailable = "cannot load package directory", namespace_not_value = "package namespace cannot be used as a value", not_namespace = "member selection requires a package namespace", invalid_import_alias = "import requires an explicit valid identifier alias", invalid_enum_backing = "enum backing must be a concrete integer type", invalid_enum_value = "enum values require explicit backing and increasing representable constant integers", enum_context_required = "enum literal requires an enum or tagged union context", invalid_distinct_backing = "distinct requires a concrete runtime backing type", invalid_union_tag = "union tag must be an enum containing every union variant", union_initializer_count = "union construction requires exactly one member", invalid_match_subject = "match subject must be an enum, tagged union, or scalar", invalid_match_pattern = "invalid match pattern", duplicate_match_pattern = "duplicate or overlapping match pattern", non_exhaustive_match = "match is not exhaustive", unreachable_match_arm = "match arm is unreachable", invalid_match_capture = "payload capture requires compatible nonvoid tagged union variants", inactive_union_field = "tagged union field is not active", invalid_pointer_type = "pointer requires a supported concrete pointee type", invalid_address_operand = "address-of requires addressable storage", invalid_dereference = "dereference requires a pointer", invalid_pointer_assignment = "pointer assignment requires a mutable pointee", invalid_pointer_access = "pointer does not refer to live accessible storage", null_unwrap = "cannot unwrap a null optional", invalid_slice_bounds = "slice bounds are invalid", sentinel_mismatch = "slice sentinel does not match the expected value", overlapping_memory_copy = "memory copy source and destination overlap", unsupported_foreign_call = "foreign function calls are unsupported by the interpreter", invalid_fallible_type = "fallible type requires a concrete success type and an enum, struct, or tagged union error channel", invalid_sum_type = "sum composition requires compatible named enum, struct, or tagged union variants", invalid_fallible_operand = "try and catch require a fallible operand", try_outside_fallible = "try requires an enclosing fallible function", incompatible_propagated_error = "propagated errors are not a subset of the function error channel", catch_type_mismatch = "catch handler must produce the success type or terminate", errdefer_outside_fallible = "errdefer requires an enclosing fallible function", cleanup_control_flow = "cleanup cannot escape with return, break, continue, or try", comptime_argument_required = "generic argument must be a compile-time value", cannot_infer_generic = "cannot infer consistent compile-time arguments from runtime arguments", specialization_cycle = "compile-time specialization depends on its unfinished result", specialization_limit = "compile-time specialization exceeds its recursion or instance limit", comptime_execution_limit = "compile-time execution exceeds its recursion or step limit", })