error handling kickoff

This commit is contained in:
2026-06-29 22:55:56 +02:00
parent 98c303d22c
commit ae5af37b85
14 changed files with 1229 additions and 173 deletions
+102 -2
View File
@@ -366,6 +366,105 @@ lower_compound_expr :: proc(state: ^State, expr_id: hir.Expr_Id) -> ir.Instructi
target=ir.INVALID_REF, a=begin, b=fallback,
diagnostic=source.INVALID_DIAGNOSTIC,
})
case .Try, .Catch:
channel := lower_nested_expr(state, expr.left)
channel_type := state.hir_module.exprs[expr.left].type
success := types.fallible_success(channel_type, &state.hir_module.types)
channel_slot := append_instruction(state, ir.Instruction{
op=.Alloca, span=expr.span, type=channel_type,
target=ir.INVALID_REF, a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
diagnostic=source.INVALID_DIAGNOSTIC,
})
append_instruction(state, ir.Instruction{
op=.Store, span=expr.span, type=channel_type,
target=ir.INVALID_REF, a=channel_slot, b=channel, diagnostic=source.INVALID_DIAGNOSTIC,
})
code := append_instruction(state, ir.Instruction{
op=.Union_Tag, span=expr.span, type=types.U16,
target=ir.INVALID_REF, a=channel_slot, b=ir.INVALID_INSTRUCTION,
diagnostic=source.INVALID_DIAGNOSTIC,
})
zero := append_instruction(state, ir.Instruction{
op=.Const, span=expr.span, type=types.U16, integer=0,
target=ir.INVALID_REF, a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
diagnostic=source.INVALID_DIAGNOSTIC,
})
ok := append_instruction(state, ir.Instruction{
op=.Compare, span=expr.span, type=types.BOOL, integer=i64(ir.Compare_Predicate.Eq),
target=ir.INVALID_REF, a=code, b=zero, diagnostic=source.INVALID_DIAGNOSTIC,
})
success_lbl := fresh_label(state)
error_lbl := fresh_label(state)
merge_lbl := fresh_label(state)
slot := append_instruction(state, ir.Instruction{
op=.Alloca, span=expr.span, type=success,
target=ir.INVALID_REF, a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
diagnostic=source.INVALID_DIAGNOSTIC,
})
append_instruction(state, ir.Instruction{
op=.Cond_Br, span=expr.span, type=types.VOID,
integer=success_lbl, target=ir.Ref(u32(error_lbl)), a=ok,
b=ir.INVALID_INSTRUCTION, diagnostic=source.INVALID_DIAGNOSTIC,
})
append_instruction(state, ir.Instruction{
op=.Label, span=expr.span, type=types.VOID, integer=error_lbl,
target=ir.INVALID_REF, a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
diagnostic=source.INVALID_DIAGNOSTIC,
})
if expr.kind == .Try {
append_instruction(state, ir.Instruction{
op=.Return, span=expr.span, type=state.func_result,
target=ir.INVALID_REF, a=channel, b=ir.INVALID_INSTRUCTION,
diagnostic=source.INVALID_DIAGNOSTIC,
})
} else {
fallback := lower_nested_expr(state, expr.right)
append_instruction(state, ir.Instruction{
op=.Store, span=expr.span, type=success,
target=ir.INVALID_REF, a=slot, b=fallback, diagnostic=source.INVALID_DIAGNOSTIC,
})
append_instruction(state, ir.Instruction{
op=.Br, span=expr.span, type=types.VOID, integer=merge_lbl,
target=ir.INVALID_REF, a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
diagnostic=source.INVALID_DIAGNOSTIC,
})
}
append_instruction(state, ir.Instruction{
op=.Label, span=expr.span, type=types.VOID, integer=success_lbl,
target=ir.INVALID_REF, a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
diagnostic=source.INVALID_DIAGNOSTIC,
})
if !types.is_void(success) {
payload := append_instruction(state, ir.Instruction{
op=.Field_Address, span=expr.span, type=success, integer=0,
target=ir.INVALID_REF, a=channel_slot, b=ir.INVALID_INSTRUCTION,
diagnostic=source.INVALID_DIAGNOSTIC,
})
loaded := append_instruction(state, ir.Instruction{
op=.Load, span=expr.span, type=success,
target=ir.INVALID_REF, a=payload, b=ir.INVALID_INSTRUCTION,
diagnostic=source.INVALID_DIAGNOSTIC,
})
append_instruction(state, ir.Instruction{
op=.Store, span=expr.span, type=success,
target=ir.INVALID_REF, a=slot, b=loaded, diagnostic=source.INVALID_DIAGNOSTIC,
})
}
append_instruction(state, ir.Instruction{
op=.Br, span=expr.span, type=types.VOID, integer=merge_lbl,
target=ir.INVALID_REF, a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
diagnostic=source.INVALID_DIAGNOSTIC,
})
append_instruction(state, ir.Instruction{
op=.Label, span=expr.span, type=types.VOID, integer=merge_lbl,
target=ir.INVALID_REF, a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
diagnostic=source.INVALID_DIAGNOSTIC,
})
return append_instruction(state, ir.Instruction{
op=.Load, span=expr.span, type=success,
target=ir.INVALID_REF, a=slot, b=ir.INVALID_INSTRUCTION,
diagnostic=source.INVALID_DIAGNOSTIC,
})
case .Not:
value := lower_nested_expr(state, expr.left)
return append_instruction(state, ir.Instruction{
@@ -475,7 +574,7 @@ lower_expr :: proc(state: ^State, expr_id: hir.Expr_Id) -> ir.Instruction_Id {
_ = pop(&stack)
case .String, .Array, .Struct, .Range, .None, .Optional_Some, .Address, .Deref,
.Index, .Slice, .Field, .Union_Tag, .Length, .Slice_Ptr, .Unwrap, .Orelse,
.Not, .Eq, .Ne, .Lt, .Le, .Gt, .Ge, .And, .Or:
.Try, .Catch, .Not, .Eq, .Ne, .Lt, .Le, .Gt, .Ge, .And, .Or:
last = lower_compound_expr(state, frame.expr)
_ = pop(&stack)
case .Local:
@@ -518,7 +617,7 @@ lower_expr :: proc(state: ^State, expr_id: hir.Expr_Id) -> ir.Instruction_Id {
})
}
_ = pop(&stack)
case .Widen, .C_Coerce, .C_Vararg_Promote, .Retype, .Weaken_Pointer, .Weaken_Slice, .Decay_Array_Pointer:
case .Widen, .Sum_Widen, .C_Coerce, .C_Vararg_Promote, .Retype, .Weaken_Pointer, .Weaken_Slice, .Decay_Array_Pointer:
stack[frame_index].stage = 1
append(&stack, Lower_Expr_Frame{expr=expr.left})
case .Negate:
@@ -572,6 +671,7 @@ lower_expr :: proc(state: ^State, expr_id: hir.Expr_Id) -> ir.Instruction_Id {
if frame.stage == 1 {
op := ir.Opcode.Widen
#partial switch expr.kind {
case .Sum_Widen: op = .Sum_Widen
case .Weaken_Pointer: op = .Weaken_Pointer
case .Weaken_Slice: op = .Weaken_Slice
case .Decay_Array_Pointer: op = .Decay_Array_Pointer