From: NeilBrown Date: Tue, 23 Nov 2021 22:31:49 +0000 (+1100) Subject: oceani: make anon types more formal X-Git-Url: https://ocean-lang.org/code/?p=ocean;a=commitdiff_plain;h=7b204b91b3e742371df976a01a4029f48aa3aa27 oceani: make anon types more formal As we need anon types - make it explicit and allow a name to be constructed. Signed-off-by: NeilBrown --- diff --git a/csrc/oceani-tests.mdc b/csrc/oceani-tests.mdc index 3156b3d..58fde75 100644 --- a/csrc/oceani-tests.mdc +++ b/csrc/oceani-tests.mdc @@ -973,7 +973,7 @@ various places that `type_err()` are called. print foo ###### output: bad_main - .tmp.code:??:??: error: expected argv but variable 'foo' is string + .tmp.code:??:??: error: expected []string but variable 'foo' is string .tmp.code:??:??: info: this is where 'NOTVAR' was set to string oceani: main has wrong type. @@ -1034,8 +1034,8 @@ Test for type errors with functions .tmp.code:20:14: error: attempt to call a non-function. .tmp.code:20:32: error: expected string found number .tmp.code:20:28: error: insufficient arguments to function. - .tmp.code:21:20: error: expected func but variable 'test2' is func - .tmp.code:??:??: info: this is where 'NOTVAR' was set to func + .tmp.code:21:20: error: expected *invalid*type* but variable 'test2' is *invalid*type* + .tmp.code:??:??: info: this is where 'NOTVAR' was set to *invalid*type* .tmp.code:10:14: error: variable used but not declared: a .tmp.code:10:17: error: variable used but not declared: z oceani: type error in program - not running. diff --git a/csrc/oceani.mdc b/csrc/oceani.mdc index 3befc63..5a728b6 100644 --- a/csrc/oceani.mdc +++ b/csrc/oceani.mdc @@ -130,7 +130,7 @@ structures can be used. struct parse_context *c = config2context(config); ###### Parser: code - + #define _GNU_SOURCE #include #include #include @@ -763,6 +763,10 @@ have not yet been implemented. Named type are stored in a simple linked list. Objects of each type are "values" which are often passed around by value. +There are both explicitly named types, and anonymous types. Anonymous +cannot be accessed by name, but are used internally and have a name +which might be reported in error messages. + ###### ast struct value { @@ -776,6 +780,7 @@ Named type are stored in a simple linked list. Objects of each type are struct text name; struct type *next; 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); void (*print)(struct type *type, struct value *val, FILE *f); @@ -800,31 +805,54 @@ Named type are stored in a simple linked list. Objects of each type are struct type *typelist; +###### includes + #include + ###### ast functions static struct type *find_type(struct parse_context *c, struct text s) { - struct type *l = c->typelist; + struct type *t = c->typelist; - while (l && - text_cmp(l->name, s) != 0) - l = l->next; - return l; + while (t && (t->anon || + text_cmp(t->name, s) != 0)) + t = t->next; + return t; } - static struct type *add_type(struct parse_context *c, struct text s, - struct type *proto) + static struct type *_add_type(struct parse_context *c, struct text s, + struct type *proto, int anon) { struct type *n; n = calloc(1, sizeof(*n)); *n = *proto; n->name = s; + n->anon = anon; n->next = c->typelist; c->typelist = n; return n; } + static struct type *add_type(struct parse_context *c, struct text s, + struct type *proto) + { + return _add_type(c, s, proto, 0); + } + + static struct type *add_anon_type(struct parse_context *c, + struct type *proto, char *name, ...) + { + struct text t; + va_list ap; + + va_start(ap, name); + vasprintf(&t.txt, name, ap); + va_end(ap); + t.len = strlen(name); + return _add_type(c, t, proto, 1); + } + static void free_type(struct type *t) { /* The type is always a reference to something in the @@ -844,12 +872,12 @@ Named type are stored in a simple linked list. Objects of each type are { if (!type) fputs("*unknown*type*", f); // NOTEST - else if (type->name.len) + else if (type->name.len && !type->anon) fprintf(f, "%.*s", type->name.len, type->name.txt); else if (type->print_type) type->print_type(type, f); else - fputs("*invalid*type*", f); // NOTEST + fputs("*invalid*type*", f); } static void val_init(struct type *type, struct value *val) @@ -903,6 +931,8 @@ Named type are stored in a simple linked list. Objects of each type are context.typelist = t->next; if (t->free_type) t->free_type(t); + if (t->anon) + free(t->name.txt); free(t); } @@ -2284,8 +2314,10 @@ with a const size by whether they are prepared at parse time or not. struct binding *b = type->array.vsize->name; fprintf(f, "%.*s%s]", b->name.len, b->name.txt, type->array.unspec ? "::" : ""); - } else + } else if (type->array.size) fprintf(f, "%d]", type->array.size); + else + fprintf(f, "]"); type_print(type->array.member, f); } @@ -2307,19 +2339,16 @@ with a const size by whether they are prepared at parse time or not. | [ NUMBER ] Type ${ { char tail[3]; mpq_t num; - struct text noname = { "", 0 }; struct type *t; + int elements = 0; - $0 = t = add_type(c, noname, &array_prototype); - t->array.member = $<4; - t->array.vsize = NULL; if (number_parse(num, tail, $2.txt) == 0) tok_err(c, "error: unrecognised number", &$2); else if (tail[0]) { tok_err(c, "error: unsupported number suffix", &$2); mpq_clear(num); } else { - t->array.size = mpz_get_ui(mpq_numref(num)); + elements = mpz_get_ui(mpq_numref(num)); if (mpz_cmp_ui(mpq_denref(num), 1) != 0) { tok_err(c, "error: array size must be an integer", &$2); @@ -2328,6 +2357,11 @@ with a const size by whether they are prepared at parse time or not. &$2); mpq_clear(num); } + + $0 = t = add_anon_type(c, &array_prototype, "array[%d]", elements ); + t->array.size = elements; + t->array.member = $<4; + t->array.vsize = NULL; t->array.static_size = 1; t->size = t->array.size * t->array.member->size; t->align = t->array.member->align; @@ -2335,14 +2369,13 @@ with a const size by whether they are prepared at parse time or not. | [ IDENTIFIER ] Type ${ { struct variable *v = var_ref(c, $2.txt); - struct text noname = { "", 0 }; if (!v) tok_err(c, "error: name undeclared", &$2); else if (!v->constant) tok_err(c, "error: array size must be a constant", &$2); - $0 = add_type(c, noname, &array_prototype); + $0 = add_anon_type(c, &array_prototype, "array[%.*s]", $2.txt.len, $2.txt.txt); $0->array.member = $<4; $0->array.size = 0; $0->array.vsize = v; @@ -2357,13 +2390,12 @@ with a const size by whether they are prepared at parse time or not. | [ IDENTIFIER :: OptType ] Type ${ { struct variable *v = var_decl(c, $ID.txt); - struct text noname = { "", 0 }; v->type = $constant = 1; if (!v->type) v->type = Tnum; - $0 = add_type(c, noname, &array_prototype); + $0 = add_anon_type(c, &array_prototype, "array[var]"); $0->array.member = $<6; $0->array.size = 0; $0->array.unspec = 1; @@ -2758,7 +2790,8 @@ function will be needed. while (target != 0) { int i = 0; for (t = context.typelist; t ; t=t->next) - if (t->print_type_decl && !t->check_args && t->name.txt[0] != ' ') { + if (!t->anon && t->print_type_decl && + !t->check_args) { i += 1; if (i == target) break; @@ -4922,8 +4955,8 @@ is a bit more interesting at this level. /* Create a 'struct' type from the results list, which * is a list for 'struct var' */ - struct text result_type_name = { " function_result", 5 }; - struct type *t = add_type(c, result_type_name, &structure_prototype); + struct type *t = add_anon_type(c, &structure_prototype, + " function result"); int cnt = 0; struct binode *b; @@ -4957,12 +4990,13 @@ is a bit more interesting at this level. struct binode *results, struct exec *code) { - struct text funcname = {" func", 5}; if (name) { struct value fn = {.function = code}; struct type *t; var_block_close(c, CloseFunction, code); - t = add_type(c, funcname, &function_prototype); + t = add_anon_type(c, &function_prototype, + "func %.*s", name->name->name.len, + name->name->name.txt); name->type = t; t->function.params = reorder_bilist(args); if (!ret) { @@ -5089,9 +5123,8 @@ is a bit more interesting at this level. int ok = 1; int arg = 0; struct type *argv_type; - struct text argv_type_name = { " argv", 5 }; - argv_type = add_type(c, argv_type_name, &array_prototype); + argv_type = add_anon_type(c, &array_prototype, "argv"); argv_type->array.member = Tstr; argv_type->array.unspec = 1;