]> ocean-lang.org Git - ocean/commitdiff
oceani: create a separate 'exec' for the while/do part
authorNeilBrown <neil@brown.name>
Sat, 6 Nov 2021 22:20:05 +0000 (09:20 +1100)
committerNeilBrown <neil@brown.name>
Mon, 8 Nov 2021 09:56:36 +0000 (20:56 +1100)
As while/do is a sub-scope within a cond-statement, create a separate
'struct exec' for it (a binode/Loop) so there is an exec for each scope.

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

index d1967562fdf6f1c94731f151f26c73ba3a1c47a0..122bcbcc6338ac33772f83c79b7256942564ef47 100644 (file)
@@ -1588,9 +1588,9 @@ in `rval`.
 
                rvtype = ret.type = Tnone;
                if (!e) {
 
                rvtype = ret.type = Tnone;
                if (!e) {
-                       ret.lval = lrv; // UNTESTED
-                       ret.rval = rv;  // UNTESTED
-                       return ret;     // UNTESTED
+                       ret.lval = lrv;
+                       ret.rval = rv;
+                       return ret;
                }
 
                switch(e->type) {
                }
 
                switch(e->type) {
@@ -3781,7 +3781,15 @@ the type of the `whilepart` code block is the reason for the
 `Rboolok` flag which is passed to `propagate_types()`.
 
 The `cond_statement` cannot fit into a `binode` so a new `exec` is
 `Rboolok` flag which is passed to `propagate_types()`.
 
 The `cond_statement` cannot fit into a `binode` so a new `exec` is
-defined.
+defined.  As there are two scopes which cover multiple parts - one for
+the whole statement and one for "while" and "do" - and as we will use
+the 'struct exec' to track scopes, we actually need two new types of
+exec.  One is a `binode` for the looping part, the rest is the
+`cond_statement`.  The `cond_statement` will use an auxilliary `struct
+casepart` to track a list of case parts.
+
+###### Binode types
+       Loop
 
 ###### exec type
        Xcond_statement,
 
 ###### exec type
        Xcond_statement,
@@ -3794,7 +3802,8 @@ defined.
        };
        struct cond_statement {
                struct exec;
        };
        struct cond_statement {
                struct exec;
-               struct exec *forpart, *condpart, *dopart, *thenpart, *elsepart;
+               struct exec *forpart, *condpart, *thenpart, *elsepart;
+               struct binode *looppart;
                struct casepart *casepart;
        };
 
                struct casepart *casepart;
        };
 
@@ -3818,7 +3827,7 @@ defined.
                        return;
                free_exec(s->forpart);
                free_exec(s->condpart);
                        return;
                free_exec(s->forpart);
                free_exec(s->condpart);
-               free_exec(s->dopart);
+               free_exec(s->looppart);
                free_exec(s->thenpart);
                free_exec(s->elsepart);
                free_casepart(s->casepart);
                free_exec(s->thenpart);
                free_exec(s->elsepart);
                free_casepart(s->casepart);
@@ -3851,21 +3860,18 @@ defined.
                        $0 = $<CS;
                        $0->forpart = $<FP;
                        $0->thenpart = $<TP;
                        $0 = $<CS;
                        $0->forpart = $<FP;
                        $0->thenpart = $<TP;
-                       $0->condpart = $WP.condpart; $WP.condpart = NULL;
-                       $0->dopart = $WP.dopart; $WP.dopart = NULL;
+                       $0->looppart = $<WP;
                        var_block_close(c, CloseSequential);
                        }$
                | ForPart OptNL WhilePart CondSuffix ${
                        $0 = $<CS;
                        $0->forpart = $<FP;
                        var_block_close(c, CloseSequential);
                        }$
                | ForPart OptNL WhilePart CondSuffix ${
                        $0 = $<CS;
                        $0->forpart = $<FP;
-                       $0->condpart = $WP.condpart; $WP.condpart = NULL;
-                       $0->dopart = $WP.dopart; $WP.dopart = NULL;
+                       $0->looppart = $<WP;
                        var_block_close(c, CloseSequential);
                        }$
                | WhilePart CondSuffix ${
                        $0 = $<CS;
                        var_block_close(c, CloseSequential);
                        }$
                | WhilePart CondSuffix ${
                        $0 = $<CS;
-                       $0->condpart = $WP.condpart; $WP.condpart = NULL;
-                       $0->dopart = $WP.dopart; $WP.dopart = NULL;
+                       $0->looppart = $<WP;
                        }$
                | SwitchPart OptNL CasePart CondSuffix ${
                        $0 = $<CS;
                        }$
                | SwitchPart OptNL CasePart CondSuffix ${
                        $0 = $<CS;
@@ -3937,19 +3943,24 @@ defined.
                        var_block_close(c, CloseSequential);
                }$
 
                        var_block_close(c, CloseSequential);
                }$
 
-       $cond_statement
+       $*binode
        // This scope is closed in CondStatement
        WhilePart -> while UseBlock OptNL do Block ${
        // This scope is closed in CondStatement
        WhilePart -> while UseBlock OptNL do Block ${
-                       $0.condpart = $<UB;
-                       $0.dopart = $<Bl;
+                       $0 = new(binode);
+                       $0->op = Loop;
+                       $0->left = $<UB;
+                       $0->right = $<Bl;
                        var_block_close(c, CloseSequential);
                }$
                | while OpenScope Expression ColonBlock ${
                        var_block_close(c, CloseSequential);
                }$
                | while OpenScope Expression ColonBlock ${
-                       $0.condpart = $<Exp;
-                       $0.dopart = $<Bl;
+                       $0 = new(binode);
+                       $0->op = Loop;
+                       $0->left = $<Exp;
+                       $0->right = $<CB;
                        var_block_close(c, CloseSequential);
                }$
 
                        var_block_close(c, CloseSequential);
                }$
 
+       $cond_statement
        IfPart -> if UseBlock OptNL then OpenBlock ${
                        $0.condpart = $<UB;
                        $0.thenpart = $<OB;
        IfPart -> if UseBlock OptNL then OpenBlock ${
                        $0.condpart = $<UB;
                        $0.thenpart = $<OB;
@@ -3975,6 +3986,35 @@ defined.
                        $0 = $<Bl;
                }$
 
                        $0 = $<Bl;
                }$
 
+###### print binode cases
+       case Loop:
+               if (b->left && b->left->type == Xbinode &&
+                   cast(binode, b->left)->op == Block) {
+                       if (bracket)
+                               do_indent(indent, "while {\n");
+                       else
+                               do_indent(indent, "while\n");
+                       print_exec(b->left, indent+1, bracket);
+                       if (bracket)
+                               do_indent(indent, "} do {\n");
+                       else
+                               do_indent(indent, "do\n");
+                       print_exec(b->right, indent+1, bracket);
+                       if (bracket)
+                               do_indent(indent, "}\n");
+               } else {
+                       do_indent(indent, "while ");
+                       print_exec(b->left, 0, bracket);
+                       if (bracket)
+                               printf(" {\n");
+                       else
+                               printf(":\n");
+                       print_exec(b->right, indent+1, bracket);
+                       if (bracket)
+                               do_indent(indent, "}\n");
+               }
+               break;
+
 ###### print exec cases
 
        case Xcond_statement:
 ###### print exec cases
 
        case Xcond_statement:
@@ -3994,33 +4034,8 @@ defined.
                        }
                        if (bracket) do_indent(indent, "}\n");
                }
                        }
                        if (bracket) do_indent(indent, "}\n");
                }
-               if (cs->dopart) {
-                       // a loop
-                       if (cs->condpart && cs->condpart->type == Xbinode &&
-                           cast(binode, cs->condpart)->op == Block) {
-                               if (bracket)
-                                       do_indent(indent, "while {\n");
-                               else
-                                       do_indent(indent, "while\n");
-                               print_exec(cs->condpart, indent+1, bracket);
-                               if (bracket)
-                                       do_indent(indent, "} do {\n");
-                               else
-                                       do_indent(indent, "do\n");
-                               print_exec(cs->dopart, indent+1, bracket);
-                               if (bracket)
-                                       do_indent(indent, "}\n");
-                       } else {
-                               do_indent(indent, "while ");
-                               print_exec(cs->condpart, 0, bracket);
-                               if (bracket)
-                                       printf(" {\n");
-                               else
-                                       printf(":\n");
-                               print_exec(cs->dopart, indent+1, bracket);
-                               if (bracket)
-                                       do_indent(indent, "}\n");
-                       }
+               if (cs->looppart) {
+                       print_exec(cs->looppart, indent, bracket);
                } else {
                        // a condition
                        if (cs->casepart)
                } else {
                        // a condition
                        if (cs->casepart)
@@ -4079,11 +4094,18 @@ defined.
                break;
        }
 
                break;
        }
 
+###### propagate binode cases
+       case Loop:
+               t = propagate_types(b->right, c, ok, Tnone, 0);
+               if (!type_compat(Tnone, t, 0))
+                       *ok = 0;        // UNTESTED
+               return propagate_types(b->left, c, ok, type, rules);
+
 ###### propagate exec cases
        case Xcond_statement:
        {
 ###### propagate exec cases
        case Xcond_statement:
        {
-               // forpart and dopart must return Tnone
-               // thenpart must return Tnone if there is a dopart,
+               // forpart and looppart->right must return Tnone
+               // thenpart must return Tnone if there is a loopart,
                // otherwise it is like elsepart.
                // condpart must:
                //    be bool if there is no casepart
                // otherwise it is like elsepart.
                // condpart must:
                //    be bool if there is no casepart
@@ -4098,17 +4120,16 @@ defined.
                t = propagate_types(cs->forpart, c, ok, Tnone, 0);
                if (!type_compat(Tnone, t, 0))
                        *ok = 0;        // UNTESTED
                t = propagate_types(cs->forpart, c, ok, Tnone, 0);
                if (!type_compat(Tnone, t, 0))
                        *ok = 0;        // UNTESTED
-               t = propagate_types(cs->dopart, c, ok, Tnone, 0);
-               if (!type_compat(Tnone, t, 0))
-                       *ok = 0;        // UNTESTED
-               if (cs->dopart) {
+
+               if (cs->looppart) {
                        t = propagate_types(cs->thenpart, c, ok, Tnone, 0);
                        if (!type_compat(Tnone, t, 0))
                                *ok = 0;        // UNTESTED
                }
                        t = propagate_types(cs->thenpart, c, ok, Tnone, 0);
                        if (!type_compat(Tnone, t, 0))
                                *ok = 0;        // UNTESTED
                }
-               if (cs->casepart == NULL)
+               if (cs->casepart == NULL) {
                        propagate_types(cs->condpart, c, ok, Tbool, 0);
                        propagate_types(cs->condpart, c, ok, Tbool, 0);
-               else {
+                       propagate_types(cs->looppart, c, ok, Tbool, 0);
+               } else {
                        /* Condpart must match case values, with bool permitted */
                        t = NULL;
                        for (cp = cs->casepart;
                        /* Condpart must match case values, with bool permitted */
                        t = NULL;
                        for (cp = cs->casepart;
@@ -4116,15 +4137,18 @@ defined.
                                t = propagate_types(cp->value, c, ok, NULL, 0);
                        if (!t && cs->condpart)
                                t = propagate_types(cs->condpart, c, ok, NULL, Rboolok);        // UNTESTED
                                t = propagate_types(cp->value, c, ok, NULL, 0);
                        if (!t && cs->condpart)
                                t = propagate_types(cs->condpart, c, ok, NULL, Rboolok);        // UNTESTED
+                       if (!t && cs->looppart)
+                               t = propagate_types(cs->looppart, c, ok, 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);
                        // 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);
                        }
                }
                // (if)then, else, and case parts must return expected type.
                        }
                }
                // (if)then, else, and case parts must return expected type.
-               if (!cs->dopart && !type)
+               if (!cs->looppart && !type)
                        type = propagate_types(cs->thenpart, c, ok, NULL, rules);
                if (!type)
                        type = propagate_types(cs->elsepart, c, ok, NULL, rules);
                        type = propagate_types(cs->thenpart, c, ok, NULL, rules);
                if (!type)
                        type = propagate_types(cs->elsepart, c, ok, NULL, rules);
@@ -4133,7 +4157,7 @@ defined.
                     cp = cp->next)     // UNTESTED
                        type = propagate_types(cp->action, c, ok, NULL, rules); // UNTESTED
                if (type) {
                     cp = cp->next)     // UNTESTED
                        type = propagate_types(cp->action, c, ok, NULL, rules); // UNTESTED
                if (type) {
-                       if (!cs->dopart)
+                       if (!cs->looppart)
                                propagate_types(cs->thenpart, c, ok, type, rules);
                        propagate_types(cs->elsepart, c, ok, type, rules);
                        for (cp = cs->casepart; cp ; cp = cp->next)
                                propagate_types(cs->thenpart, c, ok, type, rules);
                        propagate_types(cs->elsepart, c, ok, type, rules);
                        for (cp = cs->casepart; cp ; cp = cp->next)
@@ -4143,6 +4167,16 @@ defined.
                        return NULL;
        }
 
                        return NULL;
        }
 
+###### interp binode cases
+       case Loop:
+               // This just performs one iterration of the loop
+               rv = interp_exec(c, b->left, &rvtype);
+               if (rvtype == Tnone ||
+                   (rvtype == Tbool && rv.bool != 0))
+                       // cnd is Tnone or Tbool, doesn't need to be freed
+                       interp_exec(c, b->right, NULL);
+               break;
+
 ###### interp exec cases
        case Xcond_statement:
        {
 ###### interp exec cases
        case Xcond_statement:
        {
@@ -4153,27 +4187,20 @@ defined.
 
                if (cs->forpart)
                        interp_exec(c, cs->forpart, NULL);
 
                if (cs->forpart)
                        interp_exec(c, cs->forpart, NULL);
-               do {
-                       if (cs->condpart)
-                               cnd = interp_exec(c, cs->condpart, &cndtype);
-                       else
-                               cndtype = Tnone;        // UNTESTED
-                       if (!(cndtype == Tnone ||
-                             (cndtype == Tbool && cnd.bool != 0)))
-                               break;
-                       // cnd is Tnone or Tbool, doesn't need to be freed
-                       if (cs->dopart)
-                               interp_exec(c, cs->dopart, NULL);
-
-                       if (cs->thenpart) {
+               if (cs->looppart) {
+                       while ((cnd = interp_exec(c, cs->looppart, &cndtype)),
+                              cndtype == Tnone || (cndtype == Tbool && cnd.bool != 0))
+                               interp_exec(c, cs->thenpart, NULL);
+               } else {
+                       cnd = interp_exec(c, cs->condpart, &cndtype);
+                       if ((cndtype == Tnone ||
+                           (cndtype == Tbool && cnd.bool != 0))) {
+                               // cnd is Tnone or Tbool, doesn't need to be freed
                                rv = interp_exec(c, cs->thenpart, &rvtype);
                                rv = interp_exec(c, cs->thenpart, &rvtype);
-                               if (rvtype != Tnone || !cs->dopart)
-                                       goto Xcond_done;
-                               free_value(rvtype, &rv);
-                               rvtype = Tnone;
+                               // skip else (and cases)
+                               goto Xcond_done;
                        }
                        }
-               } while (cs->dopart);
-
+               }
                for (cp = cs->casepart; cp; cp = cp->next) {
                        v = interp_exec(c, cp->value, &vtype);
                        if (value_cmp(cndtype, vtype, &v, &cnd) == 0) {
                for (cp = cs->casepart; cp; cp = cp->next) {
                        v = interp_exec(c, cp->value, &vtype);
                        if (value_cmp(cndtype, vtype, &v, &cnd) == 0) {