harec

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

commit aeaef421d1e340ef046bd22afad34a16a1c1b107
parent 027edffc28616c17c13c93838f6f5d540f19eaf2
Author: Eyal Sawady <ecs@d2evs.net>
Date:   Sat, 23 Oct 2021 05:35:40 +0000

Implement offset expressions

Signed-off-by: Eyal Sawady <ecs@d2evs.net>

Diffstat:
Msrc/check.c | 18++++++++++++++++--
Msrc/eval.c | 12++++++++++--
Msrc/gen.c | 15++++++++++++++-
Msrc/parse.c | 4+++-
4 files changed, 43 insertions(+), 6 deletions(-)

diff --git a/src/check.c b/src/check.c @@ -1985,7 +1985,21 @@ check_expr_measure(struct context *ctx, ctx->store, aexpr->measure.type); break; case M_OFFSET: - assert(0); // TODO + if (aexpr->measure.value->type != EXPR_ACCESS) { + error(ctx, aexpr->measure.value->loc, expr, + "offset argument must be a field or tuple access"); + return; + } + if (aexpr->measure.value->access.type != ACCESS_FIELD + && aexpr->measure.value->access.type != ACCESS_TUPLE) { + error(ctx, aexpr->measure.value->loc, expr, + "offset argument must be a field or tuple access"); + return; + } + expr->measure.value = xcalloc(1, sizeof(struct expression)); + check_expression(ctx, aexpr->measure.value, + expr->measure.value, NULL); + break; } } @@ -3369,7 +3383,7 @@ expr_is_specified(struct context *ctx, case M_SIZE: return atype_is_specified(ctx, aexpr->measure.type, is_static); case M_OFFSET: - assert(0); // TODO + return expr_is_specified(ctx, aexpr->measure.value, is_static); } assert(0); case EXPR_PROPAGATE: diff --git a/src/eval.c b/src/eval.c @@ -472,15 +472,23 @@ eval_measurement(struct context *ctx, struct expression *in, struct expression * { assert(in->type == EXPR_MEASURE); out->type = EXPR_CONSTANT; + out->result = &builtin_type_size; switch (in->measure.op) { case M_LEN: assert(0); // TODO case M_SIZE: - out->result = &builtin_type_size; out->constant.uval = in->measure.type->size; return EVAL_OK; case M_OFFSET: - assert(0); // TODO + if (in->measure.value->access.type == ACCESS_FIELD) { + out->constant.uval = + in->measure.value->access.field->offset; + } else { + assert(in->measure.value->access.type == ACCESS_TUPLE); + out->constant.uval = + in->measure.value->access.tvalue->offset; + } + return EVAL_OK; } assert(0); } diff --git a/src/gen.c b/src/gen.c @@ -2244,7 +2244,20 @@ gen_expr_measure(struct gen_context *ctx, const struct expression *expr) .lval = expr->measure.type->size, }; case M_OFFSET: - assert(0); // TODO + if (expr->measure.value->access.type == ACCESS_FIELD) { + return (struct gen_value){ + .kind = GV_CONST, + .type = &builtin_type_size, + .lval = expr->measure.value->access.field->offset, + }; + } else { + assert(expr->measure.value->access.type == ACCESS_TUPLE); + return (struct gen_value){ + .kind = GV_CONST, + .type = &builtin_type_size, + .lval = expr->measure.value->access.tvalue->offset, + }; + } } abort(); // Invariant } diff --git a/src/parse.c b/src/parse.c @@ -1124,7 +1124,9 @@ parse_measurement_expression(struct lexer *lexer) break; case T_OFFSET: exp->measure.op = M_OFFSET; - assert(0); // TODO + // Let check error out on non-field-accesses + exp->measure.value = parse_expression(lexer); + break; default: synassert(false, &tok, T_SIZE, T_LEN, T_OFFSET, T_EOF); }