X-Git-Url: https://ocean-lang.org/code/?p=ocean;a=blobdiff_plain;f=csrc%2Foceani.mdc;h=e1a2cb076b49c43fc8c5dd95dc2e822929ff875c;hp=12be60cff7e066d9cfc9bf032047510a8701976d;hb=1f2bd5d4d22797071a344647191e63c7d2fa6f67;hpb=b57589e699a72debfbbe6a29983dfe7ed707a148 diff --git a/csrc/oceani.mdc b/csrc/oceani.mdc index 12be60c..e1a2cb0 100644 --- a/csrc/oceani.mdc +++ b/csrc/oceani.mdc @@ -110,6 +110,7 @@ structures can be used. ## macros struct parse_context; ## ast + ## ast late struct parse_context { struct token_config config; char *file_name; @@ -789,6 +790,7 @@ which might be reported in error messages. }; }; +###### ast late struct type { struct text name; struct type *next; @@ -2620,6 +2622,8 @@ function will be needed. ###### type functions void (*print_type_decl)(struct type *type, FILE *f); + struct type *(*fieldref)(struct type *t, struct parse_context *c, + struct fieldref *f, struct value **vp); ###### value functions @@ -2724,12 +2728,41 @@ function will be needed. return 1; } + static int find_struct_index(struct type *type, struct text field) + { + int i; + for (i = 0; i < type->structure.nfields; i++) + if (text_cmp(type->structure.fields[i].name, field) == 0) + return i; + return IndexInvalid; + } + + static struct type *structure_fieldref(struct type *t, struct parse_context *c, + struct fieldref *f, struct value **vp) + { + if (f->index == IndexUnknown) { + f->index = find_struct_index(t, f->name); + if (f->index < 0) + type_err(c, "error: cannot find requested field in %1", + f->left, t, 0, NULL); + } + if (f->index < 0) + return NULL; + if (vp) { + struct value *v = *vp; + v = (void*)v->ptr + t->structure.fields[f->index].offset; + *vp = v; + } + return t->structure.fields[f->index].type; + } + static struct type structure_prototype = { .init = structure_init, .free = structure_free, .free_type = structure_free_type, .print_type_decl = structure_print_type, .prepare_type = structure_prepare_type, + .fieldref = structure_fieldref, }; ###### exec type @@ -2742,6 +2775,7 @@ function will be needed. int index; struct text name; }; + enum { IndexUnknown = -1, IndexInvalid = -2 }; ###### free exec cases case Xfieldref: @@ -2758,7 +2792,7 @@ function will be needed. struct fieldref *fr = new_pos(fieldref, $2); fr->left = $<1; fr->name = $3.txt; - fr->index = -2; + fr->index = IndexUnknown; $0 = fr; } }$ @@ -2772,16 +2806,6 @@ function will be needed. break; } -###### ast functions - static int find_struct_index(struct type *type, struct text field) - { - int i; - for (i = 0; i < type->structure.nfields; i++) - if (text_cmp(type->structure.fields[i].name, field) == 0) - return i; - return -1; - } - ###### propagate exec cases case Xfieldref: @@ -2789,24 +2813,15 @@ function will be needed. struct fieldref *f = cast(fieldref, prog); struct type *st = propagate_types(f->left, c, perr, NULL, 0); - if (!st) - type_err(c, "error: unknown type for field access", f->left, // UNTESTED - NULL, 0, NULL); - else if (st->init != structure_init) - type_err(c, "error: field reference attempted on %1, not a struct", + if (!st || !st->fieldref) + type_err(c, "error: field reference on %1 is not supported", f->left, st, 0, NULL); - else if (f->index == -2) { - f->index = find_struct_index(st, f->name); - if (f->index < 0) - type_err(c, "error: cannot find requested field in %1", - f->left, st, 0, NULL); - } - if (f->index >= 0) { - struct type *ft = st->structure.fields[f->index].type; - if (!type_compat(type, ft, rules)) + else { + t = st->fieldref(st, c, f, NULL); + if (t && !type_compat(type, t, rules)) type_err(c, "error: have %1 but need %2", prog, - ft, rules, type); - return ft; + t, rules, type); + return t; } break; } @@ -2817,8 +2832,8 @@ function will be needed. struct fieldref *f = cast(fieldref, e); struct type *ltype; 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; + lrv = lleft; + rvtype = ltype->fieldref(ltype, c, f, &lrv); break; }