expressions: Fix value of $TIME variable and add a test.
[pspp] / tests / language / expressions / parse.at
1 dnl PSPP - a program for statistical analysis.
2 dnl Copyright (C) 2017 Free Software Foundation, Inc.
3 dnl
4 dnl This program is free software: you can redistribute it and/or modify
5 dnl it under the terms of the GNU General Public License as published by
6 dnl the Free Software Foundation, either version 3 of the License, or
7 dnl (at your option) any later version.
8 dnl
9 dnl This program is distributed in the hope that it will be useful,
10 dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
11 dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 dnl GNU General Public License for more details.
13 dnl
14 dnl You should have received a copy of the GNU General Public License
15 dnl along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 dnl
17 AT_BANNER([expression parsing])
18
19 AT_SETUP([parse expression with unknown variable crash])
20 AT_KEYWORDS([expression expressions parse])
21 AT_DATA([parse.sps], [dnl
22 INPUT PROGRAM.
23 LOOP c=1 to 10.
24 COMPUTE var1=NORMAL(100).
25 END CASE.
26 END LOOP.
27 END FILE.
28 END INPUT PROGRAM.
29
30
31 IF ( y > 0 ) .
32 COMPUTE x=y.
33 END IF.
34 ])
35 AT_CHECK([pspp -O format=csv parse.sps], [1], [dnl
36 parse.sps:10: error: IF: Unknown identifier y.
37
38 parse.sps:11: error: Stopping syntax file processing here to avoid a cascade of dependent command failures.
39 ])
40 AT_CLEANUP
41
42 AT_SETUP([parsing boolean expression with type mismatch])
43 AT_KEYWORDS([expression expressions parse])
44 AT_DATA([parse.sps], [dnl
45 DATA LIST NOTABLE/x 1(A).
46 IF 'foo'.
47 ])
48 AT_CHECK([pspp parse.sps], [1], [dnl
49 parse.sps:2.4-2.8: error: IF: Type mismatch: expression has string type, but a
50 boolean value is required here.
51     2 | IF 'foo'.
52       |    ^~~~~
53 ])
54 AT_CLEANUP
55
56 AT_SETUP([parsing numeric expression with type mismatch])
57 AT_KEYWORDS([expression expressions parse])
58 AT_DATA([parse.sps], [dnl
59 DATA LIST NOTABLE/x 1.
60 COMPUTE x='foo'.
61 ])
62 AT_CHECK([pspp parse.sps], [1], [dnl
63 parse.sps:2.11-2.15: error: COMPUTE: Type mismatch: expression has type
64 'string', but a numeric value is required.
65     2 | COMPUTE x='foo'.
66       |           ^~~~~
67 ])
68 AT_CLEANUP
69
70 AT_SETUP([parsing string expression with type mismatch])
71 AT_KEYWORDS([expression expressions parse negative])
72 AT_DATA([parse.sps], [dnl
73 DATA LIST NOTABLE/x 1(A).
74 COMPUTE x=1.
75 ])
76 AT_CHECK([pspp parse.sps], [1], [dnl
77 parse.sps:2.11: error: COMPUTE: Type mismatch: expression has type 'number',
78 but a string value is required.
79     2 | COMPUTE x=1.
80       |           ^
81 ])
82 AT_CLEANUP
83
84 AT_SETUP([assigning string expression to new variable])
85 AT_KEYWORDS([expression expressions parse negative])
86 AT_DATA([parse.sps], [dnl
87 DATA LIST NOTABLE/x 1(A).
88 COMPUTE y='a'.
89 ])
90 AT_CHECK([pspp parse.sps], [1], [dnl
91 parse.sps:2: error: COMPUTE: This command tries to create a new variable y by
92 assigning a string value to it, but this is not supported.  Use the STRING
93 command to create the new variable with the correct width before assigning to
94 it, e.g. STRING y(A20).
95 ])
96 AT_CLEANUP
97
98 AT_SETUP([parse expression with unknown system variable])
99 AT_KEYWORDS([expression expressions parse negative])
100 AT_DATA([parse.sps], [dnl
101 DATA LIST NOTABLE/x 1.
102 COMPUTE x=$nonexistent.
103 ])
104 AT_CHECK([pspp parse.sps], [1], [dnl
105 parse.sps:2: error: COMPUTE: Unknown system variable $nonexistent.
106 ])
107 AT_CLEANUP
108
109 AT_SETUP([parse expression with unknown identifier])
110 AT_KEYWORDS([expression expressions parse negative])
111 AT_DATA([parse.sps], [dnl
112 DATA LIST NOTABLE/x 1.
113 COMPUTE x=y.
114 ])
115 AT_CHECK([pspp parse.sps], [1], [dnl
116 parse.sps:2: error: COMPUTE: Unknown identifier y.
117 ])
118 AT_CLEANUP
119
120 AT_SETUP([parse expression with extension function in compatibility mode])
121 AT_KEYWORDS([expression expressions parse negative])
122 AT_DATA([parse.sps], [dnl
123 DEBUG EVALUATE/ACOS(0)*0.
124 ])
125 AT_CHECK([pspp --testing-mode --syntax=compatible parse.sps], [0], [dnl
126 parse.sps:1.16-1.22: warning: DEBUG EVALUATE: ACOS(number) is a PSPP extension.
127     1 | DEBUG EVALUATE/ACOS(0)*0.
128       |                ^~~~~~~
129
130 ACOS(0)*0 => 0.00
131 ])
132 AT_CLEANUP
133
134 AT_SETUP([LAG expression following TEMPORARY])
135 AT_KEYWORDS([expression expressions parse negative])
136 AT_DATA([parse.sps], [dnl
137 DATA LIST NOTABLE/x 1.
138 TEMPORARY
139 COMPUTE y=LAG(x).
140 ])
141 AT_CHECK([pspp parse.sps], [1], [dnl
142 parse.sps:3.11-3.16: error: COMPUTE: LAG(num_variable) may not appear after
143 TEMPORARY.
144     3 | COMPUTE y=LAG(x).
145       |           ^~~~~~
146 ])
147 AT_CLEANUP
148
149 AT_SETUP([parse expression with invalid logical expression])
150 AT_KEYWORDS([expression expressions parse negative])
151 AT_DATA([parse.sps], [dnl
152 INPUT PROGRAM.
153 LOOP c=1 to 10.
154 COMPUTE var1=NORMAL(100).
155 END CASE.
156 END LOOP.
157 END FILE.
158 END INPUT PROGRAM.
159
160 SELECT IF 2.
161 ])
162 AT_CHECK([pspp parse.sps], [1], [dnl
163 parse.sps:9.11: error: SELECT IF: This expression, which must be 0 or 1,
164 evaluated to 2.  It will be treated as 0.
165     9 | SELECT IF 2.
166       |           ^
167 ])
168 AT_CLEANUP
169
170 AT_SETUP([chaining operators that shouldn't be])
171 AT_KEYWORDS([expression expressions parse negative])
172 AT_DATA([parse.sps], [dnl
173 INPUT PROGRAM.
174 * These should provoke warnings.
175 COMPUTE a = 1 < 2 < 3.
176 COMPUTE b = 1 > 2 < 0.
177 COMPUTE c = 2**3**4.
178
179 * These should not provoke warnings.
180 COMPUTE d = (1 < 2) < 3.
181 COMPUTE e = (2**3)**4.
182 END INPUT PROGRAM.
183 ])
184 AT_CHECK([pspp parse.sps], [1], [dnl
185 parse.sps:3.13-3.21: warning: COMPUTE: Chaining relational operators (e.g. `a <
186 b < c') will not produce the mathematically expected result.  Use the AND
187 logical operator to fix the problem (e.g. `a < b AND b < c').  To disable this
188 warning, insert parentheses.
189     3 | COMPUTE a = 1 < 2 < 3.
190       |             ^~~~~~~~~
191
192 parse.sps:4.13-4.21: warning: COMPUTE: Chaining relational operators (e.g. `a <
193 b < c') will not produce the mathematically expected result.  Use the AND
194 logical operator to fix the problem (e.g. `a < b AND b < c').  To disable this
195 warning, insert parentheses.
196     4 | COMPUTE b = 1 > 2 < 0.
197       |             ^~~~~~~~~
198
199 parse.sps:5.13-5.19: warning: COMPUTE: The exponentiation operator (`**') is
200 left-associative: `a**b**c' equals `(a**b)**c', not `a**(b**c)'.  To disable
201 this warning, insert parentheses.
202     5 | COMPUTE c = 2**3**4.
203       |             ^~~~~~~
204
205 parse.sps:10: error: INPUT PROGRAM: Input program must contain DATA LIST or END
206 FILE.
207 ])
208 AT_CLEANUP
209
210 AT_SETUP([binary operator type mismatch])
211 AT_KEYWORDS([expression expressions parse negative])
212 AT_DATA([parse.sps], [dnl
213 DEBUG EVALUATE /1 + 'a'.
214 DEBUG EVALUATE /'a' + 1.
215 DEBUG EVALUATE /'a' + 'a'.
216 DEBUG EVALUATE /'a' + ('a').
217
218 DEBUG EVALUATE /1 < 'a'.
219 DEBUG EVALUATE /'a' < 1.
220 DEBUG EVALUATE /'a' < 'b' < 'c'.
221 ])
222 AT_CHECK([pspp --testing-mode parse.sps], [1], [dnl
223 parse.sps:1.17-1.23: error: DEBUG EVALUATE: Both operands of + must be numeric.
224     1 | DEBUG EVALUATE /1 + 'a'.
225       |                 ^~~~~~~
226
227 parse.sps:1.17: note: DEBUG EVALUATE: This operand has type 'number'.
228     1 | DEBUG EVALUATE /1 + 'a'.
229       |                 ^
230
231 parse.sps:1.21-1.23: note: DEBUG EVALUATE: This operand has type 'string'.
232     1 | DEBUG EVALUATE /1 + 'a'.
233       |                     ^~~
234
235 1 + 'a' => error
236
237 parse.sps:2.17-2.23: error: DEBUG EVALUATE: Both operands of + must be numeric.
238     2 | DEBUG EVALUATE /'a' + 1.
239       |                 ^~~~~~~
240
241 parse.sps:2.17-2.19: note: DEBUG EVALUATE: This operand has type 'string'.
242     2 | DEBUG EVALUATE /'a' + 1.
243       |                 ^~~
244
245 parse.sps:2.23: note: DEBUG EVALUATE: This operand has type 'number'.
246     2 | DEBUG EVALUATE /'a' + 1.
247       |                       ^
248
249 'a' + 1 => error
250
251 'a' + 'a' => "aa"
252
253 parse.sps:4.17-4.26: error: DEBUG EVALUATE: Both operands of + must be numeric.
254     4 | DEBUG EVALUATE /'a' + ('a').
255       |                 ^~~~~~~~~~
256
257 parse.sps:4.17-4.19: note: DEBUG EVALUATE: This operand has type 'string'.
258     4 | DEBUG EVALUATE /'a' + ('a').
259       |                 ^~~
260
261 parse.sps:4.24-4.26: note: DEBUG EVALUATE: This operand has type 'string'.
262     4 | DEBUG EVALUATE /'a' + ('a').
263       |                        ^~~
264
265 'a' + ('a') => error
266
267 parse.sps:6.17-6.23: error: DEBUG EVALUATE: Both operands of < must have the
268 same type.
269     6 | DEBUG EVALUATE /1 < 'a'.
270       |                 ^~~~~~~
271
272 parse.sps:6.17: note: DEBUG EVALUATE: This operand has type 'number'.
273     6 | DEBUG EVALUATE /1 < 'a'.
274       |                 ^
275
276 parse.sps:6.21-6.23: note: DEBUG EVALUATE: This operand has type 'string'.
277     6 | DEBUG EVALUATE /1 < 'a'.
278       |                     ^~~
279
280 1 < 'a' => error
281
282 parse.sps:7.17-7.23: error: DEBUG EVALUATE: Both operands of < must have the
283 same type.
284     7 | DEBUG EVALUATE /'a' < 1.
285       |                 ^~~~~~~
286
287 parse.sps:7.17-7.19: note: DEBUG EVALUATE: This operand has type 'string'.
288     7 | DEBUG EVALUATE /'a' < 1.
289       |                 ^~~
290
291 parse.sps:7.23: note: DEBUG EVALUATE: This operand has type 'number'.
292     7 | DEBUG EVALUATE /'a' < 1.
293       |                       ^
294
295 'a' < 1 => error
296
297 parse.sps:8.17-8.31: error: DEBUG EVALUATE: Both operands of < must have the
298 same type.
299     8 | DEBUG EVALUATE /'a' < 'b' < 'c'.
300       |                 ^~~~~~~~~~~~~~~
301
302 parse.sps:8.17-8.25: note: DEBUG EVALUATE: This operand has type 'number'.
303     8 | DEBUG EVALUATE /'a' < 'b' < 'c'.
304       |                 ^~~~~~~~~
305
306 parse.sps:8.29-8.31: note: DEBUG EVALUATE: This operand has type 'string'.
307     8 | DEBUG EVALUATE /'a' < 'b' < 'c'.
308       |                             ^~~
309
310 'a' < 'b' < 'c' => error
311 ])
312 AT_CLEANUP
313
314 AT_SETUP([unary operator type mismatch])
315 AT_KEYWORDS([expression expressions parse negative])
316 AT_DATA([parse.sps], [dnl
317 DEBUG EVALUATE /-'a'.
318 DEBUG EVALUATE /----'a'.
319 DEBUG EVALUATE /NOT 'a'.
320 DEBUG EVALUATE /NOT NOT NOT 'a'.
321 DEBUG EVALUATE /NOT F5.2.
322 ])
323 AT_CHECK([pspp --testing-mode parse.sps], [1], [dnl
324 parse.sps:1.17-1.20: error: DEBUG EVALUATE: The unary - operator requires a
325 numeric operand.
326     1 | DEBUG EVALUATE /-'a'.
327       |                 ^~~~
328
329 parse.sps:1.18-1.20: note: DEBUG EVALUATE: The operand of - has type 'string'.
330     1 | DEBUG EVALUATE /-'a'.
331       |                  ^~~
332
333 -'a' => error
334
335 parse.sps:2.17-2.23: error: DEBUG EVALUATE: The unary - operator requires a
336 numeric operand.
337     2 | DEBUG EVALUATE /----'a'.
338       |                 ^~~~~~~
339
340 parse.sps:2.21-2.23: note: DEBUG EVALUATE: The operand of - has type 'string'.
341     2 | DEBUG EVALUATE /----'a'.
342       |                     ^~~
343
344 ----'a' => error
345
346 parse.sps:3.17-3.23: error: DEBUG EVALUATE: The unary NOT operator requires a
347 numeric operand.
348     3 | DEBUG EVALUATE /NOT 'a'.
349       |                 ^~~~~~~
350
351 parse.sps:3.21-3.23: note: DEBUG EVALUATE: The operand of NOT has type
352 'string'.
353     3 | DEBUG EVALUATE /NOT 'a'.
354       |                     ^~~
355
356 NOT 'a' => error
357
358 parse.sps:4.17-4.31: error: DEBUG EVALUATE: The unary NOT operator requires a
359 numeric operand.
360     4 | DEBUG EVALUATE /NOT NOT NOT 'a'.
361       |                 ^~~~~~~~~~~~~~~
362
363 parse.sps:4.29-4.31: note: DEBUG EVALUATE: The operand of NOT has type
364 'string'.
365     4 | DEBUG EVALUATE /NOT NOT NOT 'a'.
366       |                             ^~~
367
368 NOT NOT NOT 'a' => error
369
370 parse.sps:5.17-5.24: error: DEBUG EVALUATE: The unary NOT operator requires a
371 numeric operand.
372     5 | DEBUG EVALUATE /NOT F5.2.
373       |                 ^~~~~~~~
374
375 parse.sps:5.21-5.24: note: DEBUG EVALUATE: The operand of NOT has type
376 'format'.
377     5 | DEBUG EVALUATE /NOT F5.2.
378       |                     ^~~~
379
380 NOT F5.2 => error
381 ])
382 AT_CLEANUP
383
384 AT_SETUP([parsing with negative numbers])
385 AT_KEYWORDS([expression expressions parse])
386 AT_DATA([parse.sps], [dnl
387 DEBUG EVALUATE NOOPT POSTFIX /-2**3.
388 DEBUG EVALUATE NOOPT POSTFIX /-2**-3**-4.
389 DEBUG EVALUATE/1 - 2.
390 ])
391 AT_CHECK([pspp --testing-mode parse.sps], [0], [dnl
392 number: n<2> number: n<3> POW NEG return_number
393
394 parse.sps:2.31-2.40: warning: DEBUG EVALUATE: The exponentiation operator
395 (`**') is left-associative: `a**b**c' equals `(a**b)**c', not `a**(b**c)'.  To
396 disable this warning, insert parentheses.
397     2 | DEBUG EVALUATE NOOPT POSTFIX /-2**-3**-4.
398       |                               ^~~~~~~~~~
399
400 number: n<2> number: n<-3> POW number: n<-4> POW NEG return_number
401
402 1 - 2 => -1.00
403 ])
404 AT_CLEANUP
405
406 AT_SETUP([system variables])
407 AT_KEYWORDS([expression expressions parse])
408 AT_DATA([parse.sps], [dnl
409 DEBUG EVALUATE /$WIDTH.
410 DEBUG EVALUATE /$LENGTH.
411 DEBUG EVALUATE /$SYSMIS.
412 ])
413 AT_CHECK([pspp --testing-mode parse.sps], [0], [dnl
414 $WIDTH => 79.00
415
416 $LENGTH => 24.00
417
418 $SYSMIS => sysmis
419 ])
420 AT_CLEANUP
421
422 # This test will fail if the current date changes during the test.
423 AT_SETUP([system variables - $DATE $DATE11 $JDATE $TIME])
424 AT_KEYWORDS([expression expressions parse])
425 # Get the date in the formats that $DATE and $DATE11 support.
426 date=$(date +%d-%^b-%y)
427 date11=$(date +%d-%^b-%Y)
428 echo "date=$date"               # Should be date=DD-MMM-YY.
429 echo "date11=$date11"   # Should be date11=DD-MMM-YYYY.
430
431 # Maybe we don't have the 'date' program or it doesn't work as we
432 # expect.  Check by trying to see if $date and $date11 are in the
433 # expected format.  If not, skip the test.
434 AS_CASE([$date],
435   [[[0-9][0-9]-[A-Z][A-Z][A-Z]-[0-9][0-9]]], [],
436   [AT_SKIP_IF([:])])
437 AS_CASE([$date11],
438   [[[0-9][0-9]-[A-Z][A-Z][A-Z]-[0-9][0-9][0-9][0-9]]], [],
439   [AT_SKIP_IF([:])])
440
441 AT_DATA([parse.sps], [dnl
442 DEBUG EVALUATE /$DATE.
443 DEBUG EVALUATE /$DATE11.
444 DEBUG EVALUATE FORMAT=DATE9 /$JDATE * 86400.
445 DEBUG EVALUATE FORMAT=DATE9 /$TIME.
446 ])
447 AT_CHECK_UNQUOTED([pspp --testing-mode parse.sps], [0], [dnl
448 \$DATE => "$date"
449
450 \$DATE11 => "$date11"
451
452 \$JDATE * 86400 => $date
453
454 \$TIME => $date
455 ])
456 AT_CLEANUP
457
458 AT_SETUP([expressions - negative checks])
459 AT_KEYWORDS([expression expressions parse])
460 AT_DATA([evaluate-base.sps], [dnl
461 SET EPOCH 1940.
462 DEBUG EVALUATE SET opt.
463 DEBUG EVALUATE /$nonexistent.
464 DEBUG EVALUATE /RANGE(1, 2).
465 DEBUG EVALUATE /CONCAT.1('a', 'b').
466 DEBUG EVALUATE /foobar(x).
467 DEBUG EVALUATE /CONCAT.1('a' b).
468 DEBUG EVALUATE /NCDF.CHISQ(1, 2, 3).
469 DEBUG EVALUATE (a=1)(b=2) VECTOR/v('abc').
470 ])
471
472 for opt in OPT NOOPT; do
473     AS_BOX([$opt])
474     sed "s/opt/$opt/" < evaluate-base.sps > evaluate.sps
475     AT_CHECK([pspp --testing-mode evaluate.sps], [1],
476 [[evaluate.sps:3: error: DEBUG EVALUATE: Unknown system variable $nonexistent.
477
478 $nonexistent => error
479
480 evaluate.sps:4.17-4.27: error: DEBUG EVALUATE: RANGE(number, number, number[,
481 number, number]...) must have an odd number of arguments.
482     4 | DEBUG EVALUATE /RANGE(1, 2).
483       |                 ^~~~~~~~~~~
484
485 RANGE(1, 2) => error
486
487 evaluate.sps:5.17-5.34: error: DEBUG EVALUATE: CONCAT(string[, string]...)
488 function cannot accept suffix .1 to specify the minimum number of valid
489 arguments.
490     5 | DEBUG EVALUATE /CONCAT.1('a', 'b').
491       |                 ^~~~~~~~~~~~~~~~~~
492
493 CONCAT.1('a', 'b') => error
494
495 evaluate.sps:6: error: DEBUG EVALUATE: No function or vector named foobar.
496
497 foobar(x) => error
498
499 evaluate.sps:7.30: error: DEBUG EVALUATE: Syntax error at `b': expecting `,' or
500 `)'.
501
502 CONCAT.1('a' b) => error
503
504 evaluate.sps:8.17-8.35: error: DEBUG EVALUATE: NCDF.CHISQ(number, number,
505 number) is not available in this version of PSPP.
506     8 | DEBUG EVALUATE /NCDF.CHISQ(1, 2, 3).
507       |                 ^~~~~~~~~~~~~~~~~~~
508
509 NCDF.CHISQ(1, 2, 3) => error
510
511 evaluate.sps:9.34-9.41: error: DEBUG EVALUATE: A vector index must be numeric.
512     9 | DEBUG EVALUATE (a=1)(b=2) VECTOR/v('abc').
513       |                                  ^~~~~~~~
514
515 evaluate.sps:9.36-9.40: note: DEBUG EVALUATE: This vector index has type
516 'string'.
517     9 | DEBUG EVALUATE (a=1)(b=2) VECTOR/v('abc').
518       |                                    ^~~~~
519
520 v('abc') => error
521 ]])
522 done
523 AT_CLEANUP