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:
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")?;