tests
authorBen Pfaff <blp@cs.stanford.edu>
Fri, 24 Dec 2021 21:10:34 +0000 (13:10 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Fri, 24 Dec 2021 21:10:34 +0000 (13:10 -0800)
src/language/expressions/evaluate.c
src/language/expressions/operations.def
src/language/expressions/parse.c
tests/language/expressions/evaluate.at

index bdd21e1dbe97ae98579ba1f5d24372b14ac34b06..9c809fac4cd22bc3d5950bd990aa118371bb6921 100644 (file)
@@ -127,9 +127,10 @@ cmd_debug_evaluate (struct lexer *lexer, struct dataset *dsother UNUSED)
 
   struct expression *expr;
 
+  struct dictionary *d = NULL;
+
   for (;;)
     {
-      struct dictionary *d = NULL;
       if (lex_match_id (lexer, "NOOPTIMIZE"))
         optimize = false;
       else if (lex_match_id (lexer, "OPTIMIZE"))
@@ -141,7 +142,6 @@ cmd_debug_evaluate (struct lexer *lexer, struct dataset *dsother UNUSED)
       else if (lex_match (lexer, T_LPAREN))
         {
           struct variable *v;
-          int width;
 
           if (!lex_force_id (lexer))
             goto done;
@@ -151,10 +151,25 @@ cmd_debug_evaluate (struct lexer *lexer, struct dataset *dsother UNUSED)
           if (!lex_force_match (lexer, T_EQUALS))
             goto done;
 
+          union value value;
+          int width;
           if (lex_is_number (lexer))
-            width = 0;
+            {
+              width = 0;
+              value.f = lex_number (lexer);
+              lex_get (lexer);
+            }
+          else if (lex_match_id (lexer, "SYSMIS"))
+            {
+              width = 0;
+              value.f = SYSMIS;
+            }
           else if (lex_is_string (lexer))
-            width = ss_length (lex_tokss (lexer));
+            {
+              width = ss_length (lex_tokss (lexer));
+              value.s = CHAR_CAST (uint8_t *, ss_xstrdup (lex_tokss (lexer)));
+              lex_get (lexer);
+            }
           else
             {
               lex_error (lexer, _("expecting number or string"));
@@ -171,6 +186,7 @@ cmd_debug_evaluate (struct lexer *lexer, struct dataset *dsother UNUSED)
           if (v == NULL)
             {
               msg (SE, _("Duplicate variable name %s."), name);
+              value_destroy (&value, width);
               goto done;
             }
           free (name);
@@ -181,12 +197,28 @@ cmd_debug_evaluate (struct lexer *lexer, struct dataset *dsother UNUSED)
           else
             c = case_unshare_and_resize (c, dict_get_proto (d));
 
-          if (!parse_value (lexer, case_data_rw (c, v), v))
-            NOT_REACHED ();
+          *case_data_rw (c, v) = value;
+
+          if (lex_match_id (lexer, "MISSING"))
+            {
+              struct missing_values mv;
+              mv_init (&mv, width);
+              mv_add_value (&mv, &value);
+              var_set_missing_values (v, &mv);
+              mv_destroy (&mv);
+            }
 
           if (!lex_force_match (lexer, T_RPAREN))
             goto done;
         }
+      else if (lex_match_id (lexer, "VECTOR"))
+        {
+          struct variable **vars;
+          size_t n;
+          dict_get_vars_mutable (d, &vars, &n, 0);
+          dict_create_vector_assert (d, "V", vars, n);
+          free (vars);
+        }
       else
         break;
     }
index 5c70ca00c18d6fc4f30634be5687961b902de7e1..e1132a5bc998ac44f40c1e406a3a004b051e014e 100644 (file)
@@ -1098,7 +1098,7 @@ no_opt boolean function SYSMIS (num_var v)
 {
   return case_num (c, v) == SYSMIS;
 }
-no_opt boolean function VALUE (num_var v)
+no_opt function VALUE (num_var v)
      case c;
 {
   return case_num (c, v);
index 8b62c92c4e4259e5df7a4d98d3ebfc3f1a7f781f..da027b5e7afa1e3610a1fda91979428f1789095b 100644 (file)
@@ -468,6 +468,7 @@ type_coercion__ (struct expression *e, struct expr_node *node, size_t arg_idx,
       break;
 
     case OP_format:
+      /* We never coerce to OP_format, only to OP_ni_format or OP_no_format. */
       NOT_REACHED ();
 
     case OP_ni_format:
index 87d480de035a23196ca8472f3adccfffb2f2e268..cf0fdd0783442f0c082fc0450a68ba6a26861602 100644 (file)
@@ -1554,6 +1554,49 @@ TAN('x') => error
 done
 AT_CLEANUP
 
+AT_SETUP([expressions - MISSING NMISS NVALID SYSMIS ANY RANGE MAX MIN])
+AT_KEYWORDS([expression expressions evaluate])
+AT_DATA([evaluate-base.sps], [
+DEBUG EVALUATE SET opt.
+DEBUG EVALUATE /MISSING(10).
+DEBUG EVALUATE /MISSING($SYSMIS).
+DEBUG EVALUATE /MISSING(ASIN(1.01)).
+DEBUG EVALUATE /MISSING(ASIN(.5)).
+DEBUG EVALUATE /MISSING('    ').
+
+DEBUG EVALUATE (x=5)/x.
+DEBUG EVALUATE (x=5 MISSING)/x.
+DEBUG EVALUATE (x=SYSMIS)/x.
+
+DEBUG EVALUATE (x=5) VECTOR/v(1).
+DEBUG EVALUATE (x=5 MISSING) VECTOR/v(1).
+DEBUG EVALUATE (x=SYSMIS) VECTOR/v(1).
+
+DEBUG EVALUATE (x=5)/VALUE(x).
+DEBUG EVALUATE (x=5 MISSING)/VALUE(x).
+DEBUG EVALUATE (x=SYSMIS)/VALUE(x).
+
+DEBUG EVALUATE (x=5) VECTOR/VALUE(v(1)).
+DEBUG EVALUATE (x=5 MISSING) VECTOR/VALUE(v(1)).
+DEBUG EVALUATE (x=SYSMIS) VECTOR/VALUE(v(1)).
+
+DEBUG EVALUATE (x=5)/MISSING(x).
+DEBUG EVALUATE (x=5 MISSING)/MISSING(x).
+DEBUG EVALUATE (x=SYSMIS)/MISSING(x).
+
+DEBUG EVALUATE (x=5)/SYSMIS(x).
+DEBUG EVALUATE (x=5 MISSING)/SYSMIS(x).
+DEBUG EVALUATE (x=SYSMIS)/SYSMIS(x).
+])
+
+for opt in OPT NOOPT; do
+    AS_BOX([$opt])
+    sed "s/opt/$opt/" < evaluate-base.sps > evaluate.sps
+    AT_CHECK([pspp --testing-mode evaluate.sps], [1], [dnl
+])
+done
+AT_CLEANUP
+
 # FIXME: a variable name as the argument to SYSMIS is a special case
 # that we don't yet test.  We also can't test VALUE this way.
 CHECK_EXPR_EVAL([missing nmiss nvalid sysmis any range max min],