error handling kickoff
This commit is contained in:
+102
-2
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user