5 src/classes/CardinalArray.pir - Cardinal CardinalArray class and related functions
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'
25 interp.'hll_map'(core_type, hll_type)
30 =item get_string() (vtable method)
32 Return the elements of the list concatenated.
36 .sub 'get_string' :vtable :method
45 Return a CardinalString representing the Array.
51 $P0 = new 'CardinalString'
56 =item clone() (vtable method)
62 .sub 'clone' :vtable :method
67 =item clear() (method)
69 Removes all elements from the array.
82 .sub 'ACCEPTS' :method
88 if what == "CardinalArray" goto acc_list
92 # Smartmatch against another list. Smartmatch each
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
100 if i >= count_1 goto list_cmp_loop_end
101 .local pmc elem_1, elem_2
104 ($I0) = elem_1.ACCEPTS(elem_2)
105 unless $I0 goto no_match
112 $P0 = get_hll_global ['Bool'], 'False'
115 $P0 = get_hll_global ['Bool'], 'True'
122 Return the number of elements in the list.
133 Return a sorted copy of the list
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'
148 elems = list.'elems'()
149 fpa = new 'FixedPMCArray'
155 unless i < elems goto fpa_end
162 .return 'list'(fpa :flat)
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'
180 # TODO Rewrite it. It's too naive.
192 ulist = new 'CardinalArray'
197 if i == len goto done
202 ulen = ulist.'elems'()
204 if ui == ulen goto inner_loop_done
207 if uval == val goto found
231 =item include?(ELEMENT)
233 Return true if self contains ELEMENT
236 .sub 'include?' :method
239 iter = new 'Iterator', self
241 unless iter goto done_f
246 $P0 = get_hll_global ['Bool'], 'False'
249 $P0 = get_hll_global ['Bool'], 'True'
254 =item unshift(ELEMENTS)
256 Prepends ELEMENTS to the front of the list.
260 .sub 'unshift' :method
261 .param pmc args :slurpy
270 if i == narg goto done
280 Returns a CardinalArray containing the keys of the CardinalArray.
290 res = new 'CardinalArray'
295 if i == len goto done
297 elem = new 'CardinalInteger'
310 Returns a CardinalArray containing the values of the CardinalArray.
314 .sub 'values' :method
320 res = new 'CardinalArray'
325 if i == len goto done
327 elem = new 'CardinalInteger'
340 Shifts the first item off the list and returns it.
352 Treats the list as a stack, popping the last item off the list and returning it.
362 if len == 0 goto empty
376 Treats the list as a stack, pushing ELEMENTS onto the end of the list. Returns the new length of the list.
381 .param pmc args :slurpy
390 if i == len goto done
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
407 .param string sep :optional
416 if len == 0 goto done
422 if i == len goto last
442 Returns a list of the elements in revese order.
446 .sub 'reverse' :method
451 res = new 'CardinalArray'
454 if len == 0 goto done
459 if len == 0 goto done
474 Reverses a list in place. Destructive update.
479 .sub 'reverse!' :method
489 if pos == 0 goto done
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.
511 .param pmc block :optional
512 .param int block_flag :opt_flag
527 if i == len goto done
547 if block_flag, have_block
556 Checks to see if the specified index or indices have been assigned to. Returns a Bool value.
561 .param pmc indices :slurpy
569 len = elements indices
573 if i == len goto done
577 test = exists self[ind]
578 if test == 0 goto done
584 .return 'prefix:?'(test)
597 res = new 'CardinalArray'
602 if i == len goto done
604 elem = new 'CardinalInteger'
630 res = new 'CardinalArray'
635 if i == len goto done
637 key = new 'CardinalInteger'
667 retv = new 'CardinalArray'
672 if i == narg goto done
675 newclosure block, test
676 block_res = block(block_arg)
678 if block_res goto grepped
682 retv.'push'(block_arg)
697 .sub first :method :multi(CardinalArray,_)
704 newlist = new 'CardinalArray'
706 elems = elements self
707 le count, elems, sufficient_elements
714 if i == count goto done
726 .sub first :method :multi(CardinalArray)
741 .sub last :method :multi(CardinalArray,_)
748 newlist = new 'CardinalArray'
750 elems = elements self
751 count = elems - count
752 ge count, 0, sufficient_elements
763 unshift newlist, item
771 .sub last :method :multi(CardinalArray)
785 Run C<block> once for each item in C<self>, with the item passed as an arg.
791 $P0 = new 'Iterator', self
793 unless $P0 goto each_loop_end
800 .sub 'each_with_index' :method
806 if $I0 == len goto each_loop_end
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.
821 .sub 'collect' :method
824 result = new 'CardinalArray'
825 $P0 = new 'Iterator', self
827 unless $P0 goto each_loop_end
838 recursively flatten any inner arrays into a single outer array
841 .sub 'flatten' :method
844 returnMe = new 'CardinalArray'
845 iterator = new 'Iterator', self
847 unless iterator goto each_loop_end
849 #if $P1 is an array call flatten
850 $I0 = isa $P1, 'CardinalArray'
851 if $I0 goto inner_flatten
855 $P2 = $P1.'flatten'()
856 $P3 = new 'Iterator', $P2
858 unless $P3 goto each_loop
869 Retrieve the number of elements in C<self>
879 Retrieve the number of elements in C<self>
882 .sub 'length' :method
889 Retrieve element from position C<index>.
914 Retrieve the number of elements in C<self>
921 returnMe = new 'CardinalArray'
924 unless $I0 <= end goto each_loop_end
940 .param pmc args :slurpy
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
950 iterator = new 'Iterator', self
954 unless iterator, setup_loop_done
955 args_iter = new 'Iterator', args
956 item = new 'CardinalArray'
960 unless args_iter, inner_loop_done
961 arg = shift args_iter
963 unless null $P0 goto arg_not_null
964 $P0 = get_hll_global 'nil'
985 Build a CardinalArray from its arguments.
992 .param pmc args :slurpy
993 .local pmc list, item
994 list = new 'CardinalArray'
996 unless args goto args_end
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
1014 =item C<infix:,(...)>
1016 Operator form for building a list from its arguments.
1021 .param pmc args :slurpy
1022 .return 'list'(args :flat)
1026 =item C<infix:Z(...)>
1033 .param pmc args # :slurpy
1035 num_args = elements args
1037 # Empty list of no arguments.
1038 if num_args > 0 goto has_args
1039 $P0 = new 'CardinalArray'
1043 # Get minimum element count - what we'll zip to.
1048 min_elem = elements $P0
1050 if i >= num_args goto min_elems_loop_end
1053 unless $I0 < min_elem goto not_min
1060 # Now build result list of lists.
1062 res = new 'CardinalArray'
1065 if i >= min_elem goto zip_loop_end
1067 cur_list = new 'CardinalArray'
1071 if j >= num_args goto zip_elem_loop_end
1087 =item C<infix:X(...)>
1089 The non-hyper cross operator.
1094 .param pmc args :slurpy
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.
1102 .local pmc list_elements
1104 counters = new 'FixedIntegerCardinalArray'
1105 list_elements = new 'FixedIntegerCardinalArray'
1106 num_args = elements args
1108 list_elements = num_args
1110 # Get element count for each list.
1115 if i >= num_args goto elem_get_loop_end
1117 $I0 = elements cur_list
1118 list_elements[i] = $I0
1123 # Now we'll start to produce them.
1124 .local int res_count
1128 # Start out by building list at current counters.
1130 new_list = new 'CardinalArray'
1133 if i >= num_args goto cur_perm_loop_end
1141 res[res_count] = new_list
1144 # Now increment counters.
1148 $I1 = list_elements[i]
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.
1158 # If we're on the first element, all done.
1159 if i == 0 goto all_done
1163 goto inc_counter_loop
1164 inc_counter_loop_end:
1172 =item C<infix:min(...)>
1179 .param pmc args :slurpy
1181 # If we have no arguments, undefined.
1183 elems = elements args
1184 if elems > 0 goto have_args
1195 if i >= elems goto find_min_loop_end
1197 $I0 = 'infix:cmp'($P0, cur_min)
1198 if $I0 != -1 goto not_min
1209 =item C<infix:max(...)>
1216 .param pmc args :slurpy
1218 # If we have no arguments, undefined.
1220 elems = elements args
1221 if elems > 0 goto have_args
1232 if i >= elems goto find_max_loop_end
1234 $I0 = 'infix:cmp'($P0, cur_max)
1235 if $I0 != 1 goto not_max
1245 =item C<reverse(LIST)>
1247 Returns the elements of LIST in the opposite order.
1252 .param pmc list :slurpy
1261 if len > 1 goto islist
1263 # If we're not a list, check if we're a string.
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
1276 elem = new 'CardinalString'
1280 retv = elem.'reverse'()
1284 retv = new 'CardinalArray'
1288 if i == len goto done
1290 retv.'unshift'(elem)
1298 .sub keys :multi('CardinalArray')
1301 .return list.'keys'()
1304 .sub values :multi('CardinalArray')
1307 .return list.'values'()
1310 .sub delete :multi('CardinalArray')
1312 .param pmc indices :slurpy
1314 .return list.'delete'(indices :flat)
1317 .sub exists :multi('CardinalArray')
1319 .param pmc indices :slurpy
1321 .return list.'exists'(indices :flat)
1324 .sub kv :multi('CardinalArray')
1330 .sub pairs :multi('CardinalArray')
1333 .return list.'pairs'()
1336 .sub grep :multi(_,'CardinalArray')
1338 .param pmc list :slurpy
1340 .return list.'grep'(test)
1343 .sub first :multi(_,'CardinalArray')
1345 .param pmc list :slurpy
1347 .return list.'first'(test)
1350 .sub 'infix:<<' :multi('CardinalArray',_)
1357 ## TODO: join map reduce sort zip
1367 # vim: expandtab shiftwidth=4 ft=pir: