[TT #871] Add rand as a dynop, with tests
[parrot.git] / src / pmc / array.pmc
blobd4393570d521211427f4dfdfa4eeaf708cb9d168
1 /*
2 Copyright (C) 2001-2009, Parrot Foundation.
3 $Id$
5 =head1 NAME
7 src/pmc/array.pmc - Array PMC
9 =head1 DESCRIPTION
11 These are the vtable functions for the Array base class.
13 =head2 Functions
15 =over 4
17 =cut
23 =item C<static PMC *undef(PARROT_INTERP)>
25 Returns a C<Undef> PMC.
27 =cut
31 static PMC *undef(PARROT_INTERP) {
32     return pmc_new(interp, enum_class_Undef);
37 =item C<static PMC *retval(PARROT_INTERP, void *ret)>
39 Processes C<*ret>, returning the appropriate PMC, or raising an
40 exception if necessary.
42 =cut
46 static PMC *retval(PARROT_INTERP, void *ret) {
47     PMC *value;
49     if (ret == NULL)
50         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_OUT_OF_BOUNDS,
51             "Array index out of bounds!");
53     /* XXX getting non existent value, exception or undef?
54      * current is for perlarray */
55     if (ret == (void *)-1)
56         value = undef(interp);
57     else {
58         value = *(PMC **)ret;
60         /* XXX same here */
61         if (!value)
62             value = undef(interp);
63     }
65     return value;
70 =item C<static PMC
71 *Parrot_Array_set_pmc_ptr(PARROT_INTERP, List *list, INTVAL key)>
73 Returns a pointer to the element at index C<key> of C<*list>. If
74 this element was previously empty, then this function also creates
75 and assigns an "undef" PMC to that element.
77 =cut
81 static PMC *Parrot_Array_set_pmc_ptr(PARROT_INTERP, List *list, INTVAL key) {
82     void * const ret = list_get(interp, list, key, enum_type_PMC);
83     PMC  *value;
85     if (ret == NULL)
86         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_OUT_OF_BOUNDS,
87             "Array index out of bounds!");
89     /* assign into a sparse or not yet set value */
90     if (ret == (void *)-1 || *(PMC **)ret == NULL) {
91         value = undef(interp);
92         list_assign(interp, list, key, value, enum_type_PMC);
93     }
94     else
95         value = *(PMC **)ret;
97     return value;
101 pmclass Array need_ext provides array {
105 =back
107 =head2 Methods
109 =over 4
111 =item C<void class_init()>
113 Class initialization. Creates the required memory pools.
115 =cut
119     void class_init() {
121     }
125 =item C<void init()>
127 Initializes the PMC by calling the underlying C<list_new()> function.
129 =cut
133     VTABLE void init() {
134         list_pmc_new(INTERP, SELF);
135         PObj_custom_mark_SET(SELF);
136     }
140 =item C<void init_pmc(PMC *init)>
142 C<*init> contains the initialization information specifying initial size,
143 number of dimensions, etc.
145 =cut
149     VTABLE void init_pmc(PMC *init) {
150         list_pmc_new_init(INTERP, SELF, init);
151         PObj_custom_mark_SET(SELF);
152     }
156 =item C<void assign_pmc(PMC *other)>
158 Copy the contents of other to self.
160 =cut
164     VTABLE void assign_pmc(PMC *other) {
165         const INTVAL size = VTABLE_elements(INTERP, other);
166         INTVAL       i;
168         SELF.set_integer_native(size);
169         for (i = 0; i < size; i++) {
170             PMC * const elem = VTABLE_get_pmc_keyed_int(INTERP, other, i);
171             SELF.set_pmc_keyed_int(i, elem);
172         }
173     }
178 =item C<void set_pmc(PMC *other)>
180 Implemented as an alias to C<assign_pmc> since the behavior is the same.
182 =cut
186     VTABLE void set_pmc(PMC *other) {
187         SELF.assign_pmc(other);
188     }
192 =item C<void mark()>
194 Mark the array and its contents as live.
196 =cut
200     VTABLE void mark() {
201         list_mark(INTERP, (List *)PMC_data(SELF));
202     }
206 =item C<PMC *clone()>
208 Return a clone of the array.
210 =cut
214     VTABLE PMC *clone() {
215         List       *l    = list_clone(INTERP, (List *)PMC_data(SELF));
216         PMC * const dest = pmc_new_noinit(INTERP, SELF->vtable->base_type);
218         PObj_custom_mark_SET(dest);
220         PMC_data(dest) = l;
221         l->container   = dest;
223         return dest;
224     }
228 =item C<INTVAL get_integer()>
230 Returns the number of elements in the array.
232 =cut
236     VTABLE INTVAL get_integer() {
237         return SELF.elements();
238     }
242 =item C<INTVAL get_bool()>
244 Returns true if the array has one or more elements.
246 =cut
250     VTABLE INTVAL get_bool() {
251         const INTVAL size = SELF.elements();
252         return (INTVAL)(size != 0);
253     }
257 =item C<INTVAL elements()>
259 Returns the number of elements in the array.
261 =cut
265     VTABLE INTVAL elements() {
266         return ((const List *) PMC_data(SELF))->length;
267     }
271 =item C<FLOATVAL get_number()>
273 Returns the number of elements in the array.
275 =cut
279     VTABLE FLOATVAL get_number() {
280         const INTVAL e = SELF.elements();
281         return (FLOATVAL)e;
282     }
286 =item C<STRING *get_string()>
288 Returns a string representation of the array.
290 =cut
294     VTABLE STRING *get_string() {
295         return Parrot_sprintf_c(INTERP, "array[%p]", SELF);
296     }
300 =item C<INTVAL get_integer_keyed_int(INTVAL key)>
302 Returns the integer value of the element at index C<key>.
304 =cut
308     VTABLE INTVAL get_integer_keyed_int(INTVAL key) {
309         PMC * const value = SELF.get_pmc_keyed_int(key);
311         return VTABLE_get_integer(INTERP, value);
312     }
316 =item C<INTVAL get_integer_keyed(PMC *key)>
318 Returns the integer value of the element at index C<key>.
320 =cut
324     VTABLE INTVAL get_integer_keyed(PMC *key) {
325         INTVAL ix;
326         PMC   *nextkey, *box;
328         if (!key)
329             return 0;
331         ix      = VTABLE_get_integer(INTERP, key);
332         nextkey = key_next(INTERP, key);
334         if (!nextkey)
335             return SELF.get_integer_keyed_int(ix);
337         box = SELF.get_pmc_keyed_int(ix);
339         if (!box)
340             box = undef(INTERP);
342         return VTABLE_get_integer_keyed(INTERP, box, nextkey);
343     }
347 =item C<FLOATVAL get_number_keyed_int(INTVAL key)>
349 Returns the float value of the element at index C<key>.
351 =cut
355     VTABLE FLOATVAL get_number_keyed_int(INTVAL key) {
356         PMC * const value = SELF.get_pmc_keyed_int(key);
358         return VTABLE_get_number(INTERP, value);
360     }
364 =item C<FLOATVAL get_number_keyed(PMC *key)>
366 Returns the float value of the element at index C<key>.
368 =cut
372     VTABLE FLOATVAL get_number_keyed(PMC *key) {
373         INTVAL ix;
374         PMC *nextkey, *box;
376         if (!key)
377             return (FLOATVAL)0;
379         ix      = VTABLE_get_integer(INTERP, key);
380         nextkey = key_next(INTERP, key);
382         if (!nextkey)
383             return SELF.get_number_keyed_int(ix);
385         box = SELF.get_pmc_keyed_int(ix);
387         if (!box)
388             box = undef(INTERP);
390         return VTABLE_get_number_keyed(INTERP, box, nextkey);
391     }
395 =item C<STRING *get_string_keyed_int(INTVAL key)>
397 Returns the string value of the element at index C<key>.
399 =cut
403     VTABLE STRING *get_string_keyed_int(INTVAL key) {
404         PMC * const value = SELF.get_pmc_keyed_int(key);
406         return VTABLE_get_string(INTERP, value);
407     }
411 =item C<STRING *get_string_keyed(PMC *key)>
413 Returns the string value of the element at index C<key>.
415 =cut
419     VTABLE STRING *get_string_keyed(PMC *key) {
420         INTVAL ix;
421         PMC   *nextkey, *box;
423         if (!key)
424             return NULL;
426         ix      = VTABLE_get_integer(INTERP, key);
427         nextkey = key_next(INTERP, key);
429         if (!nextkey)
430             return SELF.get_string_keyed_int(ix);
432         box = SELF.get_pmc_keyed_int(ix);
434         if (!box)
435             box = undef(INTERP);
437         return VTABLE_get_string_keyed(INTERP, box, nextkey);
438     }
442 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
444 Returns the PMC value of the element at index C<key>.
446 =cut
450     VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
452         return retval(INTERP,
453             list_get(INTERP, (List *)PMC_data(SELF), key, enum_type_PMC));
454     }
458 =item C<PMC *get_pmc_keyed(PMC *key)>
460 Returns the PMC value of the element at index C<key>.
462 =cut
466     VTABLE PMC *get_pmc_keyed(PMC *key) {
467         INTVAL ix;
468         PMC   *nextkey, *box;
470         if (!key)
471             return NULL;
473         ix      = VTABLE_get_integer(INTERP, key);
474         nextkey = key_next(INTERP, key);
476         if (!nextkey)
477             return SELF.get_pmc_keyed_int(ix);
479         box = SELF.get_pmc_keyed_int(ix);
481         if (!box)
482             box = undef(INTERP);
484         return VTABLE_get_pmc_keyed(INTERP, box, nextkey);
485     }
489 =item C<void set_integer_native(INTVAL size)>
491 Sets the length of the array to C<size>.
493 =cut
497     VTABLE void set_integer_native(INTVAL size) {
498         list_set_length(INTERP, (List *)PMC_data(SELF), size);
499     }
502 =item C<void set_integer_same(PMC *value)>
504 Sets the length of the array to the number of elements in C<*value>.
506 =cut
510     VTABLE void set_integer_same(PMC *value) {
511         const INTVAL size = VTABLE_elements(INTERP, value);
512         list_set_length(INTERP, (List *)PMC_data(SELF), size);
513     }
517 =item C<void set_integer_keyed_int(INTVAL key, INTVAL value)>
519 Sets the integer value of the PMC at element C<key> to C<value>.
521 =cut
525     VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) {
526         PMC * const ptr =
527             Parrot_Array_set_pmc_ptr(INTERP, (List *)PMC_data(SELF), key);
529         VTABLE_set_integer_native(INTERP, ptr, value);
530     }
534 =item C<void set_integer_keyed(PMC *key, INTVAL value)>
536 Sets the integer value of the PMC at element C<key> to C<value>.
538 =cut
542     VTABLE void set_integer_keyed(PMC *key, INTVAL value) {
543         INTVAL ix;
544         PMC   *nextkey, *box;
546         if (!key)
547             return;
549         ix      = VTABLE_get_integer(INTERP, key);
550         nextkey = key_next(INTERP, key);
552         if (!nextkey) {
553             SELF.set_integer_keyed_int(ix, value);
554             return;
555         }
557         box = SELF.get_pmc_keyed_int(ix);
559         /* autovivify an Array */
560         if (!box)
561             box = pmc_new(INTERP, SELF.type());
563         VTABLE_set_integer_keyed(INTERP, box, nextkey, value);
564     }
568 =item C<void set_number_keyed_int(INTVAL key, FLOATVAL value)>
570 Sets the numeric value of the PMC at element C<key> to C<value>.
572 =cut
576     VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL value) {
577         PMC * const ptr =
578             Parrot_Array_set_pmc_ptr(INTERP, (List *)PMC_data(SELF), key);
580         VTABLE_set_number_native(INTERP, ptr, value);
581     }
585 =item C<void set_number_keyed(PMC *key, FLOATVAL value)>
587 Sets the numeric value of the PMC at element C<key> to C<value>.
589 =cut
593     VTABLE void set_number_keyed(PMC *key, FLOATVAL value) {
594         INTVAL ix;
595         PMC   *nextkey, *box;
597         if (!key)
598             return;
600         ix      = VTABLE_get_integer(INTERP, key);
601         nextkey = key_next(INTERP, key);
603         if (!nextkey) {
604             SELF.set_number_keyed_int(ix, value);
605             return;
606         }
608         box = SELF.get_pmc_keyed_int(ix);
610         /* autovivify an Array */
611         if (!box)
612             box = pmc_new(INTERP, SELF.type());
614         VTABLE_set_number_keyed(INTERP, box, nextkey, value);
615     }
619 =item C<void set_string_keyed_int(INTVAL key, STRING *value)>
621 Sets the string value of the PMC at element C<key> to C<value>.
623 =cut
627     VTABLE void set_string_keyed_int(INTVAL key, STRING *value) {
628         PMC * const ptr =
629             Parrot_Array_set_pmc_ptr(INTERP, (List *)PMC_data(SELF), key);
631         VTABLE_set_string_native(INTERP, ptr, value);
632     }
636 =item C<void set_string_keyed(PMC *key, STRING *value)>
638 Sets the string value of the PMC at element C<key> to C<value>.
640 =cut
644     VTABLE void set_string_keyed(PMC *key, STRING *value) {
645         INTVAL ix;
646         PMC   *nextkey, *box;
648         if (!key)
649             return;
651         ix      = VTABLE_get_integer(INTERP, key);
652         nextkey = key_next(INTERP, key);
654         if (!nextkey) {
655             VTABLE_set_string_keyed_int(INTERP, SELF, ix, value);
656             return;
657         }
659         box = SELF.get_pmc_keyed_int(ix);
661         /* autovivify an Array */
662         if (!box)
663             box = pmc_new(INTERP, SELF.type());
665         VTABLE_set_string_keyed(INTERP, box, nextkey, value);
666     }
670 =item C<void set_pmc_keyed_int(INTVAL idx, PMC *src)>
672 Sets the PMC at element C<idx> to C<*src>.
674 =cut
678     VTABLE void set_pmc_keyed_int(INTVAL idx, PMC *src) {
679         const INTVAL length = ((List *)PMC_data(SELF))->length;
681         if (idx >= length || -idx > length)
682             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
683                 "Array index out of bounds!");
685         list_assign(INTERP, (List *)PMC_data(SELF), idx,
686             (void *)src, enum_type_PMC);
687     }
691 =item C<void set_pmc_keyed(PMC *key, PMC *value)>
693 Sets the PMC at index C<key> to C<value>.
695 =cut
699     VTABLE void set_pmc_keyed(PMC *key, PMC *value) {
700         PMC *box;
702         const INTVAL ix      = VTABLE_get_integer(INTERP, key);
703         PMC * const  nextkey = key_next(INTERP, key);
705         if (!nextkey) {
706             VTABLE_set_pmc_keyed_int(INTERP, SELF, ix, value);
707             return;
708         }
710         box = SELF.get_pmc_keyed_int(ix);
712         /* autovivify an Array */
713         if (!box)
714             box = pmc_new(INTERP, SELF.type());
716         VTABLE_set_pmc_keyed(INTERP, box, nextkey, value);
717     }
721 =item C<void push_integer(INTVAL value)>
723 Extends the array by adding an element of value C<value> to the end of
724 the array.
726 =cut
730     VTABLE void push_integer(INTVAL value) {
731         const INTVAL nextix = SELF.elements();
732         SELF.set_integer_keyed_int(nextix, value);
733     }
737 =item C<void push_float(FLOATVAL value)>
739 Extends the array by adding an element of value C<value> to the end of
740 the array.
742 =cut
746     VTABLE void push_float(FLOATVAL value) {
747         const INTVAL nextix = SELF.elements();
748         SELF.set_number_keyed_int(nextix, value);
749     }
753 =item C<void push_string(STRING *value)>
755 Extends the array by adding an element of value C<*value> to the end of
756 the array.
758 =cut
762     VTABLE void push_string(STRING *value) {
763         const INTVAL nextix = SELF.elements();
764         SELF.set_string_keyed_int(nextix, value);
765     }
769 =item C<void push_pmc(PMC *value)>
771 Extends the array by adding an element of value C<*value> to the end of
772 the array.
774 =cut
778     VTABLE void push_pmc(PMC *value) {
779         const INTVAL nextix = SELF.elements();
780         SELF.set_pmc_keyed_int(nextix, value);
781     }
785 =item C<void unshift_integer(INTVAL value)>
787 Extends the array by adding an element of value C<value> to the start
788 of the array.
790 =cut
794     VTABLE void unshift_integer(INTVAL value) {
795         PMC * const val = undef(INTERP);
797         list_unshift(INTERP, (List *)PMC_data(SELF), val, enum_type_PMC);
798         VTABLE_set_integer_native(INTERP, val, value);
799     }
803 =item C<void unshift_float(FLOATVAL value)>
805 Extends the array by adding an element of value C<value> to the start
806 of the array.
808 =cut
812     VTABLE void unshift_float(FLOATVAL value) {
813         PMC * const val = undef(INTERP);
815         list_unshift(INTERP, (List *)PMC_data(SELF), val, enum_type_PMC);
816         VTABLE_set_number_native(INTERP, val, value);
817     }
821 =item C<void unshift_string(STRING *value)>
823 Extends the array by adding an element of value C<*value> to the start
824 of the array.
826 =cut
830     VTABLE void unshift_string(STRING *value) {
831         PMC * const val = undef(INTERP);
832         list_unshift(INTERP, (List *)PMC_data(SELF), val, enum_type_PMC);
833         VTABLE_set_string_native(INTERP, val, value);
834     }
838 =item C<void unshift_pmc(PMC *value)>
840 Extends the array by adding an element of value C<*value> to the start
841 of the array.
843 =cut
847     VTABLE void unshift_pmc(PMC *value) {
848         list_unshift(INTERP, (List *)PMC_data(SELF), value, enum_type_PMC);
849     }
853 =item C<INTVAL pop_integer()>
855 Removes and returns an integer from the end of the array.
857 =cut
861     VTABLE INTVAL pop_integer() {
862         PMC * const ptr = SELF.pop_pmc();
863         return VTABLE_get_integer(INTERP, ptr);
864     }
868 =item C<FLOATVAL pop_float()>
870 Removes and returns a float value from the end of the array.
872 =cut
876     VTABLE FLOATVAL pop_float() {
877         PMC * const ptr = SELF.pop_pmc();
878         return VTABLE_get_number(INTERP, ptr);
879     }
883 =item C<STRING *pop_string()>
885 Removes and returns a string from the end of the array.
887 =cut
891     VTABLE STRING *pop_string() {
892         PMC * const ptr = SELF.pop_pmc();
893         return VTABLE_get_string(INTERP, ptr);
894     }
898 =item C<PMC *pop_pmc()>
900 Removes and returns a PMC from the end of the array.
902 =cut
906     VTABLE PMC *pop_pmc() {
907         return retval(INTERP,
908             list_pop(INTERP, (List *)PMC_data(SELF), enum_type_PMC));
909     }
913 =item C<INTVAL shift_integer()>
915 Removes and returns an integer from the start of the array.
917 =cut
921     VTABLE INTVAL shift_integer() {
922         PMC * const ptr = SELF.shift_pmc();
923         return VTABLE_get_integer(INTERP, ptr);
924     }
928 =item C<FLOATVAL shift_float()>
930 Removes and returns a float from the start of the array.
932 =cut
936     VTABLE FLOATVAL shift_float() {
937         PMC * const ptr = SELF.shift_pmc();
938         return VTABLE_get_number(INTERP, ptr);
939     }
943 =item C<STRING *shift_string()>
945 Removes and returns a string from the start of the array.
947 =cut
951     VTABLE STRING *shift_string() {
952         PMC * const ptr = SELF.shift_pmc();
953         return VTABLE_get_string(INTERP, ptr);
954     }
958 =item C<PMC *shift_pmc()>
960 Removes and returns a PMC from the start of the array.
962 =cut
966     VTABLE PMC *shift_pmc() {
967         return retval(INTERP,
968             list_shift(INTERP, (List *)PMC_data(SELF), enum_type_PMC));
969     }
973 =item C<void splice(PMC *value, INTVAL offset, INTVAL count)>
975 Replaces C<count> elements starting at C<offset> with the elements in
976 C<value>.
978 If C<count> is 0 then the elements in C<value> will be inserted after
979 C<offset>.
981 =cut
985     VTABLE void splice(PMC *value, INTVAL offset, INTVAL count) {
986         if (SELF->vtable->base_type != value->vtable->base_type)
987             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
988                 "Type mismatch in splice");
990         list_splice(INTERP, (List *)PMC_data(SELF),
991             (List *)PMC_data(value), offset, count);
992     }
996 =item C<INTVAL defined_keyed_int(INTVAL key)>
998 Returns TRUE is the element at C<key> is defined; otherwise returns false.
1000 =cut
1004     VTABLE INTVAL defined_keyed_int(INTVAL key) {
1005         PMC  *value;
1006         void * const ret =
1007             list_get(INTERP, (List *)PMC_data(pmc), key, enum_type_PMC);
1009         if (ret == NULL || ret == (void *) -1)
1010             return 0;
1012         value = *(PMC **)ret;
1014         if (!value)
1015             return 0;
1017         return VTABLE_defined(INTERP, value);
1018     }
1022 =item C<INTVAL defined_keyed(PMC *key)>
1024 Returns TRUE is the element at C<key> is defined; otherwise returns false.
1026 =cut
1030     VTABLE INTVAL defined_keyed(PMC *key) {
1031         PMC *box;
1033         const INTVAL ix      = VTABLE_get_integer(INTERP, key);
1034         PMC * const  nextkey = key_next(INTERP, key);
1036         if (!nextkey)
1037             return SELF.defined_keyed_int(ix);
1039         box = SELF.get_pmc_keyed_int(ix);
1041         if (!box)
1042             return 0;
1044         return VTABLE_defined_keyed(INTERP, box, nextkey);
1045     }
1049 =item C<INTVAL exists_keyed_int(INTVAL key)>
1051 Returns TRUE is the element at C<key> exists; otherwise returns false.
1053 =cut
1057     VTABLE INTVAL exists_keyed_int(INTVAL key) {
1058         void * ret = list_get(INTERP,
1059             (List *)PMC_data(pmc), key, enum_type_PMC);
1061         if (ret == NULL || ret == (void *)-1)
1062             return 0;
1064         return !PMC_IS_NULL(*(PMC **)ret);
1065     }
1069 =item C<INTVAL exists_keyed(PMC *key)>
1071 Returns TRUE is the element at C<key> exists; otherwise returns false.
1073 =cut
1077     VTABLE INTVAL exists_keyed(PMC *key) {
1078         PMC *box;
1080         const INTVAL ix      = VTABLE_get_integer(INTERP, key);
1081         PMC * const  nextkey = key_next(INTERP, key);
1083         if (!nextkey)
1084             return SELF.exists_keyed_int(ix);
1086         box = SELF.get_pmc_keyed_int(ix);
1088         if (!box)
1089             return 0;
1091         return VTABLE_exists_keyed(INTERP, box, nextkey);
1092     }
1096 =item C<void delete_keyed_int(INTVAL key)>
1098 Removes the element at C<key>.
1100 =cut
1104     VTABLE void delete_keyed_int(INTVAL key) {
1105         list_splice(INTERP, (List *)PMC_data(pmc), NULL, key, 1);
1106     }
1110 =item C<void delete_keyed(PMC *key)>
1112 Removes the element at C<*key>.
1114 =cut
1118     VTABLE void delete_keyed(PMC *key) {
1119         const INTVAL ix = VTABLE_get_integer(INTERP, key);
1120         list_splice(INTERP, (List *)PMC_data(pmc), NULL, ix, 1);
1121     }
1125 =item C<INTVAL is_equal(PMC *value)>
1127 The C<==> operation. Compares two array to hold equal elements.
1129 =cut
1133     VTABLE INTVAL is_equal(PMC *value) {
1134         INTVAL j, n;
1136         if (value->vtable->base_type != enum_class_Array)
1137             return 0;
1139         n = SELF.elements();
1141         if (VTABLE_elements(INTERP, value) != n)
1142             return 0;
1144         for (j = 0; j < n; ++j) {
1145             PMC * const item1 = SELF.get_pmc_keyed_int(j);
1146             PMC * const item2 = VTABLE_get_pmc_keyed_int(INTERP, value, j);
1148             if (item1 != item2) {
1149                 const INTVAL result = VTABLE_is_equal(INTERP, item1, item2);
1150                 if (!result)
1151                     return 0;
1152             }
1153         }
1155         return 1;
1156     }
1160 =item C<PMC *slice(PMC *key, INTVAL f)>
1162 Return a new iterator for the slice PMC C<key> if f == 0.
1164 Return a new pythonic array slice if f == 1.
1166 =item C<PMC *get_iter()>
1168 Return a new iterator for SELF.
1170 =cut
1174     VTABLE PMC *slice(PMC *key, INTVAL f) {
1175         if (f == 0) {
1176             STRING * const name = CONST_STRING(interp, "set_key");
1177             PMC * const iter = pmc_new_init(INTERP, enum_class_Iterator, SELF);
1178             Parrot_PCCINVOKE(interp, iter, name, "P->", key);
1179             return iter;
1180         }
1182         Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
1183                 "Array: Unknown slice type");
1184     }
1186     VTABLE PMC *get_iter() {
1187         return pmc_new_init(INTERP, enum_class_ArrayIterator, SELF);
1188     }
1192 =item C<void visit(visit_info *info)>
1194 This is used by freeze/thaw to visit the contents of the array.
1196 C<*info> is the visit info, (see F<include/parrot/pmc_freeze.h>).
1198 =cut
1202     VTABLE void visit(visit_info *info) {
1203         list_visit(INTERP, (List *)PMC_data(SELF), info);
1204         SUPER(info);
1205     }
1209 =item C<void freeze(visit_info *info)>
1211 Used to archive the array.
1213 =cut
1217     VTABLE void freeze(visit_info *info) {
1218         IMAGE_IO * const io = info->image_io;
1219         SUPER(info);
1220         VTABLE_push_integer(INTERP, io, VTABLE_elements(INTERP, SELF));
1221     }
1225 =item C<void thaw(visit_info *info)>
1227 Used to unarchive the array.
1229 =cut
1233     VTABLE void thaw(visit_info *info) {
1234         IMAGE_IO * const io = info->image_io;
1236         SUPER(info);
1237         if (info->extra_flags == EXTRA_IS_NULL) {
1238             SELF.set_integer_native(VTABLE_shift_integer(INTERP, io));
1239     }
1244 =item C<PMC *share_ro()>
1246 Recursively make the array read-only and shared.
1248 =cut
1251     VTABLE PMC *share_ro() {
1252         PMC *_true, *ret;
1254         /* prevent infinite recursion */
1255         if (PObj_is_PMC_shared_TEST(SELF))
1256             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
1257                     "share_ro on something that already is shared");
1259         _true = pmc_new(INTERP, enum_class_Integer);
1260         VTABLE_set_integer_native(INTERP, _true, 1);
1262         ret   = pt_shared_fixup(INTERP, SELF);
1264         /* first set readonly */
1265         VTABLE_setprop(INTERP, ret, CONST_STRING(INTERP, "_ro"), _true);
1267         /* XXX do something that deals better with sparse lists */
1268         {
1269             INTVAL i;
1270             const INTVAL max = VTABLE_elements(INTERP, ret);
1272             for (i = 0; i < max; ++i) {
1273                 PMC * const value =
1274                     (PMC *)list_get(INTERP, PMC_data_typed(ret, List *),
1275                                  i, enum_type_PMC);
1277                 if (!PMC_IS_NULL(value)) {
1278                     /* XXX do we need to clone first? */
1279                     PMC * const new_value = VTABLE_share_ro(INTERP, value);
1281                     if (new_value != value)
1282                         list_assign(INTERP, PMC_data_typed(ret, List *),
1283                             i, new_value, enum_type_PMC);
1284                 }
1285             }
1286         }
1288         /* XXX FIXME workaround lack of metadata sharing */
1289         PMC_metadata(SELF) = NULL;
1291         return ret;
1292     }
1297 =back
1299 =head1 SEE ALSO
1301 F<src/list.c>, F<include/parrot/list.h>
1303 =head1 TODO
1305 Create global immutable undef object.
1307 =cut
1312  * Local variables:
1313  *   c-file-style: "parrot"
1314  * End:
1315  * vim: expandtab shiftwidth=4:
1316  */