From: Ben Pfaff Date: Tue, 30 Nov 2021 14:12:14 +0000 (-0800) Subject: work on better matrix error reporting X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9d04ab289d70b2f2092f6d310b46caa6e898f01b;p=pspp work on better matrix error reporting --- diff --git a/src/language/control/define.c b/src/language/control/define.c index f33e885925..0f1049678c 100644 --- a/src/language/control/define.c +++ b/src/language/control/define.c @@ -109,14 +109,8 @@ cmd_define (struct lexer *lexer, struct dataset *ds UNUSED) } struct macro *m = xmalloc (sizeof *m); - *m = (struct macro) { - .name = xstrdup (name), - .location = xmalloc (sizeof *m->location), - }; - *m->location = (struct msg_location) { - .file_name = intern_new_if_nonnull (lex_get_file_name (lexer)), - .first_line = lex_get_first_line_number (lexer, 0), - }; + *m = (struct macro) { .name = xstrdup (name) }; + int first_line = lex_get_first_line_number (lexer, 0); lex_get (lexer); if (!lex_force_match (lexer, T_LPAREN)) @@ -282,7 +276,14 @@ cmd_define (struct lexer *lexer, struct dataset *ds UNUSED) ds_put_byte (&body, '\n'); lex_get (lexer); } - m->location->last_line = lex_get_last_line_number (lexer, 0); + + int last_line = lex_get_last_line_number (lexer, 0) - 1; + m->location = xmalloc (sizeof *m->location); + *m->location = (struct msg_location) { + .file_name = intern_new_if_nonnull (lex_get_file_name (lexer)), + .p[0] = { .line = first_line }, + .p[1] = { .line = last_line }, + }; macro_tokens_from_string (&m->body, body.ss, lex_get_syntax_mode (lexer)); ds_destroy (&body); diff --git a/src/language/data-io/data-parser.c b/src/language/data-io/data-parser.c index 09af7542bb..f40fc99dd4 100644 --- a/src/language/data-io/data-parser.c +++ b/src/language/data-io/data-parser.c @@ -500,10 +500,8 @@ parse_error (const struct dfm_reader *reader, const struct field *field, struct msg_location *location = xmalloc (sizeof *location); *location = (struct msg_location) { .file_name = intern_new (dfm_get_file_name (reader)), - .first_line = line_number, - .last_line = line_number + 1, - .first_column = first_column, - .last_column = last_column, + .p[0] = { .line = line_number, .column = first_column }, + .p[1] = { .line = line_number, .column = last_column - 1 }, }; struct msg *m = xmalloc (sizeof *m); *m = (struct msg) { diff --git a/src/language/data-io/matrix-data.c b/src/language/data-io/matrix-data.c index 31d6b710b0..fb54d30937 100644 --- a/src/language/data-io/matrix-data.c +++ b/src/language/data-io/matrix-data.c @@ -253,12 +253,13 @@ parse_msg (struct dfm_reader *reader, const struct substring *token, int line_number = dfm_get_line_number (reader); struct msg_location *location = xmalloc (sizeof *location); + int last_column = (first_column && token->length + ? first_column + token->length - 1 + : 0); *location = (struct msg_location) { .file_name = intern_new (dfm_get_file_name (reader)), - .first_line = line_number, - .last_line = line_number + 1, - .first_column = first_column, - .last_column = first_column ? first_column + token->length : 0, + .p[0] = { .line = line_number, .column = first_column }, + .p[1] = { .line = line_number, .column = last_column }, }; struct msg *m = xmalloc (sizeof *m); *m = (struct msg) { diff --git a/src/language/lexer/lexer.c b/src/language/lexer/lexer.c index df3a77de94..cf40dcbe6d 100644 --- a/src/language/lexer/lexer.c +++ b/src/language/lexer/lexer.c @@ -1248,12 +1248,13 @@ lex_token_location (const struct lex_source *src, const struct lex_token *t0, const struct lex_token *t1) { + int first_column = lex_token_get_first_column (src, t0); + int last_line = lex_token_get_last_line_number (src, t1) - 1; + int last_column = lex_token_get_last_column (src, t1) - 1; return (struct msg_location) { .file_name = intern_new_if_nonnull (src->reader->file_name), - .first_line = t0->first_line, - .last_line = lex_token_get_last_line_number (src, t1), - .first_column = lex_token_get_first_column (src, t0), - .last_column = lex_token_get_last_column (src, t1), + .p[0] = { .line = t0->first_line, .column = first_column }, + .p[1] = { .line = last_line, .column = last_column }, }; } @@ -1351,8 +1352,8 @@ struct msg_location * lex_get_location (const struct lexer *lexer, int n0, int n1) { struct msg_location *loc = lex_get_lines (lexer, n0, n1); - loc->first_column = lex_get_first_column (lexer, n0); - loc->last_column = lex_get_last_column (lexer, n1); + loc->p[0].column = lex_get_first_column (lexer, n0); + loc->p[1].column = lex_get_last_column (lexer, n1) - 1; return loc; } @@ -1364,14 +1365,24 @@ struct msg_location * lex_get_lines (const struct lexer *lexer, int n0, int n1) { struct msg_location *loc = xmalloc (sizeof *loc); + int first_line = lex_get_first_line_number (lexer, n0); + int last_line = lex_get_last_line_number (lexer, n1) - 1; *loc = (struct msg_location) { .file_name = intern_new_if_nonnull (lex_get_file_name (lexer)), - .first_line = lex_get_first_line_number (lexer, n0), - .last_line = lex_get_last_line_number (lexer, n1), + .p[0] = { .line = first_line }, + .p[1] = { .line = last_line }, }; return loc; } +void +lex_extend_location (const struct lexer *lexer, int n, struct msg_location *loc) +{ + struct msg_location *new = lex_get_location (lexer, n, n); + msg_location_merge (loc, new); + msg_location_destroy (new); +} + const char * lex_get_encoding (const struct lexer *lexer) { diff --git a/src/language/lexer/lexer.h b/src/language/lexer/lexer.h index d82470ffdd..23dd305179 100644 --- a/src/language/lexer/lexer.h +++ b/src/language/lexer/lexer.h @@ -160,7 +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 *); +void lex_extend_location (const struct lexer *, int n, struct msg_location **); const char *lex_get_encoding (const struct lexer *); /* Issuing errors. */ diff --git a/src/language/stats/matrix.c b/src/language/stats/matrix.c index 0db2f532e7..bcefb94a9c 100644 --- a/src/language/stats/matrix.c +++ b/src/language/stats/matrix.c @@ -206,9 +206,9 @@ matrix_var_set (struct matrix_var *var, gsl_matrix *value) - "ai": Restrict a to integer values. - - "a>0", "a<0", "a>=0", "a<=0". + - "a>0", "a<0", "a>=0", "a<=0", "a!=0". - - "ab", "a<=b", "a>=b". + - "ab", "a<=b", "a>=b", "b!=0". */ #define MATRIX_FUNCTIONS \ F(ABS, "ABS", m_e, NULL) \ @@ -217,7 +217,7 @@ matrix_var_set (struct matrix_var *var, gsl_matrix *value) F(ARSIN, "ARSIN", m_e, "a[-1,1]") \ F(ARTAN, "ARTAN", m_e, NULL) \ F(BLOCK, "BLOCK", m_any, NULL) \ - F(CHOL, "CHOL", m_m, NULL) \ + F(CHOL, "CHOL", m_me, NULL) \ F(CMIN, "CMIN", m_m, NULL) \ F(CMAX, "CMAX", m_m, NULL) \ F(COS, "COS", m_e, NULL) \ @@ -231,17 +231,17 @@ matrix_var_set (struct matrix_var *var, gsl_matrix *value) F(GINV, "GINV", m_m, NULL) \ F(GRADE, "GRADE", m_m, NULL) \ F(GSCH, "GSCH", m_m, NULL) \ - F(IDENT, "IDENT", IDENT, NULL) \ + F(IDENT, "IDENT", IDENT, "ai>=0 bi>=0") \ F(INV, "INV", m_m, NULL) \ F(KRONEKER, "KRONEKER", m_mm, NULL) \ F(LG10, "LG10", m_e, "a>0") \ F(LN, "LN", m_e, "a>0") \ F(MAGIC, "MAGIC", m_d, "ai>=3") \ - F(MAKE, "MAKE", m_ddd, NULL) \ + F(MAKE, "MAKE", m_ddd, "ai>=0 bi>=0") \ F(MDIAG, "MDIAG", m_v, NULL) \ F(MMAX, "MMAX", d_m, NULL) \ F(MMIN, "MMIN", d_m, NULL) \ - F(MOD, "MOD", m_md, NULL) \ + F(MOD, "MOD", m_md, "b!=0") \ F(MSSQ, "MSSQ", d_m, NULL) \ F(MSUM, "MSUM", d_m, NULL) \ F(NCOL, "NCOL", d_m, NULL) \ @@ -390,6 +390,7 @@ enum { m_d_MIN_ARGS = 1, m_d_MAX_ARGS = 1 }; enum { m_dd_MIN_ARGS = 2, m_dd_MAX_ARGS = 2 }; enum { m_ddd_MIN_ARGS = 3, m_ddd_MAX_ARGS = 3 }; enum { m_m_MIN_ARGS = 1, m_m_MAX_ARGS = 1 }; +enum { m_me_MIN_ARGS = 1, m_me_MAX_ARGS = 1 }; enum { m_e_MIN_ARGS = 1, m_e_MAX_ARGS = 1 }; enum { m_md_MIN_ARGS = 2, m_md_MAX_ARGS = 2 }; enum { m_ed_MIN_ARGS = 2, m_ed_MAX_ARGS = 2 }; @@ -412,6 +413,7 @@ typedef gsl_matrix *matrix_proto_m_d (double); typedef gsl_matrix *matrix_proto_m_dd (double, double); typedef gsl_matrix *matrix_proto_m_ddd (double, double, double); typedef gsl_matrix *matrix_proto_m_m (gsl_matrix *); +typedef gsl_matrix *matrix_proto_m_me (gsl_matrix *, const struct matrix_expr *); typedef double matrix_proto_m_e (double); typedef gsl_matrix *matrix_proto_m_md (gsl_matrix *, double); typedef double matrix_proto_m_ed (double, double); @@ -570,8 +572,6 @@ matrix_expr_create_subs (enum matrix_op op, struct matrix_expr **subs, .n_subs = n_subs }; - for (size_t i = 0; i < n_subs; i++) - msg_location_merge (&e->location, subs[i]->location); return e; } @@ -605,10 +605,15 @@ matrix_expr_create_3 (enum matrix_op op, struct matrix_expr *sub0, } static struct matrix_expr * -matrix_expr_create_number (double number) +matrix_expr_create_number (struct lexer *lexer, double number) { struct matrix_expr *e = xmalloc (sizeof *e); - *e = (struct matrix_expr) { .op = MOP_NUMBER, .number = number }; + *e = (struct matrix_expr) { + .op = MOP_NUMBER, + .number = number, + .location = lex_get_location (lexer, 0, 0), + }; + lex_get (lexer); return e; } @@ -638,7 +643,11 @@ static struct matrix_expr * matrix_parse_curly_semi (struct matrix_state *s) { if (lex_token (s->lexer) == T_RCURLY) - return matrix_expr_create_0 (MOP_EMPTY); + { + struct matrix_expr *e = matrix_expr_create_0 (MOP_EMPTY); + e->location = lex_get_location (s->lexer, -1, 0); + return e; + } struct matrix_expr *lhs = matrix_parse_curly_comma (s); if (!lhs) @@ -737,7 +746,7 @@ matrix_eval_BLOCK (gsl_matrix *m[], size_t n) } static gsl_matrix * -matrix_eval_CHOL (gsl_matrix *m) +matrix_eval_CHOL (gsl_matrix *m, const struct matrix_expr *e) { if (!gsl_linalg_cholesky_decomp1 (m)) { @@ -752,7 +761,8 @@ matrix_eval_CHOL (gsl_matrix *m) } else { - msg (SE, _("Input to CHOL function is not positive-definite.")); + msg_at (SE, e->location, + _("Input to CHOL function is not positive-definite.")); return NULL; } } @@ -1154,12 +1164,6 @@ matrix_eval_GSCH (gsl_matrix *v) static gsl_matrix * matrix_eval_IDENT (double s1, double s2) { - if (s1 < 0 || s1 > SIZE_MAX || s2 < 0 || s2 > SIZE_MAX) - { - msg (SE, _("Arguments to IDENT must be non-negative integers.")); - return NULL; - } - gsl_matrix *m = gsl_matrix_alloc (s1, s2); MATRIX_FOR_ALL_ELEMENTS (d, y, x, m) *d = x == y; @@ -1380,12 +1384,6 @@ matrix_eval_MAGIC (double n_) static gsl_matrix * matrix_eval_MAKE (double r, double c, double value) { - if (r < 0 || r >= SIZE_MAX || c < 0 || c >= SIZE_MAX) - { - msg (SE, _("Size arguments to MAKE must be integers.")); - return NULL; - } - gsl_matrix *m = gsl_matrix_alloc (r, c); MATRIX_FOR_ALL_ELEMENTS (d, y, x, m) *d = value; @@ -1416,12 +1414,6 @@ matrix_eval_MMIN (gsl_matrix *m) static gsl_matrix * matrix_eval_MOD (gsl_matrix *m, double divisor) { - if (divisor == 0.0) - { - msg (SE, _("Divisor argument to MOD function must be nonzero.")); - return NULL; - } - MATRIX_FOR_ALL_ELEMENTS (d, y, x, m) *d = fmod (*d, divisor); return m; @@ -2673,7 +2665,7 @@ matrix_parse_function (struct matrix_state *s, const char *token, } if (!sub->location) { - lex_extend_location (s->lexer, 0, arg_location); + //lex_extend_location (s->lexer, 0, arg_location); sub->location = arg_location; } else @@ -2725,18 +2717,16 @@ matrix_parse_primary (struct matrix_state *s) if (lex_is_number (s->lexer)) { double number = lex_number (s->lexer); - lex_get (s->lexer); - return matrix_expr_create_number (number); + return matrix_expr_create_number (s->lexer, number); } else if (lex_is_string (s->lexer)) { char string[sizeof (double)]; buf_copy_str_rpad (string, sizeof string, lex_tokcstr (s->lexer), ' '); - lex_get (s->lexer); double number; memcpy (&number, string, sizeof number); - return matrix_expr_create_number (number); + return matrix_expr_create_number (s->lexer, number); } else if (lex_match (s->lexer, T_LPAREN)) { @@ -3600,10 +3590,10 @@ matrix_expr_evaluate_mat_index (gsl_matrix *sm, gsl_matrix *im0, return dm; } -#define F(ENUM, STRING, PROTO, CONSTRAINTS) \ - static gsl_matrix *matrix_expr_evaluate_##PROTO ( \ - const struct matrix_function_properties *, gsl_matrix *[], size_t, \ - matrix_proto_##PROTO *); +#define F(ENUM, STRING, PROTO, CONSTRAINTS) \ + static gsl_matrix *matrix_expr_evaluate_##PROTO ( \ + const struct matrix_function_properties *, gsl_matrix *[], \ + const struct matrix_expr *, matrix_proto_##PROTO *); MATRIX_FUNCTIONS #undef F @@ -3672,32 +3662,58 @@ argument_invalid (const struct matrix_function_properties *props, gsl_matrix_get (a, y, x)); } +enum matrix_argument_relop + { + MRR_GT, /* > */ + MRR_GE, /* >= */ + MRR_LT, /* < */ + MRR_LE, /* <= */ + MRR_NE, /* <> */ + }; + static void argument_inequality_error (const struct matrix_function_properties *props, size_t a_index, gsl_matrix *a, size_t y, size_t x, size_t b_index, double b, - bool greater, bool equal) + enum matrix_argument_relop relop) { struct string s = DS_EMPTY_INITIALIZER; argument_invalid (props, a_index, a, y, x, &s); ds_put_cstr (&s, " "); - if (greater && equal) - ds_put_format (&s, _("This argument must be greater than or " - "equal to argument %zu, but that has value %g."), - b_index, b); - else if (greater && !equal) - ds_put_format (&s, _("This argument must be greater than argument %zu, " - "but that has value %g."), - b_index, b); - else if (equal) - ds_put_format (&s, _("This argument must be less than or " - "equal to argument %zu, but that has value %g."), - b_index, b); - else - ds_put_format (&s, _("This argument must be less than argument %zu, " - "but that has value %g."), - b_index, b); + switch (relop) + { + case MRR_GE: + ds_put_format (&s, _("This argument must be greater than or " + "equal to argument %zu, but that has value %g."), + b_index, b); + break; + + case MRR_GT: + ds_put_format (&s, _("This argument must be greater than argument %zu, " + "but that has value %g."), + b_index, b); + break; + + case MRR_LE: + ds_put_format (&s, _("This argument must be less than or " + "equal to argument %zu, but that has value %g."), + b_index, b); + break; + + case MRR_LT: + ds_put_format (&s, _("This argument must be less than argument %zu, " + "but that has value %g."), + b_index, b); + break; + + case MRR_NE: + ds_put_format (&s, + _("This argument must not be the same as argument %zu."), + b_index); + break; + } + msg (ME, ds_cstr (&s)); ds_destroy (&s); } @@ -3706,24 +3722,72 @@ static void argument_value_error (const struct matrix_function_properties *props, size_t a_index, gsl_matrix *a, size_t y, size_t x, double b, - bool greater, bool equal) + enum matrix_argument_relop relop) { struct string s = DS_EMPTY_INITIALIZER; argument_invalid (props, a_index, a, y, x, &s); ds_put_cstr (&s, " "); - if (greater && equal) - ds_put_format (&s, _("This argument must be greater than or equal to %g."), - b); - else if (greater && !equal) - ds_put_format (&s, _("This argument must be greater than %g."), b); - else if (equal) - ds_put_format (&s, _("This argument must be less than or equal to %g."), b); - else - ds_put_format (&s, _("This argument must be less than %g."), b); + switch (relop) + { + case MRR_GE: + ds_put_format (&s, + _("This argument must be greater than or equal to %g."), + b); + break; + + case MRR_GT: + ds_put_format (&s, _("This argument must be greater than %g."), b); + break; + + case MRR_LE: + ds_put_format (&s, _("This argument must be less than or equal to %g."), + b); + break; + + case MRR_LT: + ds_put_format (&s, _("This argument must be less than %g."), b); + break; + + case MRR_NE: + ds_put_format (&s, _("This argument may not be %g."), b); + break; + } + msg (ME, ds_cstr (&s)); ds_destroy (&s); } +static bool +matrix_argument_relop_is_satisfied (double a, double b, + enum matrix_argument_relop relop) +{ + switch (relop) + { + case MRR_GE: return a >= b; + case MRR_GT: return a > b; + case MRR_LE: return a <= b; + case MRR_LT: return a < b; + case MRR_NE: return a != b; + } + + NOT_REACHED (); +} + +static enum matrix_argument_relop +matrix_argument_relop_flip (enum matrix_argument_relop relop) +{ + switch (relop) + { + case MRR_GE: return MRR_LE; + case MRR_GT: return MRR_LT; + case MRR_LE: return MRR_GE; + case MRR_LT: return MRR_GT; + case MRR_NE: return MRR_NE; + } + + NOT_REACHED (); +} + static bool check_constraints (const struct matrix_function_properties *props, gsl_matrix *args[], size_t n_args) @@ -3773,17 +3837,38 @@ check_constraints (const struct matrix_function_properties *props, return false; } } - else if (*constraints == '>' || *constraints == '<') + else if (*constraints == '>' + || *constraints == '<' + || *constraints == '!') { - bool greater = *constraints++ == '>'; - bool equal; - if (*constraints == '=') + enum matrix_argument_relop relop; + switch (*constraints++) { - equal = true; + case '>': + if (*constraints == '=') + { + constraints++; + relop = MRR_GE; + } + else + relop = MRR_GT; + break; + + case '<': + if (*constraints == '=') + { + constraints++; + relop = MRR_LE; + } + else + relop = MRR_LT; + break; + + case '!': + assert (*constraints == '='); constraints++; + relop = MRR_NE; } - else - equal = false; if (*constraints >= 'a' && *constraints <= 'd') { @@ -3801,20 +3886,17 @@ check_constraints (const struct matrix_function_properties *props, size_t tmp_index = a_index; a_index = b_index; b_index = tmp_index; - - greater = !greater; + relop = matrix_argument_relop_flip (relop); } double b = to_scalar (args[b_index]); MATRIX_FOR_ALL_ELEMENTS (a, y, x, args[a_index]) - if (greater - ? (equal ? !(*a >= b) : !(*a > b)) - : (equal ? !(*a <= b) : !(*a < b))) + if (!matrix_argument_relop_is_satisfied (*a, b, relop)) { argument_inequality_error (props, a_index + 1, args[a_index], y, x, b_index + 1, b, - greater, equal); + relop); return false; } } @@ -3823,14 +3905,12 @@ check_constraints (const struct matrix_function_properties *props, int comparand = parse_constraint_value (&constraints); MATRIX_FOR_ALL_ELEMENTS (d, y, x, args[arg_index]) - if (greater - ? (equal ? !(*d >= comparand) : !(*d > comparand)) - : (equal ? !(*d <= comparand) : !(*d < comparand))) + if (!matrix_argument_relop_is_satisfied (*d, comparand, relop)) { argument_value_error (props, arg_index + 1, args[arg_index], y, x, comparand, - greater, equal); + relop); return false; } } @@ -3848,10 +3928,10 @@ check_constraints (const struct matrix_function_properties *props, static gsl_matrix * matrix_expr_evaluate_d_none ( const struct matrix_function_properties *props UNUSED, - gsl_matrix *subs[] UNUSED, size_t n_subs, + gsl_matrix *subs[] UNUSED, const struct matrix_expr *e, matrix_proto_d_none *f) { - assert (n_subs == 0); + assert (e->n_subs == 0); gsl_matrix *m = gsl_matrix_alloc (1, 1); gsl_matrix_set (m, 0, 0, f ()); @@ -3860,16 +3940,16 @@ matrix_expr_evaluate_d_none ( static gsl_matrix * matrix_expr_evaluate_d_d (const struct matrix_function_properties *props, - gsl_matrix *subs[], size_t n_subs, + gsl_matrix *subs[], const struct matrix_expr *e, matrix_proto_d_d *f) { - assert (n_subs == 1); + assert (e->n_subs == 1); double d; - if (!to_scalar_args (props->name, subs, n_subs, &d)) + if (!to_scalar_args (props->name, subs, e->n_subs, &d)) return NULL; - if (!check_constraints (props, subs, n_subs)) + if (!check_constraints (props, subs, e->n_subs)) return NULL; gsl_matrix *m = gsl_matrix_alloc (1, 1); @@ -3879,16 +3959,16 @@ matrix_expr_evaluate_d_d (const struct matrix_function_properties *props, static gsl_matrix * matrix_expr_evaluate_d_dd (const struct matrix_function_properties *props, - gsl_matrix *subs[], size_t n_subs, + gsl_matrix *subs[], const struct matrix_expr *e, matrix_proto_d_dd *f) { - assert (n_subs == 2); + assert (e->n_subs == 2); double d[2]; - if (!to_scalar_args (props->name, subs, n_subs, d)) + if (!to_scalar_args (props->name, subs, e->n_subs, d)) return NULL; - if (!check_constraints (props, subs, n_subs)) + if (!check_constraints (props, subs, e->n_subs)) return NULL; gsl_matrix *m = gsl_matrix_alloc (1, 1); @@ -3898,16 +3978,16 @@ matrix_expr_evaluate_d_dd (const struct matrix_function_properties *props, static gsl_matrix * matrix_expr_evaluate_d_ddd (const struct matrix_function_properties *props, - gsl_matrix *subs[], size_t n_subs, + gsl_matrix *subs[], const struct matrix_expr *e, matrix_proto_d_ddd *f) { - assert (n_subs == 3); + assert (e->n_subs == 3); double d[3]; - if (!to_scalar_args (props->name, subs, n_subs, d)) + if (!to_scalar_args (props->name, subs, e->n_subs, d)) return NULL; - if (!check_constraints (props, subs, n_subs)) + if (!check_constraints (props, subs, e->n_subs)) return NULL; gsl_matrix *m = gsl_matrix_alloc (1, 1); @@ -3917,54 +3997,63 @@ matrix_expr_evaluate_d_ddd (const struct matrix_function_properties *props, static gsl_matrix * matrix_expr_evaluate_m_d (const struct matrix_function_properties *props, - gsl_matrix *subs[], size_t n_subs, + gsl_matrix *subs[], const struct matrix_expr *e, matrix_proto_m_d *f) { - assert (n_subs == 1); + assert (e->n_subs == 1); double d; - return to_scalar_args (props->name, subs, n_subs, &d) ? f (d) : NULL; + return to_scalar_args (props->name, subs, e->n_subs, &d) ? f (d) : NULL; } static gsl_matrix * matrix_expr_evaluate_m_dd (const struct matrix_function_properties *props, - gsl_matrix *subs[], size_t n_subs, + gsl_matrix *subs[], const struct matrix_expr *e, matrix_proto_m_dd *f) { - assert (n_subs == 2); + assert (e->n_subs == 2); double d[2]; - return to_scalar_args (props->name, subs, n_subs, d) ? f(d[0], d[1]) : NULL; + return to_scalar_args (props->name, subs, e->n_subs, d) ? f(d[0], d[1]) : NULL; } static gsl_matrix * matrix_expr_evaluate_m_ddd (const struct matrix_function_properties *props, - gsl_matrix *subs[], size_t n_subs, + gsl_matrix *subs[], const struct matrix_expr *e, matrix_proto_m_ddd *f) { - assert (n_subs == 3); + assert (e->n_subs == 3); double d[3]; - return to_scalar_args (props->name, subs, n_subs, d) ? f(d[0], d[1], d[2]) : NULL; + return to_scalar_args (props->name, subs, e->n_subs, d) ? f(d[0], d[1], d[2]) : NULL; } static gsl_matrix * matrix_expr_evaluate_m_m (const struct matrix_function_properties *props UNUSED, - gsl_matrix *subs[], size_t n_subs, + gsl_matrix *subs[], const struct matrix_expr *e, matrix_proto_m_m *f) { - assert (n_subs == 1); + assert (e->n_subs == 1); return f (subs[0]); } +static gsl_matrix * +matrix_expr_evaluate_m_me (const struct matrix_function_properties *props UNUSED, + gsl_matrix *subs[], const struct matrix_expr *e, + matrix_proto_m_me *f) +{ + assert (e->n_subs == 1); + return f (subs[0], e); +} + static gsl_matrix * matrix_expr_evaluate_m_e (const struct matrix_function_properties *props, - gsl_matrix *subs[], size_t n_subs, - matrix_proto_m_e *f) + gsl_matrix *subs[], const struct matrix_expr *e, + matrix_proto_m_e *f) { - assert (n_subs == 1); + assert (e->n_subs == 1); - if (!check_constraints (props, subs, n_subs)) + if (!check_constraints (props, subs, e->n_subs)) return NULL; MATRIX_FOR_ALL_ELEMENTS (a, y, x, subs[0]) @@ -3974,10 +4063,10 @@ matrix_expr_evaluate_m_e (const struct matrix_function_properties *props, static gsl_matrix * matrix_expr_evaluate_m_md (const struct matrix_function_properties *props UNUSED, - gsl_matrix *subs[], size_t n_subs, + gsl_matrix *subs[], const struct matrix_expr *e, matrix_proto_m_md *f) { - assert (n_subs == 2); + assert (e->n_subs == 2); if (!check_scalar_arg (props->name, subs, 1)) return NULL; return f (subs[0], to_scalar (subs[1])); @@ -3985,14 +4074,14 @@ matrix_expr_evaluate_m_md (const struct matrix_function_properties *props UNUSED static gsl_matrix * matrix_expr_evaluate_m_ed (const struct matrix_function_properties *props, - gsl_matrix *subs[], size_t n_subs, + gsl_matrix *subs[], const struct matrix_expr *e, matrix_proto_m_ed *f) { - assert (n_subs == 2); + assert (e->n_subs == 2); if (!check_scalar_arg (props->name, subs, 1)) return NULL; - if (!check_constraints (props, subs, n_subs)) + if (!check_constraints (props, subs, e->n_subs)) return NULL; double b = to_scalar (subs[1]); @@ -4003,10 +4092,10 @@ matrix_expr_evaluate_m_ed (const struct matrix_function_properties *props, static gsl_matrix * matrix_expr_evaluate_m_mdd (const struct matrix_function_properties *props UNUSED, - gsl_matrix *subs[], size_t n_subs, + gsl_matrix *subs[], const struct matrix_expr *e, matrix_proto_m_mdd *f) { - assert (n_subs == 3); + assert (e->n_subs == 3); if (!check_scalar_arg (props->name, subs, 1) || !check_scalar_arg (props->name, subs, 2)) return NULL; return f (subs[0], to_scalar (subs[1]), to_scalar (subs[2])); @@ -4014,14 +4103,14 @@ matrix_expr_evaluate_m_mdd (const struct matrix_function_properties *props UNUSE static gsl_matrix * matrix_expr_evaluate_m_edd (const struct matrix_function_properties *props, - gsl_matrix *subs[], size_t n_subs, + gsl_matrix *subs[], const struct matrix_expr *e, matrix_proto_m_edd *f) { - assert (n_subs == 3); + assert (e->n_subs == 3); if (!check_scalar_arg (props->name, subs, 1) || !check_scalar_arg (props->name, subs, 2)) return NULL; - if (!check_constraints (props, subs, n_subs)) + if (!check_constraints (props, subs, e->n_subs)) return NULL; double b = to_scalar (subs[1]); @@ -4033,15 +4122,15 @@ matrix_expr_evaluate_m_edd (const struct matrix_function_properties *props, static gsl_matrix * matrix_expr_evaluate_m_eddd (const struct matrix_function_properties *props, - gsl_matrix *subs[], size_t n_subs, + gsl_matrix *subs[], const struct matrix_expr *e, matrix_proto_m_eddd *f) { - assert (n_subs == 4); + assert (e->n_subs == 4); for (size_t i = 1; i < 4; i++) if (!check_scalar_arg (props->name, subs, i)) return NULL; - if (!check_constraints (props, subs, n_subs)) + if (!check_constraints (props, subs, e->n_subs)) return NULL; double b = to_scalar (subs[1]); @@ -4054,10 +4143,10 @@ matrix_expr_evaluate_m_eddd (const struct matrix_function_properties *props, static gsl_matrix * matrix_expr_evaluate_m_eed (const struct matrix_function_properties *props, - gsl_matrix *subs[], size_t n_subs, + gsl_matrix *subs[], const struct matrix_expr *e, matrix_proto_m_eed *f) { - assert (n_subs == 3); + assert (e->n_subs == 3); if (!check_scalar_arg (props->name, subs, 2)) return NULL; @@ -4074,7 +4163,7 @@ matrix_expr_evaluate_m_eed (const struct matrix_function_properties *props, return NULL; } - if (!check_constraints (props, subs, n_subs)) + if (!check_constraints (props, subs, e->n_subs)) return NULL; double c = to_scalar (subs[2]); @@ -4097,19 +4186,19 @@ matrix_expr_evaluate_m_eed (const struct matrix_function_properties *props, static gsl_matrix * matrix_expr_evaluate_m_mm (const struct matrix_function_properties *props UNUSED, - gsl_matrix *subs[], size_t n_subs, + gsl_matrix *subs[], const struct matrix_expr *e, matrix_proto_m_mm *f) { - assert (n_subs == 2); + assert (e->n_subs == 2); return f (subs[0], subs[1]); } static gsl_matrix * matrix_expr_evaluate_m_v (const struct matrix_function_properties *props, - gsl_matrix *subs[], size_t n_subs, + gsl_matrix *subs[], const struct matrix_expr *e, matrix_proto_m_v *f) { - assert (n_subs == 1); + assert (e->n_subs == 1); if (!check_vector_arg (props->name, subs, 0)) return NULL; gsl_vector v = to_vector (subs[0]); @@ -4118,10 +4207,10 @@ matrix_expr_evaluate_m_v (const struct matrix_function_properties *props, static gsl_matrix * matrix_expr_evaluate_d_m (const struct matrix_function_properties *props UNUSED, - gsl_matrix *subs[], size_t n_subs, + gsl_matrix *subs[], const struct matrix_expr *e, matrix_proto_d_m *f) { - assert (n_subs == 1); + assert (e->n_subs == 1); gsl_matrix *m = gsl_matrix_alloc (1, 1); gsl_matrix_set (m, 0, 0, f (subs[0])); @@ -4130,24 +4219,24 @@ matrix_expr_evaluate_d_m (const struct matrix_function_properties *props UNUSED, static gsl_matrix * matrix_expr_evaluate_m_any (const struct matrix_function_properties *props UNUSED, - gsl_matrix *subs[], size_t n_subs, - matrix_proto_m_any *f) + gsl_matrix *subs[], const struct matrix_expr *e, + matrix_proto_m_any *f) { - return f (subs, n_subs); + return f (subs, e->n_subs); } static gsl_matrix * matrix_expr_evaluate_IDENT (const struct matrix_function_properties *props, - gsl_matrix *subs[], size_t n_subs, + gsl_matrix *subs[], const struct matrix_expr *e, matrix_proto_IDENT *f) { - assert (n_subs <= 2); + assert (e->n_subs <= 2); double d[2]; - if (!to_scalar_args (props->name, subs, n_subs, d)) + if (!to_scalar_args (props->name, subs, e->n_subs, d)) return NULL; - return f (d[0], d[n_subs - 1]); + return f (d[0], d[e->n_subs - 1]); } static gsl_matrix * @@ -4210,7 +4299,7 @@ matrix_expr_evaluate (const struct matrix_expr *e) .name = STRING, \ .constraints = CONSTRAINTS, \ }; \ - result = matrix_expr_evaluate_##PROTO (&props, subs, e->n_subs, \ + result = matrix_expr_evaluate_##PROTO (&props, subs, e, \ matrix_eval_##ENUM); \ } \ break; @@ -4348,9 +4437,11 @@ 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; + + struct msg_location *var_location; /* Variable name. */ + struct msg_location *index_location; /* Variable name plus indexing. */ }; static void @@ -4358,6 +4449,8 @@ matrix_lvalue_destroy (struct matrix_lvalue *lvalue) { if (lvalue) { + msg_location_destroy (lvalue->var_location); + msg_location_destroy (lvalue->index_location); for (size_t i = 0; i < lvalue->n_indexes; i++) matrix_expr_destroy (lvalue->indexes[i]); free (lvalue); @@ -4395,6 +4488,9 @@ matrix_lvalue_parse (struct matrix_state *s) } if (!lex_force_match (s->lexer, T_RPAREN)) goto error; + + lvalue->index_location = msg_location_dup (lvalue->var_location); + lex_extend_location (s->lexer, -1, lvalue->index_location); } else { @@ -6181,10 +6277,8 @@ parse_error (const struct dfm_reader *reader, enum fmt_type format, struct msg_location *location = xmalloc (sizeof *location); *location = (struct msg_location) { .file_name = intern_new (dfm_get_file_name (reader)), - .first_line = line_number, - .last_line = line_number + 1, - .first_column = first_column, - .last_column = last_column, + .p[0] = { .line = line_number, .column = first_column }, + .p[1] = { .line = line_number, .column = last_column }, }; struct msg *m = xmalloc (sizeof *m); *m = (struct msg) { @@ -6230,7 +6324,7 @@ matrix_read_set_field (struct read_command *read, struct dfm_reader *reader, if (error) { int c1 = utf8_count_columns (line_start, p.string - line_start) + 1; - int c2 = c1 + ss_utf8_count_columns (p) - 1; + int c2 = c1 + ss_utf8_count_columns (p); parse_error (reader, read->format, p, y, x, c1, c2, error); } else diff --git a/src/libpspp/message.c b/src/libpspp/message.c index d71df204ea..526e19f3a0 100644 --- a/src/libpspp/message.c +++ b/src/libpspp/message.c @@ -134,6 +134,35 @@ msg_location_destroy (struct msg_location *loc) } } +static int +msg_point_compare_3way (const struct msg_point *a, const struct msg_point *b) +{ + return (!a->line ? 1 + : !b->line ? -1 + : a->line > b->line ? 1 + : a->line < b->line ? -1 + : !a->column ? 1 + : !b->column ? -1 + : a->column > b->column ? 1 + : a->column < b->column ? -1 + : 0); +} + +void +msg_location_merge (struct msg_location **dstp, const struct msg_location *src) +{ + if (dst->file_name != src->file_name) + { + /* Failure. */ + return; + } + + if (msg_point_compare_3way (&dst->p[0], &src->p[0]) > 0) + dst->p[0] = src->p[0]; + if (msg_point_compare_3way (&dst->p[1], &src->p[1]) < 0) + dst->p[1] = src->p[1]; +} + struct msg_location * msg_location_dup (const struct msg_location *src) { @@ -143,10 +172,8 @@ msg_location_dup (const struct msg_location *src) struct msg_location *dst = xmalloc (sizeof *dst); *dst = (struct msg_location) { .file_name = intern_new_if_nonnull (src->file_name), - .first_line = src->first_line, - .last_line = src->last_line, - .first_column = src->first_column, - .last_column = src->last_column, + .p[0] = src->p[0], + .p[1] = src->p[1], }; return dst; } @@ -155,8 +182,8 @@ bool msg_location_is_empty (const struct msg_location *loc) { return !loc || (!loc->file_name - && loc->first_line <= 0 - && loc->first_column <= 0); + && loc->p[0].line <= 0 + && loc->p[0].column <= 0); } void @@ -168,10 +195,10 @@ msg_location_format (const struct msg_location *loc, struct string *s) if (loc->file_name) ds_put_cstr (s, loc->file_name); - int l1 = loc->first_line; - int l2 = MAX (loc->first_line, loc->last_line - 1); - int c1 = loc->first_column; - int c2 = MAX (loc->first_column, loc->last_column - 1); + int l1 = loc->p[0].line; + int l2 = MAX (l1, loc->p[1].line); + int c1 = loc->p[0].column; + int c2 = MAX (c1, loc->p[1].column); if (l1 > 0) { diff --git a/src/libpspp/message.h b/src/libpspp/message.h index f0066ee0a7..d54598b696 100644 --- a/src/libpspp/message.h +++ b/src/libpspp/message.h @@ -72,20 +72,29 @@ msg_class_from_category_and_severity (enum msg_category category, return category * 3 + severity; } +struct msg_point + { + int line; /* 1-based line number, or 0 if none. */ + int column; /* 1-based column number, or 0 if none. */ + }; + struct msg_location { const char *file_name; /* Interned file name, or NULL. */ + struct msg_point p[2]; +#if 0 int first_line; /* 1-based line number, or 0 if none. */ int last_line; /* 1-based exclusive last line (0=none). */ int first_column; /* 1-based first column, or 0 if none. */ int last_column; /* 1-based exclusive last column (0=none). */ +#endif }; 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 *); +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 *);