From 70bc97a66bb1bbf945a7d0ba6e5d72558e11deb9 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 1 Dec 2021 10:05:27 +1100 Subject: [PATCH] oceani: move struct field processing into ->prepare_type This will allow the preparation of the type to be moved later, possibly after necessary constants and other types have been declared. Signed-off-by: NeilBrown --- csrc/oceani.mdc | 140 ++++++++++++++++++++++++++++-------------------- 1 file changed, 81 insertions(+), 59 deletions(-) diff --git a/csrc/oceani.mdc b/csrc/oceani.mdc index 282cd30..a4a9bd7 100644 --- a/csrc/oceani.mdc +++ b/csrc/oceani.mdc @@ -647,6 +647,9 @@ the location of a value, which can be updated, in `lval`. Others will set `lval` to NULL indicating that there is a value of appropriate type in `rval`. +###### forward decls + static struct value interp_exec(struct parse_context *c, struct exec *e, + struct type **typeret); ###### core functions struct lrval { @@ -1845,6 +1848,10 @@ tell if it was set or not later. short local_size; void *global, *local; +###### forward decls + static struct value *global_alloc(struct parse_context *c, struct type *t, + struct variable *v, struct value *init); + ###### ast functions static struct value *var_value(struct parse_context *c, struct variable *v) @@ -2515,7 +2522,12 @@ function will be needed. struct type *type; struct value *init; int offset; - } *fields; + } *fields; // This is created when field_list is analysed. + struct fieldlist { + struct fieldlist *prev; + struct field f; + struct exec *init; + } *field_list; // This is created during parsing } structure; ###### type functions @@ -2550,6 +2562,15 @@ function will be needed. } } + static void free_fieldlist(struct fieldlist *f) + { + if (!f) + return; + free_fieldlist(f->prev); + free_exec(f->init); + free(f); + } + static void structure_free_type(struct type *t) { int i; @@ -2559,6 +2580,56 @@ function will be needed. t->structure.fields[i].init); } free(t->structure.fields); + free_fieldlist(t->structure.field_list); + } + + static void 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; + + for (f = t->structure.field_list; f; f=f->prev) { + int ok; + cnt += 1; + + if (f->f.type->prepare_type) + f->f.type->prepare_type(c, f->f.type, 1); + if (f->init == NULL) + continue; + do { + ok = 1; + propagate_types(f->init, c, &ok, f->f.type, 0); + } while (ok == 2); + if (!ok) + c->parse_error = 1; // NOTEST + } + + t->structure.nfields = cnt; + t->structure.fields = calloc(cnt, sizeof(struct field)); + f = t->structure.field_list; + while (cnt > 0) { + int a = f->f.type->align; + cnt -= 1; + t->structure.fields[cnt] = f->f; + if (t->size & (a-1)) + t->size = (t->size | (a-1)) + 1; + t->structure.fields[cnt].offset = t->size; + t->size += ((f->f.type->size - 1) | (a-1)) + 1; + if (a > t->align) + t->align = a; + + if (f->init && !c->parse_error) { + struct value vl = interp_exec(c, f->init, NULL); + t->structure.fields[cnt].init = + global_alloc(c, f->f.type, NULL, &vl); + } + + f = f->prev; + } } static struct type structure_prototype = { @@ -2566,6 +2637,7 @@ function will be needed. .free = structure_free, .free_type = structure_free_type, .print_type_decl = structure_print_type, + .prepare_type = structure_prepare_type, }; ###### exec type @@ -2658,51 +2730,14 @@ function will be needed. break; } -###### ast - struct fieldlist { - struct fieldlist *prev; - struct field f; - }; - -###### ast functions - static void free_fieldlist(struct fieldlist *f) - { - if (!f) - return; - free_fieldlist(f->prev); - if (f->f.init) { - free_value(f->f.type, f->f.init); // UNTESTED - free(f->f.init); // UNTESTED - } - free(f); - } - ###### top level grammar DeclareStruct -> struct IDENTIFIER FieldBlock Newlines ${ { struct type *t = add_type(c, $2.txt, &structure_prototype); - int cnt = 0; - struct fieldlist *f; - - for (f = $3; f; f=f->prev) - cnt += 1; + t->structure.field_list = $prepare_type) + t->prepare_type(c, t, 1); - t->structure.nfields = cnt; - t->structure.fields = calloc(cnt, sizeof(struct field)); - f = $3; - while (cnt > 0) { - int a = f->f.type->align; - cnt -= 1; - t->structure.fields[cnt] = f->f; - if (t->size & (a-1)) - t->size = (t->size | (a-1)) + 1; - t->structure.fields[cnt].offset = t->size; - t->size += ((f->f.type->size - 1) | (a-1)) + 1; - if (a > t->align) - t->align = a; - f->f.init = NULL; - f = f->prev; - } } }$ $*fieldlist @@ -2728,29 +2763,16 @@ function will be needed. | ERROR ${ tok_err(c, "Syntax error in struct field", &$1); }$ Field -> IDENTIFIER : Type = Expression ${ { - int ok; - $0 = calloc(1, sizeof(struct fieldlist)); - $0->f.name = $1.txt; - $0->f.type = $<3; + $0->f.name = $ID.txt; + $0->f.type = $f.init = NULL; - do { - ok = 1; - propagate_types($<5, c, &ok, $3, 0); - } while (ok == 2); - if (!ok) - c->parse_error = 1; // UNTESTED - else { - struct value vl = interp_exec(c, $5, NULL); - $0->f.init = global_alloc(c, $0->f.type, NULL, &vl); - } + $0->init = $f.name = $1.txt; - $0->f.type = $<3; - if ($0->f.type->prepare_type) - $0->f.type->prepare_type(c, $0->f.type, 1); + $0->f.name = $ID.txt; + $0->f.type = $