]> ocean-lang.org Git - ocean/commitdiff
oceani: delay constant assignment test to type analysis.
authorNeilBrown <neil@brown.name>
Tue, 30 Apr 2019 04:00:03 +0000 (14:00 +1000)
committerNeilBrown <neil@brown.name>
Wed, 1 May 2019 08:09:53 +0000 (18:09 +1000)
When we get more complex types, it will be easier to
guard against assigning to a constant during type analysis.

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

index edc3b124ff54fcaf7f39f72e6a4716dc38436494..07606745a481a5b7ec174660a6a17e0c23086db0 100644 (file)
@@ -1415,7 +1415,7 @@ propagation is needed.
 
 ###### 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':
@@ -1765,6 +1765,14 @@ link to find the primary instance.
                }
                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);
@@ -2488,20 +2496,12 @@ it is declared, and error will be raised as the name is created as
        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;
@@ -2567,8 +2567,11 @@ it is declared, and error will be raised as the name is created as
        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;
 
@@ -2580,7 +2583,8 @@ it is declared, and error will be raised as the name is created as
                } 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);