X-Git-Url: https://ocean-lang.org/code/?p=ocean;a=blobdiff_plain;f=csrc%2Foceani.mdc;h=e7976cf086ef03b338527549a4d3d069af7afd45;hp=9720d222fac37ffced3f0494c446e3af2203eb19;hb=ef3bbba20f9e426125498f78fe3b1f4ea75de68a;hpb=e4967da39aff091cd9dfa187cf77c84ba8643293 diff --git a/csrc/oceani.mdc b/csrc/oceani.mdc index 9720d22..e7976cf 100644 --- a/csrc/oceani.mdc +++ b/csrc/oceani.mdc @@ -367,6 +367,7 @@ context so indicate that parsing failed. static void type_err(struct parse_context *c, char *fmt, struct exec *loc, struct type *t1, int rules, struct type *t2); + static void tok_err(struct parse_context *c, char *fmt, struct token *t); ###### core functions @@ -588,13 +589,15 @@ which can be `NULL` signifying "unknown". A `prop_err` flag set is passed by reference. It has `Efail` set when an error is found, and `Eretry` when the type for some element is set via propagation. If any expression cannot be evaluated immediately, `Enoconst` is set. +If the expression can be copied, `Emaycopy` is set. If it remains unchanged at `0`, then no more propagation is needed. ###### ast enum val_rules {Rnolabel = 1<<0, Rboolok = 1<<1, Rnoconstant = 1<<2}; - enum prop_err {Efail = 1<<0, Eretry = 1<<1, Enoconst = 1<<2}; + enum prop_err {Efail = 1<<0, Eretry = 1<<1, Enoconst = 1<<2, + Emaycopy = 1<<3}; ###### format cases case 'r': @@ -789,10 +792,11 @@ which might be reported in error messages. struct type { struct text name; struct type *next; + struct token first_use; int size, align; int anon; void (*init)(struct type *type, struct value *val); - void (*prepare_type)(struct parse_context *c, struct type *type, int parse_time); + int (*prepare_type)(struct parse_context *c, struct type *type, int parse_time); void (*print)(struct type *type, struct value *val, FILE *f); void (*print_type)(struct type *type, FILE *f); int (*cmp_order)(struct type *t1, struct type *t2, @@ -836,7 +840,10 @@ which might be reported in error messages. struct type *n; n = calloc(1, sizeof(*n)); - *n = *proto; + if (proto) + *n = *proto; + else + n->size = -1; n->name = s; n->anon = anon; n->next = c->typelist; @@ -924,10 +931,35 @@ which might be reported in error messages. static void prepare_types(struct parse_context *c) { struct type *t; + int retry = 1; + enum { none, some, cannot } progress = none; - for (t = c->typelist; t; t = t->next) - if (t->prepare_type) - t->prepare_type(c, t, 1); + while (retry) { + retry = 0; + + for (t = c->typelist; t; t = t->next) { + if (t->size < 0) + tok_err(c, "error: type used but not declared", + &t->first_use); + if (t->size == 0 && t->prepare_type) { + if (t->prepare_type(c, t, 1)) + progress = some; + else if (progress == cannot) + tok_err(c, "error: type has recursive definition", + &t->first_use); + else + retry = 1; + } + } + switch (progress) { + case cannot: + retry = 0; break; + case none: + progress = cannot; break; + case some: + progress = none; break; + } + } } ###### forward decls @@ -966,12 +998,10 @@ symbol for those. $*type Type -> IDENTIFIER ${ - $0 = find_type(c, $1.txt); + $0 = find_type(c, $ID.txt); if (!$0) { - tok_err(c, - "error: undefined type", &$1); - - $0 = Tnone; + $0 = add_type(c, $ID.txt, NULL); + $0->first_use = $ID; } }$ ## type grammar @@ -2251,33 +2281,37 @@ with a const size by whether they are prepared at parse time or not. ###### value functions - static void array_prepare_type(struct parse_context *c, struct type *type, + static int array_prepare_type(struct parse_context *c, struct type *type, int parse_time) { struct value *vsize; mpz_t q; if (type->array.static_size) - return; + return 1; // UNTESTED if (type->array.unspec && parse_time) - return; + return 1; // UNTESTED if (parse_time && type->array.vsize && !type->array.vsize->global) - return; + return 1; // UNTESTED if (type->array.vsize) { vsize = var_value(c, type->array.vsize); if (!vsize) - return; // UNTESTED + return 1; // UNTESTED mpz_init(q); mpz_tdiv_q(q, mpq_numref(vsize->num), mpq_denref(vsize->num)); type->array.size = mpz_get_si(q); mpz_clear(q); } + if (!parse_time) + return 1; + if (type->array.member->size <= 0) + return 0; - if (parse_time && type->array.member->size) { - type->array.static_size = 1; - type->size = type->array.size * type->array.member->size; - type->align = type->array.member->align; - } + type->array.static_size = 1; + type->size = type->array.size * type->array.member->size; + type->align = type->array.member->align; + + return 1; } static void array_init(struct type *type, struct value *val) @@ -2606,21 +2640,24 @@ function will be needed. free_fieldlist(t->structure.field_list); } - static void structure_prepare_type(struct parse_context *c, - struct type *t, int parse_time) + static int structure_prepare_type(struct parse_context *c, + struct type *t, int parse_time) { int cnt = 0; struct fieldlist *f; if (!parse_time || t->structure.fields) - return; + return 1; for (f = t->structure.field_list; f; f=f->prev) { enum prop_err perr; cnt += 1; + if (f->f.type->size <= 0) + return 0; if (f->f.type->prepare_type) - f->f.type->prepare_type(c, f->f.type, 1); + f->f.type->prepare_type(c, f->f.type, parse_time); + if (f->init == NULL) continue; do { @@ -2653,6 +2690,7 @@ function will be needed. f = f->prev; } + return 1; } static struct type structure_prototype = { @@ -2755,9 +2793,23 @@ function will be needed. ###### top level grammar DeclareStruct -> struct IDENTIFIER FieldBlock Newlines ${ { - struct type *t = - add_type(c, $2.txt, &structure_prototype); + struct type *t; + t = find_type(c, $ID.txt); + if (!t) + t = add_type(c, $ID.txt, &structure_prototype); + else if (t->size >= 0) { + tok_err(c, "error: type already declared", &$ID); + tok_err(c, "info: this is location of declartion", &t->first_use); + /* Create a new one - duplicate */ + t = add_type(c, $ID.txt, &structure_prototype); + } else { + struct type tmp = *t; + *t = structure_prototype; + t->name = tmp.name; + t->next = tmp.next; + } t->structure.field_list = $first_use = $ID; } }$ $*fieldlist @@ -3159,6 +3211,8 @@ it in the "SimpleStatement Grammar" which will be described later. } *perr |= Enoconst; v->var->type->check_args(c, perr, v->var->type, args); + if (v->var->type->function.inline_result) + *perr |= Emaycopy; return v->var->type->function.return_type; } @@ -4240,7 +4294,7 @@ it is declared, and error will be raised as the name is created as propagate_types(b->left, c, perr, t, (b->op == Assign ? Rnoconstant : 0)); } - if (t && t->dup == NULL && t->name.txt[0] != ' ') // HACK + if (t && t->dup == NULL && !(*perr & Emaycopy)) type_err(c, "error: cannot assign value of type %1", b, t, 0, NULL); return Tnone; @@ -5049,7 +5103,7 @@ is a bit more interesting at this level. * is a list for 'struct var' */ struct type *t = add_anon_type(c, &structure_prototype, - " function result"); + "function result"); int cnt = 0; struct binode *b;