anonymous struct payloads
This commit is contained in:
+74
-19
@@ -494,13 +494,12 @@ parse_array_literal :: proc(parser: ^Parser, nesting: int) -> ast.Expr_Id {
|
||||
})
|
||||
}
|
||||
|
||||
parse_struct_literal :: proc(
|
||||
parse_keyed_initializers :: proc(
|
||||
parser: ^Parser,
|
||||
qualifier: symbol.Id,
|
||||
first, name: token.Token,
|
||||
left_brace: token.Token,
|
||||
nesting: int,
|
||||
) -> ast.Expr_Id {
|
||||
left_brace := advance(parser)
|
||||
close_message: string,
|
||||
) -> ([]ast.Expr_Id, token.Token) {
|
||||
parser.delimiter_depth += 1
|
||||
defer parser.delimiter_depth -= 1
|
||||
args: [dynamic]ast.Expr_Id
|
||||
@@ -539,9 +538,20 @@ parse_struct_literal :: proc(
|
||||
}
|
||||
right_brace, ok := allow(parser, .Right_Brace)
|
||||
if !ok {
|
||||
source.add(parser.diagnostics, current(parser).span, "expected '}' after struct literal")
|
||||
source.add(parser.diagnostics, current(parser).span, close_message)
|
||||
right_brace = left_brace
|
||||
}
|
||||
return args[:], right_brace
|
||||
}
|
||||
|
||||
parse_struct_literal :: proc(
|
||||
parser: ^Parser,
|
||||
qualifier: symbol.Id,
|
||||
first, name: token.Token,
|
||||
nesting: int,
|
||||
) -> ast.Expr_Id {
|
||||
left_brace := advance(parser)
|
||||
args, right_brace := parse_keyed_initializers(parser, left_brace, nesting, "expected '}' after struct literal")
|
||||
return add_expr(parser, ast.Expr{
|
||||
kind=.Struct_Literal,
|
||||
span=source.Span{file=name.span.file, start=first.span.start, end=right_brace.span.end},
|
||||
@@ -669,11 +679,32 @@ parse_primary :: proc(parser: ^Parser, nesting: int) -> ast.Expr_Id {
|
||||
advance(parser)
|
||||
payload := ast.INVALID_EXPR
|
||||
end := member.span
|
||||
if _, ok := allow(parser, .Left_Brace); ok {
|
||||
if left_brace, ok := allow(parser, .Left_Brace); ok {
|
||||
parser.delimiter_depth += 1
|
||||
skip_newlines(parser)
|
||||
if current(parser).kind == .Right_Brace {
|
||||
if current(parser).kind == .Identifier && peek(parser).kind == .Equal {
|
||||
parser.delimiter_depth -= 1
|
||||
args, right_brace := parse_keyed_initializers(parser, left_brace, nesting, "expected '}' after contextual variant payload")
|
||||
payload = add_expr(parser, ast.Expr{
|
||||
kind=.Struct_Literal,
|
||||
span=span_from(left_brace.span, right_brace.span),
|
||||
args=args,
|
||||
qualifier=symbol.INVALID,
|
||||
name=symbol.INVALID,
|
||||
left=ast.INVALID_EXPR,
|
||||
right=ast.INVALID_EXPR,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
end = right_brace.span
|
||||
} else if current(parser).kind == .Right_Brace {
|
||||
source.add(parser.diagnostics, current(parser).span, "contextual variant payload requires exactly one expression")
|
||||
right_brace, close_ok := allow(parser, .Right_Brace)
|
||||
if !close_ok {
|
||||
source.add(parser.diagnostics, current(parser).span, "expected '}' after contextual variant payload")
|
||||
right_brace = member
|
||||
}
|
||||
parser.delimiter_depth -= 1
|
||||
end = right_brace.span
|
||||
} else {
|
||||
payload = parse_expression_bp(parser, 0, nesting+1)
|
||||
skip_newlines(parser)
|
||||
@@ -683,14 +714,14 @@ parse_primary :: proc(parser: ^Parser, nesting: int) -> ast.Expr_Id {
|
||||
advance(parser)
|
||||
}
|
||||
}
|
||||
right_brace, close_ok := allow(parser, .Right_Brace)
|
||||
if !close_ok {
|
||||
source.add(parser.diagnostics, current(parser).span, "expected '}' after contextual variant payload")
|
||||
right_brace = member
|
||||
}
|
||||
parser.delimiter_depth -= 1
|
||||
end = right_brace.span
|
||||
}
|
||||
right_brace, close_ok := allow(parser, .Right_Brace)
|
||||
if !close_ok {
|
||||
source.add(parser.diagnostics, current(parser).span, "expected '}' after contextual variant payload")
|
||||
right_brace = member
|
||||
}
|
||||
parser.delimiter_depth -= 1
|
||||
end = right_brace.span
|
||||
}
|
||||
return add_expr(parser, ast.Expr{
|
||||
kind=.Enum_Literal,
|
||||
@@ -1959,7 +1990,19 @@ parse_function :: proc(parser: ^Parser, name: token.Token, c_abi: bool) {
|
||||
})
|
||||
}
|
||||
|
||||
parse_record_body :: proc(parser: ^Parser, fields: ^[dynamic]types.Field, expected_open: string) -> bool {
|
||||
parse_record_field_type :: proc(parser: ^Parser, allow_anonymous_struct_payload: bool) -> types.Type {
|
||||
if allow_anonymous_struct_payload && current(parser).kind == .Keyword_Struct {
|
||||
return parse_inline_struct_payload_type(parser)
|
||||
}
|
||||
return parse_type(parser)
|
||||
}
|
||||
|
||||
parse_record_body :: proc(
|
||||
parser: ^Parser,
|
||||
fields: ^[dynamic]types.Field,
|
||||
expected_open: string,
|
||||
allow_anonymous_struct_payload := false,
|
||||
) -> bool {
|
||||
if _, ok := allow(parser, .Left_Brace); !ok {
|
||||
source.add(parser.diagnostics, current(parser).span, expected_open)
|
||||
return false
|
||||
@@ -1977,7 +2020,7 @@ parse_record_body :: proc(parser: ^Parser, fields: ^[dynamic]types.Field, expect
|
||||
continue
|
||||
}
|
||||
field_name := advance(parser)
|
||||
field_type := parse_type(parser)
|
||||
field_type := parse_record_field_type(parser, allow_anonymous_struct_payload)
|
||||
append(fields, types.Field{name=u32(field_name.symbol), type=field_type})
|
||||
if _, ok := allow(parser, .Comma); ok {
|
||||
skip_newlines(parser)
|
||||
@@ -1991,6 +2034,17 @@ parse_record_body :: proc(parser: ^Parser, fields: ^[dynamic]types.Field, expect
|
||||
return true
|
||||
}
|
||||
|
||||
parse_inline_struct_payload_type :: proc(parser: ^Parser) -> types.Type {
|
||||
advance(parser)
|
||||
fields: [dynamic]types.Field
|
||||
fields.allocator = parser.module.allocator
|
||||
defer delete(fields)
|
||||
if !parse_record_body(parser, &fields, "expected '{' after anonymous struct payload") {
|
||||
return types.INVALID
|
||||
}
|
||||
return types.struct_anonymous(&parser.module.type_store, fields[:])
|
||||
}
|
||||
|
||||
parse_inline_union_type :: proc(parser: ^Parser) -> types.Type {
|
||||
advance(parser)
|
||||
valid := true
|
||||
@@ -2013,7 +2067,7 @@ parse_inline_union_type :: proc(parser: ^Parser) -> types.Type {
|
||||
fields: [dynamic]types.Field
|
||||
fields.allocator = parser.module.allocator
|
||||
defer delete(fields)
|
||||
if !parse_record_body(parser, &fields, "expected '{' after inline union error type") || !valid {
|
||||
if !parse_record_body(parser, &fields, "expected '{' after inline union error type", true) || !valid {
|
||||
return types.INVALID
|
||||
}
|
||||
tag := synthesize_union_tag(parser, fields[:])
|
||||
@@ -2060,7 +2114,8 @@ parse_struct :: proc(parser: ^Parser, name: token.Token, c_layout: bool, is_unio
|
||||
fields: [dynamic]types.Field
|
||||
fields.allocator = parser.module.allocator
|
||||
defer delete(fields)
|
||||
_ = parse_record_body(parser, &fields, "expected '{' after struct fields")
|
||||
allow_anonymous_struct_payload := is_union && (inferred_tag || types.is_valid(declared_tag))
|
||||
_ = parse_record_body(parser, &fields, "expected '{' after struct fields", allow_anonymous_struct_payload)
|
||||
if is_union && (inferred_tag || types.is_valid(declared_tag)) {
|
||||
tag = synthesize_union_tag(parser, fields[:])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user