hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit e952359b927844a2176aeffb9d82adad69ba647b
parent ef705aaf200fe260eb2cb71641801d0a08b45ded
Author: Eyal Sawady <ecs@d2evs.net>
Date:   Sun, 25 Apr 2021 01:23:36 -0400

hare::parse: implement ! postfix operator

Co-authored-by: Drew DeVault <sir@cmpwn.com>
Signed-off-by: Eyal Sawady <ecs@d2evs.net>
Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Mhare/ast/expr.ha | 7+++++--
Mhare/parse/+test/expr.ha | 1+
Mhare/parse/expr.ha | 17+++++++++++------
Mhare/unparse/expr.ha | 4++--
4 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/hare/ast/expr.ha b/hare/ast/expr.ha @@ -278,7 +278,10 @@ export type offset_expr = void; // TODO // An error propagation expression. // // foo? -export type propagate_expr = *expr; +export type propagate_expr = struct { + is_abort: bool, + expr: *expr, +}; // A return statement. // @@ -477,7 +480,7 @@ export fn expr_free(e: (expr | nullable *expr)) void = match (e) { free(m.cases); }, o: offset_expr => abort(), // TODO - p: propagate_expr => expr_free(p: *expr), + p: propagate_expr => expr_free(p.expr), r: return_expr => expr_free(r: *expr), s: size_expr => type_free(s: *_type), s: slice_expr => { diff --git a/hare/parse/+test/expr.ha b/hare/parse/+test/expr.ha @@ -186,6 +186,7 @@ "export fn main() void = x.42;\n" "export fn main() void = x().y.0.q;\n" "export fn main() void = x?;\n" + "export fn main() void = x!;\n" "export fn main() void = x()?.y;\n" "export fn main() void = x[10];\n" "export fn main() void = x[10 + 10][20];\n"); diff --git a/hare/parse/expr.ha b/hare/parse/expr.ha @@ -728,19 +728,24 @@ fn postfix(lexer: *lex::lexer, lvalue: (ast::expr | void)) (ast::expr | error) = ex: ast::expr => ex, }; - lvalue = match (try(lexer, ltok::LPAREN, - ltok::DOT, ltok::LBRACKET, ltok::QUESTION)) { + return postfix(lexer, match (try(lexer, ltok::LPAREN, + ltok::DOT, ltok::LBRACKET, ltok::QUESTION, ltok::LNOT)) { tok: lex::token => switch (tok.0) { ltok::LPAREN => call(lexer, lvalue)?, ltok::DOT => postfix_dot(lexer, lvalue)?, ltok::LBRACKET => indexing(lexer, lvalue)?, - ltok::QUESTION => alloc(lvalue): ast::propagate_expr, + ltok::QUESTION => ast::propagate_expr { + is_abort = false, + expr = alloc(lvalue), + }, + ltok::LNOT => ast::propagate_expr { + is_abort = true, + expr = alloc(lvalue), + }, * => abort(), }, _: void => return lvalue, - }; - - return postfix(lexer, lvalue); + }); }; fn postfix_dot(lexer: *lex::lexer, lvalue: ast::expr) (ast::expr | error) = { diff --git a/hare/unparse/expr.ha b/hare/unparse/expr.ha @@ -257,8 +257,8 @@ export fn expr( }, e: ast::offset_expr => abort(), e: ast::propagate_expr => { - let z = expr(out, indent, *e)?; - z + fmt::fprintf(out, "?")?; + let z = expr(out, indent, *e.expr)?; + z + fmt::fprintf(out, if (e.is_abort) "!" else "?")?; }, e: ast::return_expr => { let z = fmt::fprint(out, "return")?;