errdefer and try/defer fix
This commit is contained in:
@@ -1410,18 +1410,44 @@ parse_block_statement :: proc(parser: ^Parser, label := symbol.INVALID) -> ast.S
|
||||
return id
|
||||
}
|
||||
|
||||
// `defer <statement>` runs the statement when the enclosing scope exits. The
|
||||
// statement may be a block (`defer { ... }`). The checker rejects deferring a
|
||||
// `return`/`break`/`continue`/`defer`.
|
||||
// `defer <statement>` runs whenever the enclosing scope exits; `errdefer`
|
||||
// runs only when it exits through a function error and may capture that error.
|
||||
parse_defer :: proc(parser: ^Parser) -> ast.Stmt_Id {
|
||||
marker := advance(parser) // consume 'defer'
|
||||
marker := advance(parser)
|
||||
error_only := marker.kind == .Keyword_Errdefer
|
||||
skip_newlines(parser)
|
||||
captures: []symbol.Id
|
||||
if error_only {
|
||||
if _, ok := allow(parser, .Pipe); ok {
|
||||
capture := current(parser)
|
||||
if capture.kind != .Identifier && capture.kind != .Underscore {
|
||||
source.add(parser.diagnostics, capture.span, "expected an errdefer capture name")
|
||||
} else {
|
||||
advance(parser)
|
||||
captures = make([]symbol.Id, 1, parser.module.allocator)
|
||||
captures[0] = capture.symbol
|
||||
}
|
||||
if current(parser).kind == .Comma {
|
||||
source.add(parser.diagnostics, current(parser).span, "'errdefer' accepts exactly one capture")
|
||||
for current(parser).kind != .Pipe && 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 '|' after errdefer capture")
|
||||
}
|
||||
skip_newlines(parser)
|
||||
}
|
||||
}
|
||||
inner := parse_statement(parser)
|
||||
id := ast.stmt_id(len(parser.module.statements))
|
||||
append(&parser.module.statements, ast.Stmt{
|
||||
kind=.Defer,
|
||||
span=marker.span,
|
||||
update=inner,
|
||||
error_only=error_only,
|
||||
captures=captures,
|
||||
expr=ast.INVALID_EXPR,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
@@ -1486,7 +1512,7 @@ parse_statement :: proc(parser: ^Parser) -> ast.Stmt_Id {
|
||||
if current(parser).kind == .Keyword_Continue {
|
||||
return parse_loop_control(parser, .Continue)
|
||||
}
|
||||
if current(parser).kind == .Keyword_Defer {
|
||||
if current(parser).kind == .Keyword_Defer || current(parser).kind == .Keyword_Errdefer {
|
||||
return parse_defer(parser)
|
||||
}
|
||||
if current(parser).kind == .Keyword_Yield {
|
||||
|
||||
Reference in New Issue
Block a user