harec

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

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:
Minclude/types.h | 15+++++++++++++++
Msrc/type_store.c | 47+++++++++++++++++++++++++++++++++++++++++++++--
Msrc/types.c | 33+++++++++++++++++++++++----------
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));