commit 633f10d43ff4bcaf6720e5905f71d1392aecb136
parent d8c5440debe5b15d4c58b0864fb17b17c33bd986
Author: Sebastian <sebastian@sebsite.pw>
Date: Sun, 5 Feb 2023 00:35:26 -0500
Remove indirect field from assign expression
Assign expressions allow any arbitary expression for the object being
assigned to, including a dereference expression. Removing the indirect
field and instead just using a dereference expression here removes some
code duplication.
This field originally existed because it's used within parse, but it's
easy to just have parse construct a pointer dereference AST expression
rather than passing an "indirect" parameter everywhere.
Signed-off-by: Sebastian <sebastian@sebsite.pw>
Diffstat:
5 files changed, 51 insertions(+), 77 deletions(-)
diff --git a/include/ast.h b/include/ast.h
@@ -151,7 +151,6 @@ struct ast_expression_assert {
struct ast_expression_assign {
enum binarithm_operator op;
struct ast_expression *object, *value;
- bool indirect;
};
struct ast_expression_binarithm {
diff --git a/include/expr.h b/include/expr.h
@@ -127,7 +127,6 @@ enum binarithm_operator {
struct expression_assign {
enum binarithm_operator op;
struct expression *object, *value;
- bool indirect;
};
struct expression_binarithm {
diff --git a/src/check.c b/src/check.c
@@ -710,7 +710,6 @@ check_expr_assign(struct context *ctx,
{
expr->type = EXPR_ASSIGN;
expr->result = &builtin_type_void;
- expr->assign.indirect = aexpr->assign.indirect;
struct expression *object = xcalloc(1, sizeof(struct expression));
struct expression *value = xcalloc(1, sizeof(struct expression));
@@ -718,55 +717,26 @@ check_expr_assign(struct context *ctx,
expr->assign.op = aexpr->assign.op;
- if (aexpr->assign.indirect) {
- const struct type *otype = type_dealias(object->result);
- if (otype->storage != STORAGE_POINTER) {
- error(ctx, aexpr->loc, expr,
- "Cannot dereference non-pointer type for assignment");
- return;
- }
- if (otype->pointer.flags & PTR_NULLABLE) {
- error(ctx, aexpr->loc, expr,
- "Cannot dereference nullable pointer type");
- return;
- }
- check_expression(ctx, aexpr->assign.value, value, otype->pointer.referent);
- if (!type_is_assignable(otype->pointer.referent,
- value->result)) {
- error(ctx, aexpr->loc, expr,
- "Value type is not assignable to pointer type");
- return;
- }
- value = lower_implicit_cast(otype->pointer.referent, value);
- } else {
- check_expression(ctx, aexpr->assign.value, value, object->result);
- assert(object->type == EXPR_CONSTANT // If error
- || object->type == EXPR_ACCESS
- || object->type == EXPR_SLICE); // Invariant
- if (object->type == EXPR_SLICE) {
- if (expr->assign.op != BIN_LEQUAL) {
- error(ctx, aexpr->assign.object->loc, expr,
- "Slice assignments may not have a binop");
- return;
- }
- }
- if (object->result->flags & TYPE_CONST) {
- error(ctx, aexpr->loc, expr,
- "Cannot assign to const object");
- return;
- }
- if (!type_is_assignable(object->result, value->result)) {
- char *valtypename = gen_typename(value->result);
- char *objtypename = gen_typename(object->result);
- error(ctx, aexpr->loc, expr,
- "rvalue type (%s) is not assignable to lvalue (%s)",
- valtypename, objtypename);
- free(valtypename);
- free(objtypename);
+ check_expression(ctx, aexpr->assign.value, value, object->result);
+
+ if (object->type == EXPR_SLICE) {
+ if (expr->assign.op != BIN_LEQUAL) {
+ error(ctx, aexpr->assign.object->loc, expr,
+ "Slice assignments may not have a binop");
return;
}
- value = lower_implicit_cast(object->result, value);
}
+ if (!type_is_assignable(object->result, value->result)) {
+ char *valtypename = gen_typename(value->result);
+ char *objtypename = gen_typename(object->result);
+ error(ctx, aexpr->loc, expr,
+ "rvalue type (%s) is not assignable to lvalue (%s)",
+ valtypename, objtypename);
+ free(valtypename);
+ free(objtypename);
+ return;
+ }
+ value = lower_implicit_cast(object->result, value);
expr->assign.object = object;
expr->assign.value = value;
diff --git a/src/gen.c b/src/gen.c
@@ -902,14 +902,20 @@ gen_expr_assign(struct gen_context *ctx, const struct expression *expr)
if (object->type == EXPR_SLICE) {
return gen_expr_assign_slice(ctx, expr);
}
- assert(object->type == EXPR_ACCESS || expr->assign.indirect); // Invariant
struct gen_value obj;
- if (expr->assign.indirect) {
- obj = gen_expr(ctx, object);
- obj.type = type_dealias(object->result)->pointer.referent;
- } else {
+ switch (object->type) {
+ case EXPR_ACCESS:
obj = gen_expr_access_addr(ctx, object);
+ break;
+ case EXPR_UNARITHM:
+ assert(object->unarithm.op == UN_DEREF); // Invariant
+ obj = gen_expr(ctx, object->unarithm.operand);
+ assert(type_dealias(obj.type)->storage == STORAGE_POINTER);
+ obj.type = type_dealias(obj.type)->pointer.referent;
+ break;
+ default:
+ abort(); // Invariant
}
if (expr->assign.op == BIN_LEQUAL) {
gen_expr_at(ctx, value, obj);
diff --git a/src/parse.c b/src/parse.c
@@ -2138,7 +2138,7 @@ parse_binding_list(struct lexer *lexer, bool is_static)
static struct ast_expression *
parse_assignment(struct lexer *lexer, struct ast_expression *object,
- bool indirect, enum binarithm_operator op)
+ enum binarithm_operator op)
{
struct ast_expression *value = parse_expression(lexer);
struct ast_expression *expr = mkexpr(&lexer->loc);
@@ -2146,7 +2146,6 @@ parse_assignment(struct lexer *lexer, struct ast_expression *object,
expr->assign.op = op;
expr->assign.object = object;
expr->assign.value = value;
- expr->assign.indirect = indirect;
return expr;
}
@@ -2365,44 +2364,45 @@ parse_expression(struct lexer *lexer)
break;
}
+ if (indirect) {
+ struct ast_expression *deref = mkexpr(&value->loc);
+ deref->type = EXPR_UNARITHM;
+ deref->unarithm.op = UN_DEREF;
+ deref->unarithm.operand = value;
+ value = deref;
+ }
+
switch (lex(lexer, &tok)) {
case T_EQUAL:
- return parse_assignment(lexer, value, indirect, BIN_LEQUAL);
+ return parse_assignment(lexer, value, BIN_LEQUAL);
case T_BANDEQ:
- return parse_assignment(lexer, value, indirect, BIN_BAND);
+ return parse_assignment(lexer, value, BIN_BAND);
case T_LANDEQ:
- return parse_assignment(lexer, value, indirect, BIN_LAND);
+ return parse_assignment(lexer, value, BIN_LAND);
case T_DIVEQ:
- return parse_assignment(lexer, value, indirect, BIN_DIV);
+ return parse_assignment(lexer, value, BIN_DIV);
case T_LSHIFTEQ:
- return parse_assignment(lexer, value, indirect, BIN_LSHIFT);
+ return parse_assignment(lexer, value, BIN_LSHIFT);
case T_MINUSEQ:
- return parse_assignment(lexer, value, indirect, BIN_MINUS);
+ return parse_assignment(lexer, value, BIN_MINUS);
case T_MODEQ:
- return parse_assignment(lexer, value, indirect, BIN_MODULO);
+ return parse_assignment(lexer, value, BIN_MODULO);
case T_BOREQ:
- return parse_assignment(lexer, value, indirect, BIN_BOR);
+ return parse_assignment(lexer, value, BIN_BOR);
case T_LOREQ:
- return parse_assignment(lexer, value, indirect, BIN_LOR);
+ return parse_assignment(lexer, value, BIN_LOR);
case T_PLUSEQ:
- return parse_assignment(lexer, value, indirect, BIN_PLUS);
+ return parse_assignment(lexer, value, BIN_PLUS);
case T_RSHIFTEQ:
- return parse_assignment(lexer, value, indirect, BIN_RSHIFT);
+ return parse_assignment(lexer, value, BIN_RSHIFT);
case T_TIMESEQ:
- return parse_assignment(lexer, value, indirect, BIN_TIMES);
+ return parse_assignment(lexer, value, BIN_TIMES);
case T_BXOREQ:
- return parse_assignment(lexer, value, indirect, BIN_BXOR);
+ return parse_assignment(lexer, value, BIN_BXOR);
case T_LXOREQ:
- return parse_assignment(lexer, value, indirect, BIN_LXOR);
+ return parse_assignment(lexer, value, BIN_LXOR);
default:
unlex(lexer, &tok);
- if (indirect) {
- struct ast_expression *deref = mkexpr(&value->loc);
- deref->type = EXPR_UNARITHM;
- deref->unarithm.op = UN_DEREF;
- deref->unarithm.operand = value;
- value = deref;
- }
value = parse_cast_expression(lexer, value);
value = parse_bin_expression(lexer, value, 0);
return value;