2 Copyright (C) 2001-2009, Parrot Foundation.
7 src/pmc/array.pmc - Array PMC
11 These are the vtable functions for the Array base class.
23 =item C<static PMC *undef(PARROT_INTERP)>
25 Returns a C<Undef> PMC.
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.
46 static PMC *retval(PARROT_INTERP, void *ret) {
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);
62 value = undef(interp);
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.
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);
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);
101 pmclass Array need_ext provides array {
111 =item C<void class_init()>
113 Class initialization. Creates the required memory pools.
127 Initializes the PMC by calling the underlying C<list_new()> function.
134 list_pmc_new(INTERP, SELF);
135 PObj_custom_mark_SET(SELF);
140 =item C<void init_pmc(PMC *init)>
142 C<*init> contains the initialization information specifying initial size,
143 number of dimensions, etc.
149 VTABLE void init_pmc(PMC *init) {
150 list_pmc_new_init(INTERP, SELF, init);
151 PObj_custom_mark_SET(SELF);
156 =item C<void assign_pmc(PMC *other)>
158 Copy the contents of other to self.
164 VTABLE void assign_pmc(PMC *other) {
165 const INTVAL size = VTABLE_elements(INTERP, other);
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);
178 =item C<void set_pmc(PMC *other)>
180 Implemented as an alias to C<assign_pmc> since the behavior is the same.
186 VTABLE void set_pmc(PMC *other) {
187 SELF.assign_pmc(other);
194 Mark the array and its contents as live.
201 list_mark(INTERP, (List *)PMC_data(SELF));
206 =item C<PMC *clone()>
208 Return a clone of the array.
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);
228 =item C<INTVAL get_integer()>
230 Returns the number of elements in the array.
236 VTABLE INTVAL get_integer() {
237 return SELF.elements();
242 =item C<INTVAL get_bool()>
244 Returns true if the array has one or more elements.
250 VTABLE INTVAL get_bool() {
251 const INTVAL size = SELF.elements();
252 return (INTVAL)(size != 0);
257 =item C<INTVAL elements()>
259 Returns the number of elements in the array.
265 VTABLE INTVAL elements() {
266 return ((const List *) PMC_data(SELF))->length;
271 =item C<FLOATVAL get_number()>
273 Returns the number of elements in the array.
279 VTABLE FLOATVAL get_number() {
280 const INTVAL e = SELF.elements();
286 =item C<STRING *get_string()>
288 Returns a string representation of the array.
294 VTABLE STRING *get_string() {
295 return Parrot_sprintf_c(INTERP, "array[%p]", SELF);
300 =item C<INTVAL get_integer_keyed_int(INTVAL key)>
302 Returns the integer value of the element at index C<key>.
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);
316 =item C<INTVAL get_integer_keyed(PMC *key)>
318 Returns the integer value of the element at index C<key>.
324 VTABLE INTVAL get_integer_keyed(PMC *key) {
331 ix = VTABLE_get_integer(INTERP, key);
332 nextkey = key_next(INTERP, key);
335 return SELF.get_integer_keyed_int(ix);
337 box = SELF.get_pmc_keyed_int(ix);
342 return VTABLE_get_integer_keyed(INTERP, box, nextkey);
347 =item C<FLOATVAL get_number_keyed_int(INTVAL key)>
349 Returns the float value of the element at index C<key>.
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);
364 =item C<FLOATVAL get_number_keyed(PMC *key)>
366 Returns the float value of the element at index C<key>.
372 VTABLE FLOATVAL get_number_keyed(PMC *key) {
379 ix = VTABLE_get_integer(INTERP, key);
380 nextkey = key_next(INTERP, key);
383 return SELF.get_number_keyed_int(ix);
385 box = SELF.get_pmc_keyed_int(ix);
390 return VTABLE_get_number_keyed(INTERP, box, nextkey);
395 =item C<STRING *get_string_keyed_int(INTVAL key)>
397 Returns the string value of the element at index C<key>.
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);
411 =item C<STRING *get_string_keyed(PMC *key)>
413 Returns the string value of the element at index C<key>.
419 VTABLE STRING *get_string_keyed(PMC *key) {
426 ix = VTABLE_get_integer(INTERP, key);
427 nextkey = key_next(INTERP, key);
430 return SELF.get_string_keyed_int(ix);
432 box = SELF.get_pmc_keyed_int(ix);
437 return VTABLE_get_string_keyed(INTERP, box, nextkey);
442 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
444 Returns the PMC value of the element at index C<key>.
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));
458 =item C<PMC *get_pmc_keyed(PMC *key)>
460 Returns the PMC value of the element at index C<key>.
466 VTABLE PMC *get_pmc_keyed(PMC *key) {
473 ix = VTABLE_get_integer(INTERP, key);
474 nextkey = key_next(INTERP, key);
477 return SELF.get_pmc_keyed_int(ix);
479 box = SELF.get_pmc_keyed_int(ix);
484 return VTABLE_get_pmc_keyed(INTERP, box, nextkey);
489 =item C<void set_integer_native(INTVAL size)>
491 Sets the length of the array to C<size>.
497 VTABLE void set_integer_native(INTVAL size) {
498 list_set_length(INTERP, (List *)PMC_data(SELF), size);
502 =item C<void set_integer_same(PMC *value)>
504 Sets the length of the array to the number of elements in C<*value>.
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);
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>.
525 VTABLE void set_integer_keyed_int(INTVAL key, INTVAL value) {
527 Parrot_Array_set_pmc_ptr(INTERP, (List *)PMC_data(SELF), key);
529 VTABLE_set_integer_native(INTERP, ptr, value);
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>.
542 VTABLE void set_integer_keyed(PMC *key, INTVAL value) {
549 ix = VTABLE_get_integer(INTERP, key);
550 nextkey = key_next(INTERP, key);
553 SELF.set_integer_keyed_int(ix, value);
557 box = SELF.get_pmc_keyed_int(ix);
559 /* autovivify an Array */
561 box = pmc_new(INTERP, SELF.type());
563 VTABLE_set_integer_keyed(INTERP, box, nextkey, value);
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>.
576 VTABLE void set_number_keyed_int(INTVAL key, FLOATVAL value) {
578 Parrot_Array_set_pmc_ptr(INTERP, (List *)PMC_data(SELF), key);
580 VTABLE_set_number_native(INTERP, ptr, value);
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>.
593 VTABLE void set_number_keyed(PMC *key, FLOATVAL value) {
600 ix = VTABLE_get_integer(INTERP, key);
601 nextkey = key_next(INTERP, key);
604 SELF.set_number_keyed_int(ix, value);
608 box = SELF.get_pmc_keyed_int(ix);
610 /* autovivify an Array */
612 box = pmc_new(INTERP, SELF.type());
614 VTABLE_set_number_keyed(INTERP, box, nextkey, value);
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>.
627 VTABLE void set_string_keyed_int(INTVAL key, STRING *value) {
629 Parrot_Array_set_pmc_ptr(INTERP, (List *)PMC_data(SELF), key);
631 VTABLE_set_string_native(INTERP, ptr, value);
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>.
644 VTABLE void set_string_keyed(PMC *key, STRING *value) {
651 ix = VTABLE_get_integer(INTERP, key);
652 nextkey = key_next(INTERP, key);
655 VTABLE_set_string_keyed_int(INTERP, SELF, ix, value);
659 box = SELF.get_pmc_keyed_int(ix);
661 /* autovivify an Array */
663 box = pmc_new(INTERP, SELF.type());
665 VTABLE_set_string_keyed(INTERP, box, nextkey, value);
670 =item C<void set_pmc_keyed_int(INTVAL idx, PMC *src)>
672 Sets the PMC at element C<idx> to C<*src>.
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);
691 =item C<void set_pmc_keyed(PMC *key, PMC *value)>
693 Sets the PMC at index C<key> to C<value>.
699 VTABLE void set_pmc_keyed(PMC *key, PMC *value) {
702 const INTVAL ix = VTABLE_get_integer(INTERP, key);
703 PMC * const nextkey = key_next(INTERP, key);
706 VTABLE_set_pmc_keyed_int(INTERP, SELF, ix, value);
710 box = SELF.get_pmc_keyed_int(ix);
712 /* autovivify an Array */
714 box = pmc_new(INTERP, SELF.type());
716 VTABLE_set_pmc_keyed(INTERP, box, nextkey, value);
721 =item C<void push_integer(INTVAL value)>
723 Extends the array by adding an element of value C<value> to the end of
730 VTABLE void push_integer(INTVAL value) {
731 const INTVAL nextix = SELF.elements();
732 SELF.set_integer_keyed_int(nextix, value);
737 =item C<void push_float(FLOATVAL value)>
739 Extends the array by adding an element of value C<value> to the end of
746 VTABLE void push_float(FLOATVAL value) {
747 const INTVAL nextix = SELF.elements();
748 SELF.set_number_keyed_int(nextix, value);
753 =item C<void push_string(STRING *value)>
755 Extends the array by adding an element of value C<*value> to the end of
762 VTABLE void push_string(STRING *value) {
763 const INTVAL nextix = SELF.elements();
764 SELF.set_string_keyed_int(nextix, value);
769 =item C<void push_pmc(PMC *value)>
771 Extends the array by adding an element of value C<*value> to the end of
778 VTABLE void push_pmc(PMC *value) {
779 const INTVAL nextix = SELF.elements();
780 SELF.set_pmc_keyed_int(nextix, value);
785 =item C<void unshift_integer(INTVAL value)>
787 Extends the array by adding an element of value C<value> to the start
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);
803 =item C<void unshift_float(FLOATVAL value)>
805 Extends the array by adding an element of value C<value> to the start
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);
821 =item C<void unshift_string(STRING *value)>
823 Extends the array by adding an element of value C<*value> to the start
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);
838 =item C<void unshift_pmc(PMC *value)>
840 Extends the array by adding an element of value C<*value> to the start
847 VTABLE void unshift_pmc(PMC *value) {
848 list_unshift(INTERP, (List *)PMC_data(SELF), value, enum_type_PMC);
853 =item C<INTVAL pop_integer()>
855 Removes and returns an integer from the end of the array.
861 VTABLE INTVAL pop_integer() {
862 PMC * const ptr = SELF.pop_pmc();
863 return VTABLE_get_integer(INTERP, ptr);
868 =item C<FLOATVAL pop_float()>
870 Removes and returns a float value from the end of the array.
876 VTABLE FLOATVAL pop_float() {
877 PMC * const ptr = SELF.pop_pmc();
878 return VTABLE_get_number(INTERP, ptr);
883 =item C<STRING *pop_string()>
885 Removes and returns a string from the end of the array.
891 VTABLE STRING *pop_string() {
892 PMC * const ptr = SELF.pop_pmc();
893 return VTABLE_get_string(INTERP, ptr);
898 =item C<PMC *pop_pmc()>
900 Removes and returns a PMC from the end of the array.
906 VTABLE PMC *pop_pmc() {
907 return retval(INTERP,
908 list_pop(INTERP, (List *)PMC_data(SELF), enum_type_PMC));
913 =item C<INTVAL shift_integer()>
915 Removes and returns an integer from the start of the array.
921 VTABLE INTVAL shift_integer() {
922 PMC * const ptr = SELF.shift_pmc();
923 return VTABLE_get_integer(INTERP, ptr);
928 =item C<FLOATVAL shift_float()>
930 Removes and returns a float from the start of the array.
936 VTABLE FLOATVAL shift_float() {
937 PMC * const ptr = SELF.shift_pmc();
938 return VTABLE_get_number(INTERP, ptr);
943 =item C<STRING *shift_string()>
945 Removes and returns a string from the start of the array.
951 VTABLE STRING *shift_string() {
952 PMC * const ptr = SELF.shift_pmc();
953 return VTABLE_get_string(INTERP, ptr);
958 =item C<PMC *shift_pmc()>
960 Removes and returns a PMC from the start of the array.
966 VTABLE PMC *shift_pmc() {
967 return retval(INTERP,
968 list_shift(INTERP, (List *)PMC_data(SELF), enum_type_PMC));
973 =item C<void splice(PMC *value, INTVAL offset, INTVAL count)>
975 Replaces C<count> elements starting at C<offset> with the elements in
978 If C<count> is 0 then the elements in C<value> will be inserted after
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);
996 =item C<INTVAL defined_keyed_int(INTVAL key)>
998 Returns TRUE is the element at C<key> is defined; otherwise returns false.
1004 VTABLE INTVAL defined_keyed_int(INTVAL key) {
1007 list_get(INTERP, (List *)PMC_data(pmc), key, enum_type_PMC);
1009 if (ret == NULL || ret == (void *) -1)
1012 value = *(PMC **)ret;
1017 return VTABLE_defined(INTERP, value);
1022 =item C<INTVAL defined_keyed(PMC *key)>
1024 Returns TRUE is the element at C<key> is defined; otherwise returns false.
1030 VTABLE INTVAL defined_keyed(PMC *key) {
1033 const INTVAL ix = VTABLE_get_integer(INTERP, key);
1034 PMC * const nextkey = key_next(INTERP, key);
1037 return SELF.defined_keyed_int(ix);
1039 box = SELF.get_pmc_keyed_int(ix);
1044 return VTABLE_defined_keyed(INTERP, box, nextkey);
1049 =item C<INTVAL exists_keyed_int(INTVAL key)>
1051 Returns TRUE is the element at C<key> exists; otherwise returns false.
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)
1064 return !PMC_IS_NULL(*(PMC **)ret);
1069 =item C<INTVAL exists_keyed(PMC *key)>
1071 Returns TRUE is the element at C<key> exists; otherwise returns false.
1077 VTABLE INTVAL exists_keyed(PMC *key) {
1080 const INTVAL ix = VTABLE_get_integer(INTERP, key);
1081 PMC * const nextkey = key_next(INTERP, key);
1084 return SELF.exists_keyed_int(ix);
1086 box = SELF.get_pmc_keyed_int(ix);
1091 return VTABLE_exists_keyed(INTERP, box, nextkey);
1096 =item C<void delete_keyed_int(INTVAL key)>
1098 Removes the element at C<key>.
1104 VTABLE void delete_keyed_int(INTVAL key) {
1105 list_splice(INTERP, (List *)PMC_data(pmc), NULL, key, 1);
1110 =item C<void delete_keyed(PMC *key)>
1112 Removes the element at C<*key>.
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);
1125 =item C<INTVAL is_equal(PMC *value)>
1127 The C<==> operation. Compares two array to hold equal elements.
1133 VTABLE INTVAL is_equal(PMC *value) {
1136 if (value->vtable->base_type != enum_class_Array)
1139 n = SELF.elements();
1141 if (VTABLE_elements(INTERP, value) != n)
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);
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.
1174 VTABLE PMC *slice(PMC *key, INTVAL f) {
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);
1182 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION,
1183 "Array: Unknown slice type");
1186 VTABLE PMC *get_iter() {
1187 return pmc_new_init(INTERP, enum_class_ArrayIterator, SELF);
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>).
1202 VTABLE void visit(visit_info *info) {
1203 list_visit(INTERP, (List *)PMC_data(SELF), info);
1209 =item C<void freeze(visit_info *info)>
1211 Used to archive the array.
1217 VTABLE void freeze(visit_info *info) {
1218 IMAGE_IO * const io = info->image_io;
1220 VTABLE_push_integer(INTERP, io, VTABLE_elements(INTERP, SELF));
1225 =item C<void thaw(visit_info *info)>
1227 Used to unarchive the array.
1233 VTABLE void thaw(visit_info *info) {
1234 IMAGE_IO * const io = info->image_io;
1237 if (info->extra_flags == EXTRA_IS_NULL) {
1238 SELF.set_integer_native(VTABLE_shift_integer(INTERP, io));
1244 =item C<PMC *share_ro()>
1246 Recursively make the array read-only and shared.
1251 VTABLE PMC *share_ro() {
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 */
1270 const INTVAL max = VTABLE_elements(INTERP, ret);
1272 for (i = 0; i < max; ++i) {
1274 (PMC *)list_get(INTERP, PMC_data_typed(ret, List *),
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);
1288 /* XXX FIXME workaround lack of metadata sharing */
1289 PMC_metadata(SELF) = NULL;
1301 F<src/list.c>, F<include/parrot/list.h>
1305 Create global immutable undef object.
1313 * c-file-style: "parrot"
1315 * vim: expandtab shiftwidth=4: