]> ocean-lang.org Git - ocean/blobdiff - csrc/oceani.mdc
oceani: remove the HACK concerning type names starting with space
[ocean] / csrc / oceani.mdc
index 9720d222fac37ffced3f0494c446e3af2203eb19..e7976cf086ef03b338527549a4d3d069af7afd45 100644 (file)
@@ -367,6 +367,7 @@ context so indicate that parsing failed.
        static void type_err(struct parse_context *c,
                             char *fmt, struct exec *loc,
                             struct type *t1, int rules, struct type *t2);
+       static void tok_err(struct parse_context *c, char *fmt, struct token *t);
 
 ###### core functions
 
@@ -588,13 +589,15 @@ which can be `NULL` signifying "unknown".  A `prop_err` flag set is
 passed by reference.  It has `Efail` set when an error is found, and
 `Eretry` when the type for some element is set via propagation.  If
 any expression cannot be evaluated immediately, `Enoconst` is set.
+If the expression can be copied, `Emaycopy` is set.
 
 If it remains unchanged at `0`, then no more propagation is needed.
 
 ###### ast
 
        enum val_rules {Rnolabel = 1<<0, Rboolok = 1<<1, Rnoconstant = 1<<2};
-       enum prop_err {Efail = 1<<0, Eretry = 1<<1, Enoconst = 1<<2};
+       enum prop_err {Efail = 1<<0, Eretry = 1<<1, Enoconst = 1<<2,
+                      Emaycopy = 1<<3};
 
 ###### format cases
        case 'r':
@@ -789,10 +792,11 @@ which might be reported in error messages.
        struct type {
                struct text name;
                struct type *next;
+               struct token first_use;
                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);
+               int (*prepare_type)(struct parse_context *c, struct type *type, int parse_time);
                void (*print)(struct type *type, struct value *val, FILE *f);
                void (*print_type)(struct type *type, FILE *f);
                int (*cmp_order)(struct type *t1, struct type *t2,
@@ -836,7 +840,10 @@ which might be reported in error messages.
                struct type *n;
 
                n = calloc(1, sizeof(*n));
-               *n = *proto;
+               if (proto)
+                       *n = *proto;
+               else
+                       n->size = -1;
                n->name = s;
                n->anon = anon;
                n->next = c->typelist;
@@ -924,10 +931,35 @@ which might be reported in error messages.
        static void prepare_types(struct parse_context *c)
        {
                struct type *t;
+               int retry = 1;
+               enum { none, some, cannot } progress = none;
 
-               for (t = c->typelist; t; t = t->next)
-                       if (t->prepare_type)
-                               t->prepare_type(c, t, 1);
+               while (retry) {
+                       retry = 0;
+
+                       for (t = c->typelist; t; t = t->next) {
+                               if (t->size < 0)
+                                       tok_err(c, "error: type used but not declared",
+                                                &t->first_use);
+                               if (t->size == 0 && t->prepare_type) {
+                                       if (t->prepare_type(c, t, 1))
+                                               progress = some;
+                                       else if (progress == cannot)
+                                               tok_err(c, "error: type has recursive definition",
+                                                       &t->first_use);
+                                       else
+                                               retry = 1;
+                               }
+                       }
+                       switch (progress) {
+                       case cannot:
+                               retry = 0; break;
+                       case none:
+                               progress = cannot; break;
+                       case some:
+                               progress = none; break;
+                       }
+               }
        }
 
 ###### forward decls
@@ -966,12 +998,10 @@ symbol for those.
 
        $*type
        Type -> IDENTIFIER ${
-               $0 = find_type(c, $1.txt);
+               $0 = find_type(c, $ID.txt);
                if (!$0) {
-                       tok_err(c,
-                               "error: undefined type", &$1);
-
-                       $0 = Tnone;
+                       $0 = add_type(c, $ID.txt, NULL);
+                       $0->first_use = $ID;
                }
        }$
        ## type grammar
@@ -2251,33 +2281,37 @@ with a const size by whether they are prepared at parse time or not.
 
 ###### value functions
 
-       static void array_prepare_type(struct parse_context *c, struct type *type,
+       static int array_prepare_type(struct parse_context *c, struct type *type,
                                       int parse_time)
        {
                struct value *vsize;
                mpz_t q;
                if (type->array.static_size)
-                       return;
+                       return 1;       // UNTESTED
                if (type->array.unspec && parse_time)
-                       return;
+                       return 1;       // UNTESTED
                if (parse_time && type->array.vsize && !type->array.vsize->global)
-                       return;
+                       return 1;       // UNTESTED
 
                if (type->array.vsize) {
                        vsize = var_value(c, type->array.vsize);
                        if (!vsize)
-                               return; // UNTESTED
+                               return 1;       // UNTESTED
                        mpz_init(q);
                        mpz_tdiv_q(q, mpq_numref(vsize->num), mpq_denref(vsize->num));
                        type->array.size = mpz_get_si(q);
                        mpz_clear(q);
                }
+               if (!parse_time)
+                       return 1;
+               if (type->array.member->size <= 0)
+                       return 0;
 
-               if (parse_time && type->array.member->size) {
-                       type->array.static_size = 1;
-                       type->size = type->array.size * type->array.member->size;
-                       type->align = type->array.member->align;
-               }
+               type->array.static_size = 1;
+               type->size = type->array.size * type->array.member->size;
+               type->align = type->array.member->align;
+
+               return 1;
        }
 
        static void array_init(struct type *type, struct value *val)
@@ -2606,21 +2640,24 @@ function will be needed.
                free_fieldlist(t->structure.field_list);
        }
 
-       static void structure_prepare_type(struct parse_context *c,
-                                          struct type *t, int parse_time)
+       static int 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;
+                       return 1;
 
                for (f = t->structure.field_list; f; f=f->prev) {
                        enum prop_err perr;
                        cnt += 1;
 
+                       if (f->f.type->size <= 0)
+                               return 0;
                        if (f->f.type->prepare_type)
-                               f->f.type->prepare_type(c, f->f.type, 1);
+                               f->f.type->prepare_type(c, f->f.type, parse_time);
+
                        if (f->init == NULL)
                                continue;
                        do {
@@ -2653,6 +2690,7 @@ function will be needed.
 
                        f = f->prev;
                }
+               return 1;
        }
 
        static struct type structure_prototype = {
@@ -2755,9 +2793,23 @@ function will be needed.
 
 ###### top level grammar
        DeclareStruct -> struct IDENTIFIER FieldBlock Newlines ${ {
-               struct type *t =
-                       add_type(c, $2.txt, &structure_prototype);
+               struct type *t;
+               t = find_type(c, $ID.txt);
+               if (!t)
+                       t = add_type(c, $ID.txt, &structure_prototype);
+               else if (t->size >= 0) {
+                       tok_err(c, "error: type already declared", &$ID);
+                       tok_err(c, "info: this is location of declartion", &t->first_use);
+                       /* Create a new one - duplicate */
+                       t = add_type(c, $ID.txt, &structure_prototype);
+               } else {
+                       struct type tmp = *t;
+                       *t = structure_prototype;
+                       t->name = tmp.name;
+                       t->next = tmp.next;
+               }
                t->structure.field_list = $<FB;
+               t->first_use = $ID;
        } }$
 
        $*fieldlist
@@ -3159,6 +3211,8 @@ it in the "SimpleStatement Grammar" which will be described later.
                }
                *perr |= Enoconst;
                v->var->type->check_args(c, perr, v->var->type, args);
+               if (v->var->type->function.inline_result)
+                       *perr |= Emaycopy;
                return v->var->type->function.return_type;
        }
 
@@ -4240,7 +4294,7 @@ it is declared, and error will be raised as the name is created as
                                propagate_types(b->left, c, perr, t,
                                                (b->op == Assign ? Rnoconstant : 0));
                }
-               if (t && t->dup == NULL && t->name.txt[0] != ' ') // HACK
+               if (t && t->dup == NULL && !(*perr & Emaycopy))
                        type_err(c, "error: cannot assign value of type %1", b, t, 0, NULL);
                return Tnone;
 
@@ -5049,7 +5103,7 @@ is a bit more interesting at this level.
                 * is a list for 'struct var'
                 */
                struct type *t = add_anon_type(c, &structure_prototype,
-                                              " function result");
+                                              "function result");
                int cnt = 0;
                struct binode *b;