]> ocean-lang.org Git - ocean/commitdiff
oceani: differentiate static-sized arrays from others.
authorNeilBrown <neil@brown.name>
Sat, 16 Oct 2021 05:58:42 +0000 (16:58 +1100)
committerNeilBrown <neil@brown.name>
Sat, 30 Oct 2021 22:19:42 +0000 (09:19 +1100)
Some arrays will always have the same size - a static size.
Others might have a different size each time their scope is entered, if
the size is calculates from a variable.

The latter need to be reallocated whenever scope is entered, the former
do not.

This will matter when we create call frames to be able to handle
recursion.

So detect and handle the difference now.

Signed-off-by: NeilBrown <neil@brown.name>
csrc/oceani.mdc

index fedf05f8259c3b7a4e7ec2b77e17ac0d139867ab..0de2988dbc689dd0b1970c16e48bdd20b1403c84 100644 (file)
@@ -429,7 +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 (*prepare_type)(struct type *type, int parse_time);
                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,
@@ -538,7 +538,7 @@ Named type are stored in a simple linked list.  Objects of each type are
                struct value *ret;
 
                if (t->prepare_type)
-                       t->prepare_type(t);
+                       t->prepare_type(t, 0);
 
                ret = calloc(1, t->size);
                if (init)
@@ -1503,20 +1503,36 @@ ever be referenced by the name it is declared with.  It is likely that
 a "`copy`" primitive will eventually be define which can be used to
 make a copy of an array with controllable recursive depth.
 
+For now we have two sorts of array, those with fixed size either because
+it is given as a literal number or because it is a struct member (which
+cannot have a runtime-changing size), and those with a size that is
+determined at runtime - local variables with a const size.  The former
+have their size calculated at parse time, the latter at run time.
+
+For the latter type, the `size` field of the type is the size of a
+pointer, and the array is reallocated every time it comes into scope.
+
+We differentiate struct fields with a const size from local variables
+with a const size by whether they are prepared at parse time or not.
+
 ###### type union fields
 
        struct {
-               int size;
+               short size;
+               short static_size;
                struct variable *vsize;
                struct type *member;
        } array;
 
+###### value union fields
+       void *array;  // used if not static_size
+
 ###### value functions
 
-       static void array_prepare_type(struct type *type)
+       static void array_prepare_type(struct type *type, int parse_time)
        {
                mpz_t q;
-               if (!type->array.vsize)
+               if (!type->array.vsize || type->array.static_size)
                        return;
 
                mpz_init(q);
@@ -1525,19 +1541,28 @@ make a copy of an array with controllable recursive depth.
                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;
+               if (parse_time) {
+                       type->array.static_size = 1;
+                       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;
+               void *ptr = val->ptr;
 
                if (!val)
-                       return;         
+                       return;
+               if (!type->array.static_size) {
+                       val->array = calloc(type->array.size, 
+                                           type->array.member->size);
+                       ptr = val->array;
+               }
                for (i = 0; i < type->array.size; i++) {
                        struct value *v;
-                       v = (void*)val->ptr + i * type->array.member->size;
+                       v = (void*)ptr + i * type->array.member->size;
                        val_init(type->array.member, v);
                }
        }
@@ -1545,12 +1570,17 @@ make a copy of an array with controllable recursive depth.
        static void array_free(struct type *type, struct value *val)
        {
                int i;
+               void *ptr = val->ptr;
 
+               if (!type->array.static_size)
+                       ptr = val->array;
                for (i = 0; i < type->array.size; i++) {
                        struct value *v;
-                       v = (void*)val->ptr + i * type->array.member->size;
+                       v = (void*)ptr + i * type->array.member->size;
                        free_value(type->array.member, v);
                }
+               if (!type->array.static_size)
+                       free(ptr);
        }
 
        static int array_compat(struct type *require, struct type *have)
@@ -1583,6 +1613,8 @@ make a copy of an array with controllable recursive depth.
                .print_type = array_print_type,
                .compat = array_compat,
                .free = array_free,
+               .size = sizeof(void*),
+               .align = sizeof(void*),
        };
 
 ###### declare terminals
@@ -1613,6 +1645,7 @@ make a copy of an array with controllable recursive depth.
                                        &$2);
                        mpq_clear(num);
                }
+               t->array.static_size = 1;
                t->size = t->array.size * t->array.member->size;
                t->align = t->array.member->align;
        } }$
@@ -1676,6 +1709,7 @@ make a copy of an array with controllable recursive depth.
        case Index: {
                mpz_t q;
                long i;
+               void *ptr;
 
                lleft = linterp_exec(b->left, &ltype);
                right = interp_exec(b->right, &rtype);
@@ -1684,9 +1718,13 @@ make a copy of an array with controllable recursive depth.
                i = mpz_get_si(q);
                mpz_clear(q);
 
+               if (ltype->array.static_size)
+                       ptr = lleft;
+               else
+                       ptr = *(void**)lleft;
                rvtype = ltype->array.member;
                if (i >= 0 && i < ltype->array.size)
-                       lrv = (void*)lleft + i * rvtype->size;
+                       lrv = ptr + i * rvtype->size;
                else
                        val_init(ltype->array.member, &rv);
                ltype = NULL;
@@ -1979,7 +2017,7 @@ function will be needed.
                        $0->f.name = $1.txt;
                        $0->f.type = $<3;
                        if ($0->f.type->prepare_type)
-                               $0->f.type->prepare_type($0->f.type);
+                               $0->f.type->prepare_type($0->f.type, 1);
                }$
 
 ###### forward decls