From: NeilBrown Date: Sat, 16 Oct 2021 05:58:42 +0000 (+1100) Subject: oceani: differentiate static-sized arrays from others. X-Git-Url: https://ocean-lang.org/code/?p=ocean;a=commitdiff_plain;h=de86cdada39f42953e35c1a9ff6e5b0fb5bff553 oceani: differentiate static-sized arrays from others. 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 --- diff --git a/csrc/oceani.mdc b/csrc/oceani.mdc index fedf05f..0de2988 100644 --- a/csrc/oceani.mdc +++ b/csrc/oceani.mdc @@ -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, <ype); 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