commit 5b2bea4b8b7a9176c560fef287b5493ff70b68b7
parent 5a7dfb896f2c5e8037523b9c1fd842ea775bb038
Author: Eyal Sawady <ecs@d2evs.net>
Date: Fri, 13 Aug 2021 09:15:31 +0000
append: implement auto-deref
Signed-off-by: Eyal Sawady <ecs@d2evs.net>
Diffstat:
3 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/src/check.c b/src/check.c
@@ -338,11 +338,16 @@ check_expr_append(struct context *ctx,
expr->append.expr = xcalloc(sizeof(struct expression), 1);
errors = check_expression(ctx, aexpr->append.expr, expr->append.expr,
NULL, errors);
- if (type_dealias(expr->append.expr->result)->storage != STORAGE_SLICE) {
+ const struct type *stype = type_dereference(expr->append.expr->result);
+ if (!stype) {
+ return error(aexpr->access.array->loc, expr, errors,
+ "Cannot dereference nullable pointer for append");
+ }
+ if (stype->storage != STORAGE_SLICE) {
return error(aexpr->append.expr->loc, expr, errors,
"append must operate on a slice");
}
- if (type_dealias(expr->append.expr->result)->flags & TYPE_CONST) {
+ if (stype->flags & TYPE_CONST) {
return error(aexpr->append.expr->loc, expr, errors,
"append must operate on a mutable slice");
}
@@ -352,8 +357,7 @@ check_expr_append(struct context *ctx,
return error(aexpr->append.expr->loc, expr, errors,
"append must operate on a slice object");
}
- const struct type *memb =
- type_dealias(expr->append.expr->result)->array.members;
+ const struct type *memb = stype->array.members;
struct append_values **next = &expr->append.values;
for (struct ast_append_values *avalue = aexpr->append.values; avalue;
avalue = avalue->next) {
@@ -371,11 +375,10 @@ check_expr_append(struct context *ctx,
next = &value->next;
}
if (aexpr->append.variadic != NULL) {
- const struct type *type = expr->append.expr->result;
expr->append.variadic = xcalloc(sizeof(struct expression), 1);
errors = check_expression(ctx, aexpr->append.variadic,
- expr->append.variadic, type, errors);
- if (!type_is_assignable(type, expr->append.variadic->result)) {
+ expr->append.variadic, stype, errors);
+ if (!type_is_assignable(stype, expr->append.variadic->result)) {
return error(aexpr->append.variadic->loc, expr, errors,
"appended slice must be assignable to slice type");
}
diff --git a/src/gen.c b/src/gen.c
@@ -496,8 +496,8 @@ static struct gen_value
gen_expr_append(struct gen_context *ctx, const struct expression *expr)
{
struct gen_value slice = gen_expr(ctx, expr->append.expr);
+ slice = gen_autoderef(ctx, slice);
struct qbe_value qslice = mkqval(ctx, &slice);
- // TODO: Automatic dereference here
struct qbe_value ptr = mkqtmp(ctx, ctx->arch.ptr, ".%d");
struct qbe_value offs = constl(builtin_type_size.size);
diff --git a/tests/19-append.ha b/tests/19-append.ha
@@ -6,7 +6,10 @@ fn simple() void = {
assert(len(x) == 6);
assert(x[0] == 1 && x[1] == 2 && x[2] == 3 && x[3] == 4 && x[4] == 5);
assert(x[5] == 6);
- append(x, 7, 8, 9);
+ let y = &x;
+ append(y, 7, 8);
+ let z = &y;
+ append(y, 9);
assert(x[0] == 1 && x[1] == 2 && x[2] == 3 && x[3] == 4 && x[4] == 5);
assert(x[5] == 6 && x[6] == 7 && x[7] == 8 && x[8] == 9);
@@ -33,7 +36,8 @@ fn variadic() void = {
let y: []int = alloc([1, 2, 3], 3);
let z = [128, 256];
append(y, x...);
- append(y, z...);
+ let w = &y;
+ append(w, z...);
assert(len(y) == 12);
assert(y[0] == 1 && y[1] == 2 && y[2] == 3 && y[3] == 1 && y[4] == 2);
assert(y[5] == 4 && y[6] == 8 && y[7] == 16 && y[8] == 32);
@@ -46,7 +50,8 @@ fn static_append() void = {
let buf: [4]int = [0...];
let x = buf[..0];
static append(x, 1, 2);
- static append(x, [3, 4]...);
+ let y = &x;
+ static append(y, [3, 4]...);
assert(x[0] == 1 && x[1] == 2 && x[2] == 3 && x[3] == 4);
assert(buf[0] == 1 && buf[1] == 2 && buf[2] == 3 && buf[3] == 4);