commit 56853be54d30eded69604d2d6efd3cefd6e1e805
parent dcce8b33f57727f8b29dce99a5bf0785b20cb99e
Author: Drew DeVault <sir@cmpwn.com>
Date: Wed, 23 Dec 2020 13:24:50 -0500
check: initial support for assignments
Diffstat:
4 files changed, 37 insertions(+), 6 deletions(-)
diff --git a/include/ast.h b/include/ast.h
@@ -91,7 +91,7 @@ struct ast_expression_access {
};
struct ast_expression_assign {
- struct ast_expression *lvalue, *rvalue;
+ struct ast_expression *object, *value;
bool indirect;
};
diff --git a/include/expr.h b/include/expr.h
@@ -44,6 +44,11 @@ struct expression_access {
// TODO: Details for index, field selection
};
+struct expression_assign {
+ struct expression *object, *value;
+ bool indirect;
+};
+
enum binarithm_operator {
BIN_BAND,
BIN_BNOT,
@@ -112,6 +117,7 @@ struct expression {
bool terminates;
union {
struct expression_access access;
+ struct expression_assign assign;
struct expression_binarithm binarithm;
struct expression_binding binding;
union expression_constant constant;
diff --git a/src/check.c b/src/check.c
@@ -53,6 +53,29 @@ check_expr_access(struct context *ctx,
}
static void
+check_expr_assign(struct context *ctx,
+ const struct ast_expression *aexpr,
+ struct expression *expr)
+{
+ trace(TR_CHECK, "assign");
+ expr->type = EXPR_ASSIGN;
+ expr->assign.indirect = aexpr->assign.indirect;
+ expr->assign.object = calloc(1, sizeof(struct expression));
+ expr->assign.value = calloc(1, sizeof(struct expression));
+
+ check_expression(ctx, aexpr->assign.object, expr->assign.object);
+ check_expression(ctx, aexpr->assign.value, expr->assign.value);
+
+ if (aexpr->assign.indirect) {
+ assert(0); // TODO
+ } else {
+ assert(expr->assign.object->type == EXPR_ACCESS); // Invariant
+ // TODO: Test assignability rules:
+ assert(expr->assign.object->result->storage == expr->assign.value->result->storage);
+ }
+}
+
+static void
check_expr_binarithm(struct context *ctx,
const struct ast_expression *aexpr,
struct expression *expr)
@@ -262,8 +285,10 @@ check_expression(struct context *ctx,
check_expr_access(ctx, aexpr, expr);
break;
case EXPR_ASSERT:
- case EXPR_ASSIGN:
assert(0); // TODO
+ case EXPR_ASSIGN:
+ check_expr_assign(ctx, aexpr, expr);
+ break;
case EXPR_BINARITHM:
check_expr_binarithm(ctx, aexpr, expr);
break;
diff --git a/src/parse.c b/src/parse.c
@@ -778,14 +778,14 @@ parse_binding_list(struct parser *par)
}
static struct ast_expression *
-parse_assignment(struct parser *par, struct ast_expression *lvalue, bool indirect)
+parse_assignment(struct parser *par, struct ast_expression *object, bool indirect)
{
trenter(TR_PARSE, "assign");
- struct ast_expression *rvalue = parse_complex_expression(par);
+ struct ast_expression *value = parse_complex_expression(par);
struct ast_expression *expr = calloc(1, sizeof(struct ast_expression));
expr->type = EXPR_ASSIGN;
- expr->assign.lvalue = lvalue;
- expr->assign.rvalue = rvalue;
+ expr->assign.object = object;
+ expr->assign.value = value;
expr->assign.indirect = indirect;
trleave(TR_PARSE, NULL);
return expr;