work toward better error reporting
[pspp] / src / language / stats / matrix.c
index ff3c792e7ee882c615850a01d20b7261f0fd283b..0db2f532e74c4efad7f6ef19b58d1577fea15e47 100644 (file)
@@ -502,6 +502,8 @@ struct matrix_expr
         struct matrix_var *variable;
         struct read_file *eof;
       };
+
+    struct msg_location *location;
   };
 
 static void
@@ -553,6 +555,7 @@ MATRIX_FUNCTIONS
     case MOP_EOF:
       break;
     }
+  msg_location_destroy (e->location);
   free (e);
 }
 
@@ -566,6 +569,9 @@ matrix_expr_create_subs (enum matrix_op op, struct matrix_expr **subs,
     .subs = xmemdup (subs, n_subs * sizeof *subs),
     .n_subs = n_subs
   };
+
+  for (size_t i = 0; i < n_subs; i++)
+    msg_location_merge (&e->location, subs[i]->location);
   return e;
 }
 
@@ -2646,19 +2652,32 @@ matrix_parse_function (struct matrix_state *s, const char *token,
   if (!f)
     return false;
 
-  lex_get_n (s->lexer, 2);
-
   struct matrix_expr *e = xmalloc (sizeof *e);
-  *e = (struct matrix_expr) { .op = f->op, .subs = NULL };
+  *e = (struct matrix_expr) {
+    .op = f->op,
+    .location = lex_get_location (s->lexer, 0, 0)
+  };
 
+  lex_get_n (s->lexer, 2);
   if (lex_token (s->lexer) != T_RPAREN)
     {
       size_t allocated_subs = 0;
       do
         {
+          struct msg_location *arg_location = lex_get_location (s->lexer, 0, 0);
           struct matrix_expr *sub = matrix_parse_expr (s);
           if (!sub)
-            goto error;
+            {
+              msg_location_destroy (arg_location);
+              goto error;
+            }
+          if (!sub->location)
+            {
+              lex_extend_location (s->lexer, 0, arg_location);
+              sub->location = arg_location;
+            }
+          else
+            msg_location_destroy (arg_location);
 
           if (e->n_subs >= allocated_subs)
             e->subs = x2nrealloc (e->subs, &allocated_subs, sizeof *e->subs);
@@ -4329,6 +4348,7 @@ matrix_expr_evaluate_integer (const struct matrix_expr *e, const char *context,
 struct matrix_lvalue
   {
     struct matrix_var *var;
+    struct msg_location *var_location;
     struct matrix_expr *indexes[2];
     size_t n_indexes;
   };
@@ -4350,6 +4370,7 @@ matrix_lvalue_parse (struct matrix_state *s)
   struct matrix_lvalue *lvalue = xzalloc (sizeof *lvalue);
   if (!lex_force_id (s->lexer))
     goto error;
+  lvalue->var_location = lex_get_location (s->lexer, 0, 0);
   lvalue->var = matrix_var_lookup (s, lex_tokss (s->lexer));
   if (lex_next_token (s->lexer, 1) == T_LPAREN)
     {
@@ -4510,21 +4531,23 @@ matrix_lvalue_evaluate (struct matrix_lvalue *lvalue,
   gsl_matrix *dm = lvalue->var->value;
   if (!dm)
     {
-      msg (SE, _("Undefined variable %s."), lvalue->var->name);
+      msg_at (SE, lvalue->var_location,
+              _("Undefined variable %s."), lvalue->var->name);
       return false;
     }
   else if (dm->size1 == 0 || dm->size2 == 0)
     {
-      msg (SE, _("Cannot index %zu×%zu matrix."),
-           dm->size1, dm->size2);
+      msg_at (SE, lvalue->var_location,
+              _("Cannot index %zu×%zu matrix."), dm->size1, dm->size2);
       return false;
     }
   else if (lvalue->n_indexes == 1)
     {
       if (!is_vector (dm))
         {
-          msg (SE, _("Can't use vector indexing on %zu×%zu matrix %s."),
-               dm->size1, dm->size2, lvalue->var->name);
+          msg_at (SE, lvalue->var_location,
+                  _("Can't use vector indexing on %zu×%zu matrix %s."),
+                  dm->size1, dm->size2, lvalue->var->name);
           return false;
         }
       return matrix_lvalue_evaluate_vector (lvalue->indexes[0],