diff --git a/core/odin/ast/ast.odin b/core/odin/ast/ast.odin index b462a3107..67e616a9f 100644 --- a/core/odin/ast/ast.odin +++ b/core/odin/ast/ast.odin @@ -284,6 +284,13 @@ Or_Return_Expr :: struct { token: tokenizer.Token, } +Or_Branch_Expr :: struct { + using node: Expr, + expr: ^Expr, + token: tokenizer.Token, + label: ^Expr, +} + Type_Assertion :: struct { using node: Expr, expr: ^Expr, @@ -563,6 +570,8 @@ strip_or_return_expr :: proc(expr: ^Expr) -> (val: ^Expr) { #partial switch e in val.derived { case ^Or_Return_Expr: inner = e.expr + case ^Or_Branch_Expr: + inner = e.expr case ^Paren_Expr: inner = e.expr } @@ -860,6 +869,7 @@ Any_Node :: union { ^Ternary_When_Expr, ^Or_Else_Expr, ^Or_Return_Expr, + ^Or_Branch_Expr, ^Type_Assertion, ^Type_Cast, ^Auto_Cast, @@ -943,6 +953,7 @@ Any_Expr :: union { ^Ternary_When_Expr, ^Or_Else_Expr, ^Or_Return_Expr, + ^Or_Branch_Expr, ^Type_Assertion, ^Type_Cast, ^Auto_Cast, diff --git a/core/odin/ast/clone.odin b/core/odin/ast/clone.odin index 407ddf2cc..79e7a166e 100644 --- a/core/odin/ast/clone.odin +++ b/core/odin/ast/clone.odin @@ -147,8 +147,8 @@ clone_node :: proc(node: ^Node) -> ^Node { r.expr = clone(r.expr) r.index = clone(r.index) case ^Matrix_Index_Expr: - r.expr = clone(r.expr) - r.row_index = clone(r.row_index) + r.expr = clone(r.expr) + r.row_index = clone(r.row_index) r.column_index = clone(r.column_index) case ^Deref_Expr: r.expr = clone(r.expr) @@ -175,6 +175,9 @@ clone_node :: proc(node: ^Node) -> ^Node { r.y = clone(r.y) case ^Or_Return_Expr: r.expr = clone(r.expr) + case ^Or_Branch_Expr: + r.expr = clone(r.expr) + r.label = clone(r.label) case ^Type_Assertion: r.expr = clone(r.expr) r.type = clone(r.type) diff --git a/core/odin/ast/walk.odin b/core/odin/ast/walk.odin index b4eaf8140..966a8137e 100644 --- a/core/odin/ast/walk.odin +++ b/core/odin/ast/walk.odin @@ -146,6 +146,11 @@ walk :: proc(v: ^Visitor, node: ^Node) { walk(v, n.y) case ^Or_Return_Expr: walk(v, n.expr) + case ^Or_Branch_Expr: + walk(v, n.expr) + if n.label != nil { + walk(v, n.label) + } case ^Type_Assertion: walk(v, n.expr) if n.type != nil { diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin index 39280061f..a2b2a9944 100644 --- a/core/odin/parser/parser.odin +++ b/core/odin/parser/parser.odin @@ -3190,6 +3190,23 @@ parse_atom_expr :: proc(p: ^Parser, value: ^ast.Expr, lhs: bool) -> (operand: ^a operand = oe + case .Or_Break, .Or_Continue: + token := advance_token(p) + label: ^ast.Ident + + end := end_pos(token) + if p.curr_tok.kind == .Ident { + end = end_pos(p.curr_tok) + label = parse_ident(p) + } + + oe := ast.new(ast.Or_Branch_Expr, operand.pos, end) + oe.expr = operand + oe.token = token + oe.label = label + + operand = oe + case .Open_Brace: if !is_lhs && is_literal_type(operand) && p.expr_level >= 0 { operand = parse_literal_value(p, operand) diff --git a/core/odin/printer/visit.odin b/core/odin/printer/visit.odin index d3701fcc5..1aefcf967 100644 --- a/core/odin/printer/visit.odin +++ b/core/odin/printer/visit.odin @@ -972,6 +972,13 @@ visit_expr :: proc(p: ^Printer, expr: ^ast.Expr, options := List_Options{}) { case ^ast.Or_Return_Expr: visit_expr(p, v.expr) push_generic_token(p, v.token.kind, 1) + case ^ast.Or_Branch_Expr: + visit_expr(p, v.expr) + push_generic_token(p, v.token.kind, 1) + if v.label != nil { + visit_expr(p, v.label) + } + case ^ast.Selector_Call_Expr: visit_expr(p, v.call.expr) push_generic_token(p, .Open_Paren, 1)