commit 13688980dfdc1652ae8c008e30533a95447b72bd
parent 20c786e75ade06281a003645740915edce78688c
Author: Sebastian <sebastian@sebsite.pw>
Date: Mon, 9 May 2022 21:24:08 -0400
eval: support len expr
Signed-off-by: Sebastian <sebastian@sebsite.pw>
Diffstat:
3 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/src/eval.c b/src/eval.c
@@ -1,5 +1,6 @@
#include <assert.h>
#include <stdbool.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "check.h"
@@ -505,9 +506,33 @@ eval_measurement(struct context *ctx, struct expression *in, struct expression *
assert(in->type == EXPR_MEASURE);
out->type = EXPR_CONSTANT;
out->result = &builtin_type_size;
+ struct expression obj = {0};
+ enum eval_result res;
switch (in->measure.op) {
case M_LEN:
- assert(0); // TODO
+ res = eval_expr(ctx, in->measure.value, &obj);
+ if (res != EVAL_OK) {
+ return res;
+ }
+
+ switch (obj.result->storage) {
+ case STORAGE_ARRAY:
+ case STORAGE_SLICE:
+ break;
+ case STORAGE_STRING:
+ out->constant.uval = obj.constant.string.len;
+ return EVAL_OK;
+ default:
+ abort(); // Invariant
+ }
+
+ uintmax_t len = 0;
+ for (struct array_constant *c = obj.constant.array;
+ c != NULL; c = c->next) {
+ len++;
+ }
+ out->constant.uval = len;
+ return EVAL_OK;
case M_SIZE:
out->constant.uval = in->measure.dimensions.size;
return EVAL_OK;
diff --git a/tests/01-arrays.ha b/tests/01-arrays.ha
@@ -23,6 +23,8 @@ fn measurements() void = {
let x = [1, 2, 3];
assert(len(x) == 3);
assert(size([3]int) == size(int) * 3);
+
+ static assert(len([1, 2, 3]) == 3);
};
fn storage() void = {
diff --git a/tests/04-strings.ha b/tests/04-strings.ha
@@ -9,6 +9,8 @@ fn measurements() void = {
if (size(*u8) > size(size)) size(*u8)
else size(size);
assert(&x: uintptr: size % align == 0);
+
+ static assert(len("Hello!") == 6);
};
fn storage() void = {