From 3c4cea0b5abc137df4b26ef443f24186cf9cb3f5 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 14 Oct 2021 13:43:02 +1100 Subject: [PATCH] oceani: handle variable-sized arrays better. An array with size set by a constant variable(!) might have a different size each time the declaration is encountered. So we need to re-evaluate the size each time. We currently re-evaluate the size only if it is zero. So for numerical-constant sized arrays, evaluate size during parsing. For other arrays, re-evaulate each time using a new prepare_type method. Signed-off-by: NeilBrown --- csrc/oceani-tests.mdc | 2 +- csrc/oceani.mdc | 49 +++++++++++++++++++++++++------------------ 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/csrc/oceani-tests.mdc b/csrc/oceani-tests.mdc index 90bfc19..46c1a09 100644 --- a/csrc/oceani-tests.mdc +++ b/csrc/oceani-tests.mdc @@ -533,7 +533,7 @@ ad-hoc things array related. for i:=0; then i=i+1; while i<5: j ::= i - ra:[5]number + ra:[j]number ra[i-1] = i*i ra[6] = 42 // mustn't crash print '', bools[i], ra[j-1], diff --git a/csrc/oceani.mdc b/csrc/oceani.mdc index 2804224..7ff26c5 100644 --- a/csrc/oceani.mdc +++ b/csrc/oceani.mdc @@ -429,6 +429,7 @@ Named type are stored in a simple linked list. Objects of each type are struct type *next; int size, align; void (*init)(struct type *type, struct value *val); + void (*prepare_type)(struct type *type); void (*print)(struct type *type, struct value *val); void (*print_type)(struct type *type, FILE *f); int (*cmp_order)(struct type *t1, struct type *t2, @@ -536,8 +537,6 @@ Named type are stored in a simple linked list. Objects of each type are { struct value *ret; - if (!t->size) - val_init(t, NULL); ret = calloc(1, t->size); if (init) memcpy(ret, init, t->size); @@ -1511,20 +1510,25 @@ make a copy of an array with controllable recursive depth. ###### value functions - static void array_init(struct type *type, struct value *val) + static void array_prepare_type(struct type *type) { - int i; + mpz_t q; + if (!type->array.vsize) + return; + + mpz_init(q); + mpz_tdiv_q(q, mpq_numref(type->array.vsize->val->num), + mpq_denref(type->array.vsize->val->num)); + type->array.size = mpz_get_si(q); + mpz_clear(q); - if (type->array.vsize) { - mpz_t q; - mpz_init(q); - mpz_tdiv_q(q, mpq_numref(type->array.vsize->val->num), - mpq_denref(type->array.vsize->val->num)); - type->array.size = mpz_get_si(q); - mpz_clear(q); - } type->size = type->array.size * type->array.member->size; type->align = type->array.member->align; + } + + static void array_init(struct type *type, struct value *val) + { + int i; if (!val) return; @@ -1572,6 +1576,7 @@ make a copy of an array with controllable recursive depth. static struct type array_prototype = { .init = array_init, + .prepare_type = array_prepare_type, .print_type = array_print_type, .compat = array_compat, .free = array_free, @@ -1586,16 +1591,17 @@ make a copy of an array with controllable recursive depth. char tail[3]; mpq_t num; struct text noname = { "", 0 }; + struct type *t; - $0 = add_type(c, noname, &array_prototype); - $0->array.member = $<4; - $0->array.vsize = NULL; + $0 = t = add_type(c, noname, &array_prototype); + t->array.member = $<4; + t->array.vsize = NULL; if (number_parse(num, tail, $2.txt) == 0) tok_err(c, "error: unrecognised number", &$2); else if (tail[0]) tok_err(c, "error: unsupported number suffix", &$2); else { - $0->array.size = mpz_get_ui(mpq_numref(num)); + t->array.size = mpz_get_ui(mpq_numref(num)); if (mpz_cmp_ui(mpq_denref(num), 1) != 0) { tok_err(c, "error: array size must be an integer", &$2); @@ -1604,6 +1610,8 @@ make a copy of an array with controllable recursive depth. &$2); mpq_clear(num); } + t->size = t->array.size * t->array.member->size; + t->align = t->array.member->align; } }$ | [ IDENTIFIER ] Type ${ { @@ -3356,15 +3364,16 @@ it is declared, and error will be raised as the name is created as struct variable *v = cast(var, b->left)->var; if (v->merged) v = v->merged; + free_value(v->type, v->val); + free(v->val); + if (v->type->prepare_type) + // FIXME is this the first usage of the type? + v->type->prepare_type(v->type); if (b->right) { right = interp_exec(b->right, &rtype); - free_value(v->type, v->val); - free(v->val); v->val = val_alloc(v->type, &right); rtype = Tnone; } else { - free_value(v->type, v->val); - free(v->val); v->val = val_alloc(v->type, NULL); } break; -- 2.43.0