commit 6a7e41acb0ba1eed37d06f6fe601cec20535db6c
parent dfc768c822f78bd45cf20fbbf1a3a0dbf22a1561
Author: Drew DeVault <sir@cmpwn.com>
Date: Sun, 22 Aug 2021 15:29:04 +0200
eval, gen: implement tagged types
Signed-off-by: Drew DeVault <sir@cmpwn.com>
Diffstat:
4 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/include/expr.h b/include/expr.h
@@ -171,6 +171,11 @@ struct tuple_constant {
struct tuple_constant *next;
};
+struct tagged_constant {
+ const struct type *tag;
+ struct expression *value;
+};
+
struct expression_constant {
// If non-null, ival is an offset from this object's address
const struct scope_object *object;
@@ -187,6 +192,7 @@ struct expression_constant {
struct array_constant *array;
struct struct_constant *_struct;
struct tuple_constant *tuple;
+ struct tagged_constant tagged;
};
};
diff --git a/src/eval.c b/src/eval.c
@@ -380,6 +380,7 @@ eval_cast(struct context *ctx, struct expression *in, struct expression *out)
out->type = EXPR_CONSTANT;
out->result = to;
+ const struct type *subtype;
switch (to->storage) {
case STORAGE_POINTER:
if (from->storage == STORAGE_NULL) {
@@ -431,11 +432,21 @@ eval_cast(struct context *ctx, struct expression *in, struct expression *out)
ftrunc(to, (double)val.constant.uval);
}
return EVAL_OK;
+ case STORAGE_TAGGED:
+ subtype = tagged_select_subtype(to, from);
+ out->constant.tagged.value =
+ xcalloc(1, sizeof(struct expression));
+ if (subtype) {
+ out->constant.tagged.tag = subtype;
+ *out->constant.tagged.value = val;
+ } else {
+ out->constant.tagged.tag = from;
+ *out->constant.tagged.value = val;
+ }
+ return EVAL_OK;
case STORAGE_CHAR:
case STORAGE_ENUM:
case STORAGE_NULL:
- case STORAGE_TAGGED:
- assert(0); // TODO
case STORAGE_ALIAS:
assert(0); // Handled above
case STORAGE_BOOL:
diff --git a/src/gen.c b/src/gen.c
@@ -2628,6 +2628,7 @@ gen_expr_with(struct gen_context *ctx,
static struct qbe_data_item *gen_data_item(struct gen_context *,
struct expression *, struct qbe_data_item *);
+
static void
gen_function_decl(struct gen_context *ctx, const struct declaration *decl)
{
@@ -3035,6 +3036,12 @@ gen_data_item(struct gen_context *ctx, struct expression *expr,
}
break;
case STORAGE_TAGGED:
+ item->type = QD_VALUE;
+ item->value = constw((uint32_t)constant->tagged.tag->id);
+ item->next = xcalloc(1, sizeof(struct qbe_data_item));
+ item = item->next;
+ gen_data_item(ctx, constant->tagged.value, item);
+ break;
case STORAGE_UNION:
assert(0); // TODO
case STORAGE_ALIAS:
diff --git a/tests/11-globals.ha b/tests/11-globals.ha
@@ -68,6 +68,15 @@ fn pointers() void = {
assert(ptr == &val && *ptr == val);
};
+type foo = (int | uint);
+
+let subtype: foo = 10u;
+
+fn tagged() void = {
+ assert(subtype is uint);
+ // TODO: subset-compat
+};
+
export fn main() void = {
// TODO: Expand this test:
// - Declare & validate globals of more types