harec

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

commit 65fabeab00b34c85d8585483e9dea5c9dcdb7f16
parent 9e727edfbe7d08d197500fd5a4cd29f24c5156f5
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sat, 26 Dec 2020 11:26:26 -0500

check: implement array literals

Diffstat:
Minclude/expr.h | 2+-
Minclude/type_store.h | 3+++
Minclude/types.h | 2+-
Msrc/check.c | 45+++++++++++++++++++++++++++++++++++++++++++--
Msrc/type_store.c | 34+++++++++++++++++++++++++++++++---
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); +}