work toward better error reporting
authorBen Pfaff <blp@cs.stanford.edu>
Mon, 22 Nov 2021 03:39:29 +0000 (19:39 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Tue, 30 Nov 2021 14:55:06 +0000 (06:55 -0800)
src/language/lexer/lexer.h
src/language/stats/matrix.c
src/libpspp/message.c
src/libpspp/message.h

index 1282b6946b732e451ca080cd3b1cf50e621557a1..d82470ffdd456d52a2efe37f9037f7441a4c2686 100644 (file)
@@ -160,6 +160,7 @@ int lex_get_last_column (const struct lexer *, int n);
 const char *lex_get_file_name (const struct lexer *);
 struct msg_location *lex_get_location (const struct lexer *, int n0, int n1);
 struct msg_location *lex_get_lines (const struct lexer *, int n0, int n1);
+void lex_extend_location (const struct lexer *, int n, struct msg_location *);
 const char *lex_get_encoding (const struct lexer *);
 
 /* Issuing errors. */
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],
index faeb83a449d3e3058507e163d9bd7049192ea917..d71df204ea46a5dd4774246e11b1f2ef25a6e361 100644 (file)
@@ -52,12 +52,14 @@ static int messages_disabled;
 
 
 void
-vmsg (enum msg_class class, const char *format, va_list args)
+vmsg (enum msg_class class, const struct msg_location *location,
+      const char *format, va_list args)
 {
   struct msg *m = xmalloc (sizeof *m);
   *m = (struct msg) {
     .category = msg_class_to_category (class),
     .severity = msg_class_to_severity (class),
+    .location = msg_location_dup (location),
     .text = xvasprintf (format, args),
   };
   msg_emit (m);
@@ -70,11 +72,21 @@ msg (enum msg_class class, const char *format, ...)
 {
   va_list args;
   va_start (args, format);
-  vmsg (class, format, args);
+  vmsg (class, NULL, format, args);
   va_end (args);
 }
 
-
+/* Outputs error message in CLASS, with text FORMAT, formatted with printf.
+   LOCATION is the reported location for the message. */
+void
+msg_at (enum msg_class class, const struct msg_location *location,
+        const char *format, ...)
+{
+  va_list args;
+  va_start (args, format);
+  vmsg (class, location, format, args);
+  va_end (args);
+}
 
 void
 msg_error (int errnum, const char *format, ...)
index a99b0818e3438fd6514be202a46c3d6e0f6f8185..f0066ee0a745adbd9a2150281a89255947e315ff 100644 (file)
@@ -85,6 +85,8 @@ void msg_location_uninit (struct msg_location *);
 void msg_location_destroy (struct msg_location *);
 struct msg_location *msg_location_dup (const struct msg_location *);
 
+void msg_location_merge (struct msg_location **, const struct msg_location *);
+
 bool msg_location_is_empty (const struct msg_location *);
 void msg_location_format (const struct msg_location *, struct string *);
 
@@ -119,10 +121,14 @@ void msg_destroy(struct msg *);
 char *msg_to_string (const struct msg *);
 
 /* Emitting messages. */
-void vmsg (enum msg_class class, const char *format, va_list args)
-     PRINTF_FORMAT (2, 0);
+void vmsg (enum msg_class, const struct msg_location *,
+           const char *format, va_list args)
+     PRINTF_FORMAT (3, 0);
 void msg (enum msg_class, const char *format, ...)
      PRINTF_FORMAT (2, 3);
+void msg_at (enum msg_class, const struct msg_location *,
+             const char *format, ...)
+     PRINTF_FORMAT (3, 4);
 void msg_emit (struct msg *);
 
 void msg_error (int errnum, const char *format, ...)