commit 65fabeab00b34c85d8585483e9dea5c9dcdb7f16
parent 9e727edfbe7d08d197500fd5a4cd29f24c5156f5
Author: Drew DeVault <sir@cmpwn.com>
Date: Sat, 26 Dec 2020 11:26:26 -0500
check: implement array literals
Diffstat:
5 files changed, 79 insertions(+), 7 deletions(-)
diff --git a/include/expr.h b/include/expr.h
@@ -93,7 +93,7 @@ struct expression_call {
};
struct array_constant {
- struct expression *expr;
+ struct expression *value;
struct array_constant *next;
bool expand;
};
diff --git a/include/type_store.h b/include/type_store.h
@@ -35,4 +35,7 @@ const struct type *type_store_lookup_with_flags(struct type_store *store,
const struct type *type_store_lookup_pointer(struct type_store *store,
const struct type *referent, unsigned int ptrflags);
+const struct type *type_store_lookup_array(struct type_store *store,
+ const struct type *members, size_t len, bool expandable);
+
#endif
diff --git a/include/types.h b/include/types.h
@@ -46,7 +46,7 @@ struct type;
struct type_array {
size_t length; // SIZE_UNDEFINED for [*] or slices
const struct type *members;
- bool extensible;
+ bool expandable;
};
enum variadism {
diff --git a/src/check.c b/src/check.c
@@ -236,6 +236,45 @@ check_expr_call(struct context *ctx,
}
static void
+check_expr_array(struct context *ctx,
+ const struct ast_expression *aexpr,
+ struct expression *expr)
+{
+ size_t len = 0;
+ bool expandable = false;
+ const struct type *type = NULL;
+ struct ast_array_constant *item = aexpr->constant.array;
+ struct array_constant *cur, **next = &expr->constant.array;
+
+ while (item) {
+ struct expression *value = xcalloc(1, sizeof(struct expression));
+ check_expression(ctx, item->value, value);
+ cur = *next = xcalloc(1, sizeof(struct array_constant));
+ cur->value = value;
+
+ if (!type) {
+ type = value->result;
+ } else {
+ // TODO: Assignable? Requires spec update if so
+ expect(value->result == type,
+ "Array members must be of a uniform type");
+ }
+
+ if (item->expand) {
+ expandable = true;
+ cur->expand = true;
+ assert(!item->next);
+ }
+
+ item = item->next;
+ next = &cur->next;
+ ++len;
+ }
+
+ expr->result = type_store_lookup_array(&ctx->store, type, len, expandable);
+}
+
+static void
check_expr_constant(struct context *ctx,
const struct ast_expression *aexpr,
struct expression *expr)
@@ -270,19 +309,21 @@ check_expr_constant(struct context *ctx,
case TYPE_STORAGE_VOID:
// No storage
break;
+ case TYPE_STORAGE_ARRAY:
+ check_expr_array(ctx, aexpr, expr);
+ break;
case TYPE_STORAGE_F32:
case TYPE_STORAGE_F64:
case TYPE_STORAGE_STRING:
+ case TYPE_STORAGE_STRUCT:
assert(0); // TODO
case TYPE_STORAGE_CHAR:
case TYPE_STORAGE_ENUM:
case TYPE_STORAGE_UINTPTR:
case TYPE_STORAGE_ALIAS:
- case TYPE_STORAGE_ARRAY:
case TYPE_STORAGE_FUNCTION:
case TYPE_STORAGE_POINTER:
case TYPE_STORAGE_SLICE:
- case TYPE_STORAGE_STRUCT:
case TYPE_STORAGE_TAGGED_UNION:
case TYPE_STORAGE_UNION:
assert(0); // Invariant
diff --git a/src/type_store.c b/src/type_store.c
@@ -161,9 +161,8 @@ builtin_type_for_storage(enum type_storage storage, bool is_const)
case TYPE_STORAGE_STRUCT:
case TYPE_STORAGE_TAGGED_UNION:
case TYPE_STORAGE_UNION:
- return NULL;
case TYPE_STORAGE_ENUM:
- assert(0); // TODO
+ return NULL;
}
assert(0); // Unreachable
}
@@ -255,8 +254,11 @@ type_hash(struct type_store *store, const struct type *type)
case TYPE_STORAGE_VOID:
break; // built-ins
case TYPE_STORAGE_ALIAS:
- case TYPE_STORAGE_ARRAY:
assert(0); // TODO
+ case TYPE_STORAGE_ARRAY:
+ hash = djb2(hash, type_hash(store, type->array.members));
+ hash = djb2(hash, type->array.length);
+ break;
case TYPE_STORAGE_FUNCTION:
hash = djb2(hash, type_hash(store, type->func.result));
hash = djb2(hash, type->func.variadism);
@@ -540,7 +542,18 @@ type_init_from_type(struct type_store *store,
case TYPE_STORAGE_VOID:
assert(0); // Invariant
case TYPE_STORAGE_ALIAS:
+ assert(0); // TODO
case TYPE_STORAGE_ARRAY:
+ new->array.members = old->array.members;
+ new->array.length = old->array.length;
+ new->array.expandable = old->array.expandable;
+ new->align = new->array.members->align;
+ if (new->array.length == SIZE_UNDEFINED) {
+ new->size = SIZE_UNDEFINED;
+ } else {
+ new->size = new->array.members->size * new->array.length;
+ }
+ break;
case TYPE_STORAGE_ENUM:
case TYPE_STORAGE_FUNCTION:
assert(0); // TODO
@@ -636,3 +649,18 @@ type_store_lookup_pointer(struct type_store *store,
};
return type_store_lookup_type(store, &ptr);
}
+
+const struct type *
+type_store_lookup_array(struct type_store *store,
+ const struct type *members, size_t len, bool expandable)
+{
+ struct type array = {
+ .storage = TYPE_STORAGE_ARRAY,
+ .array = {
+ .members = members,
+ .length = len,
+ .expandable = expandable,
+ },
+ };
+ return type_store_lookup_type(store, &array);
+}