]> gitweb.factorcode.org Git - factor.git/blob - basis/locals/locals-tests.factor
1549a776631bf1252af7a32e28917c2f588f7807
[factor.git] / basis / locals / locals-tests.factor
1 USING: locals math sequences tools.test hashtables words kernel
2 namespaces arrays strings prettyprint io.streams.string parser
3 accessors generic eval combinators combinators.short-circuit
4 combinators.short-circuit.smart math.order math.functions
5 definitions compiler.units fry lexer words.symbol see multiline ;
6 IN: locals.tests
7
8 :: foo ( a b -- a a ) a a ;
9
10 [ 1 1 ] [ 1 2 foo ] unit-test
11
12 :: add-test ( a b -- c ) a b + ;
13
14 [ 3 ] [ 1 2 add-test ] unit-test
15
16 :: sub-test ( a b -- c ) a b - ;
17
18 [ -1 ] [ 1 2 sub-test ] unit-test
19
20 :: map-test ( a b -- seq ) a [ b + ] map ;
21
22 [ { 5 6 7 } ] [ { 1 2 3 } 4 map-test ] unit-test
23
24 :: map-test-2 ( seq inc -- seq ) seq [| elt | elt inc + ] map ;
25
26 [ { 5 6 7 } ] [ { 1 2 3 } 4 map-test-2 ] unit-test
27
28 :: let-test ( c -- d )
29     [let | a [ 1 ] b [ 2 ] | a b + c + ] ;
30
31 [ 7 ] [ 4 let-test ] unit-test
32
33 :: let-test-2 ( a -- a )
34     a [let | a [ ] | [let | b [ a ] | a ] ] ;
35
36 [ 3 ] [ 3 let-test-2 ] unit-test
37
38 :: let-test-3 ( a -- a )
39     a [let | a [ ] | [let | b [ [ a ] ] | [let | a [ 3 ] | b ] ] ] ;
40
41 :: let-test-4 ( a -- b )
42     a [let | a [ 1 ] b [ ] | a b 2array ] ;
43
44 [ { 1 2 } ] [ 2 let-test-4 ] unit-test
45
46 :: let-test-5 ( a b -- b )
47     a b [let | a [ ] b [ ] | a b 2array ] ;
48
49 [ { 2 1 } ] [ 1 2 let-test-5 ] unit-test
50
51 :: let-test-6 ( a -- b )
52     a [let | a [ ] b [ 1 ] | a b 2array ] ;
53
54 [ { 2 1 } ] [ 2 let-test-6 ] unit-test
55
56 [ -1 ] [ -1 let-test-3 call ] unit-test
57
58 [ 5 ] [
59     [let | a [ 3 ] | [wlet | func [ a + ] | 2 func ] ]
60 ] unit-test
61
62 :: wlet-test-2 ( a b -- seq )
63     [wlet | add-b [ b + ] |
64         a [ add-b ] map ] ;
65
66
67 [ { 4 5 6 } ] [ { 2 3 4 } 2 wlet-test-2 ] unit-test
68     
69 :: wlet-test-3 ( a -- b )
70     [wlet | add-a [ a + ] | [ add-a ] ]
71     [let | a [ 3 ] | a swap call ] ;
72
73 [ 5 ] [ 2 wlet-test-3 ] unit-test
74
75 :: wlet-test-4 ( a -- b )
76     [wlet | sub-a [| b | b a - ] |
77         3 sub-a ] ;
78
79 [ -7 ] [ 10 wlet-test-4 ] unit-test
80
81 :: write-test-1 ( n! -- q )
82     [| i | n i + dup n! ] ;
83
84 0 write-test-1 "q" set
85
86 { 1 1 } "q" get must-infer-as
87
88 [ 1 ] [ 1 "q" get call ] unit-test
89
90 [ 2 ] [ 1 "q" get call ] unit-test
91
92 [ 3 ] [ 1 "q" get call ] unit-test
93
94 [ 5 ] [ 2 "q" get call ] unit-test
95
96 :: write-test-2 ( -- q )
97     [let | n! [ 0 ] |
98         [| i | n i + dup n! ] ] ;
99
100 write-test-2 "q" set
101
102 [ 1 ] [ 1 "q" get call ] unit-test
103
104 [ 2 ] [ 1 "q" get call ] unit-test
105
106 [ 3 ] [ 1 "q" get call ] unit-test
107
108 [ 5 ] [ 2 "q" get call ] unit-test
109
110 [ 10 20 ]
111 [
112     20 10 [| a! | [| b! | a b ] ] call call
113 ] unit-test
114
115 :: write-test-3 ( a! -- q ) [| b | b a! ] ;
116
117 [ ] [ 1 2 write-test-3 call ] unit-test
118
119 :: write-test-4 ( x! -- q ) [ [let | y! [ 0 ] | f x! ] ] ;
120
121 [ ] [ 5 write-test-4 drop ] unit-test
122
123 ! Not really a write test; just enforcing consistency
124 :: write-test-5 ( x -- y )
125     [wlet | fun! [ x + ] | 5 fun! ] ;
126
127 [ 9 ] [ 4 write-test-5 ] unit-test
128
129 SYMBOL: a
130
131 :: use-test ( a b c -- a b c )
132     USE: kernel
133     a b c ;
134
135 [ t ] [ a symbol? ] unit-test
136
137 :: let-let-test ( n -- n ) [let | n [ n 3 + ] | n ] ;
138
139 [ 13 ] [ 10 let-let-test ] unit-test
140
141 GENERIC: lambda-generic ( a b -- c )
142
143 GENERIC# lambda-generic-1 1 ( a b -- c )
144
145 M:: integer lambda-generic-1 ( a b -- c ) a b * ;
146
147 M:: string lambda-generic-1 ( a b -- c )
148     a b CHAR: x <string> lambda-generic ;
149
150 M:: integer lambda-generic ( a b -- c ) a b lambda-generic-1 ;
151
152 GENERIC# lambda-generic-2 1 ( a b -- c )
153
154 M:: integer lambda-generic-2 ( a b -- c )
155     a CHAR: x <string> b lambda-generic ;
156
157 M:: string lambda-generic-2 ( a b -- c ) a b append ;
158
159 M:: string lambda-generic ( a b -- c ) a b lambda-generic-2 ;
160
161 [ 10 ] [ 5 2 lambda-generic ] unit-test
162
163 [ "abab" ] [ "aba" "b" lambda-generic ] unit-test
164
165 [ "abaxxx" ] [ "aba" 3 lambda-generic ] unit-test
166
167 [ "xaba" ] [ 1 "aba" lambda-generic ] unit-test
168
169 [ ] [ \ lambda-generic-1 see ] unit-test
170
171 [ ] [ \ lambda-generic-2 see ] unit-test
172
173 [ ] [ \ lambda-generic see ] unit-test
174
175 :: unparse-test-1 ( a -- ) [let | a! [ 3 ] | ] ;
176
177 [ "[let | a! [ 3 ] | ]" ] [
178     \ unparse-test-1 "lambda" word-prop body>> first unparse
179 ] unit-test
180
181 :: unparse-test-2 ( -- ) [wlet | a! [ ] | ] ;
182
183 [ "[wlet | a! [ ] | ]" ] [
184     \ unparse-test-2 "lambda" word-prop body>> first unparse
185 ] unit-test
186
187 :: unparse-test-3 ( -- b ) [| a! | ] ;
188
189 [ "[| a! | ]" ] [
190     \ unparse-test-3 "lambda" word-prop body>> first unparse
191 ] unit-test
192
193 DEFER: xyzzy
194
195 [ ] [
196     "IN: locals.tests USE: math GENERIC: xyzzy ( a -- b ) M: integer xyzzy ;"
197     <string-reader> "lambda-generic-test" parse-stream drop
198 ] unit-test
199
200 [ 10 ] [ 10 xyzzy ] unit-test
201
202 [ ] [
203     "IN: locals.tests USE: math USE: locals GENERIC: xyzzy ( a -- b ) M:: integer xyzzy ( n -- x ) 5 ;"
204     <string-reader> "lambda-generic-test" parse-stream drop
205 ] unit-test
206
207 [ 5 ] [ 10 xyzzy ] unit-test
208
209 :: let*-test-1 ( a -- b )
210     [let* | b [ a 1+ ]
211             c [ b 1+ ] |
212         a b c 3array ] ;
213
214 [ { 1 2 3 } ] [ 1 let*-test-1 ] unit-test
215
216 :: let*-test-2 ( a -- b )
217     [let* | b [ a 1+ ]
218             c! [ b 1+ ] |
219         a b c 3array ] ;
220
221 [ { 1 2 3 } ] [ 1 let*-test-2 ] unit-test
222
223 :: let*-test-3 ( a -- b )
224     [let* | b [ a 1+ ]
225             c! [ b 1+ ] |
226         c 1+ c!  a b c 3array ] ;
227
228 [ { 1 2 4 } ] [ 1 let*-test-3 ] unit-test
229
230 :: let*-test-4 ( a b -- c d )
231     [let | a [ b ]
232            b [ a ] |
233         [let* | a'  [ a  ]
234                 a'' [ a' ]
235                 b'  [ b  ]
236                 b'' [ b' ] |
237             a'' b'' ] ] ;
238
239 [ "xxx" "yyy" ] [ "yyy" "xxx" let*-test-4 ] unit-test
240
241 GENERIC: next-method-test ( a -- b )
242
243 M: integer next-method-test 3 + ;
244
245 M:: fixnum next-method-test ( a -- b ) a call-next-method 1 + ;
246
247 [ 5 ] [ 1 next-method-test ] unit-test
248
249 : no-with-locals-test ( -- seq ) { 1 2 3 } [| x | x 3 + ] map ;
250
251 [ { 4 5 6 } ] [ no-with-locals-test ] unit-test
252
253 { 3 0 } [| a b c | ] must-infer-as
254
255 [ ] [ 1 [let | a [ ] | ] ] unit-test
256
257 [ 3 ] [ 1 [let | a [ ] | 3 ] ] unit-test
258
259 [ ] [ 1 2 [let | a [ ] b [ ] | ] ] unit-test
260
261 :: a-word-with-locals ( a b -- ) ;
262
263 CONSTANT: new-definition "USING: math ;\nIN: locals.tests\n: a-word-with-locals ( -- x ) 2 3 + ;\n"
264
265 [ ] [ new-definition eval( -- ) ] unit-test
266
267 [ t ] [
268     [ \ a-word-with-locals see ] with-string-writer
269     new-definition =
270 ] unit-test
271
272 CONSTANT: method-definition "USING: locals locals.tests sequences ;\nM:: sequence method-with-locals ( a -- y ) a reverse ;\n"
273
274 GENERIC: method-with-locals ( x -- y )
275
276 M:: sequence method-with-locals ( a -- y ) a reverse ;
277
278 [ t ] [
279     [ \ sequence \ method-with-locals method see ] with-string-writer
280     method-definition =
281 ] unit-test
282
283 :: cond-test ( a b -- c )
284     {
285         { [ a b < ] [ 3 ] }
286         { [ a b = ] [ 4 ] }
287         { [ a b > ] [ 5 ] }
288     } cond ;
289
290 \ cond-test def>> must-infer
291
292 [ 3 ] [ 1 2 cond-test ] unit-test
293 [ 4 ] [ 2 2 cond-test ] unit-test
294 [ 5 ] [ 3 2 cond-test ] unit-test
295
296 :: 0&&-test ( a -- ? )
297     { [ a integer? ] [ a even? ] [ a 10 > ] } 0&& ;
298
299 \ 0&&-test def>> must-infer
300
301 [ f ] [ 1.5 0&&-test ] unit-test
302 [ f ] [ 3 0&&-test ] unit-test
303 [ f ] [ 8 0&&-test ] unit-test
304 [ t ] [ 12 0&&-test ] unit-test
305
306 :: &&-test ( a -- ? )
307     { [ a integer? ] [ a even? ] [ a 10 > ] } && ;
308
309 \ &&-test def>> must-infer
310
311 [ f ] [ 1.5 &&-test ] unit-test
312 [ f ] [ 3 &&-test ] unit-test
313 [ f ] [ 8 &&-test ] unit-test
314 [ t ] [ 12 &&-test ] unit-test
315
316 :: let-and-cond-test-1 ( -- a )
317     [let | a [ 10 ] |
318         [let | a [ 20 ] |
319             {
320                 { [ t ] [ [let | c [ 30 ] | a ] ] }
321             } cond
322         ]
323     ] ;
324
325 \ let-and-cond-test-1 def>> must-infer
326
327 [ 20 ] [ let-and-cond-test-1 ] unit-test
328
329 :: let-and-cond-test-2 ( -- pair )
330     [let | A [ 10 ] |
331         [let | B [ 20 ] |
332             { { [ t ] [ { A B } ] } } cond
333         ]
334     ] ;
335
336 \ let-and-cond-test-2 def>> must-infer
337
338 [ { 10 20 } ] [ let-and-cond-test-2 ] unit-test
339
340 [ { 10       } ] [ 10       [| a     | { a     } ] call ] unit-test
341 [ { 10 20    } ] [ 10 20    [| a b   | { a b   } ] call ] unit-test
342 [ { 10 20 30 } ] [ 10 20 30 [| a b c | { a b c } ] call ] unit-test
343
344 [ { 10 20 30 } ] [ [let | a [ 10 ] b [ 20 ] c [ 30 ] | { a b c } ] ] unit-test
345
346 [ V{ 10 20 30 } ] [ 10 20 30 [| a b c | V{ a b c } ] call ] unit-test
347
348 [ H{ { 10 "a" } { 20 "b" } { 30 "c" } } ]
349 [ 10 20 30 [| a b c | H{ { a "a" } { b "b" } { c "c" } } ] call ] unit-test
350
351 [ T{ slice f 0 3 "abc" } ]
352 [ 0 3 "abc" [| from to seq | T{ slice f from to seq } ] call ] unit-test
353
354 { 3 1 } [| from to seq | T{ slice f from to seq } ] must-infer-as
355
356 ERROR: punned-class x ;
357
358 [ T{ punned-class f 3 } ] [ 3 [| a | T{ punned-class f a } ] call ] unit-test
359
360 :: literal-identity-test ( -- a b )
361     { 1 } V{ } ;
362
363 [ t t ] [
364     literal-identity-test
365     literal-identity-test
366     [ eq? ] [ eq? ] bi-curry* bi*
367 ] unit-test
368
369 :: mutable-local-in-literal-test ( a! -- b ) a 1 + a! { a } ;
370
371 [ { 4 } ] [ 3 mutable-local-in-literal-test ] unit-test
372
373 :: compare-case ( obj1 obj2 lt-quot eq-quot gt-quot -- )
374     obj1 obj2 <=> {
375         { +lt+ [ lt-quot call ] }
376         { +eq+ [ eq-quot call ] }
377         { +gt+ [ gt-quot call ] }
378     } case ; inline
379
380 [ [ ] [ ] [ ] compare-case ] must-infer
381
382 :: big-case-test ( a -- b )
383     a {
384         { 0 [ a 1 + ] }
385         { 1 [ a 1 - ] }
386         { 2 [ a 1 swap / ] }
387         { 3 [ a dup * ] }
388         { 4 [ a sqrt ] }
389         { 5 [ a a ^ ] }
390     } case ;
391
392 \ big-case-test def>> must-infer
393
394 [ 9 ] [ 3 big-case-test ] unit-test
395
396 ! Dan found this problem
397 : littledan-case-problem-1 ( a -- b )
398     {
399         { t [ 3 ] }
400         { f [ 4 ] }
401         [| x | x 12 + { "howdy" } nth ]
402     } case ;
403
404 \ littledan-case-problem-1 def>> must-infer
405
406 [ "howdy" ] [ -12 \ littledan-case-problem-1 def>> call ] unit-test
407 [ "howdy" ] [ -12 littledan-case-problem-1 ] unit-test
408
409 :: littledan-case-problem-2 ( a -- b )
410     a {
411         { t [ a not ] }
412         { f [ 4 ] }
413         [| x | x a - { "howdy" } nth ]
414     } case ;
415
416 \ littledan-case-problem-2 def>> must-infer
417
418 [ "howdy" ] [ -12 \ littledan-case-problem-2 def>> call ] unit-test
419 [ "howdy" ] [ -12 littledan-case-problem-2 ] unit-test
420
421 :: littledan-cond-problem-1 ( a -- b )
422     a {
423         { [ dup 0 < ] [ drop a not ] }
424         { [| y | y y 0 > ] [ drop 4 ] }
425         [| x | x a - { "howdy" } nth ]
426     } cond ;
427
428 \ littledan-cond-problem-1 def>> must-infer
429
430 [ f ] [ -12 \ littledan-cond-problem-1 def>> call ] unit-test
431 [ 4 ] [ 12 \ littledan-cond-problem-1 def>> call ] unit-test
432 [ "howdy" ] [ 0 \ littledan-cond-problem-1 def>> call ] unit-test
433 [ f ] [ -12 littledan-cond-problem-1 ] unit-test
434 [ 4 ] [ 12 littledan-cond-problem-1 ] unit-test
435 [ "howdy" ] [ 0 littledan-cond-problem-1 ] unit-test
436
437 /*
438 :: littledan-case-problem-3 ( a quot -- b )
439     a {
440         { t [ a not ] }
441         { f [ 4 ] }
442         quot
443     } case ; inline
444
445 [ f ] [ t [ ] littledan-case-problem-3 ] unit-test
446 [ 144 ] [ 12 [ sq ] littledan-case-problem-3 ] unit-test
447 [| | [| a | a ] littledan-case-problem-3 ] must-infer
448
449 : littledan-case-problem-4 ( a -- b )
450     [ 1 + ] littledan-case-problem-3 ;
451
452 \ littledan-case-problem-4 def>> must-infer
453 */
454
455 GENERIC: lambda-method-forget-test ( a -- b )
456
457 M:: integer lambda-method-forget-test ( a -- b ) a ;
458
459 [ ] [ [ M\ integer lambda-method-forget-test forget ] with-compilation-unit ] unit-test
460
461 [ 10 ] [ 10 [| A | { [ A ] } ] call first call ] unit-test
462
463 [
464     "USING: locals fry math ; 1 '[ [let | A [ 10 ] | A _ + ] ]"
465     eval( -- ) call
466 ] [ error>> >r/r>-in-fry-error? ] must-fail-with
467     
468 :: (funny-macro-test) ( obj quot -- ? ) obj { quot } 1&& ; inline
469 : funny-macro-test ( n -- ? ) [ odd? ] (funny-macro-test) ;
470
471 \ funny-macro-test def>> must-infer
472
473 [ t ] [ 3 funny-macro-test ] unit-test
474 [ f ] [ 2 funny-macro-test ] unit-test
475
476 ! Some odd parser corner cases
477 [ "USE: locals [let" eval( -- ) ] [ error>> unexpected-eof? ] must-fail-with
478 [ "USE: locals [let |" eval( -- ) ] [ error>> unexpected-eof? ] must-fail-with
479 [ "USE: locals [let | a" eval( -- ) ] [ error>> unexpected-eof? ] must-fail-with
480 [ "USE: locals [|" eval( -- ) ] [ error>> unexpected-eof? ] must-fail-with
481
482 [ 25 ] [ 5 [| a | { [ a sq ] } cond ] call ] unit-test
483 [ 25 ] [ 5 [| | { [| a | a sq ] } ] call first call ] unit-test
484
485 :: FAILdog-1 ( -- b ) { [| c | c ] } ;
486
487 \ FAILdog-1 def>> must-infer
488
489 :: FAILdog-2 ( a -- b ) a { [| c | c ] } cond ;
490
491 \ FAILdog-2 def>> must-infer
492
493 [ 3 ] [ 3 [| a | \ a ] call ] unit-test
494
495 [ "USE: locals [| | { [let | a [ 0 ] | a ] } ]" eval( -- ) ] must-fail
496
497 [ "USE: locals [| | { [wlet | a [ 0 ] | a ] } ]" eval( -- ) ] must-fail
498
499 [ "USE: locals [| | { [let* | a [ 0 ] | a ] } ]" eval( -- ) ] must-fail
500
501 [ "USE: locals [| | [let | a! [ 0 ] | { a! } ] ]" eval( -- ) ] must-fail
502
503 [ "USE: locals [| | [wlet | a [ 0 ] | { a } ] ]" eval( -- ) ] must-fail
504
505 [ "USE: locals [| | { :> a } ]" eval( -- ) ] must-fail
506
507 [ "USE: locals 3 :> a" eval( -- ) ] must-fail
508
509 [ 3 ] [ 3 [| | :> a a ] call ] unit-test
510
511 [ 3 ] [ 3 [| | :> a! a ] call ] unit-test
512
513 [ 3 ] [ 2 [| | :> a! a 1+ a! a ] call ] unit-test
514
515 :: wlet-&&-test ( a -- ? )
516     [wlet | is-integer? [ a integer? ]
517             is-even? [ a even? ]
518             >10? [ a 10 > ] |
519         { [ is-integer? ] [ is-even? ] [ >10? ] } &&
520     ] ;
521
522 \ wlet-&&-test def>> must-infer
523 [ f ] [ 1.5 wlet-&&-test ] unit-test
524 [ f ] [ 3 wlet-&&-test ] unit-test
525 [ f ] [ 8 wlet-&&-test ] unit-test
526 [ t ] [ 12 wlet-&&-test ] unit-test
527
528 : fry-locals-test-1 ( -- n )
529     [let | | 6 '[ [let | A [ 4 ] | A _ + ] ] call ] ;
530
531 \ fry-locals-test-1 def>> must-infer
532 [ 10 ] [ fry-locals-test-1 ] unit-test
533
534 :: fry-locals-test-2 ( -- n )
535     [let | | 6 '[ [let | A [ 4 ] | A _ + ] ] call ] ;
536
537 \ fry-locals-test-2 def>> must-infer
538 [ 10 ] [ fry-locals-test-2 ] unit-test
539
540 [ 1 ] [ 3 4 [| | '[ [ _ swap - ] call ] call ] call ] unit-test
541 [ -1 ] [ 3 4 [| | [| a | a - ] call ] call ] unit-test
542 [ -1 ] [ 3 4 [| | [| a | a - ] curry call ] call ] unit-test
543 [ -1 ] [ 3 4 [| a | a - ] curry call ] unit-test
544 [ 1 ] [ 3 4 [| | '[ [| a | _ a - ] call ] call ] call ] unit-test
545 [ -1 ] [ 3 4 [| | '[ [| a | a _ - ] call ] call ] call ] unit-test
546
547 [ { 1 2 3 4 } ] [
548     1 3 2 4
549     [| | '[ [| a b | a _ b _ 4array ] call ] call ] call
550 ] unit-test
551
552 [ 10 ] [
553     [| | 0 '[ [let | A [ 10 ] | A _ + ] ] call ] call
554 ] unit-test
555
556 ! littledan found this problem
557 [ "bar" ] [ [let | a [ [let | foo [ "bar" ] | foo ] ] | a ] ] unit-test
558 [ 10 ] [ [let | a [ 10 ] | [let | b [ a ] | b ] ] ] unit-test
559
560 [ { \ + } ] [ [let | x [ \ + ] | { \ x } ] ] unit-test
561
562 [ { \ + 3 } ] [ [let | a [ 3 ] | { \ + a } ] ] unit-test
563
564 [ 3 ] [ [let | a [ \ + ] | 1 2 [ \ a execute ] ] call ] unit-test
565
566 ! erg found this problem
567 :: erg's-:>-bug ( n ? -- n ) ? [ n :> n n ] [ n :> b b ] if ;
568
569 [ 3 ] [ 3 f erg's-:>-bug ] unit-test
570     
571 [ 3 ] [ 3 t erg's-:>-bug ] unit-test
572
573 :: erg's-:>-bug-2 ( n ? -- n ) ? n '[ _ :> n n ] [ n :> b b ] if ;
574
575 [ 3 ] [ 3 f erg's-:>-bug-2 ] unit-test
576     
577 [ 3 ] [ 3 t erg's-:>-bug-2 ] unit-test
578
579 ! dharmatech found this problem
580 GENERIC: ed's-bug ( a -- b )
581
582 M: string ed's-bug reverse ;
583 M: integer ed's-bug neg ;
584
585 :: ed's-test-case ( a -- b )
586    { [ a ed's-bug ] } && ;
587
588 [ t ] [ \ ed's-test-case optimized? ] unit-test