fix: reflect composed payload-free enum sums
This commit is contained in:
@@ -16703,6 +16703,13 @@ TokenKind :: enum(u8) {
|
||||
}
|
||||
Simple :: enum { first, second }
|
||||
|
||||
LeftError :: enum { shared, left }
|
||||
RightError :: enum { shared, right }
|
||||
TailError :: enum { tail }
|
||||
BothErrors :: alias LeftError | RightError
|
||||
NestedErrors :: alias (BothErrors | LeftError) | TailError
|
||||
ErrorAlias :: alias NestedErrors
|
||||
|
||||
Names :: alias meta.EnumFieldStruct(TokenKind, ?[]u8, some!(null))
|
||||
Flags :: alias meta.EnumFieldStruct(Simple, bool, false)
|
||||
Direct :: alias struct_type!(.auto, {"x", "name"}, {i32, []u8}, {null, "bro"})
|
||||
@@ -16768,7 +16775,53 @@ get func($E, $V type, map @Map(E, V), key E) ?V {
|
||||
}
|
||||
}
|
||||
|
||||
composed_map :: $(init(ErrorAlias, i32, {
|
||||
shared = 10,
|
||||
left = 20,
|
||||
right = 30,
|
||||
tail = 40,
|
||||
}))
|
||||
|
||||
reflects_composed_keys func($E type) bool {
|
||||
keys [4]E := {.shared, .left, .right, .tail}
|
||||
match typeinfo!(E) {
|
||||
.enum |info|: {
|
||||
if info.fields.len != 4 { return false }
|
||||
inline for info.fields |field, index| {
|
||||
if field.type != E or field.index != index { return false }
|
||||
if field!(E, field.name) != keys[index] { return false }
|
||||
}
|
||||
return (
|
||||
field!(E, "shared") == field!(NestedErrors, "shared")
|
||||
and field!(E, "left") != field!(E, "right")
|
||||
)
|
||||
}
|
||||
else: return false
|
||||
}
|
||||
}
|
||||
|
||||
main func() i32 {
|
||||
if !$(reflects_composed_keys(ErrorAlias)) { return 27 }
|
||||
keys [4]ErrorAlias := {.shared, .left, .right, .tail}
|
||||
expected [4]i32 := {10, 20, 30, 40}
|
||||
for keys |key, index| {
|
||||
if get(&composed_map, key) |value| {
|
||||
if value != expected[index] { return 28 }
|
||||
} else { return 29 }
|
||||
}
|
||||
left LeftError := .left
|
||||
right RightError := .right
|
||||
if get(&composed_map, left) |value| {
|
||||
if value != 20 { return 30 }
|
||||
} else { return 30 }
|
||||
if get(&composed_map, right) |value| {
|
||||
if value != 30 { return 31 }
|
||||
} else { return 32 }
|
||||
partial Map(ErrorAlias, i32) := init({right = 3})
|
||||
if get(&partial, .shared) |_| { return 33 }
|
||||
if get(&partial, .right) |value| {
|
||||
if value != 3 { return 34 }
|
||||
} else { return 35 }
|
||||
other Map(OtherTokenKind, []u8) := init(OtherTokenKind, []u8, {alpha = "other"})
|
||||
if !other.present[0] { return 26 }
|
||||
_ = ordered
|
||||
@@ -16873,6 +16926,53 @@ main func() i32 {
|
||||
testing.expect_value(t, state.exit_code, 0)
|
||||
}
|
||||
|
||||
@(test)
|
||||
enum_field_struct_rejects_payload_sums_and_nominal_unions :: proc(t: ^testing.T) {
|
||||
directory := "/tmp/brolang-test-enum-field-struct-rejections"
|
||||
main_path := "/tmp/brolang-test-enum-field-struct-rejections/main.bro"
|
||||
_ = os2.remove_all(directory)
|
||||
defer _ = os2.remove_all(directory)
|
||||
testing.expect(t, os.make_directory(directory) == nil)
|
||||
declarations := [?]string{
|
||||
`Payload :: union(enum) { value i32 }
|
||||
Empty :: enum { empty }
|
||||
Keys :: alias Payload | Empty`,
|
||||
`Keys :: union(enum) { first void, second void }`,
|
||||
`Keys :: union { first i32, second i32 }`,
|
||||
}
|
||||
for declaration in declarations {
|
||||
text := fmt.aprintf(`meta :: import "@std/meta"
|
||||
%s
|
||||
Flags :: alias meta.EnumFieldStruct(Keys, bool, false)
|
||||
main func() void {
|
||||
flags Flags := {}
|
||||
_ = flags
|
||||
}
|
||||
`, declaration)
|
||||
defer delete(text)
|
||||
testing.expect(t, os.write_entire_file(main_path, transmute([]byte)text))
|
||||
sources := source.init_store()
|
||||
defer source.destroy_store(&sources)
|
||||
diagnostics := source.init_store_diagnostics(&sources)
|
||||
defer source.destroy_diagnostics(&diagnostics)
|
||||
symbols := symbol.init_table()
|
||||
defer symbol.destroy_table(&symbols)
|
||||
module, loaded := loader.load(
|
||||
directory, &sources, &diagnostics, &symbols, project_root_path=".",
|
||||
)
|
||||
defer ast.destroy_module(&module)
|
||||
hir_module := checker.check(&module, &diagnostics, &symbols)
|
||||
defer hir.destroy_module(&hir_module)
|
||||
testing.expect(t, loaded)
|
||||
found_rejection := false
|
||||
for diagnostic in diagnostics.items {
|
||||
found_rejection = found_rejection ||
|
||||
strings.contains(diagnostic.message, "EnumFieldStruct key must be an enum")
|
||||
}
|
||||
testing.expect(t, found_rejection)
|
||||
}
|
||||
}
|
||||
|
||||
@(test)
|
||||
std_meta_tests_compile_and_run :: proc(t: ^testing.T) {
|
||||
directory := "/tmp/brolang-test-std-meta"
|
||||
|
||||
Reference in New Issue
Block a user