]> ocean-lang.org Git - ocean/commitdiff
oceani: handle variable-sized arrays better.
authorNeilBrown <neil@brown.name>
Thu, 14 Oct 2021 02:43:02 +0000 (13:43 +1100)
committerNeilBrown <neil@brown.name>
Sat, 30 Oct 2021 22:18:19 +0000 (09:18 +1100)
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 <neil@brown.name>
csrc/oceani-tests.mdc
csrc/oceani.mdc

index 90bfc19da11d84241256fdba41c6b06bd5376db9..46c1a09530a8c640057529e0668fa8422a3fa01d 100644 (file)
@@ -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],
index 2804224da5759f95e08ef7cb4f0ce17618607551..7ff26c5f7aac1871ac03b9e1fa2fd79aa9c37bd2 100644 (file)
@@ -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;