commit 6ede1609fef95d37d853ae1751ee9ceaeb026912
parent 079d0afa986d1bc50e3ab0630af99e9b2564754e
Author: Eyal Sawady <ecs@d2evs.net>
Date: Thu, 31 Dec 2020 17:34:01 -0500
parse, check: implement += et al
Diffstat:
5 files changed, 33 insertions(+), 7 deletions(-)
diff --git a/include/ast.h b/include/ast.h
@@ -123,6 +123,7 @@ struct ast_expression_assert {
};
struct ast_expression_assign {
+ enum binarithm_operator op;
struct ast_expression *object, *value;
bool indirect;
};
diff --git a/include/expr.h b/include/expr.h
@@ -54,11 +54,6 @@ struct expression_assert {
bool is_static;
};
-struct expression_assign {
- struct expression *object, *value;
- bool indirect;
-};
-
enum binarithm_operator {
BIN_BAND, // &
BIN_BOR, // |
@@ -81,6 +76,12 @@ enum binarithm_operator {
BIN_BXOR, // ^
};
+struct expression_assign {
+ enum binarithm_operator op;
+ struct expression *object, *value;
+ bool indirect;
+};
+
struct expression_binarithm {
enum binarithm_operator op;
struct expression *lvalue, *rvalue;
diff --git a/src/check.c b/src/check.c
@@ -134,6 +134,7 @@ check_expr_assign(struct context *ctx,
check_expression(ctx, aexpr->assign.object, object);
check_expression(ctx, aexpr->assign.value, value);
+ expr->assign.op = aexpr->assign.op;
expr->assign.object = object;
expr->assign.value = value;
diff --git a/src/gen.c b/src/gen.c
@@ -387,6 +387,7 @@ gen_expr_assign(struct gen_context *ctx,
const struct qbe_value *out)
{
assert(out == NULL); // Invariant
+ assert(expr->assign.op == BIN_LEQUAL); // TODO
// TODO: When this grows to support e.g. indexing expressions, we need
// to ensure that the side-effects of the lvalue occur before the
// side-effects of the rvalue.
diff --git a/src/parse.c b/src/parse.c
@@ -1556,12 +1556,14 @@ parse_binding_list(struct lexer *lexer)
}
static struct ast_expression *
-parse_assignment(struct lexer *lexer, struct ast_expression *object, bool indirect)
+parse_assignment(struct lexer *lexer, struct ast_expression *object,
+ bool indirect, enum binarithm_operator op)
{
trenter(TR_PARSE, "assign");
struct ast_expression *value = parse_complex_expression(lexer);
struct ast_expression *expr = mkexpr(&lexer->loc);
expr->type = EXPR_ASSIGN;
+ expr->assign.op = op;
expr->assign.object = object;
expr->assign.value = value;
expr->assign.indirect = indirect;
@@ -1616,7 +1618,27 @@ parse_scope_expression(struct lexer *lexer)
switch (lex(lexer, &tok)) {
case T_EQUAL:
- return parse_assignment(lexer, value, indirect);
+ return parse_assignment(lexer, value, indirect, BIN_LEQUAL);
+ case T_ANDEQ:
+ return parse_assignment(lexer, value, indirect, BIN_BAND);
+ case T_DIVEQ:
+ return parse_assignment(lexer, value, indirect, BIN_DIV);
+ case T_LSHIFTEQ:
+ return parse_assignment(lexer, value, indirect, BIN_LSHIFT);
+ case T_MINUSEQ:
+ return parse_assignment(lexer, value, indirect, BIN_MINUS);
+ case T_MODEQ:
+ return parse_assignment(lexer, value, indirect, BIN_MODULO);
+ case T_OREQ:
+ return parse_assignment(lexer, value, indirect, BIN_BOR);
+ case T_PLUSEQ:
+ return parse_assignment(lexer, value, indirect, BIN_PLUS);
+ case T_RSHIFTEQ:
+ return parse_assignment(lexer, value, indirect, BIN_RSHIFT);
+ case T_TIMESEQ:
+ return parse_assignment(lexer, value, indirect, BIN_TIMES);
+ case T_BXOREQ:
+ return parse_assignment(lexer, value, indirect, BIN_BXOR);
default:
unlex(lexer, &tok);
value = parse_bin_expression(lexer, value, 0);