harec

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

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:
Msrc/eval.c | 44+++++++++++++++++++++++++++++++++++++++-----
Mtests/01-arrays.ha | 10++++++++++
Mtests/06-structs.ha | 16++++++++++++++++
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