* src/pmc/scalar.pmc:
[parrot.git] / t / op / stacks.t
blob43086e753eec5a36537c777203dcfcc31b0095cb
1 #!perl
2 # Copyright (C) 2001-2005, The Perl Foundation.
3 # $Id$
5 use strict;
6 use warnings;
7 use lib qw( . lib ../lib ../../lib );
8 use Test::More;
9 use Parrot::Test tests => 24;
11 =head1 NAME
13 t/op/stacks.t - Stacks
15 =head1 SYNOPSIS
17         % prove t/op/stacks.t
19 =head1 DESCRIPTION
21 Tests for stack operations, currently C<push*>, C<push_*_c> and C<pop*>
22 where C<*> is not C<p>.
24 =cut
26 # Tests for stack operations, currently push*, push_*_c and pop*
27 # where * != p.
29 # Assembler code is partially generated by subs at bottom of file
31 # This defines two macros:
32 # fp_eq N, N, LABEL
33 # fp_ne N, N, LABEL
34 # which will conditionally branch
35 # to LABEL if abs(n,n) < epsilon
37 my $fp_equality_macro = <<'ENDOFMACRO';
38 .macro fp_eq(J,K,L)
39         save    N0
40         save    N1
41         save    N2
43         set     N0, .J
44         set     N1, .K
45         sub     N2, N1,N0
46         abs     N2, N2
47         gt      N2, 0.000001, .$FPEQNOK
49         restore N2
50         restore N1
51         restore N0
52         branch  .L
53 .local $FPEQNOK:
54         restore N2
55         restore N1
56         restore N0
57 .endm
58 .macro fp_ne(J,K,L)
59         save    N0
60         save    N1
61         save    N2
63         set     N0, .J
64         set     N1, .K
65         sub     N2, N1,N0
66         abs     N2, N2
67         lt      N2, 0.000001, .$FPNENOK
69         restore N2
70         restore N1
71         restore N0
72         branch  .L
73 .local $FPNENOK:
74         restore N2
75         restore N1
76         restore N0
77 .endm
78 ENDOFMACRO
80 ###############     Tests   ##################
82 # Test proper stack chunk handling
83 pasm_output_is( <<CODE, <<'OUTPUT', 'save_i & restore_i' );
84         set     I3, 1
86 testloop:
87         set     I0, 0
88         set     I1, I3
90 saveloop:
91         inc     I0
92         save    I0
93         ne      I0, I1, saveloop
95 restoreloop:
96         restore I0
97         ne      I0, I1, error
98         dec     I1
99         ne      I1, 0, restoreloop
101         add     I3, I3, 1
102         ne      I3, 769, testloop       # At least 3 stack chunks
104         print   "OK\\n"
105 error:  end
106 CODE
108 OUTPUT
110 # Rotate
111 pasm_output_is( <<"CODE", <<'OUTPUT', 'rotate 0' );
112     set I0, 1
113     save I0
114     set I0, 2
115     save I0
116     rotate_up 0
117     restore I0
118     print I0
119     print "\\n"
120     end
121 CODE
123 OUTPUT
125 pasm_output_is( <<"CODE", <<'OUTPUT', 'rotate 1' );
126     set I0, 1
127     save I0
128     set I0, 2
129     save I0
130     rotate_up 1
131     restore I0
132     print I0
133     print "\\n"
134     end
135 CODE
137 OUTPUT
139 pasm_output_is( <<"CODE", <<'OUTPUT', 'rotate 2' );
140     set I0, 1
141     save I0
142     set I0, 2
143     save I0
144     rotate_up 2
145     restore I0
146     print I0
147     print "\\n"
148     end
149 CODE
151 OUTPUT
153 pasm_output_is( <<"CODE", <<'OUTPUT', 'rotate 3' );
154     set I0, 1
155     save I0
156     set I0, 2
157     save I0
158     set I0, 3
159     save I0
160     rotate_up 3
161     restore I0
162     print I0
163     restore I0
164     print I0
165     restore I0
166     print I0
167     print "\\n"
168     end
169 CODE
171 OUTPUT
173 pasm_output_is( <<"CODE", <<'OUTPUT', 'rotate -1' );
174     set I0, 1
175     save I0
176     set I0, 2
177     save I0
178     set I0, 3
179     save I0
180     rotate_up -1
181     restore I0
182     print I0
183     restore I0
184     print I0
185     restore I0
186     print I0
187     print "\\n"
188     end
189 CODE
191 OUTPUT
193 pasm_output_is( <<"CODE", <<'OUTPUT', 'rotate -2' );
194     set I0, 1
195     save I0
196     set I0, 2
197     save I0
198     set I0, 3
199     save I0
200     rotate_up -2
201     restore I0
202     print I0
203     restore I0
204     print I0
205     restore I0
206     print I0
207     print "\\n"
208     end
209 CODE
211 OUTPUT
213 pasm_output_is( <<"CODE", <<'OUTPUT', 'rotate -3' );
214     set I0, 1
215     save I0
216     set I0, 2
217     save I0
218     set I0, 3
219     save I0
220     rotate_up -3
221     restore I0
222     print I0
223     restore I0
224     print I0
225     restore I0
226     print I0
227     print "\\n"
228     end
229 CODE
231 OUTPUT
233 pasm_output_is( <<'CODE', <<'OUTPUT', 'rotate with a full stack chunk' );
234       set I0, 0
235 FOO:  save I0
236       inc I0
237       lt I0, 256, FOO
239       rotate_up 2
241       restore I1
242       print I1
243       print "\n"
244       end
245 CODE
247 OUTPUT
249 pasm_output_is( <<'CODE', <<'OUTPUT', 'rotate across stack chunk boundary' );
250       set I0, 0
251 FOO:  save I0
252       inc I0
253       lt I0, 257, FOO
255       rotate_up 2
257       restore I1
258       print I1
259       print "\n"
260       end
261 CODE
263 OUTPUT
265 pasm_output_is( <<'CODE', <<'OUTPUT', 'rotate by stack chunk size' );
266       set I0, 0
267 FOO:  save I0
268       inc I0
269       lt I0, 300, FOO
271       rotate_up -256
273       restore I1
274       print I1
275       print "\n"
276       end
277 CODE
279 OUTPUT
281 pasm_output_is( <<'CODE', <<'OUTPUT', 'rotate by more than stack chunk size' );
282       set I0, 0
283 FOO:  save I0
284       inc I0
285       lt I0, 300, FOO
287       rotate_up -257
289       restore I1
290       print I1
291       print "\n"
292       end
293 CODE
295 OUTPUT
297 pasm_output_is( <<"CODE", <<'OUTPUT', 'rotate up by more than stack size' );
298     set I0, 1
299     save I0
300     set I0, 2
301     save I0
302     rotate_up 3
303     end
304 CODE
305 Stack too shallow!
306 OUTPUT
308 pasm_output_is( <<"CODE", <<'OUTPUT', 'rotate down by more than stack size' );
309     set I0, 1
310     save I0
311     set I0, 2
312     save I0
313     rotate_up -3
314     end
315 CODE
316 Stack too shallow!
317 OUTPUT
319 pasm_output_is( <<'CODE', <<'OUTPUT', 'save/savec for strings' );
320       set S0, "Foobar"
321       savec S0
322       chopn S0, 3
323       print S0
324       print "\n"
325       restore S2
326       print S2
327       print "\n"
329       set S1, "Foobar"
330       save  S1
331       chopn S1, 3
332       print S1
333       print "\n"
334       restore S3
335       print S3
336       print "\n"
337       end
338 CODE
340 Foobar
343 OUTPUT
345 pasm_output_is( <<CODE, <<OUTPUT, "save, restore" );
346 @{[ $fp_equality_macro ]}
347         set     I0, 1
348         save    I0
349         set     I0, 2
350         print   I0
351         print   "\\n"
352         restore I0
353         print   I0
354         print   "\\n"
356         set     N0, 1.0
357         save    N0
358         set     N0, 2.0
359         .fp_eq  (N0, 2.0, EQ1)
360         print   "not "
361 EQ1:    print   "equal to 2.0\\n"
362         restore N0
363         .fp_eq  (N0, 1.0, EQ2)
364         print   "not "
365 EQ2:    print   "equal to 1.0\\n"
367         set     S0, "HONK\\n"
368         save    S0
369         set     S0, "HONK HONK\\n"
370         print   S0
371         restore S0
372         print   S0
374         save    123
375         restore I0
376         print   I0
377         print   "\\n"
379         save    3.14159
380         restore N0
381         .fp_eq  (N0, 3.14159, EQ3)
382         print   "<kansas> not "
383 EQ3:    print   "equal to PI\\n"
385         save    "All the world's people\\n"
386         restore S0
387         print   S0
389         new     P0, .String
390         set     P0, "never to escape\\n"
391         save    P0
392         new     P0, .String
393         set     P0, "find themselves caught in a loop\\n"
394         print   P0
395         restore P0
396         print   P0
398         end
399 CODE
402 equal to 2.0
403 equal to 1.0
404 HONK HONK
405 HONK
407 equal to PI
408 All the world's people
409 find themselves caught in a loop
410 never to escape
411 OUTPUT
413 pasm_output_is( <<CODE, <<OUTPUT, "entrytype" );
414         set     I0, 12
415         set     N0, 0.1
416         set     S0, "Difference Engine #2"
417         new     P0, .String
418         set     P0, "Shalmaneser"
420         save    P0
421         save    S0
422         save    "Wintermute"
423         save    N0
424         save    1.23
425         save    I0
426         save    12
428         print   "starting\\n"
430         set     I1, 0
431 LOOP:   entrytype       I0, I1
432         print   I0
433         print   "\\n"
434         inc     I1
435         lt      I1, 7, LOOP
437         print   "done\\n"
438         end
439 CODE
440 starting
448 done
449 OUTPUT
451 pasm_output_is( <<CODE, <<OUTPUT, "entrytype, beyond stack depth" );
452         save    12
453         print   "ready\\n"
454         entrytype       I0, 1
455         print   "done\\n"
456         end
457 CODE
458 ready
459 Stack Depth wrong
460 OUTPUT
462 pasm_output_is( <<'CODE', <<'OUTPUT', "depth op" );
463         depth I0
464         print I0
465         print "\n"
467         save "Foo"
468         depth I0
469         print I0
470         print "\n"
471         restore S0
473         set I1, 0
474 LOOP:   save I1
475         inc I1
476         lt I1, 1024, LOOP
477         depth I0
478         print I0
479         print "\n"
481         end
482 CODE
485 1024
486 OUTPUT
488 pasm_output_is( <<'CODE', <<'OUTPUT', "saveall/restoreall" );
489         set S0,"test ok"
490         set N0,4.3
491         set I0,6
492         saveall
493         set S0,"test not ok"
494         set N0,4.1
495         set I0,8
496         restoreall
497         print I0
498         print "\n"
499         print N0
500         print "\n"
501         print S0
502         print "\n"
503         end
504 CODE
506 4.300000
507 test ok
508 OUTPUT
510 pasm_output_is( <<CODE, <<'OUTPUT', "lookback" );
511 @{[ $fp_equality_macro ]}
512         save 1
513         save 1.0
514         save "Foo"
516         new P12, .Hash
517         set P12["Apple"], "Banana"
518         save P12
520         lookback P0, 0
521         lookback S0, 1
522         lookback N0, 2
523         lookback I0, 3
525         set S2, P0["Apple"]
526         eq S2, "Banana", OK1
527         print "not "
528 OK1:    print "ok 1\\n"
530         eq I0, 1, OK2
531         print "not "
532 OK2:    print "ok 2\\n"
534         .fp_eq (N0, 1.0, OK3)
535         print "not "
536 OK3:    print "ok 3\\n"
538         eq S0, "Foo", OK4
539         print "not "
540 OK4:    print "ok 4\\n"
542         lookback I1, -1
543         lookback N1, -2
544         lookback S1, -3
545         lookback P1, -4
547         eq I0, 1, OK5
548         print "not "
549 OK5:    print "ok 5\\n"
551         .fp_eq (N0, 1.0, OK6)
552         print "not "
553 OK6:    print "ok 6\\n"
555         eq S0, "Foo", OK7
556         print "not "
557 OK7:    print "ok 7\\n"
559         set S3, P1["Apple"]
560         eq S3, "Banana", OK8
561         print "not "
562 OK8:    print "ok 8\\n"
564         end
565 CODE
566 ok 1
567 ok 2
568 ok 3
569 ok 4
570 ok 5
571 ok 6
572 ok 7
573 ok 8
574 OUTPUT
576 SKIP: {
577     skip( "no stack limit currently", 3 );
578     pasm_output_is( <<CODE, <<'OUTPUT', "check limit - User" );
580         save I0
581         branch lp
582         end
583 CODE
584 Stack 'User' too deep
585 OUTPUT
587     pasm_output_is( <<CODE, <<'OUTPUT', "check limit - Pad" );
589         new_pad 0
590         branch lp
591         end
592 CODE
593 Stack 'Pad' too deep
594 OUTPUT
596     pasm_output_is( <<CODE, <<'OUTPUT', "check limit - Control" );
598         bsr lp
599         end
600 CODE
601 Stack 'Control' too deep
602 OUTPUT
604 ##############################
606 # Local Variables:
607 #   mode: cperl
608 #   cperl-indent-level: 4
609 #   fill-column: 100
610 # End:
611 # vim: expandtab shiftwidth=4: