commit 46837f82bb0ff467c78e8ee450a0302997e842b1
parent bf0eced5eb045f1a7987a83a2adcbeabc17c2e27
Author: Drew DeVault <sir@cmpwn.com>
Date: Wed, 23 Dec 2020 09:06:35 -0500
check: implement basic binary arithmetic
This also fixes a bug in binarithm expression parsing.
Diffstat:
3 files changed, 59 insertions(+), 5 deletions(-)
diff --git a/include/expr.h b/include/expr.h
@@ -105,6 +105,7 @@ struct expression {
bool terminates;
union {
struct expression_access access;
+ struct expression_binarithm binarithm;
struct expression_binding binding;
union expression_constant constant;
struct expression_list list;
diff --git a/src/check.c b/src/check.c
@@ -53,6 +53,55 @@ check_expr_access(struct context *ctx,
}
static void
+check_expr_binarithm(struct context *ctx,
+ const struct ast_expression *aexpr,
+ struct expression *expr)
+{
+ trace(TR_CHECK, "binarithm");
+ expr->type = EXPR_BINARITHM;
+ expr->binarithm.op = aexpr->binarithm.op;
+
+ struct expression *lvalue = calloc(1, sizeof(struct expression *)),
+ *rvalue = calloc(1, sizeof(struct expression *));
+ check_expression(ctx, aexpr->binarithm.lvalue, lvalue);
+ check_expression(ctx, aexpr->binarithm.rvalue, rvalue);
+ expr->binarithm.lvalue = lvalue;
+ expr->binarithm.rvalue = rvalue;
+
+ switch (expr->binarithm.op) {
+ // Numeric arithmetic
+ case BIN_BAND:
+ case BIN_BNOT:
+ case BIN_BOR:
+ case BIN_DIV:
+ case BIN_LSHIFT:
+ case BIN_MINUS:
+ case BIN_MODULO:
+ case BIN_PLUS:
+ case BIN_RSHIFT:
+ case BIN_TIMES:
+ case BIN_BXOR:
+ assert(lvalue->result == rvalue->result); // TODO: Promotion
+ expr->result = lvalue->result;
+ break;
+ // Logical arithmetic
+ case BIN_GREATER:
+ case BIN_GREATEREQ:
+ case BIN_LAND:
+ case BIN_LEQUAL:
+ case BIN_LESS:
+ case BIN_LESSEQ:
+ case BIN_LOR:
+ case BIN_LXOR:
+ case BIN_NEQUAL:
+ expect(lvalue->result == &builtin_type_bool
+ && rvalue->result == &builtin_type_bool,
+ "Logical expressions must have boolean operands");
+ assert(0); // TODO
+ }
+}
+
+static void
check_expr_binding(struct context *ctx,
const struct ast_expression *aexpr,
struct expression *expr)
@@ -214,7 +263,8 @@ check_expression(struct context *ctx,
case EXPR_ASSIGN:
assert(0); // TODO
case EXPR_BINARITHM:
- assert(0); // TODO
+ check_expr_binarithm(ctx, aexpr, expr);
+ break;
case EXPR_BINDING:
check_expr_binding(ctx, aexpr, expr);
break;
diff --git a/src/parse.c b/src/parse.c
@@ -596,8 +596,7 @@ parse_bin_expression(struct parser *par, struct ast_expression *lvalue, int i)
int j;
while ((j = precedence(tok.token)) >= i) {
- lvalue->type = EXPR_BINARITHM;
- lvalue->binarithm.op = binop_for_token(tok.token);
+ enum binarithm_operator op = binop_for_token(tok.token);
struct ast_expression *rvalue = parse_cast_expression(par);
lex(par->lex, &tok);
@@ -609,8 +608,12 @@ parse_bin_expression(struct parser *par, struct ast_expression *lvalue, int i)
lex(par->lex, &tok);
}
- lvalue->binarithm.lvalue = lvalue;
- lvalue->binarithm.rvalue = rvalue;
+ struct ast_expression *e = calloc(1, sizeof(struct ast_expression));
+ e->type = EXPR_BINARITHM;
+ e->binarithm.op = op;
+ e->binarithm.lvalue = lvalue;
+ e->binarithm.rvalue = rvalue;
+ lvalue = e;
}
unlex(par->lex, &tok);