comptime expandable match statements
This commit is contained in:
@@ -1680,7 +1680,15 @@ parse_statement :: proc(parser: ^Parser) -> ast.Stmt_Id {
|
||||
peek(parser).kind == .Keyword_For {
|
||||
start := advance(parser)
|
||||
id := parse_for(parser)
|
||||
parser.module.statements[id].inline = true
|
||||
parser.module.statements[id].expand = true
|
||||
parser.module.statements[id].span = span_from(start.span, parser.module.statements[id].span)
|
||||
source.add(parser.diagnostics, start.span, "'inline for' was renamed to 'expand for'")
|
||||
return id
|
||||
}
|
||||
if current(parser).kind == .Keyword_Expand && peek(parser).kind == .Keyword_For {
|
||||
start := advance(parser)
|
||||
id := parse_for(parser)
|
||||
parser.module.statements[id].expand = true
|
||||
parser.module.statements[id].span = span_from(start.span, parser.module.statements[id].span)
|
||||
return id
|
||||
}
|
||||
@@ -2104,10 +2112,8 @@ parse_arm_body :: proc(parser: ^Parser) -> []ast.Stmt_Id {
|
||||
return single
|
||||
}
|
||||
|
||||
// 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 parses one `<pattern,...> [|[@]capture|]: <body>`, `else: <body>`,
|
||||
// or `expand |[@]value[, tag]|: <body>` arm.
|
||||
parse_match_arm :: proc(parser: ^Parser) -> ast.Stmt_Id {
|
||||
start := current(parser).span
|
||||
patterns: [dynamic]ast.Expr_Id
|
||||
@@ -2115,7 +2121,43 @@ parse_match_arm :: proc(parser: ^Parser) -> ast.Stmt_Id {
|
||||
captures: [dynamic]symbol.Id
|
||||
captures.allocator = parser.module.allocator
|
||||
pointer_capture := false
|
||||
if _, is_else := allow(parser, .Keyword_Else); !is_else {
|
||||
expand := false
|
||||
if _, is_expand := allow(parser, .Keyword_Expand); is_expand {
|
||||
expand = true
|
||||
if _, ok := allow(parser, .Pipe); !ok {
|
||||
source.add(parser.diagnostics, current(parser).span, "expected '|' before expand captures")
|
||||
} else {
|
||||
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)
|
||||
append(&captures, name_tok.symbol)
|
||||
} else {
|
||||
source.add(parser.diagnostics, current(parser).span, "expected an expand value capture")
|
||||
}
|
||||
if _, comma_ok := allow(parser, .Comma); comma_ok {
|
||||
tag_tok := current(parser)
|
||||
if tag_tok.kind == .Identifier || tag_tok.kind == .Underscore {
|
||||
advance(parser)
|
||||
append(&captures, tag_tok.symbol)
|
||||
} else {
|
||||
source.add(parser.diagnostics, current(parser).span, "expected an expand tag capture")
|
||||
}
|
||||
if _, extra := allow(parser, .Comma); extra {
|
||||
source.add(parser.diagnostics, current(parser).span, "'expand' accepts at most two captures")
|
||||
for current(parser).kind != .Pipe && current(parser).kind != .Colon &&
|
||||
current(parser).kind != .Newline && current(parser).kind != .Eof {
|
||||
advance(parser)
|
||||
}
|
||||
}
|
||||
}
|
||||
if _, close_ok := allow(parser, .Pipe); !close_ok {
|
||||
source.add(parser.diagnostics, current(parser).span, "expected '|' to close expand captures")
|
||||
}
|
||||
}
|
||||
} else if _, is_else := allow(parser, .Keyword_Else); !is_else {
|
||||
saved := parser.no_struct_literal
|
||||
parser.no_struct_literal = true
|
||||
append(&patterns, parse_expression(parser))
|
||||
@@ -2155,6 +2197,7 @@ parse_match_arm :: proc(parser: ^Parser) -> ast.Stmt_Id {
|
||||
patterns=patterns[:],
|
||||
captures=captures[:],
|
||||
pointer_capture=pointer_capture,
|
||||
expand=expand,
|
||||
body=body,
|
||||
target=ast.INVALID_EXPR,
|
||||
update=ast.INVALID_STMT,
|
||||
|
||||
Reference in New Issue
Block a user