X-Git-Url: https://ocean-lang.org/code/?a=blobdiff_plain;f=csrc%2Foceani.mdc;h=0de2988dbc689dd0b1970c16e48bdd20b1403c84;hb=de86cdada39f42953e35c1a9ff6e5b0fb5bff553;hp=bc8880e72ccaf11343c1782ff6d7670db537f114;hpb=13482f902f9fa5d303a3a738a18fe17fdb734930;p=ocean diff --git a/csrc/oceani.mdc b/csrc/oceani.mdc index bc8880e..0de2988 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, 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, @@ -536,8 +537,9 @@ Named type are stored in a simple linked list. Objects of each type are { struct value *ret; - if (!t->size) - val_init(t, NULL); + if (t->prepare_type) + t->prepare_type(t, 0); + ret = calloc(1, t->size); if (init) memcpy(ret, init, t->size); @@ -1437,8 +1439,10 @@ in `rval`. { struct lrval ret = _interp_exec(e); - if (typeret) + if (ret.lval) *typeret = ret.type; + else + free_value(ret.type, &ret.rval); return ret.lval; } @@ -1499,36 +1503,66 @@ 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_init(struct type *type, struct value *val) + static void array_prepare_type(struct type *type, int parse_time) { - int i; + mpz_t q; + if (!type->array.vsize || type->array.static_size) + return; - 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); + 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 (parse_time) { + type->array.static_size = 1; + type->size = type->array.size * type->array.member->size; + type->align = type->array.member->align; } - 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); } } @@ -1536,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) @@ -1570,9 +1609,12 @@ 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, + .size = sizeof(void*), + .align = sizeof(void*), }; ###### declare terminals @@ -1584,16 +1626,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); @@ -1602,6 +1645,9 @@ 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; } }$ | [ IDENTIFIER ] Type ${ { @@ -1663,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); @@ -1671,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; @@ -1745,7 +1796,12 @@ function will be needed. for (i = 0; i < type->structure.nfields; i++) { struct value *v; v = (void*) val->ptr + type->structure.fields[i].offset; - val_init(type->structure.fields[i].type, v); + if (type->structure.fields[i].init) + dup_value(type->structure.fields[i].type, + type->structure.fields[i].init, + v); + else + val_init(type->structure.fields[i].type, v); } } @@ -1960,7 +2016,8 @@ function will be needed. $0 = calloc(1, sizeof(struct fieldlist)); $0->f.name = $1.txt; $0->f.type = $<3; - $0->f.init = val_alloc($0->f.type, NULL); + if ($0->f.type->prepare_type) + $0->f.type->prepare_type($0->f.type, 1); }$ ###### forward decls @@ -3354,14 +3411,13 @@ 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 (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); v->val = val_alloc(v->type, NULL); } break;