From dfa34c1a553605d6f72f8a7c35f0aaa935201516 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Fri, 24 Dec 2021 12:07:37 -0800 Subject: [PATCH] expression tests --- src/language/expressions/helpers.h | 1 + src/language/expressions/operations.def | 22 +- src/language/expressions/parse.c | 24 +- tests/language/expressions/evaluate.at | 1576 ++++++++++++++++++----- 4 files changed, 1255 insertions(+), 368 deletions(-) diff --git a/src/language/expressions/helpers.h b/src/language/expressions/helpers.h index 69c5ad348d..9c966cc15b 100644 --- a/src/language/expressions/helpers.h +++ b/src/language/expressions/helpers.h @@ -39,6 +39,7 @@ along with this program. If not, see . #include "data/variable.h" #include "data/vector.h" #include "language/expressions/public.h" +#include "libpspp/assertion.h" #include "libpspp/compiler.h" #include "libpspp/i18n.h" #include "libpspp/message.h" diff --git a/src/language/expressions/operations.def b/src/language/expressions/operations.def index 7360f426c1..5c70ca00c1 100644 --- a/src/language/expressions/operations.def +++ b/src/language/expressions/operations.def @@ -778,9 +778,25 @@ absorb_miss boolean operator OPERAND_TO_BOOLEAN (x, expr_node parent) if (x == 0. || x == 1. || x == SYSMIS) return x; - msg_at (SE, expr_location (e, parent), - _("The operands of %s must have value 0 or 1."), - operations[parent->type].name); + switch (parent->n_args) + { + case 2: + msg_at (SE, expr_location (e, parent), + /* TRANSLATORS: There are exactly two operands. */ + _("The operands of %s must have value 0 or 1."), + operations[parent->type].name); + break; + + case 1: + msg_at (SE, expr_location (e, parent), + _("The operand of %s must have value 0 or 1."), + operations[parent->type].name); + break; + + default: + NOT_REACHED (); + } + msg_at (SN, expr_location (e, n), _("This operand with unexpected value %g will be treated as 0."), x); return 0.; diff --git a/src/language/expressions/parse.c b/src/language/expressions/parse.c index 5a81f6bd3e..8b62c92c4e 100644 --- a/src/language/expressions/parse.c +++ b/src/language/expressions/parse.c @@ -730,8 +730,7 @@ parse_rel (struct lexer *lexer, struct expression *e) "not produce the mathematically expected result. " "Use the AND logical operator to fix the problem " "(e.g. `a < b AND b < c'). " - "If chaining is really intended, parentheses will disable " - "this warning (e.g. `(a < b) < c'.)"); + "To disable this warning, insert parentheses."); static const struct operator ops[] = { @@ -792,7 +791,7 @@ parse_exp (struct lexer *lexer, struct expression *e) const char *chain_warning = _("The exponentiation operator (`**') is left-associative: " - "`a**b**c' equals `(a**b)**c', not as `a**(b**c)'. " + "`a**b**c' equals `(a**b)**c', not `a**(b**c)'. " "To disable this warning, insert parentheses."); if (lex_token (lexer) != T_NEG_NUM || lex_next_token (lexer, 1) != T_EXP) @@ -805,6 +804,7 @@ parse_exp (struct lexer *lexer, struct expression *e) int start_ofs = lex_ofs (lexer); struct expr_node *lhs = expr_allocate_number (e, -lex_tokval (lexer)); lex_get (lexer); + expr_add_location (lexer, e, start_ofs, lhs); struct expr_node *node = parse_binary_operators__ ( lexer, e, &op, 1, parse_primary, chain_warning, lhs); @@ -977,23 +977,9 @@ parse_primary__ (struct lexer *lexer, struct expression *e) case T_LPAREN: { - /* Count number of left parentheses so that we can match them against - an equal number of right parentheses. This defeats trivial attempts - to exhaust the stack with a lot of left parentheses. (More - sophisticated attacks will still succeed.) */ - size_t n = 0; - while (lex_match (lexer, T_LPAREN)) - n++; - + lex_get (lexer); struct expr_node *node = parse_or (lexer, e); - if (!node) - return NULL; - - for (size_t i = 0; i < n; i++) - if (!lex_force_match (lexer, T_RPAREN)) - return NULL; - - return node; + return !node || !lex_force_match (lexer, T_RPAREN) ? NULL : node; } default: diff --git a/tests/language/expressions/evaluate.at b/tests/language/expressions/evaluate.at index 8af9d3ca4d..87d480de03 100644 --- a/tests/language/expressions/evaluate.at +++ b/tests/language/expressions/evaluate.at @@ -61,13 +61,15 @@ AT_BANNER([expressions]) AT_SETUP([expressions - numeric syntax]) AT_KEYWORDS([expression expressions evaluate]) AT_DATA([evaluate-base.sps], [ -DEBUG EVALUATE opt/1e2. -DEBUG EVALUATE opt/1e+2. -DEBUG EVALUATE opt/1e-2. -DEBUG EVALUATE opt/1e-99. +DEBUG EVALUATE SET opt. +DEBUG EVALUATE /1e2. +DEBUG EVALUATE /1e+2. +DEBUG EVALUATE /1e-2. +DEBUG EVALUATE /1e-99. ]) -for opt in '' 'NOOPT '; do +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], [0], [dnl 1e2 => 100.00 @@ -94,6 +96,7 @@ DEBUG EVALUATE/1 AND 3. ]) 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 0 AND 1 => false @@ -154,6 +157,7 @@ DEBUG EVALUATE /F2.0 + 3. ]) 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 1 + $true => 2.00 @@ -270,6 +274,7 @@ DEBUG EVALUATE /2 / '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 5 * 10 => 50.00 @@ -325,351 +330,1230 @@ evaluate.sps:15.21-15.23: note: DEBUG EVALUATE: This operand has type 'string'. done AT_CLEANUP -CHECK_EXPR_EVAL([exponentiation], - [[2**8], [256.00]], - [[(2**3)**4], [4096.00]], - [[2**3**4], [4096.00], - [warning: DEBUG EVALUATE: The exponentiation operator (`**') is left-associative, even though right-associative semantics are more useful. That is, `a**b**c' equals `(a**b)**c', not as `a**(b**c)'. To disable this warning, insert parentheses.]]) - -CHECK_EXPR_EVAL([unary minus], - [[2+-3], [-1.00]], - [[2*-3], [-6.00]], - [[-3**2], [-9.00]], - [[(-3)**2], [9.00]], - [[2**-1], [0.50]], - [[0**0], [sysmis]], - [[0**-1], [sysmis]], - [[(-3)**1.5], [sysmis]]) - -CHECK_EXPR_EVAL([AND truth table], - [[$false AND $false], [false]], - [[$false AND $true], [false]], - [[$false AND $sysmis], [false]], - [[$true AND $false], [false]], - [[$true AND $true], [true]], - [[$true AND $sysmis], [sysmis]], - [[$sysmis AND $false], [false]], - [[$sysmis AND $true], [sysmis]], - [[$sysmis AND $sysmis], [sysmis]], - [[$false & $false], [false]], - [[$false & $true], [false]], - [[$false & $sysmis], [false]], - [[$true & $false], [false]], - [[$true & $true], [true]], - [[$true & $sysmis], [sysmis]], - [[$sysmis & $false], [false]], - [[$sysmis & $true], [sysmis]], - [[$sysmis & $sysmis], [sysmis]]) - -CHECK_EXPR_EVAL([OR truth table], - [[$false OR $false], [false]], - [[$false OR $true], [true]], - [[$false OR $sysmis], [sysmis]], - [[$true OR $false], [true]], - [[$true OR $true], [true]], - [[$true OR $sysmis], [true]], - [[$sysmis OR $false], [sysmis]], - [[$sysmis OR $true], [true]], - [[$sysmis OR $sysmis], [sysmis]], - [[$false | $false], [false]], - [[$false | $true], [true]], - [[$false | $sysmis], [sysmis]], - [[$true | $false], [true]], - [[$true | $true], [true]], - [[$true | $sysmis], [true]], - [[$sysmis | $false], [sysmis]], - [[$sysmis | $true], [true]], - [[$sysmis | $sysmis], [sysmis]]) - -CHECK_EXPR_EVAL([NOT truth table], - [[not $false], [true]], - [[not 0], [true]], - [[not 2.5], [true], - [error: DEBUG EVALUATE: An operand of the logical negation (`NOT') operator was found to have a value other than 0 (false), 1 (true), or the system-missing value. The result was forced to 0.]], - [[not $true], [false]], - [[not 1], [false]], - [[not $sysmis], [sysmis]], - [[~ $false], [true]], - [[~ 0], [true]], - [[~ 2.5], [true], - [error: DEBUG EVALUATE: An operand of the logical negation (`NOT') operator was found to have a value other than 0 (false), 1 (true), or the system-missing value. The result was forced to 0.]], - [[~ $true], [false]], - [[~ 1], [false]], - [[~ $sysmis], [sysmis]]) - -CHECK_EXPR_EVAL([= <= <], - [[1 eq 1], [true]], - [[1 = 1], [true]], - [[1 eq 2], [false]], - [[2 = 3], [false]], - [[1 eq 'foobar'], [error], - [error: DEBUG EVALUATE: Type mismatch while applying numeric equality (`EQ') operator: cannot convert string to number.]], - [[5 eq 'foobar'], [error], - [error: DEBUG EVALUATE: Type mismatch while applying numeric equality (`EQ') operator: cannot convert string to number.]], - [['baz' = 10], [error], - [error: DEBUG EVALUATE: Type mismatch while applying string equality (`=') operator: cannot convert number to string.]], - [['quux' = 5.55], [error], - [error: DEBUG EVALUATE: Type mismatch while applying string equality (`=') operator: cannot convert number to string.]], - [['foobar' = 'foobar'], [true]], - [['quux' = 'bar'], [false]], - [['bar ' = 'bar'], [true]], - [['asdf ' = 'asdf '], [true]], - [['asdfj ' = 'asdf'], [false]], -dnl Check precedence: - [[1 + 2 = 3], [true]], - [[1 >= 2 = 2 ge 3], [false], - [warning: DEBUG EVALUATE: Chaining relational operators (e.g. `a < b < c') will not produce the mathematically expected result. Use the AND logical operator to fix the problem (e.g. `a < b AND b < c'). If chaining is really intended, parentheses will disable this warning (e.g. `(a < b) < c'.)]], -dnl Mathematically true: - [[3 ne 2 ~= 1], [false], - [warning: DEBUG EVALUATE: Chaining relational operators (e.g. `a < b < c') will not produce the mathematically expected result. Use the AND logical operator to fix the problem (e.g. `a < b AND b < c'). If chaining is really intended, parentheses will disable this warning (e.g. `(a < b) < c'.)]], - [[3 > 2 > 1], [false], - [warning: DEBUG EVALUATE: Chaining relational operators (e.g. `a < b < c') will not produce the mathematically expected result. Use the AND logical operator to fix the problem (e.g. `a < b AND b < c'). If chaining is really intended, parentheses will disable this warning (e.g. `(a < b) < c'.)]], - - [[1 <= 2], [true]], - [[2.5 <= 1.5], [false]], - [[1 le 2], [true]], - [[2 <= 2], [true]], - [[2 le 2], [true]], -dnl Make sure <= token can't be split: - [[2 < = 2], [error], - [error: DEBUG EVALUATE: Syntax error at `='.]], - [[1 <= 'foobar'], [error], - [error: DEBUG EVALUATE: Type mismatch while applying numeric less-than-or-equal-to (`<=') operator: cannot convert string to number.]], - [[5 <= 'foobar'], [error], - [error: DEBUG EVALUATE: Type mismatch while applying numeric less-than-or-equal-to (`<=') operator: cannot convert string to number.]], - [['baz' <= 10], [error], - [error: DEBUG EVALUATE: Type mismatch while applying string less-than-or-equal-to (`<=') operator: cannot convert number to string.]], - [['quux' <= 5.55], [error], - [error: DEBUG EVALUATE: Type mismatch while applying string less-than-or-equal-to (`<=') operator: cannot convert number to string.]], - [['0123' <= '0123'], [true]], - [['0123' <= '0124'], [true]], - [['0124' le '0123'], [false]], - [['0123 ' <= '0123'], [true]], - [['0123' le '0123 '], [true]], - - [[1 < 2], [true]], - [[2.5 < 1.5], [false]], - [[3.5 lt 4], [true]], - [[4 lt 3.5], [false]], - [[1 lt 'foobar'], [error], - [error: DEBUG EVALUATE: Type mismatch while applying numeric less than (`<') operator: cannot convert string to number.]], - [[5 lt 'foobar'], [error], - [error: DEBUG EVALUATE: Type mismatch while applying numeric less than (`<') operator: cannot convert string to number.]], - [['baz' < 10], [error], - [error: DEBUG EVALUATE: Type mismatch while applying string less than (`<') operator: cannot convert number to string.]], - [['quux' < 5.55], [error], - [error: DEBUG EVALUATE: Type mismatch while applying string less than (`<') operator: cannot convert number to string.]], - [['0123' lt '0123'], [false]], - [['0123' < '0124'], [true]], - [['0124' lt '0123'], [false]], - [['0123 ' < '0123'], [false]], - [['0123' lt '0123 '], [false]]) - -CHECK_EXPR_EVAL([>= > <>], - [[1 >= 2], [false]], - [[2.5 >= 1.5], [true]], - [[1 ge 2], [false]], - [[2 >= 2], [true]], - [[2 ge 2], [true]], -dnl Make sure >= token can't be split: - [[2 > = 2], [error], - [error: DEBUG EVALUATE: Syntax error at `='.]], - [[1 >= 'foobar'], [error], - [error: DEBUG EVALUATE: Type mismatch while applying numeric greater-than-or-equal-to (`>=') operator: cannot convert string to number.]], - [[5 ge 'foobar'], [error], - [error: DEBUG EVALUATE: Type mismatch while applying numeric greater-than-or-equal-to (`>=') operator: cannot convert string to number.]], - [['baz' ge 10], [error], - [error: DEBUG EVALUATE: Type mismatch while applying string greater-than-or-equal-to (`>=') operator: cannot convert number to string.]], - [['quux' >= 5.55], [error], - [error: DEBUG EVALUATE: Type mismatch while applying string greater-than-or-equal-to (`>=') operator: cannot convert number to string.]], - [['0123' ge '0123'], [true]], - [['0123' >= '0124'], [false]], - [['0124' >= '0123'], [true]], - [['0123 ' ge '0123'], [true]], - [['0123' >= '0123 '], [true]], - - [[1 > 2], [false]], - [[2.5 > 1.5], [true]], - [[3.5 gt 4], [false]], - [[4 gt 3.5], [true]], - [[1 gt 'foobar'], [error], - [error: DEBUG EVALUATE: Type mismatch while applying numeric greater than (`>') operator: cannot convert string to number.]], - [[5 gt 'foobar'], [error], - [error: DEBUG EVALUATE: Type mismatch while applying numeric greater than (`>') operator: cannot convert string to number.]], - [['baz' > 10], [error], - [error: DEBUG EVALUATE: Type mismatch while applying string greater than (`>') operator: cannot convert number to string.]], - [['quux' > 5.55], [error], - [error: DEBUG EVALUATE: Type mismatch while applying string greater than (`>') operator: cannot convert number to string.]], - [['0123' gt '0123'], [false]], - [['0123' > '0124'], [false]], - [['0124' gt '0123'], [true]], - [['0123 ' > '0123'], [false]], - [['0123' gt '0123 '], [false]], - - [[1 ne 1], [false]], - [[1 ~= 1], [false]], - [[1 <> 2], [true]], - [[2 ne 3], [true]], - [[1 ~= 'foobar'], [error], - [error: DEBUG EVALUATE: Type mismatch while applying numeric inequality (`<>') operator: cannot convert string to number.]], - [[5 <> 'foobar'], [error], - [error: DEBUG EVALUATE: Type mismatch while applying numeric inequality (`<>') operator: cannot convert string to number.]], - [['baz' ne 10], [error], - [error: DEBUG EVALUATE: Type mismatch while applying string inequality (`<>') operator: cannot convert number to string.]], - [['quux' ~= 5.55], [error], - [error: DEBUG EVALUATE: Type mismatch while applying string inequality (`<>') operator: cannot convert number to string.]], - [['foobar' <> 'foobar'], [false]], - [['quux' ne 'bar'], [true]], - [['bar ' <> 'bar'], [false]], - [['asdf ' ~= 'asdf '], [false]], - [['asdfj ' ne 'asdf'], [true]], -dnl <> token can't be split: - [[1 < > 1], [error], - [error: DEBUG EVALUATE: Syntax error at `>'.]], -dnl # ~= token can't be split: - [[1 ~ = 1], [error], - [error: DEBUG EVALUATE: Syntax error at `~': expecting end of command.]]) - -CHECK_EXPR_EVAL([exp lg10 ln sqrt abs mod mod10 rnd trunc], - [[exp(10)], [22026.47]], - [[exp('x')], [error], - [error: DEBUG EVALUATE: Type mismatch invoking EXP(number) as exp(string).]], - - [[lg10(500)], [2.70]], - [[lg10('x')], [error], - [error: DEBUG EVALUATE: Type mismatch invoking LG10(number) as lg10(string).]], - - [[ln(10)], [2.30]], - [[ln('x')], [error], - [error: DEBUG EVALUATE: Type mismatch invoking LN(number) as ln(string).]], - - [[sqrt(500)], [22.36]], - [[sqrt('x')], [error], - [error: DEBUG EVALUATE: Type mismatch invoking SQRT(number) as sqrt(string).]], - - [[abs(-10.5)], [10.50]], - [[abs(-55.79)], [55.79]], - [[abs(22)], [22.00]], - [[abs(0)], [0.00]], - - [[mod(55.5, 2)], [1.50]], - [[mod(-55.5, 2)], [-1.50]], - [[mod(55.5, -2)], [1.50]], - [[mod(-55.5, -2)], [-1.50]], - [[mod('a', 2)], [error], - [error: DEBUG EVALUATE: Type mismatch invoking MOD(number, number) as mod(string, number).]], - [[mod(2, 'a')], [error], - [error: DEBUG EVALUATE: Type mismatch invoking MOD(number, number) as mod(number, string).]], - [[mod('a', 'b')], [error], - [error: DEBUG EVALUATE: Type mismatch invoking MOD(number, number) as mod(string, string).]], - - [[mod10(55.5)], [5.50]], - [[mod10(-55.5)], [-5.50]], - [[mod10('x')], [error], - [error: DEBUG EVALUATE: Type mismatch invoking MOD10(number) as mod10(string).]], - - [[rnd(5.4)], [5.00]], - [[rnd(5.6)], [6.00]], - [[rnd(-5.4)], [-5.00]], - [[rnd(-5.6)], [-6.00]], - [[rnd(5.56, .1)], [5.60]], - [[rnd(-5.56, .1)], [-5.60]], - [[rnd(.5)], [1.00]], - [[rnd(.5 - 2**-53)], [1.00]], - [[rnd(.5 - 2**-52)], [1.00]], - [[rnd(.5 - 2**-51)], [1.00]], - [[rnd(.5 - 2**-45)], [0.00]], - [[rnd(.5 - 2**-45, 1, 10)], [1.00]], - [[rnd('x')], [error], - [error: DEBUG EVALUATE: Function invocation rnd(string) does not match any known function. Candidates are: +AT_SETUP([expressions - exponentiation]) +AT_KEYWORDS([expression expressions evaluate]) +AT_DATA([evaluate-base.sps], [ +DEBUG EVALUATE SET opt. +DEBUG EVALUATE /2**8. +DEBUG EVALUATE /(2**3)**4. +DEBUG EVALUATE /2**3**4. +DEBUG EVALUATE /-2**2. +DEBUG EVALUATE /-2**-3**-4. +DEBUG EVALUATE /-((2**-3)**-4). +]) + +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], [0], [dnl +2**8 => 256.00 + +(2**3)**4 => 4096.00 + +evaluate.sps:5.17-5.23: warning: DEBUG EVALUATE: The exponentiation operator +(`**') is left-associative: `a**b**c' equals `(a**b)**c', not `a**(b**c)'. To +disable this warning, insert parentheses. + 5 | DEBUG EVALUATE /2**3**4. + | ^~~~~~~ + +2**3**4 => 4096.00 + +-2**2 => -4.00 + +evaluate.sps:7.17-7.26: warning: DEBUG EVALUATE: The exponentiation operator +(`**') is left-associative: `a**b**c' equals `(a**b)**c', not `a**(b**c)'. To +disable this warning, insert parentheses. + 7 | DEBUG EVALUATE /-2**-3**-4. + | ^~~~~~~~~~ + +-2**-3**-4 => -4096.00 + +-((2**-3)**-4) => -4096.00 +]) +done +AT_CLEANUP + +AT_SETUP([expressions - unary minus]) +AT_KEYWORDS([expression expressions evaluate]) +AT_DATA([evaluate-base.sps], [ +DEBUG EVALUATE SET opt. +DEBUG EVALUATE /2+-3. +DEBUG EVALUATE /2*-3. +DEBUG EVALUATE /-3**2. +DEBUG EVALUATE /(-3)**2. +DEBUG EVALUATE /-(3**2). +DEBUG EVALUATE /2**-1. +DEBUG EVALUATE /0**0. +DEBUG EVALUATE /0**-1. +DEBUG EVALUATE /(-3)**1.5. +]) + +for opt in OPT NOOPT; do + sed "s/opt/$opt/" < evaluate-base.sps > evaluate.sps + AT_CHECK([pspp --testing-mode evaluate.sps], [0], [dnl +2+-3 => -1.00 + +2*-3 => -6.00 + +-3**2 => -9.00 + +(-3)**2 => 9.00 + +-(3**2) => -9.00 + +2**-1 => 0.50 + +0**0 => sysmis + +0**-1 => sysmis + +(-3)**1.5 => sysmis +]) +done +AT_CLEANUP + +AT_SETUP([expressions - AND truth table]) +AT_KEYWORDS([expression expressions evaluate]) +AT_DATA([evaluate-base.sps], [ +DEBUG EVALUATE SET opt. +DEBUG EVALUATE /$false AND $false. +DEBUG EVALUATE /$false AND $true. +DEBUG EVALUATE /$false AND $sysmis. +DEBUG EVALUATE /$true AND $false. +DEBUG EVALUATE /$true AND $true. +DEBUG EVALUATE /$true AND $sysmis. +DEBUG EVALUATE /$sysmis AND $false. +DEBUG EVALUATE /$sysmis AND $true. +DEBUG EVALUATE /$sysmis AND $sysmis. +DEBUG EVALUATE /$false & $false. +DEBUG EVALUATE /$false & $true. +DEBUG EVALUATE /$false & $sysmis. +DEBUG EVALUATE /$true & $false. +DEBUG EVALUATE /$true & $true. +DEBUG EVALUATE /$true & $sysmis. +DEBUG EVALUATE /$sysmis & $false. +DEBUG EVALUATE /$sysmis & $true. +DEBUG EVALUATE /$sysmis & $sysmis. +]) + +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], [0], [dnl +$false AND $false => false + +$false AND $true => false + +$false AND $sysmis => false + +$true AND $false => false + +$true AND $true => true + +$true AND $sysmis => sysmis + +$sysmis AND $false => false + +$sysmis AND $true => sysmis + +$sysmis AND $sysmis => sysmis + +$false & $false => false + +$false & $true => false + +$false & $sysmis => false + +$true & $false => false + +$true & $true => true + +$true & $sysmis => sysmis + +$sysmis & $false => false + +$sysmis & $true => sysmis + +$sysmis & $sysmis => sysmis +]) +done +AT_CLEANUP + +AT_SETUP([expressions - OR truth table]) +AT_KEYWORDS([expression expressions evaluate]) +AT_DATA([evaluate-base.sps], [ +DEBUG EVALUATE SET opt. +DEBUG EVALUATE /$false OR $false. +DEBUG EVALUATE /$false OR $true. +DEBUG EVALUATE /$false OR $sysmis. +DEBUG EVALUATE /$true OR $false. +DEBUG EVALUATE /$true OR $true. +DEBUG EVALUATE /$true OR $sysmis. +DEBUG EVALUATE /$sysmis OR $false. +DEBUG EVALUATE /$sysmis OR $true. +DEBUG EVALUATE /$sysmis OR $sysmis. +DEBUG EVALUATE /$false | $false. +DEBUG EVALUATE /$false | $true. +DEBUG EVALUATE /$false | $sysmis. +DEBUG EVALUATE /$true | $false. +DEBUG EVALUATE /$true | $true. +DEBUG EVALUATE /$true | $sysmis. +DEBUG EVALUATE /$sysmis | $false. +DEBUG EVALUATE /$sysmis | $true. +DEBUG EVALUATE /$sysmis | $sysmis. +]) + +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], [0], [dnl +$false OR $false => false + +$false OR $true => true + +$false OR $sysmis => sysmis + +$true OR $false => true + +$true OR $true => true + +$true OR $sysmis => true + +$sysmis OR $false => sysmis + +$sysmis OR $true => true + +$sysmis OR $sysmis => sysmis + +$false | $false => false + +$false | $true => true + +$false | $sysmis => sysmis + +$true | $false => true + +$true | $true => true + +$true | $sysmis => true + +$sysmis | $false => sysmis + +$sysmis | $true => true + +$sysmis | $sysmis => sysmis +]) +done +AT_CLEANUP + +AT_SETUP([expressions - NOT truth table]) +AT_KEYWORDS([expression expressions evaluate]) +AT_DATA([evaluate-base.sps], [ +DEBUG EVALUATE SET opt. +DEBUG EVALUATE /not $false. +DEBUG EVALUATE /not 0. +DEBUG EVALUATE /not 2.5. +DEBUG EVALUATE /not $true. +DEBUG EVALUATE /not 1. +DEBUG EVALUATE /not $sysmis. +DEBUG EVALUATE /~ $false. +DEBUG EVALUATE /~ 0. +DEBUG EVALUATE /~ 2.5. +DEBUG EVALUATE /~ $true. +DEBUG EVALUATE /~ 1. +DEBUG EVALUATE /~ $sysmis. +]) + +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 +not $false => true + +not 0 => true + +evaluate.sps:5.17-5.23: error: DEBUG EVALUATE: The operand of NOT must have +value 0 or 1. + 5 | DEBUG EVALUATE /not 2.5. + | ^~~~~~~ + +evaluate.sps:5.21-5.23: note: DEBUG EVALUATE: This operand with unexpected +value 2.5 will be treated as 0. + 5 | DEBUG EVALUATE /not 2.5. + | ^~~ + +not 2.5 => true + +not $true => false + +not 1 => false + +not $sysmis => sysmis + +~ $false => true + +~ 0 => true + +evaluate.sps:11.17-11.21: error: DEBUG EVALUATE: The operand of NOT must have +value 0 or 1. + 11 | DEBUG EVALUATE /~ 2.5. + | ^~~~~ + +evaluate.sps:11.19-11.21: note: DEBUG EVALUATE: This operand with unexpected +value 2.5 will be treated as 0. + 11 | DEBUG EVALUATE /~ 2.5. + | ^~~ + +~ 2.5 => true + +~ $true => false + +~ 1 => false + +~ $sysmis => sysmis +]) +done +AT_CLEANUP + +AT_SETUP([expressions - = <= <]) +AT_KEYWORDS([expression expressions evaluate eq le lt]) +AT_DATA([evaluate-base.sps], [ +DEBUG EVALUATE SET opt. +DEBUG EVALUATE /1 eq 1. +DEBUG EVALUATE /1 = 1. +DEBUG EVALUATE /1 eq 2. +DEBUG EVALUATE /2 = 3. +DEBUG EVALUATE /1 eq 'foobar'. +DEBUG EVALUATE /'baz' = 10. +DEBUG EVALUATE /'baz' = f8.2. +DEBUG EVALUATE /'baz' = 'baz'. +DEBUG EVALUATE /'quux' = 'bar'. +DEBUG EVALUATE /'bar ' = 'bar'. +DEBUG EVALUATE /'asdf ' = 'asdf '. +DEBUG EVALUATE /'asdfj ' = 'asdf'. +DEBUG EVALUATE /1 + 2 = 3. +DEBUG EVALUATE /1 >= 2 = 2 ge 3. +DEBUG EVALUATE /3 ne 2 != 1. +DEBUG EVALUATE /3 > 2 > 1. + +DEBUG EVALUATE /1 <= 2. +DEBUG EVALUATE /2.5 <= 1.5. +DEBUG EVALUATE /1 le 2. +DEBUG EVALUATE /2 <= 2. +DEBUG EVALUATE /2 le 2. +DEBUG EVALUATE /2 < = 2. +DEBUG EVALUATE /1 <= 'foobar'. +DEBUG EVALUATE /'baz' <= 10. +DEBUG EVALUATE /'quux' <= 5.55. +DEBUG EVALUATE /'0123' <= '0123'. +DEBUG EVALUATE /'0123' <= '0124'. +DEBUG EVALUATE /'0124' le '0123'. +DEBUG EVALUATE /'0123 ' <= '0123'. +DEBUG EVALUATE /'0123' le '0123 '. + +DEBUG EVALUATE /1 < 2. +DEBUG EVALUATE /2.5 < 1.5. +DEBUG EVALUATE /3.5 lt 4. +DEBUG EVALUATE /4 lt 3.5 +DEBUG EVALUATE /1 lt 'foobar'. +DEBUG EVALUATE /5 lt 'foobar'. +DEBUG EVALUATE /'baz' < 10. +DEBUG EVALUATE /'quux' < 5.55. +DEBUG EVALUATE /'0123' lt '0123'. +DEBUG EVALUATE /'0123' < '0124'. +DEBUG EVALUATE /'0124' lt '0123'. +DEBUG EVALUATE /'0123 ' < '0123'. +DEBUG EVALUATE /'0123' lt '0123 '. +]) + +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 +1 eq 1 => true + +1 = 1 => true + +1 eq 2 => false + +2 = 3 => false + +evaluate.sps:7.17-7.29: error: DEBUG EVALUATE: Both operands of EQ must have +the same type. + 7 | DEBUG EVALUATE /1 eq 'foobar'. + | ^~~~~~~~~~~~~ + +evaluate.sps:7.17: note: DEBUG EVALUATE: This operand has type 'number'. + 7 | DEBUG EVALUATE /1 eq 'foobar'. + | ^ + +evaluate.sps:7.22-7.29: note: DEBUG EVALUATE: This operand has type 'string'. + 7 | DEBUG EVALUATE /1 eq 'foobar'. + | ^~~~~~~~ + +1 eq 'foobar' => error + +evaluate.sps:8.17-8.26: error: DEBUG EVALUATE: Both operands of = must have the +same type. + 8 | DEBUG EVALUATE /'baz' = 10. + | ^~~~~~~~~~ + +evaluate.sps:8.17-8.21: note: DEBUG EVALUATE: This operand has type 'string'. + 8 | DEBUG EVALUATE /'baz' = 10. + | ^~~~~ + +evaluate.sps:8.25-8.26: note: DEBUG EVALUATE: This operand has type 'number'. + 8 | DEBUG EVALUATE /'baz' = 10. + | ^~ + +'baz' = 10 => error + +evaluate.sps:9.17-9.28: error: DEBUG EVALUATE: Both operands of = must have the +same type. + 9 | DEBUG EVALUATE /'baz' = f8.2. + | ^~~~~~~~~~~~ + +evaluate.sps:9.17-9.21: note: DEBUG EVALUATE: This operand has type 'string'. + 9 | DEBUG EVALUATE /'baz' = f8.2. + | ^~~~~ + +evaluate.sps:9.25-9.28: note: DEBUG EVALUATE: This operand has type 'format'. + 9 | DEBUG EVALUATE /'baz' = f8.2. + | ^~~~ + +'baz' = f8.2 => error + +'baz' = 'baz' => true + +'quux' = 'bar' => false + +'bar ' = 'bar' => true + +'asdf ' = 'asdf ' => true + +'asdfj ' = 'asdf' => false + +1 + 2 = 3 => true + +evaluate.sps:16.17-16.31: warning: DEBUG EVALUATE: Chaining relational +operators (e.g. `a < b < c') will not produce the mathematically expected +result. Use the AND logical operator to fix the problem (e.g. `a < b AND b < +c'). To disable this warning, insert parentheses. + 16 | DEBUG EVALUATE /1 >= 2 = 2 ge 3. + | ^~~~~~~~~~~~~~~ + +1 >= 2 = 2 ge 3 => false + +evaluate.sps:17.24: error: DEBUG EVALUATE: Syntax error at `!': expecting end +of command. + +3 ne 2 != 1 => error + +evaluate.sps:18.17-18.25: warning: DEBUG EVALUATE: Chaining relational +operators (e.g. `a < b < c') will not produce the mathematically expected +result. Use the AND logical operator to fix the problem (e.g. `a < b AND b < +c'). To disable this warning, insert parentheses. + 18 | DEBUG EVALUATE /3 > 2 > 1. + | ^~~~~~~~~ + +3 > 2 > 1 => false + +1 <= 2 => true + +2.5 <= 1.5 => false + +1 le 2 => true + +2 <= 2 => true + +2 le 2 => true + +evaluate.sps:25.21: error: DEBUG EVALUATE: Syntax error at `='. + +2 < = 2 => error + +evaluate.sps:26.17-26.29: error: DEBUG EVALUATE: Both operands of <= must have +the same type. + 26 | DEBUG EVALUATE /1 <= 'foobar'. + | ^~~~~~~~~~~~~ + +evaluate.sps:26.17: note: DEBUG EVALUATE: This operand has type 'number'. + 26 | DEBUG EVALUATE /1 <= 'foobar'. + | ^ + +evaluate.sps:26.22-26.29: note: DEBUG EVALUATE: This operand has type 'string'. + 26 | DEBUG EVALUATE /1 <= 'foobar'. + | ^~~~~~~~ + +1 <= 'foobar' => error + +evaluate.sps:27.17-27.27: error: DEBUG EVALUATE: Both operands of <= must have +the same type. + 27 | DEBUG EVALUATE /'baz' <= 10. + | ^~~~~~~~~~~ + +evaluate.sps:27.17-27.21: note: DEBUG EVALUATE: This operand has type 'string'. + 27 | DEBUG EVALUATE /'baz' <= 10. + | ^~~~~ + +evaluate.sps:27.26-27.27: note: DEBUG EVALUATE: This operand has type 'number'. + 27 | DEBUG EVALUATE /'baz' <= 10. + | ^~ + +'baz' <= 10 => error + +evaluate.sps:28.17-28.30: error: DEBUG EVALUATE: Both operands of <= must have +the same type. + 28 | DEBUG EVALUATE /'quux' <= 5.55. + | ^~~~~~~~~~~~~~ + +evaluate.sps:28.17-28.22: note: DEBUG EVALUATE: This operand has type 'string'. + 28 | DEBUG EVALUATE /'quux' <= 5.55. + | ^~~~~~ + +evaluate.sps:28.27-28.30: note: DEBUG EVALUATE: This operand has type 'number'. + 28 | DEBUG EVALUATE /'quux' <= 5.55. + | ^~~~ + +'quux' <= 5.55 => error + +'0123' <= '0123' => true + +'0123' <= '0124' => true + +'0124' le '0123' => false + +'0123 ' <= '0123' => true + +'0123' le '0123 ' => true + +1 < 2 => true + +2.5 < 1.5 => false + +3.5 lt 4 => true + +4 lt 3.5 => false + +evaluate.sps:39.17-39.29: error: DEBUG EVALUATE: Both operands of < must have +the same type. + 39 | DEBUG EVALUATE /1 lt 'foobar'. + | ^~~~~~~~~~~~~ + +evaluate.sps:39.17: note: DEBUG EVALUATE: This operand has type 'number'. + 39 | DEBUG EVALUATE /1 lt 'foobar'. + | ^ + +evaluate.sps:39.22-39.29: note: DEBUG EVALUATE: This operand has type 'string'. + 39 | DEBUG EVALUATE /1 lt 'foobar'. + | ^~~~~~~~ + +1 lt 'foobar' => error + +evaluate.sps:40.17-40.29: error: DEBUG EVALUATE: Both operands of < must have +the same type. + 40 | DEBUG EVALUATE /5 lt 'foobar'. + | ^~~~~~~~~~~~~ + +evaluate.sps:40.17: note: DEBUG EVALUATE: This operand has type 'number'. + 40 | DEBUG EVALUATE /5 lt 'foobar'. + | ^ + +evaluate.sps:40.22-40.29: note: DEBUG EVALUATE: This operand has type 'string'. + 40 | DEBUG EVALUATE /5 lt 'foobar'. + | ^~~~~~~~ + +5 lt 'foobar' => error + +evaluate.sps:41.17-41.26: error: DEBUG EVALUATE: Both operands of < must have +the same type. + 41 | DEBUG EVALUATE /'baz' < 10. + | ^~~~~~~~~~ + +evaluate.sps:41.17-41.21: note: DEBUG EVALUATE: This operand has type 'string'. + 41 | DEBUG EVALUATE /'baz' < 10. + | ^~~~~ + +evaluate.sps:41.25-41.26: note: DEBUG EVALUATE: This operand has type 'number'. + 41 | DEBUG EVALUATE /'baz' < 10. + | ^~ + +'baz' < 10 => error + +evaluate.sps:42.17-42.29: error: DEBUG EVALUATE: Both operands of < must have +the same type. + 42 | DEBUG EVALUATE /'quux' < 5.55. + | ^~~~~~~~~~~~~ + +evaluate.sps:42.17-42.22: note: DEBUG EVALUATE: This operand has type 'string'. + 42 | DEBUG EVALUATE /'quux' < 5.55. + | ^~~~~~ + +evaluate.sps:42.26-42.29: note: DEBUG EVALUATE: This operand has type 'number'. + 42 | DEBUG EVALUATE /'quux' < 5.55. + | ^~~~ + +'quux' < 5.55 => error + +'0123' lt '0123' => false + +'0123' < '0124' => true + +'0124' lt '0123' => false + +'0123 ' < '0123' => false + +'0123' lt '0123 ' => false +]) +done +AT_CLEANUP + +AT_SETUP([expressions - >= > <>]) +AT_KEYWORDS([expression expressions evaluate ge gt ne]) +AT_DATA([evaluate-base.sps], [ +DEBUG EVALUATE SET opt. +DEBUG EVALUATE /1 >= 2. +DEBUG EVALUATE /2.5 >= 1.5 +DEBUG EVALUATE /1 ge 2. +DEBUG EVALUATE /2 >= 2. +DEBUG EVALUATE /2 ge 2. +DEBUG EVALUATE /2 > = 2. +DEBUG EVALUATE /1 >= 'foobar'. +DEBUG EVALUATE /5 ge 'foobar'. +DEBUG EVALUATE /'baz' ge 10. +DEBUG EVALUATE /'0123' ge '0123'. +DEBUG EVALUATE /'0123' >= '0124'. +DEBUG EVALUATE /'0124' >= '0123'. +DEBUG EVALUATE /'0123 ' ge '0123'. +DEBUG EVALUATE /'0123' >= '0123 '. + +DEBUG EVALUATE /1 > 2. +DEBUG EVALUATE /2.5 > 1.5 +DEBUG EVALUATE /3.5 gt 4. +DEBUG EVALUATE /4 gt 3.5 +DEBUG EVALUATE /1 gt 'foobar'. +DEBUG EVALUATE /'baz' > 10. +DEBUG EVALUATE /'0123' > '0123'. +DEBUG EVALUATE /'0123' > '0124'. +DEBUG EVALUATE /'0124' > '0123'. +DEBUG EVALUATE /'0123 ' > '0123'. +DEBUG EVALUATE /'0123 ' > '0123 '. + +DEBUG EVALUATE /1 ne 1. +DEBUG EVALUATE /1 ~= 1. +DEBUG EVALUATE /1 <> 2. +DEBUG EVALUATE /2 ne 3. +DEBUG EVALUATE /1 ~= 'foobar'. +DEBUG EVALUATE /'baz' ne 10. +DEBUG EVALUATE /'quux' ~= 5.55. +DEBUG EVALUATE /'foobar' <> 'foobar'. +DEBUG EVALUATE /'quux' ne 'bar'. +DEBUG EVALUATE /'bar ' <> 'bar'. +DEBUG EVALUATE /'asdf ' ~= "asdf ". +DEBUG EVALUATE /1 < > 1. +DEBUG EVALUATE /1 ~ = 1. +]) + +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 +1 >= 2 => false + +2.5 >= 1.5 => true + +1 ge 2 => false + +2 >= 2 => true + +2 ge 2 => true + +evaluate.sps:8.21: error: DEBUG EVALUATE: Syntax error at `='. + +2 > = 2 => error + +evaluate.sps:9.17-9.29: error: DEBUG EVALUATE: Both operands of >= must have +the same type. + 9 | DEBUG EVALUATE /1 >= 'foobar'. + | ^~~~~~~~~~~~~ + +evaluate.sps:9.17: note: DEBUG EVALUATE: This operand has type 'number'. + 9 | DEBUG EVALUATE /1 >= 'foobar'. + | ^ + +evaluate.sps:9.22-9.29: note: DEBUG EVALUATE: This operand has type 'string'. + 9 | DEBUG EVALUATE /1 >= 'foobar'. + | ^~~~~~~~ + +1 >= 'foobar' => error + +evaluate.sps:10.17-10.29: error: DEBUG EVALUATE: Both operands of >= must have +the same type. + 10 | DEBUG EVALUATE /5 ge 'foobar'. + | ^~~~~~~~~~~~~ + +evaluate.sps:10.17: note: DEBUG EVALUATE: This operand has type 'number'. + 10 | DEBUG EVALUATE /5 ge 'foobar'. + | ^ + +evaluate.sps:10.22-10.29: note: DEBUG EVALUATE: This operand has type 'string'. + 10 | DEBUG EVALUATE /5 ge 'foobar'. + | ^~~~~~~~ + +5 ge 'foobar' => error + +evaluate.sps:11.17-11.27: error: DEBUG EVALUATE: Both operands of >= must have +the same type. + 11 | DEBUG EVALUATE /'baz' ge 10. + | ^~~~~~~~~~~ + +evaluate.sps:11.17-11.21: note: DEBUG EVALUATE: This operand has type 'string'. + 11 | DEBUG EVALUATE /'baz' ge 10. + | ^~~~~ + +evaluate.sps:11.26-11.27: note: DEBUG EVALUATE: This operand has type 'number'. + 11 | DEBUG EVALUATE /'baz' ge 10. + | ^~ + +'baz' ge 10 => error + +'0123' ge '0123' => true + +'0123' >= '0124' => false + +'0124' >= '0123' => true + +'0123 ' ge '0123' => true + +'0123' >= '0123 ' => true + +1 > 2 => false + +2.5 > 1.5 => true + +3.5 gt 4 => false + +4 gt 3.5 => true + +evaluate.sps:22.17-22.29: error: DEBUG EVALUATE: Both operands of > must have +the same type. + 22 | DEBUG EVALUATE /1 gt 'foobar'. + | ^~~~~~~~~~~~~ + +evaluate.sps:22.17: note: DEBUG EVALUATE: This operand has type 'number'. + 22 | DEBUG EVALUATE /1 gt 'foobar'. + | ^ + +evaluate.sps:22.22-22.29: note: DEBUG EVALUATE: This operand has type 'string'. + 22 | DEBUG EVALUATE /1 gt 'foobar'. + | ^~~~~~~~ + +1 gt 'foobar' => error + +evaluate.sps:23.17-23.26: error: DEBUG EVALUATE: Both operands of > must have +the same type. + 23 | DEBUG EVALUATE /'baz' > 10. + | ^~~~~~~~~~ + +evaluate.sps:23.17-23.21: note: DEBUG EVALUATE: This operand has type 'string'. + 23 | DEBUG EVALUATE /'baz' > 10. + | ^~~~~ + +evaluate.sps:23.25-23.26: note: DEBUG EVALUATE: This operand has type 'number'. + 23 | DEBUG EVALUATE /'baz' > 10. + | ^~ + +'baz' > 10 => error + +'0123' > '0123' => false + +'0123' > '0124' => false + +'0124' > '0123' => true + +'0123 ' > '0123' => false + +'0123 ' > '0123 ' => false + +1 ne 1 => false + +1 ~= 1 => false + +1 <> 2 => true + +2 ne 3 => true + +evaluate.sps:34.17-34.29: error: DEBUG EVALUATE: Both operands of ~= must have +the same type. + 34 | DEBUG EVALUATE /1 ~= 'foobar'. + | ^~~~~~~~~~~~~ + +evaluate.sps:34.17: note: DEBUG EVALUATE: This operand has type 'number'. + 34 | DEBUG EVALUATE /1 ~= 'foobar'. + | ^ + +evaluate.sps:34.22-34.29: note: DEBUG EVALUATE: This operand has type 'string'. + 34 | DEBUG EVALUATE /1 ~= 'foobar'. + | ^~~~~~~~ + +1 ~= 'foobar' => error + +evaluate.sps:35.17-35.27: error: DEBUG EVALUATE: Both operands of ~= must have +the same type. + 35 | DEBUG EVALUATE /'baz' ne 10. + | ^~~~~~~~~~~ + +evaluate.sps:35.17-35.21: note: DEBUG EVALUATE: This operand has type 'string'. + 35 | DEBUG EVALUATE /'baz' ne 10. + | ^~~~~ + +evaluate.sps:35.26-35.27: note: DEBUG EVALUATE: This operand has type 'number'. + 35 | DEBUG EVALUATE /'baz' ne 10. + | ^~ + +'baz' ne 10 => error + +evaluate.sps:36.17-36.30: error: DEBUG EVALUATE: Both operands of ~= must have +the same type. + 36 | DEBUG EVALUATE /'quux' ~= 5.55. + | ^~~~~~~~~~~~~~ + +evaluate.sps:36.17-36.22: note: DEBUG EVALUATE: This operand has type 'string'. + 36 | DEBUG EVALUATE /'quux' ~= 5.55. + | ^~~~~~ + +evaluate.sps:36.27-36.30: note: DEBUG EVALUATE: This operand has type 'number'. + 36 | DEBUG EVALUATE /'quux' ~= 5.55. + | ^~~~ + +'quux' ~= 5.55 => error + +'foobar' <> 'foobar' => false + +'quux' ne 'bar' => true + +'bar ' <> 'bar' => false + +'asdf ' ~= "asdf " => false + +evaluate.sps:41.21: error: DEBUG EVALUATE: Syntax error at `>'. + +1 < > 1 => error + +evaluate.sps:42.19: error: DEBUG EVALUATE: Syntax error at `~': expecting end +of command. + +1 ~ = 1 => error +]) +done +AT_CLEANUP + +AT_SETUP([expressions - EXP LG10 LN SQRT ABS MOD MOD10 RND TRUNC]) +AT_KEYWORDS([expression expressions evaluate]) +AT_DATA([evaluate-base.sps], [ +DEBUG EVALUATE SET opt. +DEBUG EVALUATE /EXP(10). +DEBUG EVALUATE /EXP('x'). + +DEBUG EVALUATE /LG10(500). +DEBUG EVALUATE /LG10('x'). + +DEBUG EVALUATE /SQRT(500). +DEBUG EVALUATE /SQRT(-1). + +DEBUG EVALUATE /ABS(-10.5). +DEBUG EVALUATE /ABS(55.79). +DEBUG EVALUATE /ABS(0). +DEBUG EVALUATE /ABS(-0). + +DEBUG EVALUATE /MOD(55.5, 2). +DEBUG EVALUATE /MOD(-55.5, 2). +DEBUG EVALUATE /MOD(55.5, -2). +DEBUG EVALUATE /MOD(-55.5, -2). +DEBUG EVALUATE /MOD('a', 2). +DEBUG EVALUATE /MOD(2, 'a'). +DEBUG EVALUATE /MOD('a', 'b'). + +DEBUG EVALUATE /MOD10(55.5). +DEBUG EVALUATE /MOD10(-55.5). + +DEBUG EVALUATE /RND(5.4). +DEBUG EVALUATE /RND(5.6). +DEBUG EVALUATE /RND(-5.4). +DEBUG EVALUATE /RND(-5.6). +DEBUG EVALUATE /RND(5.56, .1). +DEBUG EVALUATE /RND(-5.56, .1) +DEBUG EVALUATE /RND(.5). +DEBUG EVALUATE /RND(.5 - 2**-53). +DEBUG EVALUATE /RND(.5 - 2**-52). +DEBUG EVALUATE /RND(.5 - 2**-51). +DEBUG EVALUATE /RND(.5 - 2**-45). +DEBUG EVALUATE /RND(.5 - 2**-45, 1, 10). +DEBUG EVALUATE /RND('x'). + +DEBUG EVALUATE /TRUNC(1.2). +DEBUG EVALUATE /TRUNC(1.9). +DEBUG EVALUATE /TRUNC(-1.2). +DEBUG EVALUATE /TRUNC(-1.9). +DEBUG EVALUATE /TRUNC(5.06, .1). +DEBUG EVALUATE /TRUNC(-5.06, .1). +DEBUG EVALUATE /TRUNC(1). +DEBUG EVALUATE /TRUNC(1 - 2**-53). +DEBUG EVALUATE /TRUNC(1 - 2**-52). +DEBUG EVALUATE /TRUNC(1 - 2**-51). +DEBUG EVALUATE /TRUNC(1 - 2**-45). +DEBUG EVALUATE /TRUNC(1 - 2**-45, 1, 10). +DEBUG EVALUATE /TRUNC('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 +EXP(10) => 22026.47 + +evaluate.sps:4.17-4.24: error: DEBUG EVALUATE: Type mismatch invoking +EXP(number) as EXP(string). + 4 | DEBUG EVALUATE /EXP('x'). + | ^~~~~~~~ + +EXP('x') => error + +LG10(500) => 2.70 + +evaluate.sps:7.17-7.25: error: DEBUG EVALUATE: Type mismatch invoking +LG10(number) as LG10(string). + 7 | DEBUG EVALUATE /LG10('x'). + | ^~~~~~~~~ + +LG10('x') => error + +SQRT(500) => 22.36 + +SQRT(-1) => sysmis + +ABS(-10.5) => 10.50 + +ABS(55.79) => 55.79 + +ABS(0) => 0.00 + +ABS(-0) => 0.00 + +MOD(55.5, 2) => 1.50 + +MOD(-55.5, 2) => -1.50 + +MOD(55.5, -2) => 1.50 + +MOD(-55.5, -2) => -1.50 + +evaluate.sps:21.17-21.27: error: DEBUG EVALUATE: Type mismatch invoking +MOD(number, number) as MOD(string, number). + 21 | DEBUG EVALUATE /MOD('a', 2). + | ^~~~~~~~~~~ + +MOD('a', 2) => error + +evaluate.sps:22.17-22.27: error: DEBUG EVALUATE: Type mismatch invoking +MOD(number, number) as MOD(number, string). + 22 | DEBUG EVALUATE /MOD(2, 'a'). + | ^~~~~~~~~~~ + +MOD(2, 'a') => error + +evaluate.sps:23.17-23.29: error: DEBUG EVALUATE: Type mismatch invoking +MOD(number, number) as MOD(string, string). + 23 | DEBUG EVALUATE /MOD('a', 'b'). + | ^~~~~~~~~~~~~ + +MOD('a', 'b') => error + +MOD10(55.5) => 5.50 + +MOD10(-55.5) => -5.50 + +RND(5.4) => 5.00 + +RND(5.6) => 6.00 + +RND(-5.4) => -5.00 + +RND(-5.6) => -6.00 + +RND(5.56, .1) => 5.60 + +RND(-5.56, .1) => -5.60 + +RND(.5) => 1.00 + +RND(.5 - 2**-53) => 1.00 + +RND(.5 - 2**-52) => 1.00 + +RND(.5 - 2**-51) => 1.00 + +RND(.5 - 2**-45) => 0.00 + +RND(.5 - 2**-45, 1, 10) => 1.00 + +evaluate.sps:40.17-40.24: error: DEBUG EVALUATE: Function invocation +RND(string) does not match any known function. Candidates are: RND(number) RND(number, number) -RND(number, number, number).]], - - [[trunc(1.2)], [1.00]], - [[trunc(1.9)], [1.00]], - [[trunc(-1.2)], [-1.00]], - [[trunc(-1.9)], [-1.00]], - [[trunc(5.06, .1)], [5.00]], - [[trunc(-5.06, .1)], [-5.00]], - [[trunc(1)], [1.00]], - [[trunc(1 - 2**-53)], [1.00]], - [[trunc(1 - 2**-52)], [1.00]], - [[trunc(1 - 2**-51)], [1.00]], - [[trunc(1 - 2**-45)], [0.00]], - [[trunc(1 - 2**-45, 1, 10)], [1.00]], - [[trunc('x')], [error], - [error: DEBUG EVALUATE: Function invocation trunc(string) does not match any known function. Candidates are: +RND(number, number, number). + 40 | DEBUG EVALUATE /RND('x'). + | ^~~~~~~~ + +RND('x') => error + +TRUNC(1.2) => 1.00 + +TRUNC(1.9) => 1.00 + +TRUNC(-1.2) => -1.00 + +TRUNC(-1.9) => -1.00 + +TRUNC(5.06, .1) => 5.00 + +TRUNC(-5.06, .1) => -5.00 + +TRUNC(1) => 1.00 + +TRUNC(1 - 2**-53) => 1.00 + +TRUNC(1 - 2**-52) => 1.00 + +TRUNC(1 - 2**-51) => 1.00 + +TRUNC(1 - 2**-45) => 0.00 + +TRUNC(1 - 2**-45, 1, 10) => 1.00 + +evaluate.sps:54.17-54.26: error: DEBUG EVALUATE: Function invocation +TRUNC(string) does not match any known function. Candidates are: TRUNC(number) TRUNC(number, number) -TRUNC(number, number, number).]]) - -CHECK_EXPR_EVAL([acos arsin artan cos sin tan], - [[acos(.5) / 3.14159 * 180], [60.00]], - [[arcos(.75) / 3.14159 * 180], [41.41]], - [[arcos(-.5) / 3.14159 * 180], [120.00]], - [[acos(-.75) / 3.14159 * 180], [138.59]], - [[acos(-1) / 3.14159 * 180], [180.00]], - [[arcos(1) / 3.14159 * 180], [0.00]], - [[acos(-1.01)], [sysmis]], - [[arcos(1.01)], [sysmis]], - [[acos('x')], [error], - [error: DEBUG EVALUATE: Type mismatch invoking ACOS(number) as acos(string).]], - - [[arsin(.5) / 3.14159 * 180], [30.00]], - [[asin(.25) / 3.14159 * 180], [14.48]], - [[arsin(-.5) / 3.14159 * 180], [-30.00]], - [[asin(-.25) / 3.14159 * 180], [-14.48]], - [[arsin(-1.01)], [sysmis]], - [[asin(1.01)], [sysmis]], - [[arsin('x')], [error], - [error: DEBUG EVALUATE: Type mismatch invoking ARSIN(number) as arsin(string).]], - - [[artan(1) / 3.14159 * 180], [45.00]], - [[atan(10) / 3.14159 * 180], [84.29]], - [[artan(-1) / 3.14159 * 180], [-45.00]], - [[atan(-10) / 3.14159 * 180], [-84.29]], - [[artan('x')], [error], - [error: DEBUG EVALUATE: Type mismatch invoking ARTAN(number) as artan(string).]], - - [[cos(60 / 180 * 3.14159)], [0.50]], - [[cos(45 / 180 * 3.14159)], [0.71]], - [[cos(30 / 180 * 3.14159)], [0.87]], - [[cos(15 / 180 * 3.14159)], [0.97]], - [[cos(-60 / 180 * 3.14159)], [0.50]], - [[cos(-45 / 180 * 3.14159)], [0.71]], - [[cos(-30 / 180 * 3.14159)], [0.87]], - [[cos(-15 / 180 * 3.14159)], [0.97]], - [[cos(123 / 180 * 3.14159)], [-0.54]], - [[cos(321 / 180 * 3.14159)], [0.78]], - [[cos('x')], [error], - [error: DEBUG EVALUATE: Type mismatch invoking COS(number) as cos(string).]], - - [[sin(60 / 180 * 3.14159)], [0.87]], - [[sin(45 / 180 * 3.14159)], [0.71]], - [[sin(30 / 180 * 3.14159)], [0.50]], - [[sin(15 / 180 * 3.14159)], [0.26]], - [[sin(-60 / 180 * 3.14159)], [-0.87]], - [[sin(-45 / 180 * 3.14159)], [-0.71]], - [[sin(-30 / 180 * 3.14159)], [-0.50]], - [[sin(-15 / 180 * 3.14159)], [-0.26]], - [[sin(123 / 180 * 3.14159)], [0.84]], - [[sin(321 / 180 * 3.14159)], [-0.63]], - [[sin('x')], [error], - [error: DEBUG EVALUATE: Type mismatch invoking SIN(number) as sin(string).]], - - [[tan(60 / 180 * 3.14159)], [1.73]], - [[tan(45 / 180 * 3.14159)], [1.00]], - [[tan(30 / 180 * 3.14159)], [0.58]], - [[tan(15 / 180 * 3.14159)], [0.27]], - [[tan(-60 / 180 * 3.14159)], [-1.73]], - [[tan(-45 / 180 * 3.14159)], [-1.00]], - [[tan(-30 / 180 * 3.14159)], [-0.58]], - [[tan(-15 / 180 * 3.14159)], [-0.27]], - [[tan(123 / 180 * 3.14159)], [-1.54]], - [[tan(321 / 180 * 3.14159)], [-0.81]], - [[tan('x')], [error], - [error: DEBUG EVALUATE: Type mismatch invoking TAN(number) as tan(string).]]) +TRUNC(number, number, number). + 54 | DEBUG EVALUATE /TRUNC('x'). + | ^~~~~~~~~~ + +TRUNC('x') => error +]) +done +AT_CLEANUP + +AT_SETUP([expressions - ACOS ARSIN ARTAN COS SIN TAN]) +AT_KEYWORDS([expression expressions evaluate]) +AT_DATA([evaluate-base.sps], [ +DEBUG EVALUATE SET opt. +DEBUG EVALUATE /ACOS(.5) / 3.14159 * 180. +DEBUG EVALUATE /ARCOS(.75) / 3.14159 * 180. +DEBUG EVALUATE /ARCOS(-.5) / 3.14159 * 180. +DEBUG EVALUATE /ACOS(-.75) / 3.14159 * 180. +DEBUG EVALUATE /ACOS(-1) / 3.14159 * 180. +DEBUG EVALUATE /ARCOS(1) / 3.14159 * 180. +DEBUG EVALUATE /ACOS(-1.01) / 3.14159 * 180. +DEBUG EVALUATE /ARCOS(1.01) / 3.14159 * 180. +DEBUG EVALUATE /ACOS('x') / 3.14159 * 180. + +DEBUG EVALUATE /ASIN(.5) / 3.14159 * 180. +DEBUG EVALUATE /ARSIN(.25) / 3.14159 * 180. +DEBUG EVALUATE /ARSIN(-.5) / 3.14159 * 180. +DEBUG EVALUATE /ASIN(-.25) / 3.14159 * 180. +DEBUG EVALUATE /ASIN(-1.01) / 3.14159 * 180. +DEBUG EVALUATE /ARSIN(1.01) / 3.14159 * 180. +DEBUG EVALUATE /ASIN('x') / 3.14159 * 180. + +DEBUG EVALUATE /ATAN(1) / 3.14159 * 180. +DEBUG EVALUATE /ARTAN(10) / 3.14159 * 180. +DEBUG EVALUATE /ARTAN(-1) / 3.14159 * 180. +DEBUG EVALUATE /ATAN(-10) / 3.14159 * 180. +DEBUG EVALUATE /ATAN('x') / 3.14159 * 180. + +DEBUG EVALUATE /COS(60 / 180 * 3.14159). +DEBUG EVALUATE /COS(45 / 180 * 3.14159). +DEBUG EVALUATE /COS(30 / 180 * 3.14159). +DEBUG EVALUATE /COS(15 / 180 * 3.14159). +DEBUG EVALUATE /COS(-60 / 180 * 3.14159). +DEBUG EVALUATE /COS(-45 / 180 * 3.14159). +DEBUG EVALUATE /COS(-30 / 180 * 3.14159). +DEBUG EVALUATE /COS(-15 / 180 * 3.14159). +DEBUG EVALUATE /COS(123 / 180 * 3.14159). +DEBUG EVALUATE /COS(321 / 180 * 3.14159). +DEBUG EVALUATE /COS('x'). + +DEBUG EVALUATE /SIN(60 / 180 * 3.14159). +DEBUG EVALUATE /SIN(45 / 180 * 3.14159). +DEBUG EVALUATE /SIN(30 / 180 * 3.14159). +DEBUG EVALUATE /SIN(15 / 180 * 3.14159). +DEBUG EVALUATE /SIN(-60 / 180 * 3.14159). +DEBUG EVALUATE /SIN(-45 / 180 * 3.14159). +DEBUG EVALUATE /SIN(-30 / 180 * 3.14159). +DEBUG EVALUATE /SIN(-15 / 180 * 3.14159). +DEBUG EVALUATE /SIN(123 / 180 * 3.14159). +DEBUG EVALUATE /SIN(321 / 180 * 3.14159). +DEBUG EVALUATE /SIN('x'). + +DEBUG EVALUATE /TAN(60 / 180 * 3.14159). +DEBUG EVALUATE /TAN(45 / 180 * 3.14159). +DEBUG EVALUATE /TAN(30 / 180 * 3.14159). +DEBUG EVALUATE /TAN(15 / 180 * 3.14159). +DEBUG EVALUATE /TAN(-60 / 180 * 3.14159). +DEBUG EVALUATE /TAN(-45 / 180 * 3.14159). +DEBUG EVALUATE /TAN(-30 / 180 * 3.14159). +DEBUG EVALUATE /TAN(-15 / 180 * 3.14159). +DEBUG EVALUATE /TAN(123 / 180 * 3.14159). +DEBUG EVALUATE /TAN(321 / 180 * 3.14159). +DEBUG EVALUATE /TAN('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 +ACOS(.5) / 3.14159 * 180 => 60.00 + +ARCOS(.75) / 3.14159 * 180 => 41.41 + +ARCOS(-.5) / 3.14159 * 180 => 120.00 + +ACOS(-.75) / 3.14159 * 180 => 138.59 + +ACOS(-1) / 3.14159 * 180 => 180.00 + +ARCOS(1) / 3.14159 * 180 => 0.00 + +ACOS(-1.01) / 3.14159 * 180 => sysmis + +ARCOS(1.01) / 3.14159 * 180 => sysmis + +evaluate.sps:11.17-11.25: error: DEBUG EVALUATE: Type mismatch invoking +ACOS(number) as ACOS(string). + 11 | DEBUG EVALUATE /ACOS('x') / 3.14159 * 180. + | ^~~~~~~~~ + +ACOS('x') / 3.14159 * 180 => error + +ASIN(.5) / 3.14159 * 180 => 30.00 + +ARSIN(.25) / 3.14159 * 180 => 14.48 + +ARSIN(-.5) / 3.14159 * 180 => -30.00 + +ASIN(-.25) / 3.14159 * 180 => -14.48 + +ASIN(-1.01) / 3.14159 * 180 => sysmis + +ARSIN(1.01) / 3.14159 * 180 => sysmis + +evaluate.sps:19.17-19.25: error: DEBUG EVALUATE: Type mismatch invoking +ASIN(number) as ASIN(string). + 19 | DEBUG EVALUATE /ASIN('x') / 3.14159 * 180. + | ^~~~~~~~~ + +ASIN('x') / 3.14159 * 180 => error + +ATAN(1) / 3.14159 * 180 => 45.00 + +ARTAN(10) / 3.14159 * 180 => 84.29 + +ARTAN(-1) / 3.14159 * 180 => -45.00 + +ATAN(-10) / 3.14159 * 180 => -84.29 + +evaluate.sps:25.17-25.25: error: DEBUG EVALUATE: Type mismatch invoking +ATAN(number) as ATAN(string). + 25 | DEBUG EVALUATE /ATAN('x') / 3.14159 * 180. + | ^~~~~~~~~ + +ATAN('x') / 3.14159 * 180 => error + +COS(60 / 180 * 3.14159) => 0.50 + +COS(45 / 180 * 3.14159) => 0.71 + +COS(30 / 180 * 3.14159) => 0.87 + +COS(15 / 180 * 3.14159) => 0.97 + +COS(-60 / 180 * 3.14159) => 0.50 + +COS(-45 / 180 * 3.14159) => 0.71 + +COS(-30 / 180 * 3.14159) => 0.87 + +COS(-15 / 180 * 3.14159) => 0.97 + +COS(123 / 180 * 3.14159) => -0.54 + +COS(321 / 180 * 3.14159) => 0.78 + +evaluate.sps:37.17-37.24: error: DEBUG EVALUATE: Type mismatch invoking +COS(number) as COS(string). + 37 | DEBUG EVALUATE /COS('x'). + | ^~~~~~~~ + +COS('x') => error + +SIN(60 / 180 * 3.14159) => 0.87 + +SIN(45 / 180 * 3.14159) => 0.71 + +SIN(30 / 180 * 3.14159) => 0.50 + +SIN(15 / 180 * 3.14159) => 0.26 + +SIN(-60 / 180 * 3.14159) => -0.87 + +SIN(-45 / 180 * 3.14159) => -0.71 + +SIN(-30 / 180 * 3.14159) => -0.50 + +SIN(-15 / 180 * 3.14159) => -0.26 + +SIN(123 / 180 * 3.14159) => 0.84 + +SIN(321 / 180 * 3.14159) => -0.63 + +evaluate.sps:49.17-49.24: error: DEBUG EVALUATE: Type mismatch invoking +SIN(number) as SIN(string). + 49 | DEBUG EVALUATE /SIN('x'). + | ^~~~~~~~ + +SIN('x') => error + +TAN(60 / 180 * 3.14159) => 1.73 + +TAN(45 / 180 * 3.14159) => 1.00 + +TAN(30 / 180 * 3.14159) => 0.58 + +TAN(15 / 180 * 3.14159) => 0.27 + +TAN(-60 / 180 * 3.14159) => -1.73 + +TAN(-45 / 180 * 3.14159) => -1.00 + +TAN(-30 / 180 * 3.14159) => -0.58 + +TAN(-15 / 180 * 3.14159) => -0.27 + +TAN(123 / 180 * 3.14159) => -1.54 + +TAN(321 / 180 * 3.14159) => -0.81 + +evaluate.sps:61.17-61.24: error: DEBUG EVALUATE: Type mismatch invoking +TAN(number) as TAN(string). + 61 | DEBUG EVALUATE /TAN('x'). + | ^~~~~~~~ + +TAN('x') => error +]) +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], -- 2.30.2