commit 3ded0a2d4dee1d9715a4a85a6836be71b3bdb04e
parent af58546fbf151a25c075f85c0810034b696d02a7
Author: Drew DeVault <sir@cmpwn.com>
Date: Sat, 25 Sep 2021 14:27:48 +0200
gen: implement enum reflection
Diffstat:
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),
};