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:
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: