commit a05c0cd64e6d34ff64989842a9a8b79b3ad9f836
parent d457f7469580741d57e7ad843627b62c0b2a5a9a
Author: Drew DeVault <sir@cmpwn.com>
Date: Mon, 5 Apr 2021 19:33:07 -0400
hare::parse: (mostly) implement unary arithmetic
Diffstat:
3 files changed, 58 insertions(+), 3 deletions(-)
diff --git a/hare/parse/+test.ha b/hare/parse/+test.ha
@@ -173,7 +173,13 @@ fn roundtrip(src: str) void = {
let lexer = lex::init(buf, "<test>");
let u = ast::subunit {
imports = [],
- decls = decls(&lexer) as []ast::decl,
+ decls: []ast::decl = match (decls(&lexer)) {
+ decls: []ast::decl => decls,
+ err: error => {
+ fmt::errorln(strerror(err));
+ abort();
+ },
+ },
};
defer ast::subunit_free(u);
let out = strio::dynamic();
@@ -205,3 +211,12 @@ fn roundtrip(src: str) void = {
"export fn main() void = void: int: uint: u16: u8;\n"
"export fn main() void = void: int as uint: u16 is u8;\n");
};
+
+@test fn unarithm() void = {
+ // TODO: object selectors/addr operator
+ roundtrip("export fn main() void = +void;\n"
+ "export fn main() void = -void;\n"
+ "export fn main() void = *void;\n"
+ "export fn main() void = ~void;\n"
+ "export fn main() void = !void;\n");
+};
diff --git a/hare/parse/expr.ha b/hare/parse/expr.ha
@@ -77,11 +77,40 @@ fn cast(lexer: *lex::lexer, lvalue: (ast::expr | void)) (ast::expr | error) = {
});
};
-fn unarithm(lexer: *lex::lexer) (ast::expr | error) = {
+fn objsel(lexer: *lex::lexer) (ast::expr | error) = {
+ abort(); // TODO
+};
+
+fn postfix(lexer: *lex::lexer) (ast::expr | error) = {
want_btoken(lexer, btoken::VOID)?; // TODO
return void;
};
+fn unarithm(lexer: *lex::lexer) (ast::expr | error) = {
+ const tok = match (try_btoken(lexer,
+ btoken::PLUS, btoken::MINUS, btoken::BNOT,
+ btoken::LNOT, btoken::TIMES, btoken::BAND)) {
+ void => return postfix(lexer),
+ tok: btoken => tok,
+ };
+ const op = switch (tok) {
+ btoken::PLUS => ast::unarithm_op::PLUS,
+ btoken::MINUS => ast::unarithm_op::MINUS,
+ btoken::BNOT => ast::unarithm_op::BNOT,
+ btoken::LNOT => ast::unarithm_op::LNOT,
+ btoken::TIMES => ast::unarithm_op::DEREF,
+ btoken::BAND => ast::unarithm_op::ADDR,
+ * => abort(),
+ };
+ let operand =
+ if (tok == btoken::BAND) objsel(lexer)?
+ else unarithm(lexer)?;
+ return ast::unarithm_expr {
+ op = op,
+ operand = alloc(operand),
+ };
+};
+
fn binop_for_tok(tok: (lex::token, lex::location)) ast::binarithm_op = {
let tok = match (tok.0) {
b: btoken => b,
diff --git a/hare/unparse/expr.ha b/hare/unparse/expr.ha
@@ -73,6 +73,17 @@ export fn expr(
e: ast::return_expr => abort(),
e: ast::slice_expr => abort(),
e: ast::switch_expr => abort(),
- e: ast::unarithm_expr => abort(),
+ e: ast::unarithm_expr => {
+ let z = fmt::fprintf(out, "{}", switch (e.op) {
+ ast::unarithm_op::ADDR => "&",
+ ast::unarithm_op::BNOT => "~",
+ ast::unarithm_op::DEREF => "*",
+ ast::unarithm_op::LNOT => "!",
+ ast::unarithm_op::MINUS => "-",
+ ast::unarithm_op::PLUS => "+",
+ })?;
+ z += expr(out, indent, *e.operand)?;
+ z;
+ },
};
};