tagged release 0.6.4
[parrot.git] / src / pmc / array.pmc
blobe8add2b85cf30a008a98c69cf0b72844b895bfe2
1 /*
2 Copyright (C) 2001-2008, The Perl 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
21 #include "parrot/parrot.h"
25 =item C<static PMC *undef(PARROT_INTERP)>
27 Returns a C<Undef> PMC.
29 =cut
33 static PMC *undef(PARROT_INTERP) {
34     return pmc_new(interp, enum_class_Undef);
39 =item C<static PMC *retval(PARROT_INTERP, void *ret)>
41 Processes C<*ret>, returning the appropriate PMC, or raising an
42 exception if necessary.
44 =cut
48 static PMC *retval(PARROT_INTERP, void *ret) {
49     PMC *value;
51     if (ret == 0)
52         real_exception(interp, NULL, E_IndexError,
53             "Array index out of bounds!");
55     /* XXX getting non existent value, exception or undef?
56      * current is for perlarray */
57     if (ret == (void *)-1)
58         value = undef(interp);
59     else {
60         value = *(PMC **)ret;
62         /* XXX same here */
63         if (!value)
64             value = undef(interp);
65     }
67     return value;
72 =item C<static PMC
73 *Parrot_Array_set_pmc_ptr(PARROT_INTERP, List *list, INTVAL key)>
75 Returns a pointer to the element at index C<key> of C<*list>. If
76 this element was previously empty, then this function also creates
77 and assigns an "undef" PMC to that element.
79 =cut
83 static PMC *Parrot_Array_set_pmc_ptr(PARROT_INTERP, List *list, INTVAL key) {
84     void * const ret = list_get(interp, list, key, enum_type_PMC);
85     PMC  *value;
87     if (ret == 0)
88         real_exception(interp, NULL, E_IndexError,
89             "Array index out of bounds!");
91     /* assign into a sparse or not yet set value */
92     if (ret == (void *)-1 || *(PMC **)ret == 0) {
93         value = undef(interp);
94         list_assign(interp, list, key, value, enum_type_PMC);
95     }
96     else
97         value = *(PMC **)ret;
99     return value;
103 pmclass Array need_ext provides array {
107 =back
109 =head2 Methods
111 =over 4
113 =item C<void class_init()>
115 Class initialization. Creates the required memory pools.
117 =cut
121     void class_init() {
122         /* class_init_code; called for side effects */
123         Small_Object_Pool *List_chunks =
124             make_bufferlike_pool(INTERP, sizeof (List_chunk));
125         Small_Object_Pool *Lists       =
126             make_bufferlike_pool(INTERP, sizeof (List));
128         /* XXX until there's a function to allocate a pool in an arena */
129         UNUSED(List_chunks);
130         UNUSED(Lists);
131     }
135 =item C<void init()>
137 Initializes the PMC by calling the underlying C<list_new()> function.
139 =cut
143     VTABLE void init() {
144         list_pmc_new(INTERP, SELF);
145         PObj_custom_mark_SET(SELF);
146     }
150 =item C<void init_pmc(PMC *init)>
152 Calls C<list_new_init()> to initialize the underlying list.
154 C<*init> contains the initialization information specifying initial
155 size, number of dimensions, etc.
157 =cut
161     VTABLE void init_pmc(PMC *init) {
162         list_pmc_new_init(INTERP, SELF, init);
163         PObj_custom_mark_SET(SELF);
164     }
168 =item C<void assign_pmc(PMC *other)>
170 Copy the contents of other to self.
172 =cut
176     VTABLE void assign_pmc(PMC *other) {
177         const INTVAL size = VTABLE_elements(INTERP, other);
178         INTVAL       i;
180         SELF.set_integer_native(size);
181         for (i = 0; i < size; i++) {
182             PMC * const elem = VTABLE_get_pmc_keyed_int(INTERP, other, i);
183             SELF.set_pmc_keyed_int(i, elem);
184         }
185     }
190 =item C<void set_pmc(PMC *other)>
192 Implemented as an alias to C<assign_pmc> since the behavior is the same.
194 =cut
198     VTABLE void set_pmc(PMC *other) {
199         SELF.assign_pmc(other);
200     }
204 =item C<void mark()>
206 Mark the array and its contents as live.
208 =cut
212     VTABLE void mark() {
213         list_mark(INTERP, (List *)PMC_data(SELF));
214     }
218 =item C<PMC *clone()>
220 Return a clone of the array.
222 =cut
226     VTABLE PMC *clone() {
227         List       *l    = list_clone(INTERP, (List *)PMC_data(SELF));
228         PMC * const dest = pmc_new_noinit(INTERP, SELF->vtable->base_type);
230         PObj_custom_mark_SET(dest);
232         PMC_data(dest) = l;
233         l->container   = dest;
235         return dest;
236     }
240 =item C<INTVAL get_integer()>
242 Returns the number of elements in the array.
244 =cut
248     VTABLE INTVAL get_integer() {
249         return SELF.elements();
250     }
254 =item C<INTVAL get_bool()>
256 Returns true if the array has one or more elements.
258 =cut
262     VTABLE INTVAL get_bool() {
263         const INTVAL size = SELF.elements();
264         return (INTVAL)(size != 0);
265     }
269 =item C<INTVAL elements()>
271 Returns the number of elements in the array.
273 =cut
277     VTABLE INTVAL elements() {
278         return ((List *) PMC_data(SELF))->length;
279     }
283 =item C<FLOATVAL get_number()>
285 Returns the number of elements in the array.
287 =cut
291     VTABLE FLOATVAL get_number() {
292         INTVAL e = SELF.elements();
293         return (FLOATVAL)e;
294     }
298 =item C<STRING *get_string()>
300 Returns a string representation of the array.
302 =cut
306     VTABLE STRING *get_string() {
307         return Parrot_sprintf_c(INTERP, "array[%p]", SELF);
308     }
312 =item C<INTVAL get_integer_keyed_int(INTVAL key)>
314 Returns the integer value of the element at index C<key>.
316 =cut
320     VTABLE INTVAL get_integer_keyed_int(INTVAL key) {
321         PMC * const value = SELF.get_pmc_keyed_int(key);
323         return VTABLE_get_integer(INTERP, value);
324     }
328 =item C<INTVAL type_keyed_int(INTVAL key)>
330 =cut
334     VTABLE INTVAL type_keyed_int(INTVAL key) {
335         PMC * const value = SELF.get_pmc_keyed_int(key);
337         return VTABLE_type(INTERP, value);
338     }
342 =item C<INTVAL get_integer_keyed(PMC *key)>
344 Returns the integer value of the element at index C<key>.
346 =cut
350     VTABLE INTVAL get_integer_keyed(PMC *key) {
351         INTVAL ix;
352         PMC   *nextkey, *box;
354         if (!key)
355             return 0;
357         ix      = key_integer(INTERP, key);
358         nextkey = key_next(INTERP, key);
360         if (!nextkey)
361             return SELF.get_integer_keyed_int(ix);
363         box = SELF.get_pmc_keyed_int(ix);
365         if (!box)
366             box = undef(INTERP);
368         return VTABLE_get_integer_keyed(INTERP, box, nextkey);
369     }
373 =item C<FLOATVAL get_number_keyed_int(INTVAL key)>
375 Returns the float value of the element at index C<key>.
377 =cut
381     VTABLE FLOATVAL get_number_keyed_int(INTVAL key) {
382         PMC * const value = SELF.get_pmc_keyed_int(key);
384         return VTABLE_get_number(INTERP, value);
386     }
390 =item C<FLOATVAL get_number_keyed(PMC *key)>
392 Returns the float value of the element at index C<key>.
394 =cut
398     VTABLE FLOATVAL get_number_keyed(PMC *key) {
399         INTVAL ix;
400         PMC *nextkey, *box;
402         if (!key)
403             return (FLOATVAL)0;
405         ix      = key_integer(INTERP, key);
406         nextkey = key_next(INTERP, key);
408         if (!nextkey)
409             return SELF.get_number_keyed_int(ix);
411         box = SELF.get_pmc_keyed_int(ix);
413         if (!box)
414             box = undef(INTERP);
416         return VTABLE_get_number_keyed(INTERP, box, nextkey);
417     }
421 =item C<STRING *get_string_keyed_int(INTVAL key)>
423 Returns the string value of the element at index C<key>.
425 =cut
429     VTABLE STRING *get_string_keyed_int(INTVAL key) {
430         PMC * const value = SELF.get_pmc_keyed_int(key);
432         return VTABLE_get_string(INTERP, value);
433     }
437 =item C<STRING *get_string_keyed(PMC *key)>
439 Returns the string value of the element at index C<key>.
441 =cut
445     VTABLE STRING *get_string_keyed(PMC *key) {
446         INTVAL ix;
447         PMC   *nextkey, *box;
449         if (!key)
450             return 0;
452         ix      = key_integer(INTERP, key);
453         nextkey = key_next(INTERP, key);
455         if (!nextkey)
456             return SELF.get_string_keyed_int(ix);
458         box = SELF.get_pmc_keyed_int(ix);
460         if (!box)
461             box = undef(INTERP);
463         return VTABLE_get_string_keyed(INTERP, box, nextkey);
464     }
468 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
470 Returns the PMC value of the element at index C<key>.
472 =cut
476     VTABLE PMC *get_pmc_keyed_int(INTVAL key) {
478         return retval(INTERP,
479             list_get(INTERP, (List *)PMC_data(SELF), key, enum_type_PMC));
480     }
484 =item C<PMC *get_pmc_keyed(PMC *key)>
486 Returns the PMC value of the element at index C<key>.
488 =cut
492     VTABLE PMC *get_pmc_keyed(PMC *key) {
493         INTVAL ix;
494         PMC   *nextkey, *box;
496         if (!key)
497             return 0;
499         ix      = key_integer(INTERP, key);
500         nextkey = key_next(INTERP, key);
502         if (!nextkey)
503             return SELF.get_pmc_keyed_int(ix);
505         box = SELF.get_pmc_keyed_int(ix);
507         if (!box)
508             box = undef(INTERP);
510         return VTABLE_get_pmc_keyed(INTERP, box, nextkey);
511     }
515 =item C<void set_integer_native(INTVAL size)>
517 Sets the length of the array to C<size>.
519 =cut
523     VTABLE void set_integer_native(INTVAL size) {
524         list_set_length(INTERP, (List *)PMC_data(SELF), size);
525     }
528 =item C<void set_integer_same(PMC *value)>
530 Sets the length of the array to the number of elements in C<*value>.
532 =cut
536     VTABLE void set_integer_same(PMC *value) {
537         const INTVAL size = VTABLE_elements(INTERP, value);
538         list_set_length(INTERP, (List *)PMC_data(SELF), size);
539     }
543 =item C<void set_integer_keyed_int(INTVAL key, INTVAL value)>
545 Sets the integer value of the PMC at element C<key> to C<value>.
547 =cut
551     VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) {
552         PMC * const ptr =
553             Parrot_Array_set_pmc_ptr(INTERP, (List *)PMC_data(SELF), key);
555         VTABLE_set_integer_native(INTERP, ptr, value);
556     }
560 =item C<void set_integer_keyed(PMC *key, INTVAL value)>
562 Sets the integer value of the PMC at element C<key> to C<value>.
564 =cut
568     VTABLE void set_integer_keyed(PMC *key, INTVAL value) {
569         INTVAL ix;
570         PMC   *nextkey, *box;
572         if (!key)
573             return;
575         ix      = key_integer(INTERP, key);
576         nextkey = key_next(INTERP, key);
578         if (!nextkey) {
579             SELF.set_integer_keyed_int(ix, value);
580             return;
581         }
583         box = SELF.get_pmc_keyed_int(ix);
585         /* autovivify an Array */
586         if (!box)
587             box = pmc_new(INTERP, SELF.type());
589         VTABLE_set_integer_keyed(INTERP, box, nextkey, value);
590     }
594 =item C<void set_number_keyed_int(INTVAL key, FLOATVAL value)>
596 Sets the numeric value of the PMC at element C<key> to C<value>.
598 =cut
602     VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL value) {
603         PMC * const ptr =
604             Parrot_Array_set_pmc_ptr(INTERP, (List *)PMC_data(SELF), key);
606         VTABLE_set_number_native(INTERP, ptr, value);
607     }
611 =item C<void set_number_keyed(PMC *key, FLOATVAL value)>
613 Sets the numeric value of the PMC at element C<key> to C<value>.
615 =cut
619     VTABLE void set_number_keyed(PMC *key, FLOATVAL value) {
620         INTVAL ix;
621         PMC   *nextkey, *box;
623         if (!key)
624             return;
626         ix      = key_integer(INTERP, key);
627         nextkey = key_next(INTERP, key);
629         if (!nextkey) {
630             SELF.set_number_keyed_int(ix, value);
631             return;
632         }
634         box = SELF.get_pmc_keyed_int(ix);
636         /* autovivify an Array */
637         if (!box)
638             box = pmc_new(INTERP, SELF.type());
640         VTABLE_set_number_keyed(INTERP, box, nextkey, value);
641     }
645 =item C<void set_string_keyed_int(INTVAL key, STRING *value)>
647 Sets the string value of the PMC at element C<key> to C<value>.
649 =cut
653     VTABLE void set_string_keyed_int(INTVAL key, STRING *value) {
654         PMC * const ptr =
655             Parrot_Array_set_pmc_ptr(INTERP, (List *)PMC_data(SELF), key);
657         VTABLE_set_string_native(INTERP, ptr, value);
658     }
662 =item C<void set_string_keyed(PMC *key, STRING *value)>
664 Sets the string value of the PMC at element C<key> to C<value>.
666 =cut
670     VTABLE void set_string_keyed(PMC *key, STRING *value) {
671         INTVAL ix;
672         PMC   *nextkey, *box;
674         if (!key)
675             return;
677         ix      = key_integer(INTERP, key);
678         nextkey = key_next(INTERP, key);
680         if (!nextkey) {
681             VTABLE_set_string_keyed_int(INTERP, SELF, ix, value);
682             return;
683         }
685         box = SELF.get_pmc_keyed_int(ix);
687         /* autovivify an Array */
688         if (!box)
689             box = pmc_new(INTERP, SELF.type());
691         VTABLE_set_string_keyed(INTERP, box, nextkey, value);
692     }
696 =item C<void set_pmc_keyed_int(INTVAL idx, PMC *src)>
698 Sets the PMC at element C<idx> to C<*src>.
700 =cut
704     VTABLE void set_pmc_keyed_int(INTVAL idx, PMC *src) {
705         const INTVAL length = ((List *)PMC_data(SELF))->length;
707         if (idx >= length || -idx > length)
708             real_exception(INTERP, NULL, E_IndexError,
709                 "Array index out of bounds!");
711         list_assign(INTERP, (List *)PMC_data(SELF), idx,
712             (void *)src, enum_type_PMC);
713     }
717 =item C<void set_pmc_keyed(PMC *key, PMC *value)>
719 Sets the PMC at index C<key> to C<value>.
721 =cut
725     VTABLE void set_pmc_keyed(PMC *key, PMC *value) {
726         PMC *box;
728         const INTVAL ix      = key_integer(INTERP, key);
729         PMC * const  nextkey = key_next(INTERP, key);
731         if (!nextkey) {
732             VTABLE_set_pmc_keyed_int(INTERP, SELF, ix, value);
733             return;
734         }
736         box = SELF.get_pmc_keyed_int(ix);
738         /* autovivify an Array */
739         if (!box)
740             box = pmc_new(INTERP, SELF.type());
742         VTABLE_set_pmc_keyed(INTERP, box, nextkey, value);
743     }
747 =item C<void push_integer(INTVAL value)>
749 Extends the array by adding an element of value C<value> to the end of
750 the array.
752 =cut
756     VTABLE void push_integer(INTVAL value) {
757         const INTVAL nextix = SELF.elements();
758         SELF.set_integer_keyed_int(nextix, value);
759     }
763 =item C<void push_float(FLOATVAL value)>
765 Extends the array by adding an element of value C<value> to the end of
766 the array.
768 =cut
772     VTABLE void push_float(FLOATVAL value) {
773         const INTVAL nextix = SELF.elements();
774         SELF.set_number_keyed_int(nextix, value);
775     }
779 =item C<void push_string(STRING *value)>
781 Extends the array by adding an element of value C<*value> to the end of
782 the array.
784 =cut
788     VTABLE void push_string(STRING *value) {
789         const INTVAL nextix = SELF.elements();
790         SELF.set_string_keyed_int(nextix, value);
791     }
795 =item C<void push_pmc(PMC *value)>
797 Extends the array by adding an element of value C<*value> to the end of
798 the array.
800 =cut
804     void push_pmc(PMC *value) {
805         const INTVAL nextix = SELF.elements();
806         SELF.set_pmc_keyed_int(nextix, value);
807     }
811 =item C<void unshift_integer(INTVAL value)>
813 Extends the array by adding an element of value C<value> to the start
814 of the array.
816 =cut
820     VTABLE void unshift_integer(INTVAL value) {
821         PMC * const val = undef(INTERP);
823         list_unshift(INTERP, (List *)PMC_data(SELF), val, enum_type_PMC);
824         VTABLE_set_integer_native(INTERP, val, value);
825     }
829 =item C<void unshift_float(FLOATVAL value)>
831 Extends the array by adding an element of value C<value> to the start
832 of the array.
834 =cut
838     VTABLE void unshift_float(FLOATVAL value) {
839         PMC * const val = undef(INTERP);
841         list_unshift(INTERP, (List *)PMC_data(SELF), val, enum_type_PMC);
842         VTABLE_set_number_native(INTERP, val, value);
843     }
847 =item C<void unshift_string(STRING *value)>
849 Extends the array by adding an element of value C<*value> to the start
850 of the array.
852 =cut
856     VTABLE void unshift_string(STRING *value) {
857         PMC * const val = undef(INTERP);
858         list_unshift(INTERP, (List *)PMC_data(SELF), val, enum_type_PMC);
859         VTABLE_set_string_native(INTERP, val, value);
860     }
864 =item C<void unshift_pmc(PMC *value)>
866 Extends the array by adding an element of value C<*value> to the start
867 of the array.
869 =cut
873     void unshift_pmc(PMC *value) {
874         list_unshift(INTERP, (List *)PMC_data(SELF), value, enum_type_PMC);
875     }
879 =item C<INTVAL pop_integer()>
881 Removes and returns an integer from the end of the array.
883 =cut
887     VTABLE INTVAL pop_integer() {
888         PMC * const ptr = SELF.pop_pmc();
889         return VTABLE_get_integer(INTERP, ptr);
890     }
894 =item C<FLOATVAL pop_float()>
896 Removes and returns a float value from the end of the array.
898 =cut
902     VTABLE FLOATVAL pop_float() {
903         PMC * const ptr = SELF.pop_pmc();
904         return VTABLE_get_number(INTERP, ptr);
905     }
909 =item C<STRING *pop_string()>
911 Removes and returns a string from the end of the array.
913 =cut
917     VTABLE STRING *pop_string() {
918         PMC * const ptr = SELF.pop_pmc();
919         return VTABLE_get_string(INTERP, ptr);
920     }
924 =item C<PMC *pop_pmc()>
926 Removes and returns a PMC from the end of the array.
928 =cut
932     VTABLE PMC *pop_pmc() {
933         return retval(INTERP,
934             list_pop(INTERP, (List *)PMC_data(SELF), enum_type_PMC));
935     }
939 =item C<INTVAL shift_integer()>
941 Removes and returns an integer from the start of the array.
943 =cut
947     VTABLE INTVAL shift_integer() {
948         PMC * const ptr = SELF.shift_pmc();
949         return VTABLE_get_integer(INTERP, ptr);
950     }
954 =item C<FLOATVAL shift_float()>
956 Removes and returns a float from the start of the array.
958 =cut
962     VTABLE FLOATVAL shift_float() {
963         PMC * const ptr = SELF.shift_pmc();
964         return VTABLE_get_number(INTERP, ptr);
965     }
969 =item C<STRING *shift_string()>
971 Removes and returns a string from the start of the array.
973 =cut
977     VTABLE STRING *shift_string() {
978         PMC * const ptr = SELF.shift_pmc();
979         return VTABLE_get_string(INTERP, ptr);
980     }
984 =item C<PMC *shift_pmc()>
986 Removes and returns a PMC from the start of the array.
988 =cut
992     VTABLE PMC *shift_pmc() {
993         return retval(INTERP,
994             list_shift(INTERP, (List *)PMC_data(SELF), enum_type_PMC));
995     }
999 =item C<void splice(PMC *value, INTVAL offset, INTVAL count)>
1001 Replaces C<count> elements starting at C<offset> with the elements in
1002 C<value>.
1004 If C<count> is 0 then the elements in C<value> will be inserted after
1005 C<offset>.
1007 =cut
1011     void splice(PMC *value, INTVAL offset, INTVAL count) {
1012         if (SELF->vtable->base_type != value->vtable->base_type)
1013             real_exception(INTERP, NULL, E_TypeError,
1014                 "Type mismatch in splice");
1016         list_splice(INTERP, (List *)PMC_data(SELF),
1017             (List *)PMC_data(value), offset, count);
1018     }
1022 =item C<INTVAL defined_keyed_int(INTVAL key)>
1024 Returns TRUE is the element at C<key> is defined; otherwise returns false.
1026 =cut
1030     VTABLE INTVAL defined_keyed_int(INTVAL key) {
1031         PMC  *value;
1032         void * const ret =
1033             list_get(INTERP, (List *)PMC_data(pmc), key, enum_type_PMC);
1035         if (ret == 0 || ret == (void *) -1)
1036             return 0;
1038         value = *(PMC **)ret;
1040         if (!value)
1041             return 0;
1043         return VTABLE_defined(INTERP, value);
1044     }
1048 =item C<INTVAL defined_keyed(PMC *key)>
1050 Returns TRUE is the element at C<key> is defined; otherwise returns false.
1052 =cut
1056     VTABLE INTVAL defined_keyed(PMC *key) {
1057         PMC *box;
1059         const INTVAL ix      = key_integer(INTERP, key);
1060         PMC * const  nextkey = key_next(INTERP, key);
1062         if (!nextkey)
1063             return SELF.defined_keyed_int(ix);
1065         box = SELF.get_pmc_keyed_int(ix);
1067         if (!box)
1068             return 0;
1070         return VTABLE_defined_keyed(INTERP, box, nextkey);
1071     }
1075 =item C<INTVAL exists_keyed_int(INTVAL key)>
1077 Returns TRUE is the element at C<key> exists; otherwise returns false.
1079 =cut
1083     VTABLE INTVAL exists_keyed_int(INTVAL key) {
1084         void * ret = list_get(INTERP,
1085             (List *)PMC_data(pmc), key, enum_type_PMC);
1087         if (ret == 0 || ret == (void *)-1)
1088             return 0;
1090         return !PMC_IS_NULL(*(PMC **)ret);
1091     }
1095 =item C<INTVAL exists_keyed(PMC *key)>
1097 Returns TRUE is the element at C<key> exists; otherwise returns false.
1099 =cut
1103     VTABLE INTVAL exists_keyed(PMC *key) {
1104         PMC *box;
1106         const INTVAL ix      = key_integer(INTERP, key);
1107         PMC * const  nextkey = key_next(INTERP, key);
1109         if (!nextkey)
1110             return SELF.exists_keyed_int(ix);
1112         box = SELF.get_pmc_keyed_int(ix);
1114         if (!box)
1115             return 0;
1117         return VTABLE_exists_keyed(INTERP, box, nextkey);
1118     }
1122 =item C<void delete_keyed_int(INTVAL key)>
1124 Removes the element at C<key>.
1126 =cut
1130     VTABLE void delete_keyed_int(INTVAL key) {
1131         list_splice(INTERP, (List *)PMC_data(pmc), NULL, key, 1);
1132     }
1136 =item C<void delete_keyed(PMC *key)>
1138 Removes the element at C<*key>.
1140 =cut
1144     VTABLE void delete_keyed(PMC *key) {
1145         const INTVAL ix = key_integer(INTERP, key);
1146         list_splice(INTERP, (List *)PMC_data(pmc), NULL, ix, 1);
1147     }
1151 =item C<INTVAL is_equal(PMC *value)>
1153 The C<==> operation. Compares two array to hold equal elements.
1155 =cut
1159     VTABLE INTVAL is_equal(PMC *value) {
1160         INTVAL j, n;
1162         if (value->vtable->base_type != enum_class_Array)
1163             return 0;
1165         n = SELF.elements();
1167         if (VTABLE_elements(INTERP, value) != n)
1168             return 0;
1170         for (j = 0; j < n; ++j) {
1171             PMC * const item1 = SELF.get_pmc_keyed_int(j);
1172             PMC * const item2 = VTABLE_get_pmc_keyed_int(INTERP, value, j);
1174             if (item1 != item2)
1175                 if (!mmd_dispatch_i_pp(INTERP, item1, item2, MMD_EQ))
1176                     return 0;
1177         }
1179         return 1;
1180     }
1184 =item C<PMC *slice(PMC *key, INTVAL f)>
1186 Return a new iterator for the slice PMC C<key> if f == 0.
1188 Return a new pythonic array slice if f == 1.
1190 =item C<PMC *get_iter()>
1192 Return a new iterator for SELF.
1194 =cut
1198     VTABLE PMC *slice(PMC *key, INTVAL f) {
1199         if (f == 0) {
1200             PMC * const iter = pmc_new_init(INTERP, enum_class_Iterator, SELF);
1201             PMC_struct_val(iter) = key;
1202             return iter;
1203         }
1205         real_exception(INTERP, NULL, E_TypeError, "Array: Unknown slice type");
1206     }
1208     VTABLE PMC *get_iter() {
1209         PMC * const iter     = pmc_new_init(INTERP, enum_class_Iterator, SELF);
1210         PMC * const key      = pmc_new(INTERP, enum_class_Key);
1211         PMC_struct_val(iter) = key;
1212         PObj_get_FLAGS(key) |= KEY_integer_FLAG;
1213         PMC_int_val(key)     = 0;
1215         if (!((List *)PMC_data(SELF))->length)
1216             PMC_int_val(key) = -1;
1218         return iter;
1219     }
1223 =item C<void visit(visit_info *info)>
1225 This is used by freeze/thaw to visit the contents of the array.
1227 C<*info> is the visit info, (see F<include/parrot/pmc_freeze.h>).
1229 =cut
1233     VTABLE void visit(visit_info *info) {
1234         list_visit(INTERP, (List *)PMC_data(SELF), info);
1235         SUPER(info);
1236     }
1240 =item C<void freeze(visit_info *info)>
1242 Used to archive the array.
1244 =cut
1248     VTABLE void freeze(visit_info *info) {
1249         IMAGE_IO * const io = info->image_io;
1250         SUPER(info);
1251         VTABLE_push_integer(INTERP, io, VTABLE_elements(INTERP, SELF));
1252     }
1256 =item C<void thaw(visit_info *info)>
1258 Used to unarchive the array.
1260 =cut
1264     VTABLE void thaw(visit_info *info) {
1265         IMAGE_IO * const io = info->image_io;
1267         SUPER(info);
1268         if (info->extra_flags == EXTRA_IS_NULL) {
1269             SELF.set_integer_native(VTABLE_shift_integer(INTERP, io));
1270     }
1275 =item C<PMC *share_ro()>
1277 Recursively make the array read-only and shared.
1279 =cut
1282     VTABLE PMC *share_ro() {
1283         PMC *_true, *ret;
1285         /* prevent infinite recursion */
1286         if (PObj_is_PMC_shared_TEST(SELF))
1287             real_exception(INTERP, NULL, INVALID_OPERATION, "share_ro on "
1288                            "something that already is shared");
1290         _true = pmc_new(INTERP, enum_class_Integer);
1291         VTABLE_set_integer_native(INTERP, _true, 1);
1293         ret   = pt_shared_fixup(INTERP, SELF);
1295         /* first set readonly */
1296         VTABLE_setprop(INTERP, ret, CONST_STRING(INTERP, "_ro"), _true);
1298         /* XXX do something that deals better with sparse lists */
1299         {
1300             INTVAL i;
1301             const INTVAL max = VTABLE_elements(INTERP, ret);
1303             for (i = 0; i < max; ++i) {
1304                 PMC * const value =
1305                     (PMC *)list_get(INTERP, PMC_data_typed(ret, List *),
1306                                  i, enum_type_PMC);
1308                 if (!PMC_IS_NULL(value)) {
1309                     /* XXX do we need to clone first? */
1310                     PMC * const new_value = VTABLE_share_ro(INTERP, value);
1312                     if (new_value != value)
1313                         list_assign(INTERP, PMC_data_typed(ret, List *),
1314                             i, new_value, enum_type_PMC);
1315                 }
1316             }
1317         }
1319         /* XXX FIXME workaround lack of metadata sharing */
1320         PMC_metadata(SELF) = NULL;
1322         return ret;
1323     }
1328 =back
1330 =head1 SEE ALSO
1332 F<src/list.c>, F<include/parrot/list.h>
1334 =head1 TODO
1336 Create global immutable undef object.
1338 =cut
1343  * Local variables:
1344  *   c-file-style: "parrot"
1345  * End:
1346  * vim: expandtab shiftwidth=4:
1347  */