default struct fields

This commit is contained in:
2026-07-18 16:23:47 +02:00
parent e889a99e55
commit 9eb7476522
10 changed files with 191 additions and 11 deletions
+34
View File
@@ -2532,6 +2532,7 @@ parse_record_body :: proc(
allow_anonymous_struct_payload := false,
allow_keyword_names := false,
tuple_result: ^bool = nil,
defaults: ^[dynamic]ast.Expr_Id = nil,
) -> bool {
if _, ok := allow(parser, .Left_Brace); !ok {
source.add(parser.diagnostics, current(parser).span, expected_open)
@@ -2557,6 +2558,9 @@ parse_record_body :: proc(
mode = 2
field_type := parse_type(parser)
append(fields, types.Field{name=0, type=field_type})
if defaults != nil {
append(defaults, ast.INVALID_EXPR)
}
} else {
if mode == 2 {
source.add(parser.diagnostics, current(parser).span, "struct fields cannot mix named and unnamed forms")
@@ -2575,6 +2579,14 @@ parse_record_body :: proc(
}
field_type := parse_record_field_type(parser, allow_anonymous_struct_payload)
append(fields, types.Field{name=u32(field_name.symbol), type=field_type})
if defaults != nil {
value := ast.INVALID_EXPR
if _, ok := allow(parser, .Equal); ok {
skip_newlines(parser)
value = parse_expression(parser)
}
append(defaults, value)
}
}
if _, ok := allow(parser, .Comma); ok {
skip_newlines(parser)
@@ -2678,6 +2690,9 @@ parse_struct :: proc(parser: ^Parser, name: token.Token, c_layout, file_hidden:
fields: [dynamic]types.Field
fields.allocator = parser.module.allocator
defer delete(fields)
defaults: [dynamic]ast.Expr_Id
defaults.allocator = parser.module.allocator
defer delete(defaults)
allow_anonymous_struct_payload := is_union && (inferred_tag || types.is_valid(declared_tag))
tuple := false
_ = parse_record_body(
@@ -2687,7 +2702,13 @@ parse_struct :: proc(parser: ^Parser, name: token.Token, c_layout, file_hidden:
allow_anonymous_struct_payload,
allow_anonymous_struct_payload,
&tuple,
&defaults,
)
for value in defaults {
if value != ast.INVALID_EXPR && (c_layout || is_union || tuple) {
source.add(parser.diagnostics, parser.module.exprs[value].span, "field defaults are only supported by named native structs")
}
}
if tuple && (c_layout || is_union) {
source.add(parser.diagnostics, start.span, "unnamed fields are only supported by native structs")
tuple = false
@@ -2697,6 +2718,19 @@ parse_struct :: proc(parser: ^Parser, name: token.Token, c_layout, file_hidden:
}
if !types.define_record(&parser.module.type_store, id, fields[:], c_layout, false, is_union, tag=tag, declared_tag=declared_tag, tuple=tuple) {
source.addf(parser.diagnostics, name.span, "duplicate type declaration '%s'", token_text(parser, name))
} else if !c_layout && !is_union && !tuple {
for value, index in defaults {
if value == ast.INVALID_EXPR {
continue
}
append(&parser.module.struct_field_defaults, ast.Struct_Field_Default{
record=id,
field=symbol.Id(fields[index].name),
expr=value,
pkg=parser.pkg,
file=parser.file,
})
}
}
_ = finish_statement(parser)
}