Add even more expression tests and fix the bugs they found.
authorBen Pfaff <blp@gnu.org>
Mon, 7 Mar 2005 03:04:50 +0000 (03:04 +0000)
committerBen Pfaff <blp@gnu.org>
Mon, 7 Mar 2005 03:04:50 +0000 (03:04 +0000)
25 files changed:
src/ChangeLog
src/aggregate.c
src/count.c
src/data-list.c
src/examine.q
src/expressions/ChangeLog
src/expressions/evaluate.c
src/expressions/optimize.c
src/expressions/parse.c
src/file-type.c
src/frequencies.q
src/lexer.c
src/lexer.h
src/matrix-data.c
src/mis-val.c
src/moments.c
src/print.c
src/q2c.c
src/recode.c
src/repeat.c
src/sample.c
src/set.q
src/val-labs.c
tests/ChangeLog
tests/expressions/expressions.sh

index 7e49e91fd830aef65c4a1fbc32b43c5221162334..281bcaebd440d6a23cdb79179d1134099b27fbc8 100644 (file)
@@ -1,3 +1,30 @@
+Sun Mar  6 17:07:20 2005  Ben Pfaff  <blp@gnu.org>
+
+       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 <john@darrington.wattle.id.au>
 
        * Makefile.am : Fixed up CLEANFILES target.
index a2569837eea9d5e3c0cca06d30262f5b5276a104..3037a150fbb07e92dea17ec284b42302d042a19b 100644 (file)
@@ -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;
index 35021f09e3589d8055c240d528711dcb0ef73d5f..af9642b8a233d2cb65bb914737cd391a417089da 100644 (file)
@@ -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;
index eb491d1d9dd72e0f50c19300b50a142e4550bc74..9d935609f41d09c5136f01045225642188b314e9 100644 (file)
@@ -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;
index 96d8210da59d3341fe176215e65521c23c0bc113..e35c7049c800fc3698db43168ecc50d80afcd50a 100644 (file)
@@ -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();
 
index 73c619ca2d26105ab58613475ef17ae32fda52e8..94063e7acff932707325824c90c03b1bd3ca94f4 100644 (file)
@@ -1,3 +1,15 @@
+Sun Mar  6 17:51:05 2005  Ben Pfaff  <blp@gnu.org>
+
+       * 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  <blp@gnu.org>
 
        * operations.def: Add VALUE function.
index c2868429b246b6f9dc06d5d739b0629ce80c01e3..7f066a50df025cbcc4d0a27c654a3dfc009a8559 100644 (file)
@@ -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);
index 268141627e7cf98031627e0e2d7f7c2256336d33..5432e9ab938d9479e8ec91a1e71b43a7dbe5ba76 100644 (file)
@@ -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
index b1998f63c8f89daa5ea41456ad4c0bba80659de9..5e917a0e80386e65b936078ebe6090175b7dfb7f 100644 (file)
@@ -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 ();
index e549ae9693a3ae42490130562bd33d16f27c6f45..cf0a3725673c2495ce7a6831a99f91ae847085aa 100644 (file)
@@ -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)
            {
index 50b11f37d00d22768f3825d0e166bfa59006f602..fa380dea0fef49b18a78a4b94b93da1f483a6759 100644 (file)
@@ -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)
                  {
index e573bbb7818f9b3cce8d07fe9edd9b930c8936bc..f676375e9409ac4478ec8bf5e5c333277a90a888 100644 (file)
@@ -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)
 \f
 /* 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;
-}
-
 \f  
 /* 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;
 
index 0028128167557fd0b07fb0ac8bc92609df1171a8..3250704ca73055f81a43e195386ff8619d895b62 100644 (file)
@@ -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);
index a57680d841e9174f44556361801d10074bd3f836..e7747a89324fc8f8ab7f9f2bd854ac025471281d 100644 (file)
@@ -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;
index ce32625532c00d69b541472270d8b2fa021850a9..6933f0ea029b54eed1b0c8c0d6c4e78d1f31c1fa 100644 (file)
@@ -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 ();
index c4f3fe18db76573a38c5a8869540f64a0a6aa19a..3890cbde441d83867c319c3b2a256c6a0bad274c 100644 (file)
@@ -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;
index d8f4d77040834a375d9fa31bdb16734b99137abc..8cb7b1d432d92f2bac609ad108d9c6a0894ef899 100644 (file)
@@ -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 ();
index 37ec08f033093d74f203c9560767df9032105175..7af81865ad663b4808aea707976b7b4223979156 100644 (file)
--- 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)
            );
 
index 034ae959e83c2bd7aa02e5c2bbfd26b3fd954aa4..0a0aa61aa93ad48db79d487ac1430373ef4871b7 100644 (file)
@@ -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;
index 3b57b66a7398db1b391e5cadc38eb8daa1e76faf..4a5bf2f9dc1a983c8edd235b547082441a2b6012 100644 (file)
@@ -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);
index 96c5f4d9070705fadd7cebb297753aaec9ebd91b..11e4ad66e64dd4c536478ba33dc119669ef053fc 100644 (file)
@@ -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 ());
index c7d22771ac35c2cac07cbe243940b3571a3fb250..fdb2d30949e1e6e2d3fb96f7c59b773ea53fdaf8 100644 (file)
--- 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 ();
index 1cc7b84c7c8fb3b07de654e950f2f0273e9da736..35158b7754954f17c6c72b28f414817b89dc2c64 100644 (file)
@@ -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;
        }
index bf2e3462bea9cfcc8f93d251e5bcb03e82a43c10..3e97048a86a2f84f766f06c1a8ca69ba29ff3adc 100644 (file)
@@ -1,3 +1,7 @@
+Sun Mar  6 17:56:27 2005  Ben Pfaff  <blp@gnu.org>
+
+       * expressions/expressions.sh: Add tests for generic optimizations.
+
 Sun Mar  6 11:03:58 2005  Ben Pfaff  <blp@gnu.org>
 
        * Makefile.am: Add expressions/variables.sh.  Remove expr.stat.
index 4ddb5537a0e608ac34a462a2feaa1f954ab2020a..4cac5571bd75550b98afa771c7425a33e9530306 100755 (executable)
@@ -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