]> ocean-lang.org Git - ocean/blobdiff - csrc/oceani.mdc
oceani: differentiate static-sized arrays from others.
[ocean] / 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