commit 62762c8f21f90bf8b52c8de1a2358c07c89323ac
parent 414c1934ccb43c37e9cb733810d4eac813ac9a89
Author: Drew DeVault <sir@cmpwn.com>
Date: Mon, 1 Feb 2021 15:12:17 -0500
eval: implement struct constants
Diffstat:
2 files changed, 60 insertions(+), 2 deletions(-)
diff --git a/include/expr.h b/include/expr.h
@@ -149,6 +149,12 @@ struct array_constant {
bool expand;
};
+struct struct_constant {
+ const struct struct_field *field;
+ struct expression *value;
+ struct struct_constant *next;
+};
+
union expression_constant {
bool bval;
double fval;
@@ -160,7 +166,7 @@ union expression_constant {
char *value;
} string;
struct array_constant *array;
- // TODO: Struct constants
+ struct struct_constant *_struct;
};
struct expression_control {
diff --git a/src/eval.c b/src/eval.c
@@ -1,5 +1,6 @@
#include <assert.h>
#include <stdbool.h>
+#include <stdlib.h>
#include <string.h>
#include "eval.h"
#include "expr.h"
@@ -372,6 +373,56 @@ eval_measurement(struct context *ctx, struct expression *in, struct expression *
assert(0);
}
+static int
+field_compar(const void *_a, const void *_b)
+{
+ const struct struct_constant **a = (const struct struct_constant **)_a;
+ const struct struct_constant **b = (const struct struct_constant **)_b;
+ return (*a)->field->offset - (*b)->field->offset;
+}
+
+enum eval_result
+eval_struct(struct context *ctx, struct expression *in, struct expression *out)
+{
+ assert(in->type == EXPR_STRUCT);
+ out->type = EXPR_CONSTANT;
+
+ size_t n = 0;
+ for (const struct expression_struct *field = &in->_struct;
+ field; field = field->next) {
+ ++n;
+ }
+ assert(n > 0);
+
+ struct struct_constant **fields =
+ xcalloc(n, sizeof(struct struct_constant *));
+ n = 0;
+ for (const struct expression_struct *field = &in->_struct;
+ field; field = field->next) {
+ struct struct_constant *cfield = fields[n] =
+ xcalloc(1, sizeof(struct struct_constant));
+ cfield->field = field->field;
+ cfield->value = xcalloc(1, sizeof(struct expression));
+ enum eval_result r = eval_expr(ctx,
+ field->value, cfield->value);
+ if (r != EVAL_OK) {
+ return r;
+ }
+ ++n;
+ }
+
+ qsort(fields, n, sizeof(struct struct_constant *), field_compar);
+
+ for (size_t i = 0; i < n - 1; ++i) {
+ fields[i]->next = fields[i + 1];
+ }
+
+ out->constant._struct = fields[0];
+ out->result = in->result;
+ free(fields);
+ return EVAL_OK;
+}
+
enum eval_result
eval_expr(struct context *ctx, struct expression *in, struct expression *out)
{
@@ -386,8 +437,9 @@ eval_expr(struct context *ctx, struct expression *in, struct expression *out)
return eval_const(ctx, in, out);
case EXPR_MEASURE:
return eval_measurement(ctx, in, out);
- case EXPR_SLICE:
case EXPR_STRUCT:
+ return eval_struct(ctx, in, out);
+ case EXPR_SLICE:
case EXPR_UNARITHM:
assert(0); // TODO
case EXPR_ALLOC: