###### ast
- enum val_rules {Rnolabel = 1<<0, Rboolok = 1<<1};
+ enum val_rules {Rnolabel = 1<<0, Rboolok = 1<<1, Rnoconstant = 2<<1};
###### format cases
case 'r':
}
if (v->merged)
v = v->merged;
+ if (v->constant && (rules & Rnoconstant)) {
+ type_err(c, "error: Cannot assign to a constant: %v",
+ prog, NULL, 0, NULL);
+ type_err(c, "info: name was defined as a constant here",
+ v->where_decl, NULL, 0, NULL);
+ *ok = 0;
+ return v->val.type;
+ }
if (v->val.type == NULL) {
if (type && *ok != 0) {
v->val = val_prepare(type);
Declare,
###### SimpleStatement Grammar
- | Variable = Expression ${ {
- struct var *v = cast(var, $1);
-
+ | Variable = Expression ${
$0 = new(binode);
$0->op = Assign;
$0->left = $<1;
$0->right = $<3;
- if (v->var && v->var->constant) {
- type_err(config2context(config), "Cannot assign to a constant: %v",
- $0->left, NULL, 0, NULL);
- type_err(config2context(config), "name was defined as a constant here",
- v->var->where_decl, NULL, 0, NULL);
- }
- } }$
+ }$
| VariableDecl = Expression ${
$0 = new(binode);
$0->op = Declare;
case Declare:
/* Both must match and not be labels,
* Type must support 'dup',
- * result is Tnone */
- t = propagate_types(b->left, c, ok, NULL, Rnolabel);
+ * For Assign, left must not be constant.
+ * result is Tnone
+ */
+ t = propagate_types(b->left, c, ok, NULL,
+ Rnolabel | (b->op == Assign ? Rnoconstant : 0));
if (!b->right)
return Tnone;
} else {
t = propagate_types(b->right, c, ok, NULL, Rnolabel);
if (t)
- propagate_types(b->left, c, ok, t, 0);
+ propagate_types(b->left, c, ok, t,
+ (b->op == Assign ? Rnoconstant : 0));
}
if (t && t->dup == NULL) {
type_err(c, "error: cannot assign value of type %1", b, t, 0, NULL);