conditional optional unwrapping
This commit is contained in:
@@ -633,7 +633,22 @@ lower_statements :: proc(state: ^State, statements: []hir.Stmt_Id) {
|
||||
diagnostic=statement.diagnostic,
|
||||
})
|
||||
case .If:
|
||||
cond := lower_expr(state, statement.expr)
|
||||
// A conditional unwrap (`if opt |v| { ... }`) carries the binding local id in
|
||||
// `statement.local`; `expr` is then the optional, not a bool condition. Test it
|
||||
// for presence, and inside the then-block bind the unwrapped value to the local.
|
||||
is_unwrap := statement.local != hir.INVALID_LOCAL
|
||||
opt := ir.INVALID_INSTRUCTION
|
||||
cond: ir.Instruction_Id
|
||||
if is_unwrap {
|
||||
opt = lower_expr(state, statement.expr)
|
||||
cond = append_instruction(state, ir.Instruction{
|
||||
op=.Optional_Is_Some, span=statement.span, type=types.BOOL,
|
||||
target=ir.INVALID_REF, a=opt, b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
} else {
|
||||
cond = lower_expr(state, statement.expr)
|
||||
}
|
||||
has_else := statement.else_body != nil
|
||||
then_lbl := fresh_label(state)
|
||||
else_lbl := fresh_label(state) if has_else else then_lbl
|
||||
@@ -649,6 +664,26 @@ lower_statements :: proc(state: ^State, statements: []hir.Stmt_Id) {
|
||||
target=ir.INVALID_REF, a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
if is_unwrap && int(statement.local) < len(state.func_locals) {
|
||||
local := state.func_locals[statement.local]
|
||||
slot := append_instruction(state, ir.Instruction{
|
||||
op=.Alloca, span=statement.span, type=local.type,
|
||||
target=ir.local_ref(ir.Local_Id(statement.local)),
|
||||
a=ir.INVALID_INSTRUCTION, b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
state.local_slots[statement.local] = slot
|
||||
inner := append_instruction(state, ir.Instruction{
|
||||
op=.Optional_Value, span=statement.span, type=local.type,
|
||||
target=ir.INVALID_REF, a=opt, b=ir.INVALID_INSTRUCTION,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
append_instruction(state, ir.Instruction{
|
||||
op=.Store, span=statement.span, type=local.type,
|
||||
target=ir.INVALID_REF, a=slot, b=inner,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
}
|
||||
lower_statements(state, statement.then_body)
|
||||
append_instruction(state, ir.Instruction{
|
||||
op=.Br, span=statement.span, type=types.VOID, integer=merge_lbl,
|
||||
|
||||
Reference in New Issue
Block a user