]> ocean-lang.org Git - ocean/commitdiff
oceani: move struct field processing into ->prepare_type
authorNeilBrown <neil@brown.name>
Tue, 30 Nov 2021 23:05:27 +0000 (10:05 +1100)
committerNeilBrown <neil@brown.name>
Fri, 3 Dec 2021 08:13:35 +0000 (19:13 +1100)
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 <neil@brown.name>
csrc/oceani.mdc

index 282cd3054518430936cf0b82238db1a77e1d712d..a4a9bd7b8b13415d5d9b70ac579fad456b92e09e 100644 (file)
@@ -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 = $<FB;
+               if (t->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 = $<Type;
                $0->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 = $<Expr;
        } }$
        | IDENTIFIER : Type ${
                $0 = calloc(1, sizeof(struct fieldlist));
-               $0->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 = $<Type;
        }$
 
 ###### forward decls