harec

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

commit 3ded0a2d4dee1d9715a4a85a6836be71b3bdb04e
parent af58546fbf151a25c075f85c0810034b696d02a7
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sat, 25 Sep 2021 14:27:48 +0200

gen: implement enum reflection

Diffstat:
Minclude/types.h | 2+-
Mrt/types.ha | 4++--
Msrc/gen.c | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Mtests/34-reflect.ha | 28++++++++++++++++++++++++++++
Mtypes/reflect.ha | 20++++++++++++++++----
5 files changed, 128 insertions(+), 11 deletions(-)

diff --git a/include/types.h b/include/types.h @@ -28,6 +28,7 @@ enum type_storage { STORAGE_UINT, STORAGE_UINTPTR, STORAGE_VOID, + STORAGE_TYPE, // Handled separately // Other types STORAGE_ALIAS, STORAGE_ARRAY, @@ -38,7 +39,6 @@ enum type_storage { STORAGE_TAGGED, STORAGE_TUPLE, STORAGE_UNION, - STORAGE_TYPE, STORAGE_FCONST, STORAGE_ICONST, }; diff --git a/rt/types.ha b/rt/types.ha @@ -29,8 +29,8 @@ type types::array = struct { }; type types::builtin = enum u8 { - BOOL, CHAR, F32, F64, I16, I32, I64, I8, INT, NULL, RUNE, SIZE, STR, - TYPE, U16, U32, U64, U8, UINT, UINTPTR, VOID, + BOOL, CHAR, ENUM, F32, F64, I16, I32, I64, I8, INT, NULL, RUNE, SIZE, + STR, U16, U32, U64, U8, UINT, UINTPTR, VOID, TYPE, }; type types::enum_ = struct { diff --git a/src/gen.c b/src/gen.c @@ -2562,7 +2562,7 @@ mktyperef(struct gen_context *ctx, const struct type *type) case STORAGE_TUPLE: case STORAGE_UNION: qdef = xcalloc(1, sizeof(struct qbe_def)); - qdef->name = gen_name(ctx, ".typeinfo.%d"); + qdef->name = gen_name(ctx, "typeinfo.%d"); qdef->kind = Q_DATA; struct qbe_data_item *subitem = &qdef->data.items; @@ -3330,6 +3330,9 @@ gen_type_info(struct gen_context *ctx, char **repr_name = &repr.alias.ident.name; item->type = QD_VALUE; + size_t len = 0; + struct qbe_def *def; + struct qbe_data_item *subitem; switch (type->storage) { case STORAGE_FCONST: case STORAGE_ICONST: @@ -3364,12 +3367,11 @@ gen_type_info(struct gen_context *ctx, item->next = xcalloc(1, sizeof(struct qbe_data_item)); item = item->next; - struct qbe_def *def = xcalloc(1, sizeof(struct qbe_def)); + def = xcalloc(1, sizeof(struct qbe_def)); def->name = gen_name(ctx, "sldata.%d"); def->kind = Q_DATA; - size_t len = 0; - struct qbe_data_item *subitem = &def->data.items; + subitem = &def->data.items; gen_ident_data(ctx, &type->alias.ident, subitem, &len); qbe_append_def(ctx->out, def); @@ -3396,6 +3398,81 @@ gen_type_info(struct gen_context *ctx, item->value.name = ref.name; break; case STORAGE_ENUM: + *repr_name = "enumerated"; + item->value = constw(type_hash(&repr)); + item->next = xcalloc(1, sizeof(struct qbe_data_item)); + item = item->next; + + item->type = QD_ZEROED; + item->zeroed = 4; + item->next = xcalloc(1, sizeof(struct qbe_data_item)); + item = item->next; + + item->type = QD_VALUE; + item->value = constw(type->_enum.storage); + item->value.type = &qbe_byte; + item->next = xcalloc(1, sizeof(struct qbe_data_item)); + item = item->next; + + item->type = QD_ZEROED; + item->zeroed = 7; + item->next = xcalloc(1, sizeof(struct qbe_data_item)); + item = item->next; + + def = xcalloc(1, sizeof(struct qbe_def)); + def->name = gen_name(ctx, "sldata.%d"); + def->kind = Q_DATA; + subitem = &def->data.items; + for (struct type_enum_value *ev = type->_enum.values; + ev; ev = ev->next) { + size_t l = strlen(ev->name); + struct qbe_def *sdef = xcalloc(1, sizeof(struct qbe_def)); + sdef->name = gen_name(ctx, "strdata.%d"); + sdef->kind = Q_DATA; + sdef->data.items.type = QD_STRING; + sdef->data.items.str = xcalloc(1, l); + sdef->data.items.sz = l; + memcpy(sdef->data.items.str, ev->name, l); + qbe_append_def(ctx->out, sdef); + + subitem->value.kind = QV_GLOBAL; + subitem->value.type = &qbe_long; + subitem->value.name = strdup(sdef->name); + subitem->next = xcalloc(1, sizeof(struct qbe_data_item)); + subitem = subitem->next; + subitem->type = QD_VALUE; + subitem->value = constl(l); + subitem->next = xcalloc(1, sizeof(struct qbe_data_item)); + subitem = subitem->next; + subitem->type = QD_VALUE; + subitem->value = constl(l); + subitem->next = xcalloc(1, sizeof(struct qbe_data_item)); + subitem = subitem->next; + + subitem->type = QD_VALUE; + subitem->value = constl(ev->uval); + if (ev->next) { + subitem->next = xcalloc(1, sizeof(struct qbe_data_item)); + subitem = subitem->next; + } + ++len; + } + + qbe_append_def(ctx->out, def); + + item->type = QD_VALUE; + item->value.kind = QV_GLOBAL; + item->value.type = &qbe_long; + item->value.name = strdup(def->name); + item->next = xcalloc(1, sizeof(struct qbe_data_item)); + item = item->next; + item->type = QD_VALUE; + item->value = constl(len); + item->next = xcalloc(1, sizeof(struct qbe_data_item)); + item = item->next; + item->type = QD_VALUE; + item->value = constl(len); + break; case STORAGE_ARRAY: case STORAGE_FUNCTION: case STORAGE_POINTER: diff --git a/tests/34-reflect.ha b/tests/34-reflect.ha @@ -46,7 +46,35 @@ fn aliases() void = { assert(a.ident[0] == "alias"); }; +type watchmen = enum { + VIMES, + CARROT, + ANGUA, + COLON, + NOBBY = -1, +}; + +fn enums() void = { + let ty = types::unwrap(type(watchmen)); + let em = ty.repr as types::enumerated; + assert(em.storage == builtin::INT); + + const cases: [_](str, u64) = [ + ("VIMES", 0), + ("CARROT", 1), + ("ANGUA", 2), + ("COLON", 3), + ("NOBBY", -1: u64), + ]; + for (let i = 0z; i < len(em.values); i += 1) { + const val = em.values[i]; + const expect = cases[i]; + assert(val.0 == expect.0 && val.1 == expect.1); + }; +}; + export fn main() void = { builtins(); aliases(); + enums(); }; diff --git a/types/reflect.ha b/types/reflect.ha @@ -14,6 +14,18 @@ export type typeinfo = struct { // Returns [[typeinfo]] for the provided type. export fn reflect(in: type) *typeinfo = in: *typeinfo; +// Returns [[typeinfo]] for the provided type, unwrapping any aliases along the +// way. +export fn unwrap(in: type) *typeinfo = { + let info = reflect(in); + match (info.repr) { + case a: alias => + return unwrap(a.secondary); + case => + return info; + }; +}; + // Type flags. export type flags = enum u8 { NONE = 0, @@ -23,7 +35,7 @@ export type flags = enum u8 { // Details of the type representation. export type repr = (alias | array | builtin - | enum_ | func | pointer | slice_repr + | enumerated | func | pointer | slice_repr | struct_union | tagged | tuple); // A type alias. @@ -40,12 +52,12 @@ export type array = struct { // A built-in type. export type builtin = enum u8 { - BOOL, CHAR, F32, F64, I16, I32, I64, I8, INT, NULL, RUNE, SIZE, STR, - TYPE, U16, U32, U64, U8, UINT, UINTPTR, VOID, + BOOL, CHAR, ENUM, F32, F64, I16, I32, I64, I8, INT, NULL, RUNE, SIZE, + STR, U16, U32, U64, U8, UINT, UINTPTR, VOID, TYPE, }; // An enum type. -export type enum_ = struct { +export type enumerated = struct { storage: builtin, values: [](str, u64), };