harec

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

commit 7caf7c291d14af6743f4274f54155648488d1acc
parent 5a58ba55c2b8e8119ffd28f1c6af348e6bad85d9
Author: Drew DeVault <sir@cmpwn.com>
Date:   Mon, 11 Jan 2021 13:44:38 -0500

Implement spec simplifications for array types

Diffstat:
Minclude/check.h | 1+
Mrt/compile.ha | 14+++-----------
Msrc/check.c | 29+++++++++++++++++++++--------
Msrc/type_store.c | 25+++++++++++++++++++++----
4 files changed, 46 insertions(+), 23 deletions(-)

diff --git a/include/check.h b/include/check.h @@ -11,6 +11,7 @@ struct scope; struct context { struct type_store store; const struct type *current_fntype; + const struct type *type_hint; struct identifier *ns; struct scope *unit; struct scope *scope; diff --git a/rt/compile.ha b/rt/compile.ha @@ -11,19 +11,11 @@ export fn compile(src: str) int = { close(1); close(2); - // XXX: This could be simplified a lot with some compiler - // improvements const path = "./harec"; const param = "-"; - const argv = [ - path: nullable *const char, - param: nullable *const char, - null: nullable *const char, - ]; - const envp = [null: nullable *const char]; - execve(path: *const char, - &argv: *[*]nullable *const char, - &envp: *[*]nullable *const char); + const argv: [3]nullable *const char = [path, param, null]; + const envp: [1]nullable *const char = [null]; + execve(path: *const char, &argv, &envp); abort(); } else { close(pipefd[0]); diff --git a/src/check.c b/src/check.c @@ -273,6 +273,15 @@ check_expr_binding(struct context *ctx, const struct ast_expression_binding *abinding = &aexpr->binding; while (abinding) { + const struct type *type = NULL; + if (abinding->type) { + type = type_store_lookup_atype( + &ctx->store, abinding->type); + type = type_store_lookup_with_flags(&ctx->store, + type, type->flags | abinding->flags); + ctx->type_hint = type; + } + struct identifier ident = { .name = abinding->name, }; @@ -280,15 +289,11 @@ check_expr_binding(struct context *ctx, xcalloc(1, sizeof(struct expression)); check_expression(ctx, abinding->initializer, initializer); - const struct type *type; - if (abinding->type) { - type = type_store_lookup_atype( - &ctx->store, abinding->type); - type = type_store_lookup_with_flags(&ctx->store, - type, type->flags | abinding->flags); - } else { + if (!type) { type = type_store_lookup_with_flags(&ctx->store, initializer->result, abinding->flags); + } else { + ctx->type_hint = NULL; } expect(&aexpr->loc, type->size != 0 && type->size != SIZE_UNDEFINED, @@ -391,6 +396,12 @@ check_expr_array(struct context *ctx, struct ast_array_constant *item = aexpr->constant.array; struct array_constant *cur, **next = &expr->constant.array; + if (ctx->type_hint && ( + ctx->type_hint->storage == TYPE_STORAGE_ARRAY || + ctx->type_hint->storage == TYPE_STORAGE_SLICE)) { + type = ctx->type_hint->array.members; + } + while (item) { struct expression *value = xcalloc(1, sizeof(struct expression)); check_expression(ctx, item->value, value); @@ -401,8 +412,10 @@ check_expr_array(struct context *ctx, type = value->result; } else { // TODO: Assignable? Requires spec update if so - expect(&item->value->loc, value->result == type, + expect(&item->value->loc, + type_is_assignable(&ctx->store, type, value->result), "Array members must be of a uniform type"); + cur->value = lower_implicit_cast(type, cur->value); } if (item->expand) { diff --git a/src/type_store.c b/src/type_store.c @@ -50,6 +50,10 @@ type_is_assignable(struct type_store *store, from, from->flags & ~TYPE_CONST); } + if (to->storage == TYPE_STORAGE_ARRAY + && from->storage == TYPE_STORAGE_ARRAY) { + } + if (to == from) { return true; } @@ -87,11 +91,22 @@ type_is_assignable(struct type_store *store, case TYPE_STORAGE_NULL: return to->pointer.flags & PTR_NULLABLE; case TYPE_STORAGE_POINTER: - if (to->pointer.referent->storage == TYPE_STORAGE_VOID) { + switch (to->pointer.referent->storage) { + case TYPE_STORAGE_VOID: // TODO: const transitivity return to->pointer.referent->flags == from->pointer.referent->flags; - } else if (to->pointer.referent != from->pointer.referent) { - return false; + case TYPE_STORAGE_ARRAY: + if (type_is_assignable(store, + to->pointer.referent, + from->pointer.referent)) { + return true; + } + break; + default: + if (to->pointer.referent != from->pointer.referent) { + return false; + } + break; } if (from->pointer.flags & PTR_NULLABLE) { return to->pointer.flags & PTR_NULLABLE; @@ -117,9 +132,11 @@ type_is_assignable(struct type_store *store, case TYPE_STORAGE_SLICE: return from->storage == TYPE_STORAGE_ARRAY && to->array.members == from->array.members; + case TYPE_STORAGE_ARRAY: + return to->array.length == SIZE_UNDEFINED + && from->array.length != SIZE_UNDEFINED; // The following types are only assignable from themselves, and are // handled above: - case TYPE_STORAGE_ARRAY: case TYPE_STORAGE_BOOL: case TYPE_STORAGE_CHAR: case TYPE_STORAGE_FUNCTION: