tagged release 0.7.1
[parrot.git] / languages / cardinal / src / classes / Array.pir
blob401b55de3450f015692082795e97c3925518cd18
1 ## $Id$
3 =head1 NAME
5 src/classes/CardinalArray.pir - Cardinal CardinalArray class and related functions
6 Stolen from Rakudo
8 =head1 Methods
10 =over 4
12 =cut
14 .namespace ['CardinalArray']
16 .sub 'onload' :anon :load :init
17     .local pmc cardinalmeta, arrayproto, interp, core_type, hll_type
18     cardinalmeta = get_hll_global ['CardinalObject'], '!CARDINALMETA'
19     arrayproto = cardinalmeta.'new_class'('CardinalArray', 'parent'=>'ResizablePMCArray CardinalObject')
20     cardinalmeta.'register'('ResizablePMCArray', 'parent'=>'CardinalObject', 'protoobject'=>arrayproto)
21     core_type = get_class 'ResizablePMCArray'
22     hll_type = get_class 'CardinalArray'
24     interp = getinterp
25     interp.'hll_map'(core_type, hll_type)
27 .end
30 =item get_string()    (vtable method)
32 Return the elements of the list concatenated.
34 =cut
36 .sub 'get_string' :vtable :method
37     $S0 = join ', ', self
38     $S0 = concat '[', $S0
39     $S0 = concat $S0, ']'
40     .return ($S0)
41 .end
43 =item to_s()    (method)
45 Return a CardinalString representing the Array.
47 =cut
49 .sub 'to_s' :method
50     $S0 = join '', self
51     $P0 = new 'CardinalString'
52     $P0 = $S0
53     .return($P0)
54 .end
56 =item clone()    (vtable method)
58 Clones the list.
60 =cut
62 .sub 'clone' :vtable :method
63     $P0 = 'list'(self)
64     .return ($P0)
65 .end
67 =item clear()    (method)
69 Removes all elements from the array.
71 =cut
73 .sub 'clear' :method
74     self = 0
75 .end
78 =item ACCEPTS(topic)
80 =cut
82 .sub 'ACCEPTS' :method
83     .param pmc topic
84     .local int i
86     .local string what
87     what = topic.'WHAT'()
88     if what == "CardinalArray" goto acc_list
89     goto no_match
91 acc_list:
92     # Smartmatch against another list. Smartmatch each
93     # element.
94     .local int count_1, count_2
95     count_1 = elements self
96     count_2 = elements topic
97     if count_1 != count_2 goto no_match
98     i = 0
99 list_cmp_loop:
100     if i >= count_1 goto list_cmp_loop_end
101     .local pmc elem_1, elem_2
102     elem_1 = self[i]
103     elem_2 = topic[i]
104     ($I0) = elem_1.ACCEPTS(elem_2)
105     unless $I0 goto no_match
106     inc i
107     goto list_cmp_loop
108 list_cmp_loop_end:
109     goto match
111 no_match:
112     $P0 = get_hll_global ['Bool'], 'False'
113     .return($P0)
114 match:
115     $P0 = get_hll_global ['Bool'], 'True'
116     .return($P0)
117 .end
120 =item elems()
122 Return the number of elements in the list.
124 =cut
126 .sub 'elems' :method
127     $I0 = elements self
128     .return ($I0)
129 .end
131 =item sort()
133 Return a sorted copy of the list
135 =cut
137 .sub 'sort' :method
138     .param pmc by              :optional
139     .param int has_by          :opt_flag
140     if has_by goto have_by
141     by = get_hll_global 'infix:cmp'
142   have_by:
144     .local pmc list, fpa
145     .local int elems
147     list = self
148     elems = list.'elems'()
149     fpa = new 'FixedPMCArray'
150     fpa = elems
152     .local int i
153     i = 0
154   fpa_loop:
155     unless i < elems goto fpa_end
156     $P0 = list[i]
157     fpa[i] = $P0
158     inc i
159     goto fpa_loop
160   fpa_end:
161     fpa.'sort'(by)
162     .return 'list'(fpa :flat)
163 .end
165 .sub 'sort!' :method
166     .param pmc by              :optional
167     .param int has_by          :opt_flag
168     if has_by goto have_by
169     by = get_hll_global 'infix:cmp'
170   have_by:
171     $P0 = self.sort()
172     self = 0
173     self.append($P0)
174 .end
176 =item uniq(...)
178 =cut
180 # TODO Rewrite it. It's too naive.
182 .sub uniq :method
183     .local pmc ulist
184     .local pmc key
185     .local pmc val
186     .local pmc uval
187     .local int len
188     .local int i
189     .local int ulen
190     .local int ui
192     ulist = new 'CardinalArray'
193     len = self.'elems'()
194     i = 0
196   loop:
197     if i == len goto done
199     val = self[i]
201     ui = 0
202     ulen = ulist.'elems'()
203     inner_loop:
204         if ui == ulen goto inner_loop_done
206         uval = ulist[ui]
207         if uval == val goto found
209         inc ui
210         goto inner_loop
211     inner_loop_done:
213     ulist.'push'(val)
215     found:
217     inc i
218     goto loop
220   done:
221     .return(ulist)
222 .end
224 .sub 'uniq!' :method
225     $P0 = self.uniq()
226     self = 0
227     self.append($P0)
228 .end
231 =item include?(ELEMENT)
233 Return true if self contains ELEMENT
235 =cut
236 .sub 'include?' :method
237     .param pmc args
238     .local pmc iter
239     iter = new 'Iterator', self
240   iter_loop:
241     unless iter goto done_f
242     $P0 = shift iter
243     eq $P0, args, done_t
244     goto iter_loop
245    done_f:
246         $P0 = get_hll_global ['Bool'], 'False'
247         .return($P0)
248    done_t:
249         $P0 = get_hll_global ['Bool'], 'True'
250         .return($P0)
251 .end
254 =item unshift(ELEMENTS)
256 Prepends ELEMENTS to the front of the list.
258 =cut
260 .sub 'unshift' :method
261     .param pmc args :slurpy
262     .local int narg
263     .local int i
265     narg = args
266     i = 0
268     .local pmc tmp
269   loop:
270     if i == narg goto done
271     pop tmp, args
272     unshift self, tmp
273     inc i
274     goto loop
275   done:
276 .end
278 =item keys()
280 Returns a CardinalArray containing the keys of the CardinalArray.
282 =cut
284 .sub 'keys' :method
285     .local pmc elem
286     .local pmc res
287     .local int len
288     .local int i
290     res = new 'CardinalArray'
291     len = elements self
292     i = 0
294   loop:
295     if i == len goto done
297     elem = new 'CardinalInteger'
298     elem = i
299     res.'push'(elem)
301     inc i
302     goto loop
304   done:
305     .return(res)
306 .end
308 =item values()
310 Returns a CardinalArray containing the values of the CardinalArray.
312 =cut
314 .sub 'values' :method
315     .local pmc elem
316     .local pmc res
317     .local int len
318     .local int i
320     res = new 'CardinalArray'
321     len = elements self
322     i = 0
324   loop:
325     if i == len goto done
327     elem = new 'CardinalInteger'
328     elem = self[i]
329     res.'push'(elem)
331     inc i
332     goto loop
334   done:
335     .return(res)
336 .end
338 =item shift()
340 Shifts the first item off the list and returns it.
342 =cut
344 .sub 'shift' :method
345     .local pmc x
346     x = shift self
347     .return (x)
348 .end
350 =item pop()
352 Treats the list as a stack, popping the last item off the list and returning it.
354 =cut
356 .sub 'pop' :method
357     .local pmc x
358     .local int len
360     len = elements self
362     if len == 0 goto empty
363     pop x, self
364     goto done
366   empty:
367     x = undef()
368     goto done
370   done:
371     .return (x)
372 .end
374 =item push(ELEMENTS)
376 Treats the list as a stack, pushing ELEMENTS onto the end of the list.  Returns the new length of the list.
378 =cut
380 .sub 'push' :method
381     .param pmc args :slurpy
382     .local int len
383     .local pmc tmp
384     .local int i
386     len = args
387     i = 0
389   loop:
390     if i == len goto done
391     shift tmp, args
392     push self, tmp
393     inc i
394     goto loop
395   done:
396     len = elements self
397     .return (len)
398 .end
400 =item join(SEPARATOR)
402 Returns a string comprised of all of the list, separated by the string SEPARATOR.  Given an empty list, join returns the empty string. SEPARATOR is an optional parameter
404 =cut
406 .sub 'join' :method
407     .param string sep :optional
408     .local string res
409     .local string tmp
410     .local int len
411     .local int i
413     res = ""
415     len = elements self
416     if len == 0 goto done
418     len = len - 1
419     i = 0
421   loop:
422     if i == len goto last
424     tmp = self[i]
425     concat res, tmp
426     concat res, sep
428     inc i
429     goto loop
431   last:
432     tmp = self[i]
433     concat res, tmp
435   done:
436     $S0 = res
437     .return(res)
438 .end
440 =item reverse()
442 Returns a list of the elements in revese order.
444 =cut
446 .sub 'reverse' :method
447     .local pmc res
448     .local int len
449     .local int i
451     res = new 'CardinalArray'
453     len = elements self
454     if len == 0 goto done
455     i = 0
457     .local pmc elem
458 loop:
459     if len == 0 goto done
461     dec len
462     elem = self[len]
463     res[i] = elem
464     inc i
466     goto loop
468 done:
469     .return(res)
470 .end
472 =item reverse!()
474 Reverses a list in place.  Destructive update.
475 Returns self.
477 =cut
479 .sub 'reverse!' :method
480     .local int pos
481     .local int len
482     .local pmc tmp1
483     .local pmc tmp2
484     pos = elements self
485     len = pos
486     dec len
487     pos = pos / 2
488   loop:
489     if pos == 0 goto done
490     dec pos
491     tmp1 = self[pos]
492     $I0 = len-pos
493     tmp2 = self[$I0]
494     self[pos] = tmp2
495     self[$I0] = tmp1
496     goto loop
497   done:
498     .return(self)
499 .end
501 =item delete()
503 Deletes the given element from the CardinalArray, replacing them with Undef.
504 Returns the item if found, otherwise returns the result of running the block
505 if passed, otherwise returns nil.
507 =cut
509 .sub delete :method
510     .param pmc item
511     .param pmc block :optional
512     .param int block_flag :opt_flag
513     .local pmc nil
514     .local pmc elem
515     .local int len
516     .local int i
517     .local pmc return
518     .local pmc nil
520     nil = new 'NilClass'
521     return = nil
523     len = elements self
524     i = 0
526   loop:
527     if i == len goto done
529     elem = self[i]
532     $I0 = elem == item
533     if $I0, found
534     inc i
536     goto loop
537   found:
538     return = item
539     delete self[i]
540     dec len
541     goto loop
542   done:
543     $I0 = return == nil
544     if $I0, not_found
545     .return(return)
546   not_found:
547     if block_flag, have_block
548     .return(return)
549   have_block:
550     $P0 = block()
551     .return($P0)
552 .end
554 =item exists(INDEX)
556 Checks to see if the specified index or indices have been assigned to.  Returns a Bool value.
558 =cut
560 .sub exists :method
561     .param pmc indices :slurpy
562     .local int test
563     .local int len
564     .local pmc res
565     .local int ind
566     .local int i
568     test = 1
569     len = elements indices
570     i = 0
572   loop:
573     if i == len goto done
575     ind = indices[i]
577     test = exists self[ind]
578     if test == 0 goto done
580     inc i
581     goto loop
583   done:
584     .return 'prefix:?'(test)
585 .end
587 =item kv()
589 =cut
591 .sub kv :method
592     .local pmc elem
593     .local pmc res
594     .local int len
595     .local int i
597     res = new 'CardinalArray'
598     len = elements self
599     i = 0
601   loop:
602     if i == len goto done
604     elem = new 'CardinalInteger'
605     elem = i
606     res.'push'(elem)
608     elem = self[i]
609     res.'push'(elem)
611     inc i
612     goto loop
614   done:
615     .return(res)
616 .end
618 =item pairs()
620 =cut
622 .sub pairs :method
623     .local pmc pair
624     .local pmc key
625     .local pmc val
626     .local pmc res
627     .local int len
628     .local int i
630     res = new 'CardinalArray'
631     len = elements self
632     i = 0
634   loop:
635     if i == len goto done
637     key = new 'CardinalInteger'
638     key = i
640     val = self[i]
642     pair = new 'Pair'
643     pair[key] = val
645     res.'push'(pair)
647     inc i
648     goto loop
650   done:
651     .return(res)
652 .end
654 =item grep(...)
656 =cut
658 .sub grep :method
659     .param pmc test
660     .local pmc retv
661     .local pmc block
662     .local pmc block_res
663     .local pmc block_arg
664     .local int narg
665     .local int i
667     retv = new 'CardinalArray'
668     narg = elements self
669     i = 0
671   loop:
672     if i == narg goto done
673     block_arg = self[i]
675     newclosure block, test
676     block_res = block(block_arg)
678     if block_res goto grepped
679     goto next
681   grepped:
682     retv.'push'(block_arg)
683     goto next
685   next:
686     inc i
687     goto loop
689   done:
690     .return(retv)
691 .end
693 =item first(...)
695 =cut
697 .sub first :method :multi(CardinalArray,_)
698     .param int count
699     .local pmc newlist
700     .local pmc item
701     .local int elems
702     .local int i
704     newlist = new 'CardinalArray'
706     elems = elements self
707     le count, elems, sufficient_elements
708     count = elems
709   sufficient_elements:
711     i = 0
713   loop:
714     if i == count goto done
715     item = self[i]
716     item = clone item
718     push newlist, item
720     inc i
721     goto loop
722   done:
723     .return(newlist)
724 .end
726 .sub first :method :multi(CardinalArray)
727     .local pmc item
728     $I0 = elements self
729     eq $I0, 0, empty
730     item = self[0]
731     .return (item)
732   empty:
733     item = new 'Undef'
734     .return (item)
735 .end
737 =item first(...)
739 =cut
741 .sub last :method :multi(CardinalArray,_)
742     .param int count
743     .local pmc newlist
744     .local pmc item
745     .local int elems
746     .local int i
748     newlist = new 'CardinalArray'
750     elems = elements self
751     count = elems - count
752     ge count, 0, sufficient_elements
753     count = 0
754   sufficient_elements:
756     i = elems - 1
758   loop:
759     lt i, count, done
760     item = self[i]
761     item = clone item
763     unshift newlist, item
765     dec i
766     goto loop
767   done:
768     .return(newlist)
769 .end
771 .sub last :method :multi(CardinalArray)
772     .local pmc item
773     $I0 = elements self
774     eq $I0, 0, empty
775     dec $I0
776     item = self[$I0]
777     .return (item)
778   empty:
779     item = new 'Undef'
780     .return (item)
781 .end
783 =item each(block)
785 Run C<block> once for each item in C<self>, with the item passed as an arg.
787 =cut
789 .sub 'each' :method
790     .param pmc block
791     $P0 = new 'Iterator', self
792   each_loop:
793     unless $P0 goto each_loop_end
794     $P1 = shift $P0
795     block($P1)
796     goto each_loop
797   each_loop_end:
798 .end
800 .sub 'each_with_index' :method
801     .param pmc block
802     .local int len
803     len = elements self
804     $I0 = 0
805   each_loop:
806     if $I0 == len goto each_loop_end
807     $P0 = self[$I0]
808     block($P0,$I0)
809     inc $I0
810     goto each_loop
811   each_loop_end:
812 .end
814 =item collect(block)
816 Run C<block> once for each item in C<self>, with the item passed as an arg.
817 Creates a new Array containing the results and returns it.
819 =cut
821 .sub 'collect' :method
822     .param pmc block
823     .local pmc result
824     result = new 'CardinalArray'
825     $P0 = new 'Iterator', self
826   each_loop:
827     unless $P0 goto each_loop_end
828     $P1 = shift $P0
829     $P2 = block($P1)
830     result.push($P2)
831     goto each_loop
832   each_loop_end:
833     .return (result)
834 .end
836 =item flatten
838  recursively flatten any inner arrays into a single outer array
840 =cut
841 .sub 'flatten' :method
842     .local pmc returnMe
843     .local pmc iterator
844     returnMe = new 'CardinalArray'
845     iterator = new 'Iterator', self
846   each_loop:
847     unless iterator goto each_loop_end
848     $P1 = shift iterator
849     #if $P1 is an array call flatten
850     $I0 = isa $P1, 'CardinalArray'
851     if $I0 goto inner_flatten
852     push returnMe, $P1
853     goto each_loop
854   inner_flatten:
855     $P2 = $P1.'flatten'()
856     $P3 = new 'Iterator', $P2
857     inner_loop:
858         unless $P3 goto each_loop
859         $P4 = shift $P3
860         push returnMe, $P4
861         goto inner_loop
862     goto each_loop
863   each_loop_end:
864   .return(returnMe)
865 .end
867 =item size
869 Retrieve the number of elements in C<self>
871 =cut
872 .sub 'size' :method
873      $I0 = self
874      .return($I0)
875 .end
877 =item length
879 Retrieve the number of elements in C<self>
881 =cut
882 .sub 'length' :method
883      $I0 = self
884      .return($I0)
885 .end
887 =item at(index)
889     Retrieve element from position C<index>.
891 =cut
892 .sub 'at' :method
893     .param pmc i
894     $P0 = self[i]
895     .return($P0)
896 .end
898 .sub '[]' :method
899     .param pmc i
900     $P0 = self[i]
901     .return($P0)
902 .end
904 .sub '[]=' :method
905     .param pmc k
906     .param pmc v
907     self[k] = v
908     .return()
909 .end
912 =item slice
914 Retrieve the number of elements in C<self>
916 =cut
917 .sub 'slice' :method
918     .param int start
919     .param int end
920     .local pmc returnMe
921     returnMe = new 'CardinalArray'
922     $I0 = start
923   each_loop:
924     unless $I0 <= end goto each_loop_end
925     $P0 = self[$I0]
926     inc $I0
927     push returnMe, $P0
928     goto each_loop
929   each_loop_end:
930   .return(returnMe)
931 .end
933 =item zip
935 The zip operator.
937 =cut
939 .sub 'zip' :method
940     .param pmc args :slurpy
941     .local int num_args
942     .local pmc zipped
943     num_args = elements args
945     zipped = new 'CardinalArray'
947     # Get minimum element count - what we'll zip to.
948     .local pmc iterator, args_iter, arg, item
949     .local int i
950     iterator = new 'Iterator', self
951     i = 0
953   setup_loop:
954     unless iterator, setup_loop_done
955     args_iter = new 'Iterator', args
956     item = new 'CardinalArray'
957     $P0 = shift iterator
958     item.push($P0)
959   inner_loop:
960     unless args_iter, inner_loop_done
961     arg = shift args_iter
962     $P0 = arg[i]
963     unless null $P0 goto arg_not_null
964     $P0 = get_hll_global 'nil'
965   arg_not_null:
966     item.push($P0)
967     goto inner_loop
968   inner_loop_done:
969     inc i
970     zipped.push(item)
971     goto setup_loop
972   setup_loop_done:
974     .return (zipped)
975 .end
977 =back
979 =head1 Functions
981 =over 4
983 =item C<list(...)>
985 Build a CardinalArray from its arguments.
987 =cut
989 .namespace []
991 .sub 'list'
992     .param pmc args            :slurpy
993     .local pmc list, item
994     list = new 'CardinalArray'
995   args_loop:
996     unless args goto args_end
997     item = shift args
998     $I0 = defined item
999     unless $I0 goto add_item
1000     $I0 = isa item, 'CardinalArray'
1001     if $I0 goto add_item
1002     $I0 = does item, 'array'
1003     unless $I0 goto add_item
1004     splice args, item, 0, 0
1005     goto args_loop
1006   add_item:
1007     push list, item
1008     goto args_loop
1009   args_end:
1010     .return (list)
1011 .end
1014 =item C<infix:,(...)>
1016 Operator form for building a list from its arguments.
1018 =cut
1020 .sub 'infix:,'
1021     .param pmc args            :slurpy
1022     .return 'list'(args :flat)
1023 .end
1026 =item C<infix:Z(...)>
1028 The zip operator.
1030 =cut
1032 .sub 'infix:Z'
1033     .param pmc args # :slurpy
1034     .local int num_args
1035     num_args = elements args
1037     # Empty list of no arguments.
1038     if num_args > 0 goto has_args
1039     $P0 = new 'CardinalArray'
1040     .return($P0)
1041 has_args:
1043     # Get minimum element count - what we'll zip to.
1044     .local int min_elem
1045     .local int i
1046     i = 0
1047     $P0 = args[0]
1048     min_elem = elements $P0
1049 min_elems_loop:
1050     if i >= num_args goto min_elems_loop_end
1051     $P0 = args[i]
1052     $I0 = elements $P0
1053     unless $I0 < min_elem goto not_min
1054     min_elem = $I0
1055 not_min:
1056     inc i
1057     goto min_elems_loop
1058 min_elems_loop_end:
1060     # Now build result list of lists.
1061     .local pmc res
1062     res = new 'CardinalArray'
1063     i = 0
1064 zip_loop:
1065     if i >= min_elem goto zip_loop_end
1066     .local pmc cur_list
1067     cur_list = new 'CardinalArray'
1068     .local int j
1069     j = 0
1070 zip_elem_loop:
1071     if j >= num_args goto zip_elem_loop_end
1072     $P0 = args[j]
1073     $P0 = $P0[i]
1074     cur_list[j] = $P0
1075     inc j
1076     goto zip_elem_loop
1077 zip_elem_loop_end:
1078     res[i] = cur_list
1079     inc i
1080     goto zip_loop
1081 zip_loop_end:
1083     .return(res)
1084 .end
1087 =item C<infix:X(...)>
1089 The non-hyper cross operator.
1091 =cut
1093 .sub 'infix:X'
1094     .param pmc args            :slurpy
1095     .local pmc res
1096     res = new 'CardinalArray'
1098     # Algorithm: we'll maintain a list of counters for each list, incrementing
1099     # the counter for the right-most list and, when it we reach its final
1100     # element, roll over the counter to the next list to the left as we go.
1101     .local pmc counters
1102     .local pmc list_elements
1103     .local int num_args
1104     counters = new 'FixedIntegerCardinalArray'
1105     list_elements = new 'FixedIntegerCardinalArray'
1106     num_args = elements args
1107     counters = num_args
1108     list_elements = num_args
1110     # Get element count for each list.
1111     .local int i
1112     .local pmc cur_list
1113     i = 0
1114 elem_get_loop:
1115     if i >= num_args goto elem_get_loop_end
1116     cur_list = args[i]
1117     $I0 = elements cur_list
1118     list_elements[i] = $I0
1119     inc i
1120     goto elem_get_loop
1121 elem_get_loop_end:
1123     # Now we'll start to produce them.
1124     .local int res_count
1125     res_count = 0
1126 produce_next:
1128     # Start out by building list at current counters.
1129     .local pmc new_list
1130     new_list = new 'CardinalArray'
1131     i = 0
1132 cur_perm_loop:
1133     if i >= num_args goto cur_perm_loop_end
1134     $I0 = counters[i]
1135     $P0 = args[i]
1136     $P1 = $P0[$I0]
1137     new_list[i] = $P1
1138     inc i
1139     goto cur_perm_loop
1140 cur_perm_loop_end:
1141     res[res_count] = new_list
1142     inc res_count
1144     # Now increment counters.
1145     i = num_args - 1
1146 inc_counter_loop:
1147     $I0 = counters[i]
1148     $I1 = list_elements[i]
1149     inc $I0
1150     counters[i] = $I0
1152     # In simple case, we just increment this and we're done.
1153     if $I0 < $I1 goto inc_counter_loop_end
1155     # Otherwise we have to carry.
1156     counters[i] = 0
1158     # If we're on the first element, all done.
1159     if i == 0 goto all_done
1161     # Otherwise, loop.
1162     dec i
1163     goto inc_counter_loop
1164 inc_counter_loop_end:
1165     goto produce_next
1167 all_done:
1168     .return(res)
1169 .end
1172 =item C<infix:min(...)>
1174 The min operator.
1176 =cut
1178 .sub 'infix:min'
1179     .param pmc args :slurpy
1181     # If we have no arguments, undefined.
1182     .local int elems
1183     elems = elements args
1184     if elems > 0 goto have_args
1185     $P0 = undef()
1186     .return($P0)
1187 have_args:
1189     # Find minimum.
1190     .local pmc cur_min
1191     .local int i
1192     cur_min = args[0]
1193     i = 1
1194 find_min_loop:
1195     if i >= elems goto find_min_loop_end
1196     $P0 = args[i]
1197     $I0 = 'infix:cmp'($P0, cur_min)
1198     if $I0 != -1 goto not_min
1199     set cur_min, $P0
1200 not_min:
1201     inc i
1202     goto find_min_loop
1203 find_min_loop_end:
1205     .return(cur_min)
1206 .end
1209 =item C<infix:max(...)>
1211 The max operator.
1213 =cut
1215 .sub 'infix:max'
1216     .param pmc args :slurpy
1218     # If we have no arguments, undefined.
1219     .local int elems
1220     elems = elements args
1221     if elems > 0 goto have_args
1222     $P0 = undef()
1223     .return($P0)
1224 have_args:
1226     # Find maximum.
1227     .local pmc cur_max
1228     .local int i
1229     cur_max = args[0]
1230     i = 1
1231 find_max_loop:
1232     if i >= elems goto find_max_loop_end
1233     $P0 = args[i]
1234     $I0 = 'infix:cmp'($P0, cur_max)
1235     if $I0 != 1 goto not_max
1236     set cur_max, $P0
1237 not_max:
1238     inc i
1239     goto find_max_loop
1240 find_max_loop_end:
1242     .return(cur_max)
1243 .end
1245 =item C<reverse(LIST)>
1247 Returns the elements of LIST in the opposite order.
1249 =cut
1251 .sub 'reverse'
1252     .param pmc list :slurpy
1253     .local string type
1254     .local pmc retv
1255     .local pmc elem
1256     .local int len
1257     .local int i
1259     len = elements list
1261     if len > 1 goto islist
1263     # If we're not a list, check if we're a string.
1264     elem = list[0]
1265     typeof type, elem
1267     # This is a bit of a work around - some operators (ie. ~) return
1268     # a String object instead of a CardinalString.
1269     eq type, 'String', parrotstring
1270     eq type, 'CardinalString', perl6string
1271     goto islist
1273   parrotstring:
1274     .local string tmps
1275     tmps = elem
1276     elem = new 'CardinalString'
1277     elem = tmps
1279   perl6string:
1280     retv = elem.'reverse'()
1281     goto done
1283   islist:
1284     retv = new 'CardinalArray'
1285     i = 0
1287   loop:
1288     if i == len goto done
1289     elem = list[i]
1290     retv.'unshift'(elem)
1291     inc i
1292     goto loop
1294   done:
1295     .return(retv)
1296 .end
1298 .sub keys :multi('CardinalArray')
1299   .param pmc list
1301   .return list.'keys'()
1302 .end
1304 .sub values :multi('CardinalArray')
1305   .param pmc list
1307   .return list.'values'()
1308 .end
1310 .sub delete :multi('CardinalArray')
1311   .param pmc list
1312   .param pmc indices :slurpy
1314   .return list.'delete'(indices :flat)
1315 .end
1317 .sub exists :multi('CardinalArray')
1318   .param pmc list
1319   .param pmc indices :slurpy
1321   .return list.'exists'(indices :flat)
1322 .end
1324 .sub kv :multi('CardinalArray')
1325     .param pmc list
1327     .return list.'kv'()
1328 .end
1330 .sub pairs :multi('CardinalArray')
1331     .param pmc list
1333     .return list.'pairs'()
1334 .end
1336 .sub grep :multi(_,'CardinalArray')
1337     .param pmc test
1338     .param pmc list :slurpy
1340     .return list.'grep'(test)
1341 .end
1343 .sub first :multi(_,'CardinalArray')
1344     .param pmc test
1345     .param pmc list :slurpy
1347     .return list.'first'(test)
1348 .end
1350 .sub 'infix:<<' :multi('CardinalArray',_)
1351     .param pmc array
1352     .param pmc item
1353     push array, item
1354     .return(array)
1355 .end
1357 ## TODO: join map reduce sort zip
1359 =back
1361 =cut
1363 # Local Variables:
1364 #   mode: pir
1365 #   fill-column: 100
1366 # End:
1367 # vim: expandtab shiftwidth=4 ft=pir: