allow keywords as values in enums (and tagged unions)

This commit is contained in:
2026-07-13 17:51:59 +02:00
parent de56dc7315
commit 5a958d9bfd
5 changed files with 156 additions and 18 deletions
+87
View File
@@ -10223,6 +10223,93 @@ main func() i32 {
testing.expect(t, found_promotion)
}
@(test)
keywords_are_valid_enum_members_and_tagged_union_variants :: proc(t: ^testing.T) {
testing.expect(t, token.is_keyword(.Keyword_Func))
testing.expect(t, token.is_keyword(.Keyword_C_Longdouble))
testing.expect(t, !token.is_keyword(.Identifier))
testing.expect(t, !token.is_keyword(.Underscore))
text := `TokenKind :: enum {
if
else
return
}
Token :: union(TokenKind) {
if i32
else void
return i32
}
kind func(value bool) TokenKind {
if value {
return .if
}
return TokenKind.else
}
main func() i32 {
first TokenKind = kind(true)
second TokenKind = .return
a Token = Token{ if = 1 }
b Token = Token{ else }
c Token = .return{2}
total i32 = a.if + c.return
match first {
.if: total = total + 1
.else: total = total + 2
.return: total = total + 3
}
match b {
.if |value|: total = total + value
.else: total = total + 4
.return |value|: total = total + value
}
_ = second
return total
}
`
source_file := source.Source{path="test.bro", text=text}
diagnostics := source.init_diagnostics(&source_file)
defer source.destroy_diagnostics(&diagnostics)
symbols := symbol.init_table()
defer symbol.destroy_table(&symbols)
stream := lexer.lex(&source_file, &diagnostics, &symbols)
defer delete(stream.items)
ast_module := parser.parse(&stream, &source_file, &diagnostics)
defer ast.destroy_module(&ast_module)
hir_module := checker.check(&ast_module, &diagnostics, &symbols)
defer hir.destroy_module(&hir_module)
ir_module := lower.lower(&hir_module)
defer ir.destroy_module(&ir_module)
llvm_text := llvm.emit(&ir_module, &diagnostics, &symbols)
defer delete(llvm_text)
testing.expect_value(t, len(diagnostics.items), 0)
testing.expect(t, len(llvm_text) > 0)
}
@(test)
keyword_names_remain_invalid_for_struct_fields :: proc(t: ^testing.T) {
text := `Bad :: struct {
if i32
}
`
source_file := source.Source{path="test.bro", text=text}
diagnostics := source.init_diagnostics(&source_file)
defer source.destroy_diagnostics(&diagnostics)
symbols := symbol.init_table()
defer symbol.destroy_table(&symbols)
stream := lexer.lex(&source_file, &diagnostics, &symbols)
defer delete(stream.items)
module := parser.parse(&stream, &source_file, &diagnostics)
defer ast.destroy_module(&module)
found := false
for diagnostic in diagnostics.items {
found = found || strings.contains(diagnostic.message, "expected a struct field name")
}
testing.expect(t, found)
}
@(test)
unbacked_enum_uses_global_u16_backing :: proc(t: ^testing.T) {
builder := strings.builder_make()