]> ocean-lang.org Git - ocean/commitdiff
oceani: make anon types more formal
authorNeilBrown <neil@brown.name>
Tue, 23 Nov 2021 22:31:49 +0000 (09:31 +1100)
committerNeilBrown <neil@brown.name>
Thu, 25 Nov 2021 09:08:27 +0000 (20:08 +1100)
As we need anon types - make it explicit and allow a name to be constructed.

Signed-off-by: NeilBrown <neil@brown.name>
csrc/oceani-tests.mdc
csrc/oceani.mdc

index 3156b3d4bcd372babc885c6a658d9382e5d1d53f..58fde75620d45c479b8840abea87fc5db643eca7 100644 (file)
@@ -973,7 +973,7 @@ various places that `type_err()` are called.
                print foo
 
 ###### output: bad_main
                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.
 
        .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: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.
        .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.
index 3befc631dbf4ce72dd2adf34517a0deaeeb97c9d..5a728b6086463bf76cadcc0d52ffc6f7be90b93c 100644 (file)
@@ -130,7 +130,7 @@ structures can be used.
        struct parse_context *c = config2context(config);
 
 ###### Parser: code
        struct parse_context *c = config2context(config);
 
 ###### Parser: code
-
+       #define _GNU_SOURCE
        #include <unistd.h>
        #include <stdlib.h>
        #include <fcntl.h>
        #include <unistd.h>
        #include <stdlib.h>
        #include <fcntl.h>
@@ -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.
 
 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 {
 ###### 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;
                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);
                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;
 
 
        struct type *typelist;
 
+###### includes
+       #include <stdarg.h>
+
 ###### ast functions
 
        static struct type *find_type(struct parse_context *c, struct text s)
        {
 ###### 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;
        {
                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;
        }
 
                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
        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
        {
                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
                        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)
        }
 
        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);
                context.typelist = t->next;
                if (t->free_type)
                        t->free_type(t);
+               if (t->anon)
+                       free(t->name.txt);
                free(t);
        }
 
                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 ? "::" : "");
                        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);
                        fprintf(f, "%d]", type->array.size);
+               else
+                       fprintf(f, "]");
                type_print(type->array.member, 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;
        | [ NUMBER ] Type ${ {
                char tail[3];
                mpq_t num;
-               struct text noname = { "", 0 };
                struct type *t;
                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 {
                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);
                        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);
                }
                                        &$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;
                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);
 
        | [ 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);
 
 
                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;
                $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);
 
        | [ IDENTIFIER :: OptType ] Type ${ {
                struct variable *v = var_decl(c, $ID.txt);
-               struct text noname = { "", 0 };
 
                v->type = $<OT;
                v->constant = 1;
                if (!v->type)
                        v->type = Tnum;
 
                v->type = $<OT;
                v->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;
                $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)
                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;
                                        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'
                 */
                /* 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;
 
                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 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);
                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) {
                        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;
                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;
 
                argv_type->array.member = Tstr;
                argv_type->array.unspec = 1;