]> ocean-lang.org Git - ocean/commitdiff
oceani: change the 'ok' flag to 'perr' with well defined bits.
authorNeilBrown <neil@brown.name>
Sat, 4 Dec 2021 22:13:51 +0000 (09:13 +1100)
committerNeilBrown <neil@brown.name>
Sat, 4 Dec 2021 22:13:51 +0000 (09:13 +1100)
I'll want to extend the information gathered by propagate_types() to
report if a value can be computed immediately.  So generalize
'ok' (which contains a magic value) to a set of flags that can be
reported.

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

index 180c36fb4d9bb059f30ca0f2b101f6d1b4a1946c..d40cf9a42f5335a3f30ebf263fb8c82ab9c37d01 100644 (file)
@@ -583,15 +583,16 @@ program and looking for errors.
 
 So `propagate_types` is passed an expected type (being a `struct type`
 pointer together with some `val_rules` flags) that the `exec` is
-expected to return, and returns the type that it does return, either
-of which can be `NULL` signifying "unknown".  An `ok` flag is passed
-by reference. It is set to `0` when an error is found, and `2` when
-any change is made.  If it remains unchanged at `1`, then no more
-propagation is needed.
+expected to return, and returns the type that it does return, either of
+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 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};
 
 ###### format cases
        case 'r':
@@ -600,11 +601,11 @@ propagation is needed.
                break;
 
 ###### forward decls
-       static struct type *propagate_types(struct exec *prog, struct parse_context *c, int *ok,
+       static struct type *propagate_types(struct exec *prog, struct parse_context *c, enum prop_err *perr,
                                            struct type *type, int rules);
 ###### core functions
 
-       static struct type *__propagate_types(struct exec *prog, struct parse_context *c, int *ok,
+       static struct type *__propagate_types(struct exec *prog, struct parse_context *c, enum prop_err *perr,
                                              struct type *type, int rules)
        {
                struct type *t;
@@ -626,13 +627,13 @@ propagation is needed.
                return Tnone;
        }
 
-       static struct type *propagate_types(struct exec *prog, struct parse_context *c, int *ok,
+       static struct type *propagate_types(struct exec *prog, struct parse_context *c, enum prop_err *perr,
                                            struct type *type, int rules)
        {
-               struct type *ret = __propagate_types(prog, c, ok, type, rules);
+               struct type *ret = __propagate_types(prog, c, perr, type, rules);
 
                if (c->parse_error)
-                       *ok = 0;
+                       *perr |= Efail;
                return ret;
        }
 
@@ -2129,10 +2130,10 @@ correctly.
                        type_err(c, "error: variable used but not declared: %v",
                                 prog, NULL, 0, NULL);
                if (v->type == NULL) {
-                       if (type && *ok != 0) {
+                       if (type && !(*perr & Efail)) {
                                v->type = type;
                                v->where_set = prog;
-                               *ok = 2;
+                               *perr |= Eretry;
                        }
                        return type;
                }
@@ -2445,8 +2446,8 @@ with a const size by whether they are prepared at parse time or not.
                /* left must be an array, right must be a number,
                 * result is the member type of the array
                 */
-               propagate_types(b->right, c, ok, Tnum, 0);
-               t = propagate_types(b->left, c, ok, NULL, rules & Rnoconstant);
+               propagate_types(b->right, c, perr, Tnum, 0);
+               t = propagate_types(b->left, c, perr, NULL, rules & Rnoconstant);
                if (!t || t->compat != array_compat) {
                        type_err(c, "error: %1 cannot be indexed", prog, t, 0, NULL);
                        return NULL;
@@ -2606,7 +2607,7 @@ function will be needed.
                        return;
 
                for (f = t->structure.field_list; f; f=f->prev) {
-                       int ok;
+                       enum prop_err perr;
                        cnt += 1;
 
                        if (f->f.type->prepare_type)
@@ -2614,10 +2615,10 @@ function will be needed.
                        if (f->init == NULL)
                                continue;
                        do {
-                               ok = 1;
-                               propagate_types(f->init, c, &ok, f->f.type, 0);
-                       } while (ok == 2);
-                       if (!ok)
+                               perr = 0;
+                               propagate_types(f->init, c, &perr, f->f.type, 0);
+                       } while (perr & Eretry);
+                       if (perr & Efail)
                                c->parse_error = 1;     // NOTEST
                }
 
@@ -2708,7 +2709,7 @@ function will be needed.
        case Xfieldref:
        {
                struct fieldref *f = cast(fieldref, prog);
-               struct type *st = propagate_types(f->left, c, ok, NULL, 0);
+               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
@@ -2914,7 +2915,7 @@ further detailed when Expression Lists are introduced.
        struct exec *function;
 
 ###### type functions
-       void (*check_args)(struct parse_context *c, int *ok,
+       void (*check_args)(struct parse_context *c, enum prop_err *perr,
                           struct type *require, struct exec *args);
 
 ###### value functions
@@ -2931,7 +2932,7 @@ further detailed when Expression Lists are introduced.
                return 0;
        }
 
-       static void function_check_args(struct parse_context *c, int *ok,
+       static void function_check_args(struct parse_context *c, enum prop_err *perr,
                                        struct type *require, struct exec *args)
        {
                /* This should be 'compat', but we don't have a 'tuple' type to
@@ -2947,8 +2948,8 @@ further detailed when Expression Lists are introduced.
                                         args, NULL, 0, NULL);
                                break;
                        }
-                       *ok = 1;
-                       propagate_types(arg->left, c, ok, pv->var->type, 0);
+                       *perr = 0;
+                       propagate_types(arg->left, c, perr, pv->var->type, 0);
                        param = cast(binode, param->right);
                        arg = cast(binode, arg->right);
                }
@@ -3147,7 +3148,7 @@ it in the "SimpleStatement Grammar" which will be described later.
                                 prog, NULL, 0, NULL);
                        return NULL;
                }
-               v->var->type->check_args(c, ok, v->var->type, args);
+               v->var->type->check_args(c, perr, v->var->type, args);
                return v->var->type->function.return_type;
        }
 
@@ -3260,9 +3261,9 @@ there.
                struct binode *b2 = cast(binode, b->right);
                struct type *t2;
 
-               propagate_types(b->left, c, ok, Tbool, 0);
-               t = propagate_types(b2->left, c, ok, type, Rnolabel);
-               t2 = propagate_types(b2->right, c, ok, type ?: t, Rnolabel);
+               propagate_types(b->left, c, perr, Tbool, 0);
+               t = propagate_types(b2->left, c, perr, type, Rnolabel);
+               t2 = propagate_types(b2->right, c, perr, type ?: t, Rnolabel);
                return t ?: t2;
        }
 
@@ -3429,8 +3430,8 @@ evaluate the second expression if not necessary.
        case OrElse:
        case Not:
                /* both must be Tbool, result is Tbool */
-               propagate_types(b->left, c, ok, Tbool, 0);
-               propagate_types(b->right, c, ok, Tbool, 0);
+               propagate_types(b->left, c, perr, Tbool, 0);
+               propagate_types(b->right, c, perr, Tbool, 0);
                if (type && type != Tbool)
                        type_err(c, "error: %1 operation found where %2 expected", prog,
                                   Tbool, 0, type);
@@ -3544,13 +3545,13 @@ expression operator, and the `CMPop` non-terminal will match one of them.
        case Eql:
        case NEql:
                /* Both must match but not be labels, result is Tbool */
-               t = propagate_types(b->left, c, ok, NULL, Rnolabel);
+               t = propagate_types(b->left, c, perr, NULL, Rnolabel);
                if (t)
-                       propagate_types(b->right, c, ok, t, 0);
+                       propagate_types(b->right, c, perr, t, 0);
                else {
-                       t = propagate_types(b->right, c, ok, NULL, Rnolabel);   // UNTESTED
+                       t = propagate_types(b->right, c, perr, NULL, Rnolabel); // UNTESTED
                        if (t)  // UNTESTED
-                               t = propagate_types(b->left, c, ok, t, 0);      // UNTESTED
+                               t = propagate_types(b->left, c, perr, t, 0);    // UNTESTED
                }
                if (!type_compat(type, Tbool, 0))
                        type_err(c, "error: Comparison returns %1 but %2 expected", prog,
@@ -3714,8 +3715,8 @@ parentheses around an expression converts it into a Term,
        case Negate:
                /* as propagate_types ignores a NULL,
                 * unary ops fit here too */
-               propagate_types(b->left, c, ok, Tnum, 0);
-               propagate_types(b->right, c, ok, Tnum, 0);
+               propagate_types(b->left, c, perr, Tnum, 0);
+               propagate_types(b->right, c, perr, Tnum, 0);
                if (!type_compat(type, Tnum, 0))
                        type_err(c, "error: Arithmetic returns %1 but %2 expected", prog,
                                   Tnum, rules, type);
@@ -3723,8 +3724,8 @@ parentheses around an expression converts it into a Term,
 
        case Concat:
                /* both must be Tstr, result is Tstr */
-               propagate_types(b->left, c, ok, Tstr, 0);
-               propagate_types(b->right, c, ok, Tstr, 0);
+               propagate_types(b->left, c, perr, Tstr, 0);
+               propagate_types(b->right, c, perr, Tstr, 0);
                if (!type_compat(type, Tstr, 0))
                        type_err(c, "error: Concat returns %1 but %2 expected", prog,
                                   Tstr, rules, type);
@@ -3732,7 +3733,7 @@ parentheses around an expression converts it into a Term,
 
        case StringConv:
                /* op must be string, result is number */
-               propagate_types(b->left, c, ok, Tstr, 0);
+               propagate_types(b->left, c, perr, Tstr, 0);
                if (!type_compat(type, Tnum, 0))
                        type_err(c,     // UNTESTED
                          "error: Can only convert string to number, not %1",
@@ -3740,7 +3741,7 @@ parentheses around an expression converts it into a Term,
                return Tnum;
 
        case Bracket:
-               return propagate_types(b->right, c, ok, type, 0);
+               return propagate_types(b->right, c, perr, type, 0);
 
 ###### interp binode cases
 
@@ -4007,7 +4008,7 @@ the common header for all reductions to use.
                struct binode *e;
 
                for (e = b; e; e = cast(binode, e->right)) {
-                       t = propagate_types(e->left, c, ok, NULL, rules);
+                       t = propagate_types(e->left, c, perr, NULL, rules);
                        if ((rules & Rboolok) && (t == Tbool || t == Tnone))
                                t = NULL;
                        if (t == Tnone && e->right)
@@ -4096,7 +4097,7 @@ printed.
                else
                        b = cast(binode, b->right);
                while (b) {
-                       propagate_types(b->left, c, ok, NULL, Rnolabel);
+                       propagate_types(b->left, c, perr, NULL, Rnolabel);
                        b = cast(binode, b->right);
                }
                break;
@@ -4213,20 +4214,20 @@ it is declared, and error will be raised as the name is created as
                 * For Assign, left must not be constant.
                 * result is Tnone
                 */
-               t = propagate_types(b->left, c, ok, NULL,
+               t = propagate_types(b->left, c, perr, NULL,
                                    Rnolabel | (b->op == Assign ? Rnoconstant : 0));
                if (!b->right)
                        return Tnone;
 
                if (t) {
-                       if (propagate_types(b->right, c, ok, t, 0) != t)
+                       if (propagate_types(b->right, c, perr, t, 0) != t)
                                if (b->left->type == Xvar)
                                        type_err(c, "info: variable '%v' was set as %1 here.",
                                                 cast(var, b->left)->var->where_set, t, rules, NULL);
                } else {
-                       t = propagate_types(b->right, c, ok, NULL, Rnolabel);
+                       t = propagate_types(b->right, c, perr, NULL, Rnolabel);
                        if (t)
-                               propagate_types(b->left, c, ok, t,
+                               propagate_types(b->left, c, perr, t,
                                                (b->op == Assign ? Rnoconstant : 0));
                }
                if (t && t->dup == NULL && t->name.txt[0] != ' ') // HACK
@@ -4303,7 +4304,7 @@ function which has a return type, and the "condition" code blocks in
 
        case Use:
                /* result matches value */
-               return propagate_types(b->right, c, ok, type, 0);
+               return propagate_types(b->right, c, perr, type, 0);
 
 ###### interp binode cases
 
@@ -4690,10 +4691,10 @@ casepart` to track a list of case parts.
 
 ###### propagate binode cases
        case Loop:
-               t = propagate_types(b->right, c, ok, Tnone, 0);
+               t = propagate_types(b->right, c, perr, Tnone, 0);
                if (!type_compat(Tnone, t, 0))
-                       *ok = 0;        // UNTESTED
-               return propagate_types(b->left, c, ok, type, rules);
+                       *perr |= Efail; // UNTESTED
+               return propagate_types(b->left, c, perr, type, rules);
 
 ###### propagate exec cases
        case Xcond_statement:
@@ -4711,51 +4712,51 @@ casepart` to track a list of case parts.
                struct cond_statement *cs = cast(cond_statement, prog);
                struct casepart *cp;
 
-               t = propagate_types(cs->forpart, c, ok, Tnone, 0);
+               t = propagate_types(cs->forpart, c, perr, Tnone, 0);
                if (!type_compat(Tnone, t, 0))
-                       *ok = 0;        // UNTESTED
+                       *perr |= Efail; // UNTESTED
 
                if (cs->looppart) {
-                       t = propagate_types(cs->thenpart, c, ok, Tnone, 0);
+                       t = propagate_types(cs->thenpart, c, perr, Tnone, 0);
                        if (!type_compat(Tnone, t, 0))
-                               *ok = 0;        // UNTESTED
+                               *perr |= Efail; // UNTESTED
                }
                if (cs->casepart == NULL) {
-                       propagate_types(cs->condpart, c, ok, Tbool, 0);
-                       propagate_types(cs->looppart, c, ok, Tbool, 0);
+                       propagate_types(cs->condpart, c, perr, Tbool, 0);
+                       propagate_types(cs->looppart, c, perr, Tbool, 0);
                } else {
                        /* Condpart must match case values, with bool permitted */
                        t = NULL;
                        for (cp = cs->casepart;
                             cp && !t; cp = cp->next)
-                               t = propagate_types(cp->value, c, ok, NULL, 0);
+                               t = propagate_types(cp->value, c, perr, NULL, 0);
                        if (!t && cs->condpart)
-                               t = propagate_types(cs->condpart, c, ok, NULL, Rboolok);        // UNTESTED
+                               t = propagate_types(cs->condpart, c, perr, NULL, Rboolok);      // UNTESTED
                        if (!t && cs->looppart)
-                               t = propagate_types(cs->looppart, c, ok, NULL, Rboolok);        // UNTESTED
+                               t = propagate_types(cs->looppart, c, perr, NULL, Rboolok);      // UNTESTED
                        // Now we have a type (I hope) push it down
                        if (t) {
                                for (cp = cs->casepart; cp; cp = cp->next)
-                                       propagate_types(cp->value, c, ok, t, 0);
-                               propagate_types(cs->condpart, c, ok, t, Rboolok);
-                               propagate_types(cs->looppart, c, ok, t, Rboolok);
+                                       propagate_types(cp->value, c, perr, t, 0);
+                               propagate_types(cs->condpart, c, perr, t, Rboolok);
+                               propagate_types(cs->looppart, c, perr, t, Rboolok);
                        }
                }
                // (if)then, else, and case parts must return expected type.
                if (!cs->looppart && !type)
-                       type = propagate_types(cs->thenpart, c, ok, NULL, rules);
+                       type = propagate_types(cs->thenpart, c, perr, NULL, rules);
                if (!type)
-                       type = propagate_types(cs->elsepart, c, ok, NULL, rules);
+                       type = propagate_types(cs->elsepart, c, perr, NULL, rules);
                for (cp = cs->casepart;
                     cp && !type;
                     cp = cp->next)     // UNTESTED
-                       type = propagate_types(cp->action, c, ok, NULL, rules); // UNTESTED
+                       type = propagate_types(cp->action, c, perr, NULL, rules);       // UNTESTED
                if (type) {
                        if (!cs->looppart)
-                               propagate_types(cs->thenpart, c, ok, type, rules);
-                       propagate_types(cs->elsepart, c, ok, type, rules);
+                               propagate_types(cs->thenpart, c, perr, type, rules);
+                       propagate_types(cs->elsepart, c, perr, type, rules);
                        for (cp = cs->casepart; cp ; cp = cp->next)
-                               propagate_types(cp->action, c, ok, type, rules);
+                               propagate_types(cp->action, c, perr, type, rules);
                        return type;
                } else
                        return NULL;
@@ -4943,15 +4944,15 @@ constants.
                c->constlist = reorder_bilist(c->constlist);
                for (b = cast(binode, c->constlist); b;
                     b = cast(binode, b->right)) {
-                       int ok;
+                       enum prop_err perr;
                        struct binode *vb = cast(binode, b->left);
                        struct var *v = cast(var, vb->left);
                        do {
-                               ok = 1;
-                               propagate_types(vb->right, c, &ok,
+                               perr = 0;
+                               propagate_types(vb->right, c, &perr,
                                                v->var->type, 0);
-                       } while (ok == 2);
-                       if (!ok)
+                       } while (perr & Eretry);
+                       if (perr & Efail)
                                c->parse_error = 1;
                        else {
                                struct value res = interp_exec(
@@ -5141,20 +5142,20 @@ is a bit more interesting at this level.
                for (v = c->in_scope; v; v = v->in_scope) {
                        struct value *val;
                        struct type *ret;
-                       int ok = 1;
+                       enum prop_err perr;
                        if (v->depth != 0 || !v->type || !v->type->check_args)
                                continue;
                        ret = v->type->function.inline_result ?
                                Tnone : v->type->function.return_type;
                        val = var_value(c, v);
                        do {
-                               ok = 1;
-                               propagate_types(val->function, c, &ok, ret, 0);
-                       } while (ok == 2);
-                       if (ok)
+                               perr = 0;
+                               propagate_types(val->function, c, &perr, ret, 0);
+                       } while (!(perr & Efail) && (perr & Eretry));
+                       if (!(perr & Efail))
                                /* Make sure everything is still consistent */
-                               propagate_types(val->function, c, &ok, ret, 0);
-                       if (!ok)
+                               propagate_types(val->function, c, &perr, ret, 0);
+                       if (perr & Efail)
                                all_ok = 0;
                        if (!v->type->function.inline_result &&
                            !v->type->function.return_type->dup) {
@@ -5171,7 +5172,7 @@ is a bit more interesting at this level.
        {
                struct binode *bp = type->function.params;
                struct binode *b;
-               int ok = 1;
+               enum prop_err perr;
                int arg = 0;
                struct type *argv_type;
 
@@ -5180,15 +5181,15 @@ is a bit more interesting at this level.
                argv_type->array.unspec = 1;
 
                for (b = bp; b; b = cast(binode, b->right)) {
-                       ok = 1;
+                       perr = 0;
                        switch (arg++) {
                        case 0: /* argv */
-                               propagate_types(b->left, c, &ok, argv_type, 0);
+                               propagate_types(b->left, c, &perr, argv_type, 0);
                                break;
                        default: /* invalid */  // NOTEST
-                               propagate_types(b->left, c, &ok, Tnone, 0);     // NOTEST
+                               propagate_types(b->left, c, &perr, Tnone, 0);   // NOTEST
                        }
-                       if (!ok)
+                       if (perr & Efail)
                                c->parse_error = 1;
                }