From 4848cff524922cc77ed21662406807471e96a68e Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 7 Mar 2005 03:04:50 +0000 Subject: [PATCH] Add even more expression tests and fix the bugs they found. --- src/ChangeLog | 27 +++++++++++++ src/aggregate.c | 2 +- src/count.c | 6 +-- src/data-list.c | 12 +++--- src/examine.q | 4 +- src/expressions/ChangeLog | 12 ++++++ src/expressions/evaluate.c | 6 +-- src/expressions/optimize.c | 9 +++-- src/expressions/parse.c | 27 +++++++------ src/file-type.c | 2 +- src/frequencies.q | 2 +- src/lexer.c | 67 +++++++++++++++++--------------- src/lexer.h | 11 ++++-- src/matrix-data.c | 4 +- src/mis-val.c | 2 +- src/moments.c | 4 +- src/print.c | 16 ++++---- src/q2c.c | 8 ++-- src/recode.c | 8 ++-- src/repeat.c | 2 +- src/sample.c | 2 +- src/set.q | 2 +- src/val-labs.c | 4 +- tests/ChangeLog | 4 ++ tests/expressions/expressions.sh | 14 +++++++ 25 files changed, 163 insertions(+), 94 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 7e49e91f..281bcaeb 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,30 @@ +Sun Mar 6 17:07:20 2005 Ben Pfaff + + When the lexer sees something like `-5' in the input, it has to + decide whether it's a negative numeric constant token or a '-' + token followed by a positive numeric constant token. It always + decides on the former, and then the parser can call + lex_negative_to_dash() if it wants the latter. However, this + doesn't work for the case of `-0', because negative zero is + (portably) indistinguishable from positive zero. So now we divide + T_NUM into two tokens, T_POS_NUM and T_NEG_NUM, to make the + distinction clear. This requires a little bit of extra effort, + because there were several references to T_NUM in the code base. + + * lexer.c: (lex_get) Use T_NEG_NUM and T_POS_NUM to distinguish + positive and negative numeric constants. + (lex_double_p) Renamed lex_is_number(). Changed return type to + bool. Updated all relevant references to T_NUM to instead use + this function. + (lex_double) Renamed lex_number(). All references updated. + (lex_integer_p) Renamed lex_is_integer(). Changed return type to + bool. All references updated. + (lex_token_representation) Understand T_NEG_NUM and T_POS_NUM. + (lex_negative_to_dash) Ditto. + (dump_token) Ditto. + + * lexer.h: (enum) Add T_POS_NUM, T_NEG_NUM. Remove T_NUM. + Thu Mar 3 22:08:35 WST 2005 John Darrington * Makefile.am : Fixed up CLEANFILES target. diff --git a/src/aggregate.c b/src/aggregate.c index a2569837..3037a150 100644 --- a/src/aggregate.c +++ b/src/aggregate.c @@ -450,7 +450,7 @@ parse_aggregate_functions (struct agr_proc *agr) arg[i].c = xstrdup (ds_c_str (&tokstr)); type = ALPHA; } - else if (token == T_NUM) + else if (lex_is_number ()) { arg[i].f = tokval; type = NUMERIC; diff --git a/src/count.c b/src/count.c index 35021f09..af9642b8 100644 --- a/src/count.c +++ b/src/count.c @@ -244,13 +244,13 @@ parse_numeric_criteria (struct counting * c) } cur = &c->crit.n[n++]; - if (token == T_NUM) + if (lex_is_number ()) { cur->a = tokval; lex_get (); if (lex_match_id ("THRU")) { - if (token == T_NUM) + if (lex_is_number ()) { if (!lex_force_num ()) return 0; @@ -282,7 +282,7 @@ parse_numeric_criteria (struct counting * c) { if (!lex_force_match_id ("THRU")) return 0; - if (token == T_NUM) + if (lex_is_number ()) { cur->type = CNT_LOW; cur->a = tokval; diff --git a/src/data-list.c b/src/data-list.c index eb491d1d..9d935609 100644 --- a/src/data-list.c +++ b/src/data-list.c @@ -350,7 +350,7 @@ parse_fixed (struct data_list_pgm *dls) while (lex_match ('/')) { fx.recno++; - if (lex_integer_p ()) + if (lex_is_integer ()) { if (lex_integer () < fx.recno) { @@ -371,7 +371,7 @@ parse_fixed (struct data_list_pgm *dls) if (!parse_DATA_LIST_vars (&fx.name, &fx.name_cnt, PV_NONE)) return 0; - if (token == T_NUM) + if (lex_is_number ()) { if (!fixed_parse_compatible (&fx, &dls->first, &dls->last)) goto fail; @@ -501,7 +501,7 @@ fixed_parse_compatible (struct fixed_parsing_state *fx, else input.type = FMT_F; - if (lex_integer_p ()) + if (lex_is_integer ()) { if (lex_integer () < 1) { @@ -713,7 +713,7 @@ fixed_parse_fortran_internal (struct fixed_parsing_state *fx, tail = new; /* Parse count. */ - if (lex_integer_p ()) + if (lex_is_integer ()) { new->count = lex_integer (); lex_get (); @@ -1690,7 +1690,7 @@ parse_num_or_var (struct rpd_num_or_var *value, const char *message) return 0; } } - else if (lex_integer_p ()) + else if (lex_is_integer ()) { value->num = lex_integer (); @@ -1725,7 +1725,7 @@ parse_repeating_data (struct dls_var_spec **first, struct dls_var_spec **last) if (!parse_DATA_LIST_vars (&fx.name, &fx.name_cnt, PV_NONE)) return 0; - if (token == T_NUM) + if (lex_is_number ()) { if (!fixed_parse_compatible (&fx, first, last)) goto fail; diff --git a/src/examine.q b/src/examine.q index 96d8210d..e35c7049 100644 --- a/src/examine.q +++ b/src/examine.q @@ -413,9 +413,9 @@ xmn_custom_percentiles(struct cmd_examine *p UNUSED) lex_match('('); - while ( lex_double_p() ) + while ( lex_is_number() ) { - subc_list_double_push(&percentile_list,lex_double()); + subc_list_double_push(&percentile_list,lex_number()); lex_get(); diff --git a/src/expressions/ChangeLog b/src/expressions/ChangeLog index 73c619ca..94063e7a 100644 --- a/src/expressions/ChangeLog +++ b/src/expressions/ChangeLog @@ -1,3 +1,15 @@ +Sun Mar 6 17:51:05 2005 Ben Pfaff + + * optimize.c: (optimize_tree) Fix optimization bug for x**2. + + * parse.c: (type_coercion_core) Set *node to NULL on failure, as + indicated by function comment. + (parse_binary_operators) Always return NULL on type_coercion() + failure. Should have been doing this anyway, but bug in + type_coercion_core() filtered through. + (parse_add) Fix typo in user message. + (parse_primary) Understand T_NEG_NUM and T_POS_NUM. + Sun Mar 6 10:47:13 2005 Ben Pfaff * operations.def: Add VALUE function. diff --git a/src/expressions/evaluate.c b/src/expressions/evaluate.c index c2868429..7f066a50 100644 --- a/src/expressions/evaluate.c +++ b/src/expressions/evaluate.c @@ -140,7 +140,7 @@ cmd_debug_evaluate (void) if (!lex_force_match ('=')) goto done; - if (token == T_NUM) + if (lex_is_number ()) { width = 0; fprintf (stderr, "(%s = %.2f)", name, tokval); @@ -174,7 +174,7 @@ cmd_debug_evaluate (void) } case_resize (c, old_value_cnt, dict_get_next_value_idx (d)); - if (token == T_NUM) + if (lex_is_number ()) case_data_rw (c, v->fv)->f = tokval; else memcpy (case_data_rw (c, v->fv)->s, ds_data (&tokstr), @@ -198,7 +198,7 @@ cmd_debug_evaluate (void) lex_get (); expr = expr_parse_any (d, optimize); - if (!expr || token != '.') + if (!expr || lex_end_of_command () != CMD_SUCCESS) { if (expr != NULL) expr_free (expr); diff --git a/src/expressions/optimize.c b/src/expressions/optimize.c index 26814162..5432e9ab 100644 --- a/src/expressions/optimize.c +++ b/src/expressions/optimize.c @@ -102,6 +102,9 @@ optimize_tree (union any_node *node, struct expression *e) struct composite_node *n = &node->composite; assert (is_composite (node->type)); + /* If you add to these optimizations, please also add a + correctness test in tests/expressions/expressions.sh. */ + /* x+0, x-0, 0+x => x. */ if ((n->type == OP_ADD || n->type == OP_SUB) && eq_double (n->args[1], 0.)) return n->args[0]; @@ -115,7 +118,7 @@ optimize_tree (union any_node *node, struct expression *e) else if (n->type == OP_MUL && eq_double (n->args[0], 1.)) return n->args[1]; - /* 0*x, 0/x, x*0, MOD(0,x) => x. */ + /* 0*x, 0/x, x*0, MOD(0,x) => 0. */ else if (((n->type == OP_MUL || n->type == OP_DIV || n->type == OP_MOD_nn) && eq_double (n->args[0], 0.)) || (n->type == OP_MUL && eq_double (n->args[1], 0.))) @@ -126,8 +129,8 @@ optimize_tree (union any_node *node, struct expression *e) return n->args[0]; /* x**2 => SQUARE(x). */ - else if (n->type == OP_POW && eq_double (n->args[2], 2)) - return expr_allocate_unary (e,OP_SQUARE, node); + else if (n->type == OP_POW && eq_double (n->args[1], 2)) + return expr_allocate_unary (e, OP_SQUARE, n->args[0]); /* Otherwise, nothing to do. */ else diff --git a/src/expressions/parse.c b/src/expressions/parse.c index b1998f63..5e917a0e 100644 --- a/src/expressions/parse.c +++ b/src/expressions/parse.c @@ -269,13 +269,12 @@ type_check (struct expression *e, /* Considers whether *NODE may be coerced to type REQUIRED_TYPE. Returns true if possible, false if disallowed. - If DO_COERCION is zero, then *NODE is not modified and there + If DO_COERCION is false, then *NODE is not modified and there are no side effects. - Otherwise, DO_COERCION is nonzero. In this case, we perform - the coercion if possible, possibly modifying *NODE. If the - coercion is not possible then we free *NODE and set *NODE to - a null pointer. + If DO_COERCION is true, we perform the coercion if possible, + modifying *NODE if necessary. If the coercion is not possible + then we free *NODE and set *NODE to a null pointer. This function's interface is somewhat awkward. Use one of the wrapper functions type_coercion(), type_coercion_assert(), or @@ -389,10 +388,13 @@ type_coercion_core (struct expression *e, } if (do_coercion) - msg (SE, _("Type mismatch while applying %s operator: " - "cannot convert %s to %s."), - operator_name, - atom_type_name (actual_type), atom_type_name (required_type)); + { + msg (SE, _("Type mismatch while applying %s operator: " + "cannot convert %s to %s."), + operator_name, + atom_type_name (actual_type), atom_type_name (required_type)); + *node = NULL; + } return false; } @@ -519,7 +521,7 @@ parse_binary_operators (struct expression *e, union any_node *node, /* Convert the left-hand side to type OPERAND_TYPE. */ if (!type_coercion (e, operand_type, &node, operator->name)) - return node; + return NULL; /* Parse the right-hand side and coerce to type OPERAND_TYPE. */ @@ -653,7 +655,7 @@ parse_add (struct expression *e) static const struct operator ops[] = { { '+', OP_ADD, "addition (\"+\")" }, - { '-', OP_SUB, "subtraction (\"-\")-" }, + { '-', OP_SUB, "subtraction (\"-\")" }, }; return parse_binary_operators (e, parse_mul (e), @@ -800,7 +802,8 @@ parse_primary (struct expression *e) } break; - case T_NUM: + case T_POS_NUM: + case T_NEG_NUM: { union any_node *node = expr_allocate_number (e, tokval); lex_get (); diff --git a/src/file-type.c b/src/file-type.c index e549ae96..cf0a3725 100644 --- a/src/file-type.c +++ b/src/file-type.c @@ -435,7 +435,7 @@ cmd_record_type (void) { int mv = 0; - while (token == T_NUM || token == T_STRING) + while (lex_is_number () || token == T_STRING) { if (rct->nv >= mv) { diff --git a/src/frequencies.q b/src/frequencies.q index 50b11f37..fa380dea 100644 --- a/src/frequencies.q +++ b/src/frequencies.q @@ -868,7 +868,7 @@ frq_custom_grouped (struct cmd_frequencies *cmd UNUSED) { nl = ml = 0; dl = NULL; - while (token == T_NUM) + while (lex_integer ()) { if (nl >= ml) { diff --git a/src/lexer.c b/src/lexer.c index e573bbb7..f676375e 100644 --- a/src/lexer.c +++ b/src/lexer.c @@ -44,7 +44,7 @@ /* Current token. */ int token; -/* T_NUM: the token's value. */ +/* T_POS_NUM, T_NEG_NUM: the token's value. */ double tokval; /* T_ID: the identifier. */ @@ -224,8 +224,11 @@ lex_get (void) token = '-'; break; } + token = T_NEG_NUM; } - + else + token = T_POS_NUM; + /* Parse the number, copying it into tokstr. */ while (isdigit ((unsigned char) *prog)) ds_putc (&tokstr, *prog++); @@ -256,7 +259,6 @@ lex_get (void) ds_putc (&tokstr, '0'); } - token = T_NUM; break; } @@ -425,11 +427,27 @@ lex_end_of_command (void) /* Token testing functions. */ -/* Returns nonzero if the current token is an integer. */ -int -lex_integer_p (void) +/* Returns true if the current token is a number. */ +bool +lex_is_number (void) +{ + return token == T_POS_NUM || token == T_NEG_NUM; +} + +/* Returns the value of the current token, which must be a + floating point number. */ +double +lex_number (void) +{ + assert (lex_is_number ()); + return tokval; +} + +/* Returns true iff the current token is an integer. */ +bool +lex_is_integer (void) { - return (token == T_NUM + return (lex_is_number () && tokval != NOT_LONG && tokval >= LONG_MIN && tokval <= LONG_MAX @@ -441,26 +459,9 @@ lex_integer_p (void) long lex_integer (void) { - assert (lex_integer_p ()); + assert (lex_is_integer ()); return tokval; } -/* Returns nonzero if the current token is an floating point. */ -int -lex_double_p (void) -{ - return ( token == T_NUM - && tokval != NOT_DOUBLE ); -} - -/* Returns the value of the current token, which must be a - floating point number. */ -double -lex_double (void) -{ - assert (lex_double_p ()); - return tokval; -} - /* Token matching functions. */ @@ -498,7 +499,7 @@ lex_match_id (const char *s) int lex_match_int (int x) { - if (lex_integer_p () && lex_integer () == x) + if (lex_is_integer () && lex_integer () == x) { lex_get (); return 1; @@ -563,7 +564,7 @@ lex_force_string (void) int lex_force_int (void) { - if (lex_integer_p ()) + if (lex_is_integer ()) return 1; else { @@ -577,7 +578,7 @@ lex_force_int (void) int lex_force_num (void) { - if (token == T_NUM) + if (lex_is_number ()) return 1; else { @@ -877,7 +878,8 @@ lex_token_representation (void) switch (token) { case T_ID: - case T_NUM: + case T_POS_NUM: + case T_NEG_NUM: return xstrdup (ds_c_str (&tokstr)); break; @@ -952,9 +954,9 @@ lex_token_representation (void) void lex_negative_to_dash (void) { - if (token == T_NUM && tokval < 0.0) + if (token == T_NEG_NUM) { - token = T_NUM; + token = T_POS_NUM; tokval = -tokval; ds_replace (&tokstr, ds_c_str (&tokstr) + 1); save_token (); @@ -1216,7 +1218,8 @@ dump_token (void) fprintf (stderr, "ID\t%s\n", tokid); break; - case T_NUM: + case T_POS_NUM: + case T_NEG_NUM: fprintf (stderr, "NUM\t%f\n", tokval); break; diff --git a/src/lexer.h b/src/lexer.h index 00281281..3250704c 100644 --- a/src/lexer.h +++ b/src/lexer.h @@ -20,6 +20,8 @@ #if !lexer_h #define lexer_h 1 +#include "bool.h" + /* Returns nonzero if character CH may be the first character in an identifier. */ #define CHAR_IS_ID1(CH) \ @@ -41,7 +43,8 @@ enum { T_ID = 256, /* Identifier. */ - T_NUM, /* Number. */ + T_POS_NUM, /* Positive number. */ + T_NEG_NUM, /* Negative number. */ T_STRING, /* Quoted string. */ T_STOP, /* End of input. */ @@ -86,10 +89,10 @@ void lex_error (const char *, ...); int lex_end_of_command (void); /* Token testing functions. */ -int lex_integer_p (void); +bool lex_is_number (void); +double lex_number (void); +bool lex_is_integer (void); long lex_integer (void); -int lex_double_p (void); -double lex_double (void); /* Token matching functions. */ int lex_match (int); diff --git a/src/matrix-data.c b/src/matrix-data.c index a57680d8..e7747a89 100644 --- a/src/matrix-data.c +++ b/src/matrix-data.c @@ -394,7 +394,7 @@ cmd_matrix_data (void) goto lossage; } - if (!lex_integer_p () || lex_integer () < 1) + if (!lex_is_integer () || lex_integer () < 1) { lex_error (_("expecting positive integer")); goto lossage; @@ -413,7 +413,7 @@ cmd_matrix_data (void) goto lossage; } - if (!lex_integer_p () || lex_integer () < 1) + if (!lex_is_integer () || lex_integer () < 1) { lex_error (_("expecting positive integer")); goto lossage; diff --git a/src/mis-val.c b/src/mis-val.c index ce326255..6933f0ea 100644 --- a/src/mis-val.c +++ b/src/mis-val.c @@ -153,7 +153,7 @@ parse_num_or_range (struct num_or_range * nor) nor->d[0] = LOWEST; nor->d[1] = tokval; } - else if (token == T_NUM) + else if (lex_is_number ()) { nor->d[0] = tokval; lex_get (); diff --git a/src/moments.c b/src/moments.c index c4f3fe18..3890cbde 100644 --- a/src/moments.c +++ b/src/moments.c @@ -501,14 +501,14 @@ read_values (double **values, double **weights, size_t *cnt) *values = NULL; *weights = NULL; *cnt = 0; - while (token == T_NUM) + while (lex_is_number ()) { double value = tokval; double weight = 1.; lex_get (); if (lex_match ('*')) { - if (token != T_NUM) + if (!lex_is_number ()) { lex_error (_("expecting weight value")); return 0; diff --git a/src/print.c b/src/print.c index d8f4d770..8cb7b1d4 100644 --- a/src/print.c +++ b/src/print.c @@ -287,7 +287,7 @@ parse_specs (void) int prev_recno = fx.recno; fx.recno++; - if (token == T_NUM) + if (lex_is_number ()) { if (!lex_force_int ()) return 0; @@ -349,7 +349,7 @@ parse_string_argument (void) lex_get (); /* Parse the included column range. */ - if (token == T_NUM) + if (lex_is_number ()) { /* Width of column range in characters. */ int c_len; @@ -360,7 +360,7 @@ parse_string_argument (void) /* 1-based index of last column in range. */ int lc; - if (!lex_integer_p () || lex_integer () <= 0) + if (!lex_is_integer () || lex_integer () <= 0) { msg (SE, _("%g is not a valid column location."), tokval); goto fail; @@ -371,7 +371,7 @@ parse_string_argument (void) lex_negative_to_dash (); if (lex_match ('-')) { - if (!lex_integer_p ()) + if (!lex_is_integer ()) { msg (SE, _("Column location expected following `%d-'."), fx.spec.fc + 1); @@ -434,7 +434,7 @@ parse_variable_argument (void) if (!parse_variables (default_dict, &fx.v, &fx.nv, PV_DUPLICATE)) return 0; - if (token == T_NUM) + if (lex_is_number ()) { if (!fixed_parse_compatible ()) goto fail; @@ -553,7 +553,7 @@ fixed_parse_compatible (void) else fx.spec.u.v.f.type = FMT_F; - if (token == T_NUM) + if (lex_is_number ()) { if (!lex_force_int ()) return 0; @@ -727,9 +727,9 @@ fixed_parse_fortran (void) else head = fl = xmalloc (sizeof *fl); - if (token == T_NUM) + if (lex_is_number ()) { - if (!lex_integer_p ()) + if (!lex_is_integer ()) goto fail; fl->count = lex_integer (); lex_get (); diff --git a/src/q2c.c b/src/q2c.c index 37ec08f0..7af81865 100644 --- a/src/q2c.c +++ b/src/q2c.c @@ -1461,7 +1461,7 @@ dump_specifier_parse (const specifier *spec, const subcommand *sbc) if (s->value == VAL_INT) { - dump (1, "if (!lex_integer_p ())"); + dump (1, "if (!lex_is_integer ())"); dump (1, "{"); dump (0, "msg (SE, _(\"%s specifier of %s subcommand " "requires an integer argument.\"));", @@ -1473,7 +1473,7 @@ dump_specifier_parse (const specifier *spec, const subcommand *sbc) } else { - dump (1, "if (token != T_NUM)"); + dump (1, "if (!lex_is_number ())"); dump (1, "{"); dump (0, "msg (SE, _(\"Number expected after %s " "specifier of %s subcommand.\"));", @@ -1661,7 +1661,7 @@ dump_subcommand (const subcommand *sbc) { dump (1, "if (!lex_force_num ())"); dump (0, "goto lossage;"); - dump (-1, "p->n_%s[p->sbc_%s - 1] = lex_double ();", + dump (-1, "p->n_%s[p->sbc_%s - 1] = lex_number ();", st_lower (sbc->name), st_lower (sbc->name) ); dump (0, "lex_get();"); } @@ -1713,7 +1713,7 @@ dump_subcommand (const subcommand *sbc) dump (0, "goto lossage;"); dump (-1,"}"); - dump (0, "subc_list_double_push(&p->dl_%s[p->sbc_%s-1],lex_double ());", + dump (0, "subc_list_double_push(&p->dl_%s[p->sbc_%s-1],lex_number ());", st_lower (sbc->name),st_lower (sbc->name) ); diff --git a/src/recode.c b/src/recode.c index 034ae959..0a0aa61a 100644 --- a/src/recode.c +++ b/src/recode.c @@ -445,7 +445,7 @@ parse_dest_spec (struct rcd_var * rcd, union value * v, size_t *max_dst_width) v->c = NULL; - if (token == T_NUM) + if (lex_is_number ()) { v->f = tokval; lex_get (); @@ -540,7 +540,7 @@ parse_src_spec (struct rcd_var * rcd, int type, size_t max_src_width) return 0; if (lex_match_id ("HI") || lex_match_id ("HIGHEST")) c->type = RCD_ELSE; - else if (token == T_NUM) + else if (lex_is_number ()) { c->type = RCD_LOW; c->f1.f = tokval; @@ -568,7 +568,7 @@ parse_src_spec (struct rcd_var * rcd, int type, size_t max_src_width) return 0; } } - else if (token == T_NUM) + else if (lex_is_number ()) { c->f1.f = tokval; lex_get (); @@ -576,7 +576,7 @@ parse_src_spec (struct rcd_var * rcd, int type, size_t max_src_width) { if (lex_match_id ("HI") || lex_match_id ("HIGHEST")) c->type = RCD_HIGH; - else if (token == T_NUM) + else if (lex_is_number ()) { c->type = RCD_RANGE; c->f2.f = tokval; diff --git a/src/repeat.c b/src/repeat.c index 3b57b66a..4a5bf2f9 100644 --- a/src/repeat.c +++ b/src/repeat.c @@ -169,7 +169,7 @@ internal_cmd_do_repeat (void) if (token == T_ID) result = parse_ids (e); - else if (token == T_NUM) + else if (lex_is_number ()) result = parse_numbers (e); else if (token == T_STRING) result = parse_strings (e); diff --git a/src/sample.c b/src/sample.c index 96c5f4d9..11e4ad66 100644 --- a/src/sample.c +++ b/src/sample.c @@ -62,7 +62,7 @@ cmd_sample (void) if (!lex_force_num ()) return CMD_FAILURE; - if (!lex_integer_p ()) + if (!lex_is_integer ()) { unsigned long min = gsl_rng_min (get_rng ()); unsigned long max = gsl_rng_max (get_rng ()); diff --git a/src/set.q b/src/set.q index c7d22771..fdb2d309 100644 --- a/src/set.q +++ b/src/set.q @@ -650,7 +650,7 @@ stc_custom_epoch (struct cmd_set *cmd UNUSED) lex_match ('='); if (lex_match_id ("AUTOMATIC")) set_epoch = -1; - else if (lex_integer_p ()) + else if (lex_is_integer ()) { int new_epoch = lex_integer (); lex_get (); diff --git a/src/val-labs.c b/src/val-labs.c index 1cc7b84c..35158b77 100644 --- a/src/val-labs.c +++ b/src/val-labs.c @@ -158,12 +158,12 @@ get_label (struct variable **vars, int var_cnt) } else { - if (token != T_NUM) + if (!lex_is_number ()) { lex_error (_("expecting integer")); return 0; } - if (!lex_integer_p ()) + if (!lex_is_integer ()) msg (SW, _("Value label `%g' is not integer."), tokval); value.f = tokval; } diff --git a/tests/ChangeLog b/tests/ChangeLog index bf2e3462..3e97048a 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,7 @@ +Sun Mar 6 17:56:27 2005 Ben Pfaff + + * expressions/expressions.sh: Add tests for generic optimizations. + Sun Mar 6 11:03:58 2005 Ben Pfaff * Makefile.am: Add expressions/variables.sh. Remove expr.stat. diff --git a/tests/expressions/expressions.sh b/tests/expressions/expressions.sh index 4ddb5537..4cac5571 100755 --- a/tests/expressions/expressions.sh +++ b/tests/expressions/expressions.sh @@ -1273,6 +1273,20 @@ SYSMIS($SYSMIS) => true SYSMIS(1 + $SYSMIS) => true # FIXME: out-of-range and nearly out-of-range values on dates + +# Tests correctness of generic optimizations in optimize_tree(). +(X = 10.00); x + 0 => 10.00 +(X = -3.00); x - 0 => -3.00 +(X = 5.00); 0 + x => 5.00 +(X = 10.00); x * 1 => 10.00 +(X = -3.00); 1 * x => -3.00 +(X = 5.00); x / 1 => 5.00 +(X = 10.00); 0 * x => 0.00 +(X = -3.00); x * 0 => 0.00 +(X = 5.00); 0 / x => 0.00 +(X = 5.00); mod(0, x) => 0.00 +(X = 5.00); x ** 1 => 5.00 +(X = 5.00); x ** 2 => 25.00 EOF if [ $? -ne 0 ] ; then no_result ; fi -- 2.30.2