From 1f2bd5d4d22797071a344647191e63c7d2fa6f67 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sun, 12 Dec 2021 10:33:39 +1100 Subject: [PATCH] oceani: factor out field reference into per-type handler knowledge about how field references for strutures is now in structure-specific code. This will allow other types to behave differently. Signed-off-by: NeilBrown --- csrc/oceani-tests.mdc | 4 +-- csrc/oceani.mdc | 70 ++++++++++++++++++++++++++----------------- 2 files changed, 44 insertions(+), 30 deletions(-) diff --git a/csrc/oceani-tests.mdc b/csrc/oceani-tests.mdc index 12116d4..d672cff 100644 --- a/csrc/oceani-tests.mdc +++ b/csrc/oceani-tests.mdc @@ -973,9 +973,9 @@ various places that `type_err()` are called. .tmp.code:29:12: error: have number but need string .tmp.code:7:8: info: variable 'c' was set as string here. .tmp.code:32:8: error: variable used but not declared: foo - .tmp.code:32:8: error: field reference attempted on none, not a struct + .tmp.code:32:8: error: field reference on none is not supported .tmp.code:32:16: error: expected none found number - .tmp.code:33:14: error: field reference attempted on string, not a struct + .tmp.code:33:14: error: field reference on string is not supported .tmp.code:34:14: error: cannot find requested field in foo .tmp.code:35:17: error: have string but need number .tmp.code:38:29: error: expected number (labels not permitted) found Boolean diff --git a/csrc/oceani.mdc b/csrc/oceani.mdc index 178532c..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 @@ -2773,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 IndexInvalid; - } - ###### propagate exec cases case Xfieldref: @@ -2790,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 == IndexUnknown) { - 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; } @@ -2818,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; } -- 2.43.0