commit 9e727edfbe7d08d197500fd5a4cd29f24c5156f5
parent 4db3a7129372f4a13421fb70c50fa244b3a1813e
Author: Drew DeVault <sir@cmpwn.com>
Date: Sat, 26 Dec 2020 11:10:28 -0500
type store: rig up array types
Diffstat:
4 files changed, 71 insertions(+), 5 deletions(-)
diff --git a/include/expr.h b/include/expr.h
@@ -92,6 +92,12 @@ struct expression_call {
struct call_argument *args;
};
+struct array_constant {
+ struct expression *expr;
+ struct array_constant *next;
+ bool expand;
+};
+
union expression_constant {
struct {
char *sval;
@@ -102,7 +108,8 @@ union expression_constant {
intmax_t ival;
uintmax_t uval;
uint32_t rune;
- // TODO: Array, slice, struct constants
+ struct array_constant *array;
+ // TODO: Struct constants
};
struct expressions {
diff --git a/include/types.h b/include/types.h
@@ -40,6 +40,15 @@ enum type_storage {
struct type;
+#define SIZE_UNDEFINED ((size_t)-1)
+#define ALIGN_UNDEFINED ((size_t)-1)
+
+struct type_array {
+ size_t length; // SIZE_UNDEFINED for [*] or slices
+ const struct type *members;
+ bool extensible;
+};
+
enum variadism {
VARIADISM_NONE,
VARIADISM_C,
@@ -75,14 +84,12 @@ enum type_flags {
TYPE_CONST = 1 << 0,
};
-#define SIZE_UNDEFINED ((size_t)-1)
-#define ALIGN_UNDEFINED ((size_t)-1)
-
struct type {
enum type_storage storage;
unsigned int flags;
size_t size, align;
union {
+ struct type_array array;
struct type_func func;
struct type_pointer pointer;
};
diff --git a/src/eval.c b/src/eval.c
@@ -7,13 +7,24 @@
#include "types.h"
enum eval_result
+eval_const(struct context *ctx, struct expression *in, struct expression *out)
+{
+ out->type = EXPR_CONSTANT;
+ out->result = in->result;
+ out->constant = in->constant;
+ return EVAL_OK;
+}
+
+enum eval_result
eval_expr(struct context *ctx, struct expression *in, struct expression *out)
{
switch (in->type) {
case EXPR_ACCESS:
case EXPR_BINARITHM:
case EXPR_CAST:
+ assert(0); // TODO
case EXPR_CONSTANT:
+ return eval_const(ctx, in, out);
case EXPR_CONTINUE:
case EXPR_FOR:
case EXPR_MEASURE:
diff --git a/src/type_store.c b/src/type_store.c
@@ -1,9 +1,29 @@
#include <assert.h>
#include <stdlib.h>
#include "check.h"
+#include "eval.h"
#include "type_store.h"
#include "util.h"
+static size_t
+ast_array_len(struct type_store *store, const struct ast_type *atype)
+{
+ // TODO: Maybe we should cache these
+ struct expression in, out;
+ if (atype->array.length == NULL) {
+ return SIZE_UNDEFINED;
+ }
+ check_expression(store->check_context, atype->array.length, &in);
+ enum eval_result r = eval_expr(store->check_context, &in, &out);
+ // TODO: Bubble up these errors:
+ assert(r == EVAL_OK);
+ assert(type_is_integer(out.result));
+ if (type_is_signed(out.result)) {
+ assert(out.constant.ival > 0);
+ }
+ return (size_t)out.constant.uval;
+}
+
bool
type_is_assignable(struct type_store *store,
const struct type *to,
@@ -154,6 +174,7 @@ atype_hash(struct type_store *store, const struct ast_type *type)
unsigned long hash = DJB2_INIT;
hash = djb2(hash, type->storage);
hash = djb2(hash, type->flags);
+
switch (type->storage) {
case TYPE_STORAGE_BOOL:
case TYPE_STORAGE_CHAR:
@@ -176,8 +197,11 @@ atype_hash(struct type_store *store, const struct ast_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, atype_hash(store, type->array.members));
+ hash = djb2(hash, ast_array_len(store, type));
+ break;
case TYPE_STORAGE_FUNCTION:
hash = djb2(hash, atype_hash(store, type->func.result));
hash = djb2(hash, type->func.variadism);
@@ -303,7 +327,10 @@ type_eq_atype(struct type_store *store,
case TYPE_STORAGE_VOID:
return true;
case TYPE_STORAGE_ALIAS:
+ assert(0); // TODO
case TYPE_STORAGE_ARRAY:
+ return type->array.length == ast_array_len(store, atype)
+ && type_eq_atype(store, type->array.members, atype->array.members);
case TYPE_STORAGE_ENUM:
assert(0); // TODO
case TYPE_STORAGE_FUNCTION:
@@ -433,7 +460,21 @@ type_init_from_atype(struct type_store *store,
case TYPE_STORAGE_VOID:
assert(0); // Invariant
case TYPE_STORAGE_ALIAS:
+ assert(0); // TODO
case TYPE_STORAGE_ARRAY:
+ type->array.length = ast_array_len(store, atype);
+ type->array.members = type_store_lookup_atype(
+ store, atype->array.members);
+ // TODO: Bubble this up:
+ assert(type->array.members->size != SIZE_UNDEFINED);
+
+ type->align = type->array.members->align;
+ if (type->array.length == SIZE_UNDEFINED) {
+ type->size = SIZE_UNDEFINED;
+ } else {
+ type->size = type->array.members->size * type->array.length;
+ }
+ break;
case TYPE_STORAGE_ENUM:
assert(0); // TODO
case TYPE_STORAGE_FUNCTION: