void-payloads, multi-pattern arms, and range patterns (match statements)
This commit is contained in:
+30
-11
@@ -477,14 +477,18 @@ parse_struct_literal :: proc(
|
||||
break
|
||||
}
|
||||
advance(parser)
|
||||
if _, ok := allow(parser, .Equal); !ok {
|
||||
source.add(parser.diagnostics, current(parser).span, "expected '=' after struct field name")
|
||||
// A bare key (`T{ variant }`, no `= value`) constructs a void-payload union
|
||||
// variant; the checker validates that the field actually has a void type.
|
||||
value := ast.INVALID_EXPR
|
||||
key_end := field.span
|
||||
if _, ok := allow(parser, .Equal); ok {
|
||||
skip_newlines(parser)
|
||||
value = parse_expression_bp(parser, 0, nesting+1)
|
||||
key_end = parser.module.exprs[value].span
|
||||
}
|
||||
skip_newlines(parser)
|
||||
value := parse_expression_bp(parser, 0, nesting+1)
|
||||
append(&args, add_expr(parser, ast.Expr{
|
||||
kind=.Keyed,
|
||||
span=span_from(field.span, parser.module.exprs[value].span),
|
||||
span=span_from(field.span, key_end),
|
||||
name=field.symbol,
|
||||
left=value,
|
||||
right=ast.INVALID_EXPR,
|
||||
@@ -1544,20 +1548,33 @@ parse_arm_body :: proc(parser: ^Parser) -> []ast.Stmt_Id {
|
||||
return single
|
||||
}
|
||||
|
||||
// parse_match_arm parses one `<pattern> [|capture|]: <body>` arm (or `else: <body>`).
|
||||
// The pattern is `INVALID_EXPR` for `else`; `captures` holds the optional 0-or-1
|
||||
// payload capture name (tagged-union variants only).
|
||||
// parse_match_arm parses one `<pattern,...> [|[@]capture|]: <body>` arm (or
|
||||
// `else: <body>`). `patterns` is empty for `else`, one expr for a single pattern, or
|
||||
// several for a multi-pattern arm; `captures` holds the optional 0-or-1 payload capture
|
||||
// name with `pointer_capture` set for the `|@cap|` form (validated in the checker).
|
||||
parse_match_arm :: proc(parser: ^Parser) -> ast.Stmt_Id {
|
||||
start := current(parser).span
|
||||
pattern := ast.INVALID_EXPR
|
||||
patterns: [dynamic]ast.Expr_Id
|
||||
patterns.allocator = parser.module.allocator
|
||||
captures: [dynamic]symbol.Id
|
||||
captures.allocator = parser.module.allocator
|
||||
pointer_capture := false
|
||||
if _, is_else := allow(parser, .Keyword_Else); !is_else {
|
||||
saved := parser.no_struct_literal
|
||||
parser.no_struct_literal = true
|
||||
pattern = parse_expression(parser)
|
||||
append(&patterns, parse_expression(parser))
|
||||
for {
|
||||
if _, ok := allow(parser, .Comma); !ok {
|
||||
break
|
||||
}
|
||||
skip_newlines(parser)
|
||||
append(&patterns, parse_expression(parser))
|
||||
}
|
||||
parser.no_struct_literal = saved
|
||||
if _, ok := allow(parser, .Pipe); ok {
|
||||
if _, at_ok := allow(parser, .At); at_ok {
|
||||
pointer_capture = true
|
||||
}
|
||||
name_tok := current(parser)
|
||||
if name_tok.kind == .Identifier || name_tok.kind == .Underscore {
|
||||
advance(parser)
|
||||
@@ -1578,8 +1595,10 @@ parse_match_arm :: proc(parser: ^Parser) -> ast.Stmt_Id {
|
||||
append(&parser.module.statements, ast.Stmt{
|
||||
kind=.Match_Arm,
|
||||
span=span_from(start, previous(parser).span),
|
||||
expr=pattern,
|
||||
expr=ast.INVALID_EXPR,
|
||||
patterns=patterns[:],
|
||||
captures=captures[:],
|
||||
pointer_capture=pointer_capture,
|
||||
body=body,
|
||||
target=ast.INVALID_EXPR,
|
||||
update=ast.INVALID_STMT,
|
||||
|
||||
Reference in New Issue
Block a user