commit 414c1934ccb43c37e9cb733810d4eac813ac9a89
parent d3406b24cd4d899cd4d587513429e39cb682641f
Author: Drew DeVault <sir@cmpwn.com>
Date: Mon, 1 Feb 2021 14:44:08 -0500
Implement casting slices to array pointers
Diffstat:
3 files changed, 18 insertions(+), 9 deletions(-)
diff --git a/src/gen.c b/src/gen.c
@@ -1042,10 +1042,12 @@ gen_expr_cast(struct gen_context *ctx,
struct qbe_value in = {0}, result = {0};
gen_temp(ctx, &result, qtype_for_type(ctx, to, false), "cast.out.%d");
- // Special case: str -> *const char
- if (to->storage == TYPE_STORAGE_POINTER
+ // Special case: str -> *const char; slice -> ptr
+ if ((to->storage == TYPE_STORAGE_POINTER
&& to->pointer.referent->storage == TYPE_STORAGE_CHAR
- && from->storage == TYPE_STORAGE_STRING) {
+ && from->storage == TYPE_STORAGE_STRING)
+ || (to->storage == TYPE_STORAGE_POINTER
+ && from->storage == TYPE_STORAGE_SLICE)) {
alloc_temp(ctx, &in, from, "cast.in.%d");
in.indirect = false;
gen_expression(ctx, expr->cast.value, &in);
@@ -1123,11 +1125,8 @@ gen_expr_cast(struct gen_context *ctx,
case TYPE_STORAGE_F64:
assert(0); // TODO
case TYPE_STORAGE_ARRAY:
- if (from->storage == TYPE_STORAGE_ARRAY) {
- pushi(ctx->current, &result, Q_COPY, &in, NULL);
- break;
- }
- assert(0); // TODO: Convert slice to array
+ assert(from->storage == TYPE_STORAGE_ARRAY);
+ pushi(ctx->current, &result, Q_COPY, &in, NULL);
break;
case TYPE_STORAGE_SLICE:
if (from->storage == TYPE_STORAGE_SLICE) {
diff --git a/src/types.c b/src/types.c
@@ -579,7 +579,9 @@ type_is_castable(const struct type *to, const struct type *from)
}
return from->storage == TYPE_STORAGE_POINTER
|| from->storage == TYPE_STORAGE_NULL
- || from->storage == TYPE_STORAGE_UINTPTR;
+ || from->storage == TYPE_STORAGE_UINTPTR
+ || (to->pointer.referent->storage == TYPE_STORAGE_ARRAY
+ && from->storage == TYPE_STORAGE_SLICE);
case TYPE_STORAGE_SLICE:
case TYPE_STORAGE_ARRAY:
return from->storage == TYPE_STORAGE_SLICE
diff --git a/tests/08-slices.ha b/tests/08-slices.ha
@@ -29,6 +29,14 @@ fn storage() void = {
};
};
+fn casting() void = {
+ let x: []int = [1, 2, 3, 4, 5];
+ let y = x: *[5]int;
+ for (let i = 0z; i < len(x); i += 1z) {
+ assert(x[i] == y[i]);
+ };
+};
+
fn measurements() void = {
let x: []int = [1, 2, 3, 4, 5];
assert(size([]int) == size(*[*]int) + size(size) * 2z);