add yield
This commit is contained in:
@@ -986,6 +986,23 @@ parse_return :: proc(parser: ^Parser) -> ast.Stmt_Id {
|
||||
return id
|
||||
}
|
||||
|
||||
// `yield <expr>` supplies the value of the enclosing value block. The checker
|
||||
// only accepts it as the final statement of a value block (a `{ ... }` on the
|
||||
// right of a declaration/assignment); it is the block analogue of `return`.
|
||||
parse_yield :: proc(parser: ^Parser) -> ast.Stmt_Id {
|
||||
start := advance(parser) // consume 'yield'
|
||||
skip_newlines(parser)
|
||||
expr := parse_expression(parser)
|
||||
id := ast.stmt_id(len(parser.module.statements))
|
||||
append(&parser.module.statements, ast.Stmt{
|
||||
kind=.Yield,
|
||||
span=span_from(start.span, parser.module.exprs[expr].span),
|
||||
expr=expr,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
return id
|
||||
}
|
||||
|
||||
// `break` / `continue` carry no value and target the innermost loop; the
|
||||
// checker rejects them outside a loop.
|
||||
parse_loop_control :: proc(parser: ^Parser, kind: ast.Stmt_Kind) -> ast.Stmt_Id {
|
||||
@@ -1083,6 +1100,9 @@ parse_statement :: proc(parser: ^Parser) -> ast.Stmt_Id {
|
||||
if current(parser).kind == .Keyword_Defer {
|
||||
return parse_defer(parser)
|
||||
}
|
||||
if current(parser).kind == .Keyword_Yield {
|
||||
return parse_yield(parser)
|
||||
}
|
||||
// A leading `{` opens a bare block scope (struct literals are postfix only).
|
||||
if current(parser).kind == .Left_Brace {
|
||||
return parse_block_statement(parser)
|
||||
@@ -1101,13 +1121,32 @@ parse_statement :: proc(parser: ^Parser) -> ast.Stmt_Id {
|
||||
if operator.kind == .Colon_Colon || operator.kind == .Equal {
|
||||
advance(parser)
|
||||
skip_newlines(parser)
|
||||
expr := parse_expression(parser)
|
||||
kind := ast.Stmt_Kind.Assignment
|
||||
immutable := false
|
||||
if operator.kind == .Colon_Colon || had_type {
|
||||
kind = .Declaration
|
||||
immutable = operator.kind == .Colon_Colon
|
||||
}
|
||||
// A `{` on the right is a value block: parse its statements now; the
|
||||
// checker turns its final `yield` into the declared/assigned value.
|
||||
if current(parser).kind == .Left_Brace {
|
||||
brace := current(parser)
|
||||
body := parse_block(parser)
|
||||
id := ast.stmt_id(len(parser.module.statements))
|
||||
append(&parser.module.statements, ast.Stmt{
|
||||
kind=kind,
|
||||
span=span_from(name.span, brace.span),
|
||||
name=name.symbol,
|
||||
type=type_syntax,
|
||||
immutable=immutable,
|
||||
target=ast.INVALID_EXPR,
|
||||
expr=ast.INVALID_EXPR,
|
||||
body=body,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
return id
|
||||
}
|
||||
expr := parse_expression(parser)
|
||||
id := ast.stmt_id(len(parser.module.statements))
|
||||
append(&parser.module.statements, ast.Stmt{
|
||||
kind=kind,
|
||||
@@ -1127,6 +1166,21 @@ parse_statement :: proc(parser: ^Parser) -> ast.Stmt_Id {
|
||||
expr := parse_expression(parser)
|
||||
if _, ok := allow(parser, .Equal); ok {
|
||||
skip_newlines(parser)
|
||||
// A value block assigned to a complex target (`a[i] = { ... }`, `p.f = { ... }`).
|
||||
if current(parser).kind == .Left_Brace {
|
||||
brace := current(parser)
|
||||
body := parse_block(parser)
|
||||
id := ast.stmt_id(len(parser.module.statements))
|
||||
append(&parser.module.statements, ast.Stmt{
|
||||
kind=.Assignment,
|
||||
span=span_from(parser.module.exprs[expr].span, brace.span),
|
||||
target=expr,
|
||||
expr=ast.INVALID_EXPR,
|
||||
body=body,
|
||||
diagnostic=source.INVALID_DIAGNOSTIC,
|
||||
})
|
||||
return id
|
||||
}
|
||||
value := parse_expression(parser)
|
||||
id := ast.stmt_id(len(parser.module.statements))
|
||||
append(&parser.module.statements, ast.Stmt{
|
||||
@@ -1375,7 +1429,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, .Block, .Defer:
|
||||
case .Invalid, .Declaration, .Return, .If, .While, .For, .Break, .Continue, .Block, .Defer, .Yield:
|
||||
diagnostic := source.add(
|
||||
parser.diagnostics,
|
||||
statement.span,
|
||||
|
||||
Reference in New Issue
Block a user