X-Git-Url: https://ocean-lang.org/code/?p=ocean;a=blobdiff_plain;f=csrc%2Foceani.mdc;h=b83f6bca4e5a3683d1166281cca7c2852e4dfd9b;hp=fedf05f8259c3b7a4e7ec2b77e17ac0d139867ab;hb=9e98e1c58af49338d0a0710e27ad0529a32345e6;hpb=809b04eb484b75d8c0e26ba12642ed34bc6b1fd7 diff --git a/csrc/oceani.mdc b/csrc/oceani.mdc index fedf05f..b83f6bc 100644 --- a/csrc/oceani.mdc +++ b/csrc/oceani.mdc @@ -105,6 +105,7 @@ structures can be used. ###### Parser: header ## macros + struct parse_context; ## ast struct parse_context { struct token_config config; @@ -242,7 +243,7 @@ structures can be used. fprintf(stderr, "oceani: type error in program - not running.\n"); exit(1); } - interp_prog(context.prog, argv+optind+1); + interp_prog(&context, context.prog, argv+optind+1); } free_exec(context.prog); @@ -429,7 +430,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 parse_context *c, 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, @@ -533,12 +534,13 @@ Named type are stored in a simple linked list. Objects of each type are printf("*Unknown*"); // NOTEST } - static struct value *val_alloc(struct type *t, struct value *init) + static struct value *val_alloc(struct parse_context *c, struct type *t, + struct value *init) { struct value *ret; if (t->prepare_type) - t->prepare_type(t); + t->prepare_type(c, t, 0); ret = calloc(1, t->size); if (init) @@ -1421,11 +1423,12 @@ in `rval`. struct value rval, *lval; }; - static struct lrval _interp_exec(struct exec *e); + static struct lrval _interp_exec(struct parse_context *c, struct exec *e); - static struct value interp_exec(struct exec *e, struct type **typeret) + static struct value interp_exec(struct parse_context *c, struct exec *e, + struct type **typeret) { - struct lrval ret = _interp_exec(e); + struct lrval ret = _interp_exec(c, e); if (!ret.type) abort(); if (typeret) @@ -1435,9 +1438,10 @@ in `rval`. return ret.rval; } - static struct value *linterp_exec(struct exec *e, struct type **typeret) + static struct value *linterp_exec(struct parse_context *c, struct exec *e, + struct type **typeret) { - struct lrval ret = _interp_exec(e); + struct lrval ret = _interp_exec(c, e); if (ret.lval) *typeret = ret.type; @@ -1446,7 +1450,7 @@ in `rval`. return ret.lval; } - static struct lrval _interp_exec(struct exec *e) + static struct lrval _interp_exec(struct parse_context *c, struct exec *e) { struct lrval ret; struct value rv = {}, *lrv = NULL; @@ -1503,20 +1507,37 @@ 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 parse_context *c, 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 +1546,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 +1575,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 +1618,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 +1650,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,17 +1714,22 @@ 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); + lleft = linterp_exec(c, b->left, <ype); + right = interp_exec(c, b->right, &rtype); mpz_init(q); mpz_tdiv_q(q, mpq_numref(right.num), mpq_denref(right.num)); 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; @@ -1881,7 +1924,7 @@ function will be needed. { struct fieldref *f = cast(fieldref, e); struct type *ltype; - struct value *lleft = linterp_exec(f->left, <ype); + struct value *lleft = linterp_exec(c, f->left, <ype); lrv = (void*)lleft->ptr + ltype->structure.fields[f->index].offset; rvtype = ltype->structure.fields[f->index].type; break; @@ -1970,8 +2013,8 @@ function will be needed. if (!ok) c->parse_error = 1; else { - struct value vl = interp_exec($5, NULL); - $0->f.init = val_alloc($0->f.type, &vl); + struct value vl = interp_exec(c, $5, NULL); + $0->f.init = val_alloc(c, $0->f.type, &vl); } } }$ | IDENTIFIER : Type ${ @@ -1979,7 +2022,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(c, $0->f.type, 1); }$ ###### forward decls @@ -2445,11 +2488,11 @@ there. case CondExpr: { struct binode *b2 = cast(binode, b->right); - left = interp_exec(b->left, <ype); + left = interp_exec(c, b->left, <ype); if (left.bool) - rv = interp_exec(b2->left, &rvtype); + rv = interp_exec(c, b2->left, &rvtype); else - rv = interp_exec(b2->right, &rvtype); + rv = interp_exec(c, b2->right, &rvtype); } break; @@ -2562,27 +2605,27 @@ evaluate the second expression if not necessary. ###### interp binode cases case And: - rv = interp_exec(b->left, &rvtype); - right = interp_exec(b->right, &rtype); + rv = interp_exec(c, b->left, &rvtype); + right = interp_exec(c, b->right, &rtype); rv.bool = rv.bool && right.bool; break; case AndThen: - rv = interp_exec(b->left, &rvtype); + rv = interp_exec(c, b->left, &rvtype); if (rv.bool) - rv = interp_exec(b->right, NULL); + rv = interp_exec(c, b->right, NULL); break; case Or: - rv = interp_exec(b->left, &rvtype); - right = interp_exec(b->right, &rtype); + rv = interp_exec(c, b->left, &rvtype); + right = interp_exec(c, b->right, &rtype); rv.bool = rv.bool || right.bool; break; case OrElse: - rv = interp_exec(b->left, &rvtype); + rv = interp_exec(c, b->left, &rvtype); if (!rv.bool) - rv = interp_exec(b->right, NULL); + rv = interp_exec(c, b->right, NULL); break; case Not: - rv = interp_exec(b->right, &rvtype); + rv = interp_exec(c, b->right, &rvtype); rv.bool = !rv.bool; break; @@ -2690,8 +2733,8 @@ expression operator, and the `CMPop` non-terminal will match one of them. case NEql: { int cmp; - left = interp_exec(b->left, <ype); - right = interp_exec(b->right, &rtype); + left = interp_exec(c, b->left, <ype); + right = interp_exec(c, b->right, &rtype); cmp = value_cmp(ltype, rtype, &left, &right); rvtype = Tbool; switch (b->op) { @@ -2865,30 +2908,30 @@ should only insert brackets were needed for precedence. ###### interp binode cases case Plus: - rv = interp_exec(b->left, &rvtype); - right = interp_exec(b->right, &rtype); + rv = interp_exec(c, b->left, &rvtype); + right = interp_exec(c, b->right, &rtype); mpq_add(rv.num, rv.num, right.num); break; case Minus: - rv = interp_exec(b->left, &rvtype); - right = interp_exec(b->right, &rtype); + rv = interp_exec(c, b->left, &rvtype); + right = interp_exec(c, b->right, &rtype); mpq_sub(rv.num, rv.num, right.num); break; case Times: - rv = interp_exec(b->left, &rvtype); - right = interp_exec(b->right, &rtype); + rv = interp_exec(c, b->left, &rvtype); + right = interp_exec(c, b->right, &rtype); mpq_mul(rv.num, rv.num, right.num); break; case Divide: - rv = interp_exec(b->left, &rvtype); - right = interp_exec(b->right, &rtype); + rv = interp_exec(c, b->left, &rvtype); + right = interp_exec(c, b->right, &rtype); mpq_div(rv.num, rv.num, right.num); break; case Rem: { mpz_t l, r, rem; - left = interp_exec(b->left, <ype); - right = interp_exec(b->right, &rtype); + left = interp_exec(c, b->left, <ype); + right = interp_exec(c, b->right, &rtype); mpz_init(l); mpz_init(r); mpz_init(rem); mpz_tdiv_q(l, mpq_numref(left.num), mpq_denref(left.num)); mpz_tdiv_q(r, mpq_numref(right.num), mpq_denref(right.num)); @@ -2900,24 +2943,24 @@ should only insert brackets were needed for precedence. break; } case Negate: - rv = interp_exec(b->right, &rvtype); + rv = interp_exec(c, b->right, &rvtype); mpq_neg(rv.num, rv.num); break; case Absolute: - rv = interp_exec(b->right, &rvtype); + rv = interp_exec(c, b->right, &rvtype); mpq_abs(rv.num, rv.num); break; case Bracket: - rv = interp_exec(b->right, &rvtype); + rv = interp_exec(c, b->right, &rvtype); break; case Concat: - left = interp_exec(b->left, <ype); - right = interp_exec(b->right, &rtype); + left = interp_exec(c, b->left, <ype); + right = interp_exec(c, b->right, &rtype); rvtype = Tstr; rv.str = text_join(left.str, right.str); break; case StringConv: - right = interp_exec(b->right, &rvtype); + right = interp_exec(c, b->right, &rvtype); rtype = Tstr; rvtype = Tnum; @@ -3139,7 +3182,7 @@ is in-place. while (rvtype == Tnone && b) { if (b->left) - rv = interp_exec(b->left, &rvtype); + rv = interp_exec(c, b->left, &rvtype); b = cast(binode, b->right); } break; @@ -3228,7 +3271,7 @@ same solution. if (b->left) { if (sep) putchar(sep); - left = interp_exec(b->left, <ype); + left = interp_exec(c, b->left, <ype); print_value(ltype, &left); free_value(ltype, &left); if (b->right) @@ -3359,8 +3402,8 @@ it is declared, and error will be raised as the name is created as ###### interp binode cases case Assign: - lleft = linterp_exec(b->left, <ype); - right = interp_exec(b->right, &rtype); + lleft = linterp_exec(c, b->left, <ype); + right = interp_exec(c, b->right, &rtype); if (lleft) { free_value(ltype, lleft); dup_value(ltype, &right, lleft); @@ -3376,11 +3419,11 @@ it is declared, and error will be raised as the name is created as free_value(v->type, v->val); free(v->val); if (b->right) { - right = interp_exec(b->right, &rtype); - v->val = val_alloc(v->type, &right); + right = interp_exec(c, b->right, &rtype); + v->val = val_alloc(c, v->type, &right); rtype = Tnone; } else { - v->val = val_alloc(v->type, NULL); + v->val = val_alloc(c, v->type, NULL); } break; } @@ -3408,7 +3451,7 @@ function. if (v->var->type == Tnone) { /* Convert this to a label */ v->var->type = Tlabel; - v->var->val = val_alloc(Tlabel, NULL); + v->var->val = val_alloc(c, Tlabel, NULL); v->var->val->label = v->var->val; } } @@ -3432,7 +3475,7 @@ function. ###### interp binode cases case Use: - rv = interp_exec(b->right, &rvtype); + rv = interp_exec(c, b->right, &rvtype); break; ### The Conditional Statement @@ -3862,44 +3905,44 @@ defined. struct value v, cnd; struct type *vtype, *cndtype; struct casepart *cp; - struct cond_statement *c = cast(cond_statement, e); + struct cond_statement *cs = cast(cond_statement, e); - if (c->forpart) - interp_exec(c->forpart, NULL); + if (cs->forpart) + interp_exec(c, cs->forpart, NULL); do { - if (c->condpart) - cnd = interp_exec(c->condpart, &cndtype); + if (cs->condpart) + cnd = interp_exec(c, cs->condpart, &cndtype); else cndtype = Tnone; if (!(cndtype == Tnone || (cndtype == Tbool && cnd.bool != 0))) break; // cnd is Tnone or Tbool, doesn't need to be freed - if (c->dopart) - interp_exec(c->dopart, NULL); + if (cs->dopart) + interp_exec(c, cs->dopart, NULL); - if (c->thenpart) { - rv = interp_exec(c->thenpart, &rvtype); - if (rvtype != Tnone || !c->dopart) + if (cs->thenpart) { + rv = interp_exec(c, cs->thenpart, &rvtype); + if (rvtype != Tnone || !cs->dopart) goto Xcond_done; free_value(rvtype, &rv); rvtype = Tnone; } - } while (c->dopart); + } while (cs->dopart); - for (cp = c->casepart; cp; cp = cp->next) { - v = interp_exec(cp->value, &vtype); + for (cp = cs->casepart; cp; cp = cp->next) { + v = interp_exec(c, cp->value, &vtype); if (value_cmp(cndtype, vtype, &v, &cnd) == 0) { free_value(vtype, &v); free_value(cndtype, &cnd); - rv = interp_exec(cp->action, &rvtype); + rv = interp_exec(c, cp->action, &rvtype); goto Xcond_done; } free_value(vtype, &v); } free_value(cndtype, &cnd); - if (c->elsepart) - rv = interp_exec(c->elsepart, &rvtype); + if (cs->elsepart) + rv = interp_exec(c, cs->elsepart, &rvtype); else rvtype = Tnone; Xcond_done: @@ -4015,8 +4058,8 @@ searching through for the Nth constant for decreasing N. if (!ok) c->parse_error = 1; else if (v) { - struct value res = interp_exec($5, &v->type); - v->val = val_alloc(v->type, &res); + struct value res = interp_exec(c, $5, &v->type); + v->val = val_alloc(c, v->type, &res); } } }$ @@ -4165,7 +4208,7 @@ analysis is a bit more interesting at this level. return !!ok; } - static void interp_prog(struct exec *prog, char **argv) + static void interp_prog(struct parse_context *c, struct exec *prog, char **argv) { struct binode *p = cast(binode, prog); struct binode *al; @@ -4178,25 +4221,30 @@ analysis is a bit more interesting at this level. while (al) { struct var *v = cast(var, al->left); struct value *vl = v->var->val; + struct value arg; if (argv[0] == NULL) { printf("Not enough args\n"); exit(1); } - al = cast(binode, al->right); - if (vl) - free_value(v->var->type, vl); + if (v->var->type != Tstr) { + printf("Arg not string!!\n"); // NOTEST + exit(2); // NOTEST + } if (!vl) { - vl = val_alloc(v->var->type, NULL); + vl = val_alloc(c, v->var->type, NULL); v->var->val = vl; } - free_value(v->var->type, vl); - vl->str.len = strlen(argv[0]); - vl->str.txt = malloc(vl->str.len); - memcpy(vl->str.txt, argv[0], vl->str.len); + + arg.str.txt = argv[0]; + arg.str.len = strlen(argv[0]); + free_value(Tstr, vl); + dup_value(Tstr, &arg, vl); + + al = cast(binode, al->right); argv++; } - v = interp_exec(p->right, &vtype); + v = interp_exec(c, p->right, &vtype); free_value(vtype, &v); }