feat: support existing enum map initialization and lookup
This commit is contained in:
+18
-2
@@ -1725,8 +1725,16 @@ lower_slice proc(state @mut State, id ast.NodeId) ir.ValueId ! (mem.AllocError |
|
||||
lower_builtin proc(state @mut State, id ast.NodeId) ir.ValueId ! (mem.AllocError | diagnostics.CapacityError) {
|
||||
tree :: state.tree
|
||||
span :: ast.node_span(tree, id)
|
||||
name :: ast.source_text(tree, ast.node_span(tree, ast.builtin_call(tree, id).name))
|
||||
name :: ast.literal_text(tree, ast.builtin_call(tree, id).name)
|
||||
if (trap_type(state, id)) return ir.no_value
|
||||
if (mem.eql(name, "some")) {
|
||||
type :: typecheck.type_of(state.checked, id)
|
||||
child :: typecheck.array_type(state.checked, type.array_type).element
|
||||
payload :: try lower_as(state, ast.call_arg(tree, id, 0), child)
|
||||
if (state.terminated or child.kind == .pointer or child.kind == .function) return payload
|
||||
present :: try constant(state, ir.Value{ type = .bool, data = ir.ValueData{ boolean = true } }, span)
|
||||
return try record_pair(state, try array_shape(state, type), present, payload, span)
|
||||
}
|
||||
if (mem.eql(name, "sizeof") or mem.eql(name, "alignof")) {
|
||||
checked :: typecheck.type_of(state.checked, ast.call_arg(tree, id, 0))
|
||||
type :: lower_type(state, checked)
|
||||
@@ -1893,7 +1901,15 @@ lower_expression proc(state @mut State, id ast.NodeId) ir.ValueId ! (mem.AllocEr
|
||||
if (!trap_type(state, id)) trap(state, try diagnostics.add(state.diagnostics, .type_not_value, span), span)
|
||||
}
|
||||
.alias_expr: return try lower_expression(state, ast.type_operand(tree, id))
|
||||
.enum_literal, .literal_undefined: {
|
||||
.literal_undefined: {
|
||||
if (trap_type(state, id)) return ir.no_value
|
||||
checked :: typecheck.type_of(state.checked, id)
|
||||
return try emit(state, ir.Instruction{
|
||||
op = .undefined_value, type = lower_type(state, checked),
|
||||
array_type = try array_shape(state, checked), span = span,
|
||||
})
|
||||
}
|
||||
.enum_literal: {
|
||||
if (!trap_type(state, id)) unreachable
|
||||
}
|
||||
.match_expr: return try lower_match(state, id)
|
||||
|
||||
@@ -174,6 +174,66 @@ supports_bare_void_value_returns_and_fallthrough test {
|
||||
}
|
||||
}
|
||||
|
||||
constructs_present_optionals_without_losing_nested_null_or_repeating_values test {
|
||||
diagnostic_store := diagnostics.init(mem.c_allocator)
|
||||
defer diagnostics.deinit(&diagnostic_store)
|
||||
source ::
|
||||
`next proc(calls @mut i16) i16 {
|
||||
` calls^ = calls^ + 1
|
||||
` return 42
|
||||
`}
|
||||
`nested proc() ??i16 { return some!(null) }
|
||||
`Box :: struct { values [2]i16 }
|
||||
`main proc() bool {
|
||||
` calls i16 := 0
|
||||
` absent ??i16 :: null
|
||||
` present ??i16 :: nested()
|
||||
` full ??i16 :: some!(some!(42))
|
||||
` exact i16 :: 42
|
||||
` value ?i16 :: some!(exact)
|
||||
` once ?i16 :: some!(next(&calls))
|
||||
` boxed ?Box :: some!(Box{ values = [20, 22] })
|
||||
` pointer ?@i16 :: some!(&exact)
|
||||
` nested_pointer ??@i16 :: some!(null)
|
||||
` return (
|
||||
` absent == null and present != null and present? == null
|
||||
` and full != null and full? != null and full?? == 42
|
||||
` and value? == 42 and once? == 42 and calls == 1
|
||||
` and boxed?.values[0] + boxed?.values[1] == 42
|
||||
` and pointer?^ == 42 and nested_pointer != null and nested_pointer? == null
|
||||
` )
|
||||
`}
|
||||
module := try compile_owned(source, &diagnostic_store)
|
||||
defer ir.deinit(&module)
|
||||
try testing.expect_equal(0, diagnostics.count(&diagnostic_store))
|
||||
outcome := try interpreter.run(mem.c_allocator, &module, &diagnostic_store)
|
||||
defer interpreter.deinit(&outcome)
|
||||
try testing.expect(outcome.trap == null)
|
||||
try testing.expect_equal(ir.Type.bool, outcome.value.type)
|
||||
try testing.expect(outcome.value.data.boolean)
|
||||
}
|
||||
|
||||
rejects_some_without_optional_context_wrong_arity_and_inexact_payloads test {
|
||||
sources [6][]u8 :: [
|
||||
"main proc() ?i16 { return some!() }\n",
|
||||
"main proc() ?i16 { return some!(1, 2) }\n",
|
||||
"main proc() bool { return some!(true) }\n",
|
||||
"main proc() ?i16 { return some!(true) }\n",
|
||||
"main proc() ?i16 { value i32 :: 42\nreturn some!(value) }\n",
|
||||
"main proc() ?i16 { return some!(null) }\n",
|
||||
]
|
||||
for (sources) |source, i| {
|
||||
diagnostic_store := diagnostics.init(mem.c_allocator)
|
||||
defer diagnostics.deinit(&diagnostic_store)
|
||||
module := try compile_owned(source, &diagnostic_store)
|
||||
defer ir.deinit(&module)
|
||||
outcome := try interpreter.run(mem.c_allocator, &module, &diagnostic_store)
|
||||
defer interpreter.deinit(&outcome)
|
||||
code diagnostics.Code :: if (i < 2) .argument_count_mismatch else if (i == 2) .invalid_operand else .type_mismatch
|
||||
try expect_trap(outcome, &diagnostic_store, code)
|
||||
}
|
||||
}
|
||||
|
||||
preserves_demanded_diagnostic_identity_and_source_location test {
|
||||
diagnostic_store := diagnostics.init(mem.c_allocator)
|
||||
defer diagnostics.deinit(&diagnostic_store)
|
||||
|
||||
Reference in New Issue
Block a user