harec

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

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:
Msrc/check.c | 17++++++++++-------
Msrc/gen.c | 2+-
Mtests/19-append.ha | 11++++++++---
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);