commit 7c0ed9d0d8cca8f786d60b14602de9e6bf53e606
parent 42fe38fae1971ee8c5292f5d953f0d23811d928c
Author: Armin Weigl <tb46305@gmail.com>
Date: Wed, 3 Aug 2022 19:32:48 +0200
eval: implement type assertions and tests
Signed-off-by: Armin Weigl <tb46305@gmail.com>
Diffstat:
2 files changed, 62 insertions(+), 1 deletion(-)
diff --git a/src/eval.c b/src/eval.c
@@ -433,6 +433,44 @@ eval_expand_array(struct context *ctx,
}
enum eval_result
+eval_type_assertion(struct context *ctx, struct expression *in,
+ struct expression *out)
+{
+ struct expression val = {0};
+ enum eval_result r = eval_expr(ctx, in->cast.value, &val);
+ if (r != EVAL_OK) {
+ return r;
+ }
+
+ const struct type *from = type_dealias(in->cast.value->result);
+ assert(from->storage == STORAGE_TAGGED);
+ if (val.constant.tagged.tag == in->cast.secondary) {
+ out->constant = val.constant.tagged.value->constant;
+ return EVAL_OK;
+ } else {
+ return EVAL_INVALID;
+ }
+}
+
+enum eval_result
+eval_type_test(struct context *ctx, struct expression *in,
+ struct expression *out)
+{
+ struct expression val = {0};
+ enum eval_result r = eval_expr(ctx, in->cast.value, &val);
+ if (r != EVAL_OK) {
+ return r;
+ }
+
+ const struct type *from = type_dealias(in->cast.value->result);
+ assert(from->storage == STORAGE_TAGGED);
+
+ out->constant.bval = val.constant.tagged.tag == in->cast.secondary;
+
+ return EVAL_OK;
+}
+
+enum eval_result
eval_cast(struct context *ctx, struct expression *in, struct expression *out)
{
struct expression val = {0};
@@ -842,7 +880,16 @@ eval_expr(struct context *ctx, struct expression *in, struct expression *out)
case EXPR_BINARITHM:
return eval_binarithm(ctx, in, out);
case EXPR_CAST:
- return eval_cast(ctx, in, out);
+ switch (in->cast.kind) {
+ case C_CAST:
+ return eval_cast(ctx, in, out);
+ case C_ASSERTION:
+ return eval_type_assertion(ctx, in, out);
+ case C_TEST:
+ return eval_type_test(ctx, in, out);
+ default:
+ assert(0); // Unreacheable
+ }
case EXPR_CONSTANT:
return eval_const(ctx, in, out);
case EXPR_MEASURE:
diff --git a/tests/13-tagged.ha b/tests/13-tagged.ha
@@ -238,11 +238,25 @@ fn reject() void = {
};
def val1: integer = 8u8;
+def val1val: u8 = val1 as u8;
+def val1type: bool = val1 is u8;
def val2: integer = val1;
+def val2val: u8 = val2 as u8;
+def val2type: bool = val2 is u8;
+def val3: integer = 8u8: u16;
+def val3val: u16 = val3 as u16;
+def val3type: bool = val3 is u16;
fn translation() void = {
assert(val1 as u8 == 8u8);
+ assert(val1val == 8u8);
+ assert(val1type == true);
assert(val2 as u8 == 8u8);
+ assert(val2val == 8u8);
+ assert(val2type == true);
+ assert(val3 as u16 == 8u16);
+ assert(val3val == 8u16);
+ assert(val3type == true);
};
export fn main() void = {