add defer
This commit is contained in:
@@ -1001,6 +1001,41 @@ parse_loop_control :: proc(parser: ^Parser, kind: ast.Stmt_Kind) -> ast.Stmt_Id
|
||||
return id
|
||||
}
|
||||
|
||||
// A bare `{ ... }` introduces a nested scope. Locals declared inside are not
|
||||
// visible after it, and any `defer`s inside it run at the closing brace.
|
||||
parse_block_statement :: proc(parser: ^Parser) -> ast.Stmt_Id {
|
||||
start := current(parser).span // the '{'
|
||||
body := parse_block(parser)
|
||||
id := ast.stmt_id(len(parser.module.statements))
|
||||
append(&parser.module.statements, ast.Stmt{
|
||||
kind=.Block,
|
||||
span=start,
|
||||
body=body,
|
||||
expr=ast.INVALID_EXPR,
|
||||
update=ast.INVALID_STMT,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
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`.
|
||||
parse_defer :: proc(parser: ^Parser) -> ast.Stmt_Id {
|
||||
marker := advance(parser) // consume 'defer'
|
||||
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,
|
||||
expr=ast.INVALID_EXPR,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
return id
|
||||
}
|
||||
|
||||
starts_declared_type :: proc(parser: ^Parser) -> bool {
|
||||
if current(parser).kind != .Left_Bracket {
|
||||
return is_type_token(current(parser).kind)
|
||||
@@ -1045,6 +1080,13 @@ 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 {
|
||||
return parse_defer(parser)
|
||||
}
|
||||
// A leading `{` opens a bare block scope (struct literals are postfix only).
|
||||
if current(parser).kind == .Left_Brace {
|
||||
return parse_block_statement(parser)
|
||||
}
|
||||
|
||||
if current(parser).kind == .Identifier || current(parser).kind == .Underscore {
|
||||
start_cursor := parser.cursor
|
||||
@@ -1333,7 +1375,7 @@ parse_while_update :: proc(parser: ^Parser) -> ast.Stmt_Id {
|
||||
statement := &parser.module.statements[update]
|
||||
switch statement.kind {
|
||||
case .Assignment, .Expression:
|
||||
case .Invalid, .Declaration, .Return, .If, .While, .For, .Break, .Continue:
|
||||
case .Invalid, .Declaration, .Return, .If, .While, .For, .Break, .Continue, .Block, .Defer:
|
||||
diagnostic := source.add(
|
||||
parser.diagnostics,
|
||||
statement.span,
|
||||
|
||||
Reference in New Issue
Block a user