]> ocean-lang.org Git - ocean/commitdiff
oceani: track where each variable was declared.
authorNeilBrown <neil@brown.name>
Mon, 19 Feb 2018 06:08:11 +0000 (17:08 +1100)
committerNeilBrown <neil@brown.name>
Mon, 19 Feb 2018 06:08:11 +0000 (17:08 +1100)
This allows better error messages when they are
redeclared.

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

index 4689a525233f020dd92362fddbb8712b200ff5d3..10ac4ff543780f6df721ca0ffa2b954750fc5a09 100644 (file)
@@ -663,6 +663,7 @@ cannot nest, so a declaration while a name is in-scope is an error.
                struct variable *previous;
                struct value val;
                struct binding *name;
+               struct exec *where_decl;// where name was declared
                struct exec *where_set; // where type was set
                ## variable fields
        };
@@ -895,7 +896,7 @@ all pending-scope variables become conditionally scoped.
 
                switch (v ? v->scope : OutScope) {
                case InScope:
-                       /* Signal error ... once I build error signalling support */
+                       /* Caller will report the error */
                        return NULL;
                case CondScope:
                        for (;
@@ -1378,12 +1379,32 @@ link to find the primary instance.
                struct variable *v = var_decl(config2context(config), $1.txt);
                $0 = new_pos(var, $1);
                $0->var = v;
+               if (v)
+                       v->where_decl = $0;
+               else {
+                       v = var_ref(config2context(config), $1.txt);
+                       $0->var = v;
+                       type_err(config2context(config), "error: variable '%v' redeclared",
+                                $0, Vnone, Vnone);
+                       type_err(config2context(config), "info: this is where '%v' was first declared",
+                                v->where_decl, Vnone, Vnone);
+               }
        } }$
            | IDENTIFIER ::= ${ {
                struct variable *v = var_decl(config2context(config), $1.txt);
-               v->constant = 1;
                $0 = new_pos(var, $1);
                $0->var = v;
+               if (v) {
+                       v->where_decl = $0;
+                       v->constant = 1;
+               } else {
+                       v = var_ref(config2context(config), $1.txt);
+                       $0->var = v;
+                       type_err(config2context(config), "error: variable '%v' redeclared",
+                                $0, Vnone, Vnone);
+                       type_err(config2context(config), "info: this is where '%v' was first declared",
+                                v->where_decl, Vnone, Vnone);
+               }
        } }$
 
        Variable -> IDENTIFIER ${ {
@@ -1446,9 +1467,9 @@ link to find the primary instance.
                        return type;
                }
                if (!vtype_compat(type, v->val.vtype, bool_permitted)) {
-                       type_err(c, "error: expected %1 but variable %v is %2", prog,
+                       type_err(c, "error: expected %1 but variable '%v' is %2", prog,
                                 type, v->val.vtype);
-                       type_err(c, "info: this is where %v was set to %1", v->where_set,
+                       type_err(c, "info: this is where '%v' was set to %1", v->where_set,
                                 v->val.vtype, Vnone);
                        *ok = 0;
                }
@@ -2195,7 +2216,7 @@ it is declared, and error will be raised as the name is created as
                if (t > Vunknown) {
                        if (propagate_types(b->right, c, ok, t, 0) != t)
                                if (b->left->type == Xvar)
-                                       type_err(c, "info: variable %v was set as %1 here.",
+                                       type_err(c, "info: variable '%v' was set as %1 here.",
                                                 cast(var, b->left)->var->where_set, t, Vnone);
                } else {
                        t = propagate_types(b->right, c, ok, Vnolabel, 0);