###### core functions
- static enum vtype propagate_types(struct exec *prog, int *ok,
+ static enum vtype propagate_types(struct exec *prog, struct parse_context *c, int *ok,
enum vtype type, int bool_permitted)
{
enum vtype t;
case Or:
case Not:
/* both must be Vbool, result is Vbool */
- propagate_types(b->left, ok, Vbool, 0);
- propagate_types(b->right, ok, Vbool, 0);
+ propagate_types(b->left, c, ok, Vbool, 0);
+ propagate_types(b->right, c, ok, Vbool, 0);
if (type != Vbool && type > Vunknown)
*ok = 0;
return Vbool;
case Eql:
case NEql:
/* Both must match but not labels, result is Vbool */
- t = propagate_types(b->left, ok, Vnolabel, 0);
+ t = propagate_types(b->left, c, ok, Vnolabel, 0);
if (t > Vunknown)
- propagate_types(b->right, ok, t, 0);
+ propagate_types(b->right, c, ok, t, 0);
else {
- t = propagate_types(b->right, ok, Vnolabel, 0);
+ t = propagate_types(b->right, c, ok, Vnolabel, 0);
if (t > Vunknown)
- t = propagate_types(b->left, ok, t, 0);
+ t = propagate_types(b->left, c, ok, t, 0);
}
if (!vtype_compat(type, Vbool, 0))
*ok = 0;
case Negate:
/* as propagate_types ignores a NULL,
* unary ops fit here too */
- propagate_types(b->left, ok, Vnum, 0);
- propagate_types(b->right, ok, Vnum, 0);
+ propagate_types(b->left, c, ok, Vnum, 0);
+ propagate_types(b->right, c, ok, Vnum, 0);
if (!vtype_compat(type, Vnum, 0))
*ok = 0;
return Vnum;
case Concat:
/* both must be Vstr, result is Vstr */
- propagate_types(b->left, ok, Vstr, 0);
- propagate_types(b->right, ok, Vstr, 0);
+ propagate_types(b->left, c, ok, Vstr, 0);
+ propagate_types(b->right, c, ok, Vstr, 0);
if (!vtype_compat(type, Vstr, 0))
*ok = 0;
return Vstr;
case Bracket:
- return propagate_types(b->right, ok, type, 0);
+ return propagate_types(b->right, c, ok, type, 0);
###### interp binode cases
struct binode *e;
for (e = b; e; e = cast(binode, e->right)) {
- t = propagate_types(e->left, ok, Vunknown, bool_permitted);
+ t = propagate_types(e->left, c, ok, Vunknown, bool_permitted);
if (bool_permitted && t == Vbool)
t = Vunknown;
if (t != Vunknown && t != Vnone) {
case Print:
/* don't care but all must be consistent */
- propagate_types(b->left, ok, Vnolabel, 0);
- propagate_types(b->right, ok, Vnolabel, 0);
+ propagate_types(b->left, c, ok, Vnolabel, 0);
+ propagate_types(b->right, c, ok, Vnolabel, 0);
break;
###### interp binode cases
case Assign:
case Declare:
/* Both must match and not be labels, result is Vnone */
- t = propagate_types(b->left, ok, Vnolabel, 0);
+ t = propagate_types(b->left, c, ok, Vnolabel, 0);
if (t > Vunknown)
- propagate_types(b->right, ok, t, 0);
+ propagate_types(b->right, c, ok, t, 0);
else {
- t = propagate_types(b->right, ok, Vnolabel, 0);
+ t = propagate_types(b->right, c, ok, Vnolabel, 0);
if (t > Vunknown)
- t = propagate_types(b->left, ok, t, 0);
+ t = propagate_types(b->left, c, ok, t, 0);
}
return Vnone;
case Use:
/* result matches value */
- return propagate_types(b->right, ok, type, 0);
+ return propagate_types(b->right, c, ok, type, 0);
###### interp binode cases
// elsepart, casepart->action must match there return type
// expected of this statement.
struct cond_statement *cs = cast(cond_statement, prog);
- struct casepart *c;
+ struct casepart *cp;
- t = propagate_types(cs->forpart, ok, Vnone, 0);
+ t = propagate_types(cs->forpart, c, ok, Vnone, 0);
if (!vtype_compat(Vnone, t, 0))
*ok = 0;
- t = propagate_types(cs->dopart, ok, Vnone, 0);
+ t = propagate_types(cs->dopart, c, ok, Vnone, 0);
if (!vtype_compat(Vnone, t, 0))
*ok = 0;
if (cs->dopart) {
- t = propagate_types(cs->thenpart, ok, Vnone, 0);
+ t = propagate_types(cs->thenpart, c, ok, Vnone, 0);
if (!vtype_compat(Vnone, t, 0))
*ok = 0;
}
if (cs->casepart == NULL)
- propagate_types(cs->condpart, ok, Vbool, 0);
+ propagate_types(cs->condpart, c, ok, Vbool, 0);
else {
/* Condpart must match case values, with bool permitted */
t = Vunknown;
- for (c = cs->casepart;
- c && (t == Vunknown); c = c->next)
- t = propagate_types(c->value, ok, Vunknown, 0);
+ for (cp = cs->casepart;
+ cp && (t == Vunknown); cp = cp->next)
+ t = propagate_types(cp->value, c, ok, Vunknown, 0);
if (t == Vunknown && cs->condpart)
- t = propagate_types(cs->condpart, ok, Vunknown, 1);
+ t = propagate_types(cs->condpart, c, ok, Vunknown, 1);
// Now we have a type (I hope) push it down
if (t != Vunknown) {
- for (c = cs->casepart; c; c = c->next)
- propagate_types(c->value, ok, t, 0);
- propagate_types(cs->condpart, ok, t, 1);
+ for (cp = cs->casepart; cp; cp = cp->next)
+ propagate_types(cp->value, c, ok, t, 0);
+ propagate_types(cs->condpart, c, ok, t, 1);
}
}
// (if)then, else, and case parts must return expected type.
if (!cs->dopart && type == Vunknown)
- type = propagate_types(cs->thenpart, ok, Vunknown, bool_permitted);
+ type = propagate_types(cs->thenpart, c, ok, Vunknown, bool_permitted);
if (type == Vunknown)
- type = propagate_types(cs->elsepart, ok, Vunknown, bool_permitted);
- for (c = cs->casepart;
- c && type == Vunknown;
- c = c->next)
- type = propagate_types(c->action, ok, Vunknown, bool_permitted);
+ type = propagate_types(cs->elsepart, c, ok, Vunknown, bool_permitted);
+ for (cp = cs->casepart;
+ cp && type == Vunknown;
+ cp = cp->next)
+ type = propagate_types(cp->action, c, ok, Vunknown, bool_permitted);
if (type > Vunknown) {
if (!cs->dopart)
- propagate_types(cs->thenpart, ok, type, bool_permitted);
- propagate_types(cs->elsepart, ok, type, bool_permitted);
- for (c = cs->casepart; c ; c = c->next)
- propagate_types(c->action, ok, type, bool_permitted);
+ propagate_types(cs->thenpart, c, ok, type, bool_permitted);
+ propagate_types(cs->elsepart, c, ok, type, bool_permitted);
+ for (cp = cs->casepart; cp ; cp = cp->next)
+ propagate_types(cp->action, c, ok, type, bool_permitted);
return type;
} else
return Vunknown;
do {
ok = 1;
- propagate_types(b->right, &ok, Vnone, 0);
+ propagate_types(b->right, c, &ok, Vnone, 0);
} while (ok == 2);
if (!ok)
return 0;
b = cast(binode, prog);
do {
ok = 1;
- propagate_types(b->right, &ok, Vnone, 0);
+ propagate_types(b->right, c, &ok, Vnone, 0);
} while (ok == 2);
if (!ok)
return 0;
/* Make sure everything is still consistent */
- propagate_types(b->right, &ok, Vnone, 0);
+ propagate_types(b->right, c, &ok, Vnone, 0);
return !!ok;
}