harec

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

commit a8f7752df0f0c42e2311ec85240dde16491d808b
parent dc46d6f9206a2f6c11a89a13f66b2c6513839a12
Author: Drew DeVault <sir@cmpwn.com>
Date:   Tue,  2 Feb 2021 21:36:08 -0500

eval: fix struct autofill

Diffstat:
Msrc/eval.c | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Mtests/11-globals.ha | 9++++++++-
2 files changed, 84 insertions(+), 12 deletions(-)

diff --git a/src/eval.c b/src/eval.c @@ -373,6 +373,56 @@ eval_measurement(struct context *ctx, struct expression *in, struct expression * assert(0); } +static void +constant_default(struct context *ctx, struct expression *v) +{ + struct expression b = {0}; + switch (type_dealias(v->result)->storage) { + case TYPE_STORAGE_POINTER: + case TYPE_STORAGE_I16: + case TYPE_STORAGE_I32: + case TYPE_STORAGE_I64: + case TYPE_STORAGE_I8: + case TYPE_STORAGE_INT: + case TYPE_STORAGE_U16: + case TYPE_STORAGE_U32: + case TYPE_STORAGE_U64: + case TYPE_STORAGE_U8: + case TYPE_STORAGE_UINT: + case TYPE_STORAGE_UINTPTR: + case TYPE_STORAGE_SIZE: + case TYPE_STORAGE_F32: + case TYPE_STORAGE_F64: + case TYPE_STORAGE_CHAR: + case TYPE_STORAGE_ENUM: + case TYPE_STORAGE_NULL: + case TYPE_STORAGE_RUNE: + case TYPE_STORAGE_BOOL: + break; // calloc does this for us + case TYPE_STORAGE_STRUCT: + case TYPE_STORAGE_UNION: + b.type = EXPR_STRUCT; + b.result = v->result; + b._struct.autofill = true; + enum eval_result r = eval_expr(ctx, &b, v); + assert(r == EVAL_OK); + break; + case TYPE_STORAGE_STRING: + v->constant.string.value = strdup(""); + v->constant.string.len = 0; + break; + case TYPE_STORAGE_TAGGED: + case TYPE_STORAGE_ARRAY: + case TYPE_STORAGE_SLICE: + assert(0); // TODO + case TYPE_STORAGE_ALIAS: + case TYPE_STORAGE_FUNCTION: + assert(0); // Invariant + case TYPE_STORAGE_VOID: + break; // no-op + } +} + static int field_compar(const void *_a, const void *_b) { @@ -386,30 +436,45 @@ eval_struct(struct context *ctx, struct expression *in, struct expression *out) { assert(in->type == EXPR_STRUCT); assert(type_dealias(in->result)->storage != TYPE_STORAGE_UNION); // TODO + const struct type *type = type_dealias(in->result); out->type = EXPR_CONSTANT; size_t n = 0; - for (const struct expr_struct_field *field = &in->_struct.fields; + for (const struct struct_field *field = type->struct_union.fields; field; field = field->next) { ++n; } assert(n > 0); + size_t i = 0; struct struct_constant **fields = xcalloc(n, sizeof(struct struct_constant *)); - n = 0; - for (const struct expr_struct_field *field = &in->_struct.fields; - field; field = field->next) { - struct struct_constant *cfield = fields[n] = + for (const struct struct_field *field = type->struct_union.fields; + field; field = field->next, ++i) { + const struct expr_struct_field *field_in = NULL; + for (field_in = &in->_struct.fields; field_in; field_in = field_in->next) { + if (field_in->field == field) { + break; + } + } + + struct struct_constant *cfield = fields[i] = xcalloc(1, sizeof(struct struct_constant)); - cfield->field = field->field; + cfield->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; + + if (!field_in) { + assert(in->_struct.autofill); + cfield->value->type = EXPR_CONSTANT; + cfield->value->result = field->type; + constant_default(ctx, cfield->value); + } else { + enum eval_result r = eval_expr(ctx, + field_in->value, cfield->value); + if (r != EVAL_OK) { + return r; + } } - ++n; } qsort(fields, n, sizeof(struct struct_constant *), field_compar); diff --git a/tests/11-globals.ha b/tests/11-globals.ha @@ -8,11 +8,16 @@ fn write() void = { assert(x == 1337); }; -type coords = struct { x: int, y: int }; let ar: [3]int = [1, 2, 3]; let sl: []int = [1, 2, 3]; let st: str = "Hello!"; + +type coords = struct { x: int, y: int }; let su: coords = coords { y = 10, x = 20 }; +let au: coords = coords { ... }; + +type coords3 = struct { coords: coords, z: int }; +let a3: coords3 = coords3 { ... }; fn storage() void = { assert(len(ar) == 3z); @@ -21,6 +26,8 @@ fn storage() void = { assert(sl[0] == 1 && sl[1] == 2 && sl[2] == 3); assert(len(st) == 6z); assert(su.x == 20 && su.y == 10); + assert(au.x == 0 && au.y == 0); + assert(a3.coords.x == 0 && a3.coords.y == 0 && a3.z == 0); }; fn invariants() void = {