commit 852ad83dd2a7ca31f69d0a7280008c6fe9b295cf
parent 7334dc8b3974528c231110ee190e3be17a3a85cc
Author: Sebastian <sebastian@sebsite.pw>
Date: Mon, 9 May 2022 21:22:14 -0400
eval: support index and struct access exprs
Signed-off-by: Sebastian <sebastian@sebsite.pw>
Diffstat:
3 files changed, 65 insertions(+), 5 deletions(-)
diff --git a/src/eval.c b/src/eval.c
@@ -14,6 +14,9 @@
static enum eval_result
eval_access(struct context *ctx, struct expression *in, struct expression *out)
{
+ struct expression tmp = {0};
+ enum eval_result r;
+
out->type = EXPR_CONSTANT;
out->result = in->result;
@@ -21,18 +24,49 @@ eval_access(struct context *ctx, struct expression *in, struct expression *out)
case ACCESS_IDENTIFIER:
return EVAL_INVALID; // &ident handled in eval_unarithm
case ACCESS_INDEX:
- assert(0); // TODO
+ r = eval_expr(ctx, in->access.array, &tmp);
+ if (r != EVAL_OK) {
+ return r;
+ }
+ const struct array_constant *array = tmp.constant.array;
+ r = eval_expr(ctx, in->access.index, &tmp);
+ if (r != EVAL_OK) {
+ return r;
+ }
+ for (size_t i = tmp.constant.uval; i > 0; --i) {
+ if (array == NULL) {
+ // out of bounds
+ return EVAL_INVALID;
+ }
+ array = array->next;
+ }
+ return eval_expr(ctx, array->value, out);
case ACCESS_FIELD:
- assert(0); // TODO
+ r = eval_expr(ctx, in->access._struct, &tmp);
+ if (r != EVAL_OK) {
+ return r;
+ }
+ const struct struct_constant *fields = tmp.constant._struct;
+ for (; fields != NULL; fields = fields->next) {
+ if (!strcmp(fields->field->name, in->access.field->name)) {
+ break;
+ }
+ }
+ if (fields == NULL) {
+ return EVAL_INVALID;
+ }
+ return eval_expr(ctx, fields->value, out);
case ACCESS_TUPLE:
- out->type = EXPR_CONSTANT;
- struct expression tmp = {0};
- enum eval_result r = eval_expr(ctx, in->access.tuple, &tmp);
+ r = eval_expr(ctx, in->access.tuple, &tmp);
if (r != EVAL_OK) {
return r;
}
const struct tuple_constant *tuple = tmp.constant.tuple;
for (size_t i = in->access.tindex; i > 0; --i) {
+ if (tuple == NULL) {
+ // out of bounds
+ return EVAL_INVALID;
+ }
tuple = tuple->next;
}
return eval_expr(ctx, tuple->value, out);
diff --git a/tests/01-arrays.ha b/tests/01-arrays.ha
@@ -125,6 +125,14 @@ fn extype() void = {
assert(x[1] == 42);
};
+fn eval_array() void = {
+ static let a = [1, 2];
+};
+
+fn eval_access() void = {
+ static assert([1, 2][0] == 1 && [1, 2][1] == 2);
+};
+
export fn main() void = {
indexing();
measurements();
@@ -135,4 +143,6 @@ export fn main() void = {
nested();
expanded();
extype();
+ eval_array();
+ eval_access();
};
diff --git a/tests/06-structs.ha b/tests/06-structs.ha
@@ -225,6 +225,20 @@ fn fields() void = {
assert(&sp.c: uintptr == &n: uintptr + 2);
};
+fn eval_struct() void = {
+ static let s = struct {
+ a: u8 = 69,
+ b: u32 = 1337,
+ };
+};
+
+fn eval_access() void = {
+ static assert(struct {
+ a: u8 = 69,
+ b: u32 = 1337,
+ }.b == 1337);
+};
+
export fn main() void = {
padding();
storage();
@@ -235,6 +249,8 @@ export fn main() void = {
autofill();
invariants();
fields();
+ eval_struct();
+ eval_access();
// TODO:
// - Union tests
// - Embedded structs