fix codetest failure - ASSERT_ARGS does not have a ; after and
[parrot.git] / t / pmc / iterator.t
blobed86d900b653b8f95f86004f1e818da1f6615668
1 #!perl
2 # Copyright (C) 2001-2008, Parrot Foundation.
3 # $Id$
5 use strict;
6 use warnings;
7 use lib qw( . lib ../lib ../../lib );
9 use Test::More;
10 use Parrot::Test tests => 21;
12 =head1 NAME
14 t/pmc/iterator.t - Test the Iterator PMC
16 =head1 SYNOPSIS
18     % prove t/pmc/iterator.t
20 =head1 DESCRIPTION
22 Tests the C<Iterator> PMC.
24 =cut
26 # TT #1478: Split this test into aggregate specific one.
28 pasm_output_is( <<'CODE', <<'OUTPUT', "new iter" );
29     new P2, ['ResizablePMCArray']
30     iter P1, P2
31     print "ok 1\n"
32     end
33 CODE
34 ok 1
35 OUTPUT
37 pasm_output_is( <<'CODE', <<'OUTPUT', "int test" );
38     .include "iterator.pasm"
39     new P0, ['ResizablePMCArray']    # empty array
40     new P2, ['ResizablePMCArray']    # array with 2 elements
41     push P2, 10
42     push P2, 20
43     set I0, P2
44     iter P1, P2
45     print "ok 1\n"
46     set I1, P1
47     eq I0, I1, ok2        # iter.length() == array.length()
48     print "not "
49 ok2:    print "ok 2\n"
50     iter P1, P0
51     set P1, .ITERATE_FROM_START
52     print "ok 3\n"
53     unless P1, ok4        # if(iter) == false on empty
54     print "not "
55 ok4:    print "ok 4\n"
56     iter P1, P2
57     set P1, .ITERATE_FROM_START
58     if P1, ok5        # if(iter) == true on non empty
59     print "not "
60 ok5:    print "ok 5\n"
61     # now iterate over P2
62     # while (P1) { element = shift(P1) }
63     unless P1, nok6
64         shift I3, P1
65     eq I3, 10, ok6
66 nok6:    print "not "
67 ok6:    print "ok 6\n"
68     unless P1, nok7
69         shift I3, P1
70     eq I3, 20, ok7
71 nok7:    print "not "
72 ok7:    print "ok 7\n"
73     unless P1, ok8        # if(iter) == false after last
74     print "not "
75 ok8:    print "ok 8\n"
77     # now iterate from end
78     set P1, .ITERATE_FROM_END
79     if P1, ok9        # if(iter) == true on non empty
80     print "not "
81 ok9:    print "ok 9\n"
82     # while (P1) { element = pop(P1) }
83     unless P1, nok10
84         pop I3, P1
85     eq I3, 20, ok10
86 nok10:    print "not "
87 ok10:    print "ok 10\n"
88     unless P1, nok11
89         pop I3, P1
90     eq I3, 10, ok11
91 nok11:    print "not "
92 ok11:    print "ok 11\n"
93     unless P1, ok12        # if(iter) == false after last
94     print "not "
95 ok12:    print "ok 12\n"
96     end
98 CODE
99 ok 1
100 ok 2
101 ok 3
102 ok 4
103 ok 5
104 ok 6
105 ok 7
106 ok 8
107 ok 9
108 ok 10
109 ok 11
110 ok 12
111 OUTPUT
113 pasm_output_is( <<'CODE', <<'OUTPUT', "Hash iter 1" );
114     .include "iterator.pasm"
115     new P0, ['Hash']    # empty Hash
116     new P2, ['Hash']    # Hash with 2 elements
117     set P2["ab"], 100
118     set P2["xy"], "value"
119     set I0, P2
120     iter P1, P2
121     print "ok 1\n"
122     set I1, P1
123     eq I0, I1, ok2        # iter.length() == hash.length()
124     print "not "
125 ok2:    print "ok 2\n"
126     iter P1, P0
127     set P1, .ITERATE_FROM_START
128     print "ok 3\n"
129     unless P1, ok4        # if(iter) == false on empty
130     print "not "
131 ok4:    print "ok 4\n"
132     iter P1, P2
133     set P1, .ITERATE_FROM_START
134     if P1, ok5        # if(iter) == true on non empty
135     print "not "
136 ok5:    print "ok 5\n"
137     # now iterate over P2
138     # while (P1) { key = shift(P1) }
139     unless P1, nok6
140         shift S3, P1        # get hash.key
141     eq S3, "ab", ok6
142     eq S3, "xy", ok6
143 nok6:    print " not "
144 ok6:    print "ok 6\n"
145     unless P1, nok7
146         shift S3, P1
147     eq S3, "ab", ok7
148     eq S3, "xy", ok7
149 nok7:    print "not "
150 ok7:    print "ok 7\n"
151     unless P1, ok8        # if(iter) == false after last
152     print "not "
153 ok8:    print "ok 8\n"
154     end
156 CODE
157 ok 1
158 ok 2
159 ok 3
160 ok 4
161 ok 5
162 ok 6
163 ok 7
164 ok 8
165 OUTPUT
167 pasm_output_is( <<'CODE', <<'OUTPUT', "Hash iter 1" );
168     .include "iterator.pasm"
169     new P0, ['Hash']    # empty Hash
170     new P2, ['Hash']    # Hash with 2 elements
171     set P2["ab"], 100
172     set P2["xy"], "value"
173     set I0, P2
174     iter P1, P2
175     print "ok 1\n"
176     set I1, P1
177     eq I0, I1, ok2        # iter.length() == hash.length()
178     print "not "
179 ok2:    print "ok 2\n"
180     iter P1, P0
181     set P1, .ITERATE_FROM_START
182     print "ok 3\n"
183     unless P1, ok4        # if(iter) == false on empty
184     print "not "
185 ok4:    print "ok 4\n"
186     iter P1, P2
187     set P1, .ITERATE_FROM_START
188     if P1, ok5        # if(iter) == true on non empty
189     print "not "
190 ok5:    print "ok 5\n"
191     # now iterate over P2
192     # while (P1) { key = shift(P1) }
193     unless P1, nok6
194         shift S3, P1        # get hash.key
195     eq S3, "ab", ok6
196     eq S3, "xy", ok6
197 nok6:    print " not "
198 ok6:    print "ok 6\n"
199     unless P1, nok7
200         shift S3, P1
201     eq S3, "ab", ok7
202     eq S3, "xy", ok7
203 nok7:    print "not "
204 ok7:    print "ok 7\n"
205     unless P1, ok8        # if(iter) == false after last
206     print "not "
207 ok8:    print "ok 8\n"
208     end
210 CODE
211 ok 1
212 ok 2
213 ok 3
214 ok 4
215 ok 5
216 ok 6
217 ok 7
218 ok 8
219 OUTPUT
221 pasm_output_is( <<'CODE', <<'OUTPUT', "Hash iter 2" );
222     .include "iterator.pasm"
223     new P0, ['Hash']    # Hash for iteration
224     new P2, ['Hash']    # for test
226     set I0, 65
227     set I1, 35
228     set I10, I1
229 fill:
230     chr S0, I0
231     set P0[S0], I0
232     inc I0
233     dec I1
234     if I1, fill
236     iter P1, P0
237     set I0, P1
238     eq I0, I10, ok1
239     print "not "
240 ok1:
241     print "ok 1\n"
242     set P1, .ITERATE_FROM_START
243 get:
244     unless P1, done
245         shift S3, P1        # get hash.key
246     set I0, P0[S3]        # and value
247     set P2[S3], I0
248     branch get
250 done:
251     set I0, P2
252     eq I0, I10, ok2
253     print "not "
254 ok2:
255     print "ok 2\n"
256     end
257 CODE
258 ok 1
259 ok 2
260 OUTPUT
261 pasm_output_is( <<'CODE', <<OUTPUT, "string iteration forward" );
262     .include "iterator.pasm"
263     new P2, ['String']
264     set P2, "parrot"
265     iter P1, P2
266     set P1, .ITERATE_FROM_START
267 iter_loop:
268         unless P1, iter_end        # while (entries) ...
269     shift S1, P1
270     print S1
271     branch iter_loop
272 iter_end:
273     print "\n"
274     print P2
275     print "\n"
276     end
277 CODE
278 parrot
279 parrot
280 OUTPUT
282 pasm_output_is( <<'CODE', <<OUTPUT, "string iteration backward" );
283     .include "iterator.pasm"
284     new P2, ['String']
285     set P2, "parrot"
286     iter P1, P2
287     set P1, .ITERATE_FROM_END
288 iter_loop:
289         unless P1, iter_end        # while (entries) ...
290     pop S1, P1
291     print S1
292     branch iter_loop
293 iter_end:
294     print "\n"
295     print P2
296     print "\n"
297     end
298 CODE
299 torrap
300 parrot
301 OUTPUT
303 pasm_output_is( <<'CODE', <<OUTPUT, "string iteration forward get ord" );
304     .include "iterator.pasm"
305     new P2, ['String']
306     set P2, "ABC"
307     iter P1, P2
308     set P1, .ITERATE_FROM_START
309 iter_loop:
310         unless P1, iter_end        # while (entries) ...
311     shift I1, P1
312     print I1
313     branch iter_loop
314 iter_end:
315     print "\n"
316     print P2
317     print "\n"
318     end
319 CODE
320 656667
322 OUTPUT
324 pasm_output_is( <<'CODE', <<OUTPUT, "string iteration backward get ord" );
325 .include "iterator.pasm"
326     new P2, ['String']
327     set P2, "ABC"
328     iter P1, P2
329     set P1, .ITERATE_FROM_END
330 iter_loop:
331         unless P1, iter_end        # while (entries) ...
332     pop I1, P1
333     print I1
334     branch iter_loop
335 iter_end:
336     print "\n"
337     print P2
338     print "\n"
339     end
340 CODE
341 676665
343 OUTPUT
345 pir_output_is( << 'CODE', << 'OUTPUT', "String iterator in PIR" );
347 .include "iterator.pasm"
348 .sub _main
349     .local pmc string_1
350     string_1 = new ['String']
351     string_1 = "abcd\x65\x66\x67"
352     print string_1
353     print "\n"
355     .local pmc iter_1
356     iter_1 = iter string_1
357     iter_1 = .ITERATE_FROM_START
359     .local int code_point_1
360 ITER_LOOP:
361     unless iter_1 goto ITER_END
362     shift code_point_1, iter_1
363     print code_point_1
364     print "\n"
365     branch ITER_LOOP
366 ITER_END:
367     print "reached end\n"
368     end
369 .end
370 CODE
371 abcdefg
379 reached end
380 OUTPUT
382 pir_output_is( <<'CODE', <<'OUTPUT', "Index access for Iterator on String" );
384 .include "iterator.pasm"
385 .sub _main
386     .local pmc string_1
387     string_1 = new ['String']
388     string_1 = "abcd\x65\x66\x67"
389     print 'String new: '
390     print string_1
391     print "\n"
393     .local pmc iter_1
394     iter_1 = iter string_1
395     iter_1 = .ITERATE_FROM_START
397     .local int    code_point_1
398     .local num  code_point_2
399     .local string code_point_3
400     .local pmc    code_point_4
402     print 'Iterator shift_integer: '
403     shift code_point_1, iter_1
404     print code_point_1
405     print "\n"
407     print 'Iterator get_integer_keyed_int 2: '
408     code_point_1 = iter_1[2]
409     print code_point_1
410     print "\n"
412     print 'Iterator get_integer_keyed_int 0: '
413     code_point_1 = iter_1[0]
414     print code_point_1
415     print "\n"
417     print 'Iterator get_integer_keyed_int -1: '
418     code_point_1 = iter_1[-1]
419     print code_point_1
420     print "\n"
422     end
423 .end
424 CODE
425 String new: abcdefg
426 Iterator shift_integer: 97
427 Iterator get_integer_keyed_int 2: 100
428 Iterator get_integer_keyed_int 0: 98
429 Iterator get_integer_keyed_int -1: 97
430 OUTPUT
432 pir_output_is( << 'CODE', << 'OUTPUT', "Index access for Iterator on ResizablePMCArray" );
434 .include "iterator.pasm"
435 .sub _main
436     .local pmc array_1
437     array_1 = new ['ResizablePMCArray']
438     push array_1, 'a'
439     push array_1, 'b'
440     push array_1, 'c'
441     push array_1, 'd'
442     push array_1, 'e'
443     push array_1, 'f'
444     push array_1, '7'
445     push array_1, '-8.8'
447     print 'ResizablePMCArray get_string: '
448     print array_1
449     print "\n"
451     .local pmc iter_1
452     iter_1 = iter array_1
453     iter_1 = .ITERATE_FROM_START
455     .local string elem_1
457     print 'Iterator shift_string: '
458     shift elem_1, iter_1
459     print elem_1
460     print "\n"
462     print 'Iterator get_string_keyed_int 2: '
463     elem_1 = iter_1[2]
464     print elem_1
465     print "\n"
467     print 'Iterator get_string_keyed_int -1: '
468     elem_1 = iter_1[-1]
469     print elem_1
470     print "\n"
472     print 'Iterator get_string_keyed_int 0: '
473     elem_1 = iter_1[0]
474     print elem_1
475     print "\n"
477     print 'Iterator get_pmc_keyed_int 3: '
478     .local pmc elem_2
479     elem_2 = iter_1[3]
480     print elem_2
481     print "\n"
483     .local int flag
485     print 'Iterator exists_keyed_int 3: '
486     flag = exists iter_1[3]
487     print flag
488     print "\n"
490     print 'Iterator exists_keyed_int 28: '
491     flag = exists iter_1[28]
492     print flag
493     print "\n"
496     print 'Iterator defined_keyed_int 3: '
497     flag = defined iter_1[3]
498     print flag
499     print "\n"
501     print 'Iterator defined_keyed_int -1278: '
502     flag = defined iter_1[-1278]
503     print flag
504     print "\n"
506     .local pmc iter_2
507     iter_2 = iter array_1
508     iter_2 = .ITERATE_FROM_END
510     print 'Iterator shift_float: '
511     .local num felem_2
512     pop felem_2, iter_2
513     print felem_2
514     print "\n"
516     print 'Iterator get_integer: '
517     .local int elem_3
518     elem_3 = iter_2[-1]
519     print elem_3
520     print "\n"
522     end
523 .end
524 CODE
525 ResizablePMCArray get_string: 8
526 Iterator shift_string: a
527 Iterator get_string_keyed_int 2: d
528 Iterator get_string_keyed_int -1: a
529 Iterator get_string_keyed_int 0: b
530 Iterator get_pmc_keyed_int 3: e
531 Iterator exists_keyed_int 3: 1
532 Iterator exists_keyed_int 28: 0
533 Iterator defined_keyed_int 3: 1
534 Iterator defined_keyed_int -1278: 0
535 Iterator shift_float: -8.8
536 Iterator get_integer: 7
537 OUTPUT
539 TODO: {
540     pasm_output_is( <<'CODE', <<'OUTPUT', "shift + index access", todo => "N/Y: length of rest of array ");
541     .include "iterator.pasm"
543     new P2, ['ResizablePMCArray']    # array with 4 elements
544     push P2, 10
545     push P2, 20
546     push P2, 30
547     push P2, 40
548     iter P1, P2
549     set P1, .ITERATE_FROM_START
551     set I0, P1        # arr.length
552     eq I0, 4, ok1
553     print I0
554     print " not "
555 ok1:    print "ok 1\n"
557     shift I0, P1        # get one
558     eq I0, 10, ok2
559     print "not "
560 ok2:    print "ok 2\n"
562     shift I0, P1        # get one
563     eq I0, 20, ok3
564     print "not "
565 ok3:    print "ok 3\n"
567     set I0, P1        # arr.length of rest
568     eq I0, 2, ok6
569     print I0
570     print " not "
571 ok6:    print "ok 6\n"
573         print P1
574     end
575 CODE
576 ok 1
577 ok 2
578 ok 3
579 ok 6
581 OUTPUT
586 pasm_output_is( <<'CODE', <<'OUTPUT', "iter vtable" );
587    .include "iterator.pasm"
588    new P0, ['ResizablePMCArray']
589    push P0, 100
590    push P0, 200
591    push P0, 300
592    push P0, 400
593    push P0, 500
594    push P0, 600
595    push P0, 700
596    push P0, 800
597    iter P2, P0
598    print "ok 1\n"
600    unless P2, ex
601    shift I0, P2
602    print I0
603    print "\n"
604    branch lp
606    print "ok 2\n"
607    end
608 CODE
609 ok 1
618 ok 2
619 OUTPUT
621 pasm_output_is( <<'CODE', <<OUTPUT, "string iteration with get_iter" );
622     .include "iterator.pasm"
623     new P2, ['String']
624     set P2, "parrot"
625     iter P1, P2
626 iter_loop:
627         unless P1, iter_end        # while (entries) ...
628     shift S1, P1
629     print S1
630     branch iter_loop
631 iter_end:
632     print "\n"
633     print P2
634     print "\n"
635     end
636 CODE
637 parrot
638 parrot
639 OUTPUT
641 TODO: {
642     local $TODO = "adding keys during iteration";
644     pir_output_is( << 'CODE', << 'OUTPUT', "adding keys during iteration" );
645 .sub main :main
646     .local pmc h, it, ar
647     .local string k
648     .local int i,v
650     h = new ['Hash']
651     i = 0
652 lp1:
653     $I0 = i + 65
654     k = chr $I0
655     h[k] = i
656     inc i
657     if i < 10 goto lp1
659     it = iter h
660     ar = new ['ResizablePMCArray']
661     i = 20
662 lp2:
663     unless it goto ex
664     k = shift it
665     v = h[k]
666     push ar, v
667     if i == 29 goto no_add
668     $I0 = i + 65
669     k = chr $I0
670     h[k] = i
671     inc i
672 no_add:
673     goto lp2
675     ar."sort"()
676     i = elements ar
677 lp3:
678     dec i
679     v = ar[i]
680     print v
681     print "_"
682     if i goto lp3
683     print "\n"
684 .end
685 # or some such output
686 CODE
687 29_28_27_26_25_24_23_22_21_20_9_8_7_6_5_4_3_2_1_0_
688 OUTPUT
691 pir_output_is( << 'CODE', << 'OUTPUT', "by default, iterate from start" );
692 .sub main :main
693     .local pmc ar, it
694     ar= new ['ResizablePMCArray']
695     push ar, 'pi'
696     push ar, 3
697     push ar, 6.28
699     it = iter ar
700 lp: unless it, ex
701     $P0 = shift it
702     print $P0
703     print "\n"
704     branch lp
706 .end
707 CODE
710 6.28
711 OUTPUT
713 pir_output_is( << 'CODE', << 'OUTPUT', "iterator can be cloned" );
714 .sub main :main
715     .local pmc ar, i1, i2
716     ar = new ['ResizableIntegerArray']
717     push ar, 17
718     i1 = iter ar
719     clone i2, i1
720 .end
721 CODE
722 OUTPUT
724 pir_output_is( << 'CODE', << 'OUTPUT', "cloned iterator independent of original" );
725 .sub main :main
726     .local pmc ar, i1, i2
727     ar = new ['ResizableIntegerArray']
728     push ar, 17
729     push ar, 42
731     i1 = iter ar
732     clone i2, i1
734     .local pmc temp
736     shift temp, i1
737     unless temp == 17 goto fail
739     shift temp, i1
740     unless temp == 42 goto fail
742     shift temp, i2
743     unless temp == 17 goto fail
745     shift temp, i2
746     unless temp == 42 goto fail
748     say "ok"
749     end
750 fail:
751     say "not ok"
752 .end
753 CODE
755 OUTPUT
757 pir_output_is( <<'CODE', <<'OUTPUT', "clone of partly-advanced iterator" );
758 .sub main :main
759     .local pmc ar, i1, i2
760     .local pmc temp
761     ar = new ['ResizableIntegerArray']
762     push ar, 1
763     push ar, 2
764     i1 = iter ar
766     shift temp, i1
767     unless temp == 1 goto fail
769     clone i2, i1
770     shift temp, i1
771     unless temp == 2 goto fail
773     shift temp, i2
774     unless temp == 2 goto fail
776     say "ok"
777     end
778 fail:
779     say "not ok"
780 .end
781 CODE
783 OUTPUT
785 TODO: {
786     local $TODO = "cloned iterator doesn't copy the array to which it 'points'";
787     pir_output_is(
788         <<'CODE', <<'OUTPUT', "cloned iterator doesn't copy the array to which it 'points'" );
789 .sub main :main
790     .local pmc ar, i1, i2
791     .local pmc temp
792     temp = new ['Integer']
793     ar   = new ['ResizableIntegerArray']
794     push ar, 1
795     i1 = iter ar
797     # i1 and i2 now "point" to the same element of the same array.
798     clone i2, i1
800     # Modify the array ...
801     temp = 17
802     i1   = temp
804     # Now read back the modified value ...
805     shift temp, i2
807     unless temp == 17 goto fail
809     say "ok"
810     end
811 fail:
812     say "not ok"
813 .end
814 CODE
816 OUTPUT
819 # Local Variables:
820 #   mode: cperl
821 #   cperl-indent-level: 4
822 #   fill-column: 100
823 # End:
824 # vim: expandtab shiftwidth=4: