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) {
`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,
};
struct cond_statement {
struct exec;
- struct exec *forpart, *condpart, *dopart, *thenpart, *elsepart;
+ struct exec *forpart, *condpart, *thenpart, *elsepart;
+ struct binode *looppart;
struct casepart *casepart;
};
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);
$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;
- $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;
- $0->condpart = $WP.condpart; $WP.condpart = NULL;
- $0->dopart = $WP.dopart; $WP.dopart = NULL;
+ $0->looppart = $<WP;
}$
| SwitchPart OptNL CasePart CondSuffix ${
$0 = $<CS;
var_block_close(c, CloseSequential);
}$
- $cond_statement
+ $*binode
// 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 ${
- $0.condpart = $<Exp;
- $0.dopart = $<Bl;
+ $0 = new(binode);
+ $0->op = Loop;
+ $0->left = $<Exp;
+ $0->right = $<CB;
var_block_close(c, CloseSequential);
}$
+ $cond_statement
IfPart -> if UseBlock OptNL then OpenBlock ${
$0.condpart = $<UB;
$0.thenpart = $<OB;
$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:
}
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)
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:
{
- // 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
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
}
- if (cs->casepart == NULL)
+ if (cs->casepart == NULL) {
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;
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);
+ propagate_types(cs->looppart, c, ok, t, Rboolok);
}
}
// (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);
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)
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:
{
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);
- 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) {