commit 2dec667c8f427ada97856dd58e4463a0d1d6ed39
parent 1a0505eba114a4685a73a3aa6ab7c42088b8b566
Author: Eyal Sawady <ecs@d2evs.net>
Date: Tue, 19 Jan 2021 11:21:08 -0500
type store: (partially) implement enums
Still needs to check for duplicates and make sure that enum values fit
in the specified precision
Diffstat:
3 files changed, 83 insertions(+), 12 deletions(-)
diff --git a/include/types.h b/include/types.h
@@ -53,6 +53,20 @@ struct type_array {
const struct type *members;
};
+struct type_enum_value {
+ char *name;
+ struct type_enum_value *next;
+ union {
+ intmax_t ival;
+ uintmax_t uval;
+ };
+};
+
+struct type_enum {
+ enum type_storage storage;
+ struct type_enum_value *values;
+};
+
enum variadism {
VARIADISM_NONE,
VARIADISM_C,
@@ -118,6 +132,7 @@ struct type {
union {
struct type_alias alias;
struct type_array array;
+ struct type_enum _enum;
struct type_func func;
struct type_pointer pointer;
struct type_struct_union struct_union;
diff --git a/src/type_store.c b/src/type_store.c
@@ -147,7 +147,6 @@ type_is_assignable(struct type_store *store,
assert(0); // Unreachable
case TYPE_STORAGE_ALIAS:
return type_is_assignable(store, to->alias.type, from);
- case TYPE_STORAGE_ENUM:
case TYPE_STORAGE_STRING:
return to == &builtin_type_const_ptr_char;
case TYPE_STORAGE_VOID:
@@ -171,6 +170,7 @@ type_is_assignable(struct type_store *store,
// handled above:
case TYPE_STORAGE_BOOL:
case TYPE_STORAGE_CHAR:
+ case TYPE_STORAGE_ENUM:
case TYPE_STORAGE_FUNCTION:
case TYPE_STORAGE_NULL:
case TYPE_STORAGE_RUNE:
@@ -569,6 +569,9 @@ tagged_init_from_atype(struct type_store *store,
}
}
+
+static const struct type *type_store_lookup_type(struct type_store *store, const struct type *type);
+
static void
type_init_from_atype(struct type_store *store,
struct type *type,
@@ -627,7 +630,47 @@ type_init_from_atype(struct type_store *store,
}
break;
case TYPE_STORAGE_ENUM:
- assert(0); // TODO
+ type->_enum.storage = atype->_enum.storage;
+ const struct type *storage =
+ builtin_type_for_storage(type->_enum.storage, true);
+ // TODO: Bubble this up
+ assert(type_is_integer(storage));
+ type->size = storage->size;
+ type->align = storage->size;
+
+ // TODO: Check for duplicates
+ struct ast_enum_field *avalue = atype->_enum.values;
+ struct type_enum_value **values = &type->_enum.values;
+ intmax_t iimplicit = 0;
+ uintmax_t uimplicit = 0;
+ while (avalue) {
+ struct type_enum_value *value = *values =
+ xcalloc(sizeof(struct type_enum_value), 1);
+ value->name = strdup(avalue->name);
+ if (avalue->value != NULL) {
+ struct expression in, out;
+ check_expression(store->check_context,
+ avalue->value, &in, NULL);
+ enum eval_result r =
+ eval_expr(store->check_context, &in, &out);
+ // TODO: Bubble this up
+ assert(r == EVAL_OK && type_is_assignable(store, storage, out.result));
+ if (type_is_signed(storage)) {
+ iimplicit = out.constant.ival;
+ } else {
+ uimplicit = out.constant.uval;
+ }
+ }
+ // TODO: Test that the value fits into this precision
+ if (type_is_signed(storage)) {
+ value->ival = iimplicit++;
+ } else {
+ value->uval = uimplicit++;
+ }
+ values = &value->next;
+ avalue = avalue->next;
+ }
+ break;
case TYPE_STORAGE_FUNCTION:
type->size = SIZE_UNDEFINED;
type->align = SIZE_UNDEFINED;
diff --git a/src/types.c b/src/types.c
@@ -126,13 +126,13 @@ type_is_integer(const struct type *type)
case TYPE_STORAGE_TAGGED_UNION:
case TYPE_STORAGE_UNION:
case TYPE_STORAGE_BOOL:
- case TYPE_STORAGE_CHAR:
case TYPE_STORAGE_NULL:
case TYPE_STORAGE_RUNE:
- case TYPE_STORAGE_ENUM:
case TYPE_STORAGE_F32:
case TYPE_STORAGE_F64:
return false;
+ case TYPE_STORAGE_CHAR:
+ case TYPE_STORAGE_ENUM:
case TYPE_STORAGE_I8:
case TYPE_STORAGE_I16:
case TYPE_STORAGE_I32:
@@ -198,12 +198,14 @@ type_is_float(const struct type *type)
return type->storage == TYPE_STORAGE_F32 || type->storage == TYPE_STORAGE_F64;
}
-bool
-type_is_signed(const struct type *type)
+static bool
+storage_is_signed(enum type_storage storage)
{
- switch (type->storage) {
+ switch (storage) {
case TYPE_STORAGE_VOID:
+ case TYPE_STORAGE_ALIAS:
case TYPE_STORAGE_ARRAY:
+ case TYPE_STORAGE_ENUM:
case TYPE_STORAGE_FUNCTION:
case TYPE_STORAGE_POINTER:
case TYPE_STORAGE_SLICE:
@@ -231,14 +233,19 @@ type_is_signed(const struct type *type)
case TYPE_STORAGE_F32:
case TYPE_STORAGE_F64:
return true;
- case TYPE_STORAGE_ALIAS:
- return type_is_signed(type_dealias(type));
- case TYPE_STORAGE_ENUM:
- assert(0); // TODO
}
assert(0); // Unreachable
}
+bool
+type_is_signed(const struct type *type)
+{
+ if (type->storage == TYPE_STORAGE_ENUM) {
+ return storage_is_signed(type->_enum.storage);
+ }
+ return storage_is_signed(type_dealias(type)->storage);
+}
+
uint32_t
type_hash(const struct type *type)
{
@@ -290,7 +297,13 @@ type_hash(const struct type *type)
}
break;
case TYPE_STORAGE_ENUM:
- assert(0); // TODO
+ hash = fnv1a(hash, type->_enum.storage);
+ for (struct type_enum_value *value = type->_enum.values; value;
+ value = value->next) {
+ hash = fnv1a_s(hash, value->name);
+ hash = fnv1a(hash, value->uval);
+ }
+ break;
case TYPE_STORAGE_POINTER:
hash = fnv1a(hash, type->pointer.flags);
hash = fnv1a_u32(hash, type_hash(type->pointer.referent));