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.
+any expression cannot be evaluated a compile time, `Eruntime` 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 val_rules {Rboolok = 1<<1, Rnoconstant = 1<<2};
+ enum prop_err {Efail = 1<<0, Eretry = 1<<1, Eruntime = 1<<2,
Emaycopy = 1<<3};
-###### format cases
- case 'r':
- if (rules & Rnolabel)
- fputs(" (labels not permitted)", stderr);
- break;
-
###### forward decls
static struct type *propagate_types(struct exec *prog, struct parse_context *c, enum prop_err *perr,
struct type *type, int rules);
{
if ((rules & Rboolok) && have == Tbool)
return 1; // NOTEST
- if ((rules & Rnolabel) && have == Tlabel)
- return 0; // NOTEST
if (!require || !have)
return 1;
{
struct val *val = cast(val, prog);
if (!type_compat(type, val->vtype, rules))
- type_err(c, "error: expected %1%r found %2",
+ type_err(c, "error: expected %1 found %2",
prog, type, rules, val->vtype);
return val->vtype;
}
struct label *l = cast(label, prog);
l->value = label_lookup(c, l->name);
if (!type_compat(type, Tlabel, rules))
- type_err(c, "error: expected %1%r found %2",
+ type_err(c, "error: expected %1 found %2",
prog, type, rules, Tlabel);
return Tlabel;
}
*perr |= Eretry;
}
} else if (!type_compat(type, v->type, rules)) {
- type_err(c, "error: expected %1%r but variable '%v' is %2", prog,
+ type_err(c, "error: expected %1 but variable '%v' is %2", prog,
type, rules, v->type);
type_err(c, "info: this is where '%v' was set to %1", v->where_set,
v->type, rules, NULL);
}
if (!v->global || v->frame_pos < 0)
- *perr |= Enoconst;
+ *perr |= Eruntime;
if (!type)
return v->type;
return type;
prog, NULL, 0, NULL);
return NULL;
}
- *perr |= Enoconst;
+ *perr |= Eruntime;
v->var->type->check_args(c, perr, v->var->type, args);
if (v->var->type->function.inline_result)
*perr |= Emaycopy;
struct type *t2;
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);
+ t = propagate_types(b2->left, c, perr, type, 0);
+ t2 = propagate_types(b2->right, c, perr, type ?: t, 0);
return t ?: t2;
}
case Eql:
case NEql:
/* Both must match but not be labels, result is Tbool */
- t = propagate_types(b->left, c, perr, NULL, Rnolabel);
+ t = propagate_types(b->left, c, perr, NULL, 0);
if (t)
propagate_types(b->right, c, perr, t, 0);
else {
- t = propagate_types(b->right, c, perr, NULL, Rnolabel); // UNTESTED
+ t = propagate_types(b->right, c, perr, NULL, 0); // UNTESTED
if (t) // UNTESTED
t = propagate_types(b->left, c, perr, t, 0); // UNTESTED
}
if (!type)
type = t;
else if (t != type)
- type_err(c, "error: expected %1%r, found %2",
+ type_err(c, "error: expected %1, found %2",
e->left, type, rules, t);
}
}
else
b = cast(binode, b->right);
while (b) {
- propagate_types(b->left, c, perr, NULL, Rnolabel);
+ propagate_types(b->left, c, perr, NULL, 0);
b = cast(binode, b->right);
}
break;
* result is Tnone
*/
t = propagate_types(b->left, c, perr, NULL,
- Rnolabel | (b->op == Assign ? Rnoconstant : 0));
+ (b->op == Assign ? Rnoconstant : 0));
if (!b->right)
return Tnone;
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, perr, NULL, Rnolabel);
+ t = propagate_types(b->right, c, perr, NULL, 0);
if (t)
propagate_types(b->left, c, perr, t,
(b->op == Assign ? Rnoconstant : 0));
} while (perr & Eretry);
if (perr & Efail)
c->parse_error += 1;
- else if (!(perr & Enoconst)) {
+ else if (!(perr & Eruntime)) {
progress = some;
struct value res = interp_exec(
c, vb->right, &v->var->type);