harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 62762c8f21f90bf8b52c8de1a2358c07c89323ac
parent 414c1934ccb43c37e9cb733810d4eac813ac9a89
Author: Drew DeVault <sir@cmpwn.com>
Date:   Mon,  1 Feb 2021 15:12:17 -0500

eval: implement struct constants

Diffstat:
Minclude/expr.h | 8+++++++-
Msrc/eval.c | 54+++++++++++++++++++++++++++++++++++++++++++++++++++++-
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: