harec

[hare] Hare compiler, written in C11 for POSIX OSs
Log | Files | Refs | README | LICENSE

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:
Msrc/eval.c | 49++++++++++++++++++++++++++++++++++++++++++++++++-
Mtests/13-tagged.ha | 14++++++++++++++
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 = {