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:
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);
}