harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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:
Minclude/expr.h | 1+
Msrc/check.c | 52+++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/parse.c | 11+++++++----
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);