2 Copyright (C) 2001-2008, The Perl Foundation.
7 src/pmc/iterator.pmc - Iterator PMC
11 These are the vtable functions for the Iterator base class. Iterators are
12 used in combination with other classes(mainly aggregates) to visit all entries
19 .local pmc iterator, array, entry
20 iterator = new 'Iterator', array
22 unless iterator, iter_end # while (more values)
23 entry = shift iterator # get an entry
28 The C<new> can alteratively be written as:
32 =head2 iterate from the end, for arrays
34 .local pmc iterator, array, entry
35 iterator = new 'Iterator', array
36 iterator = .ITERATE_FROM_END
38 unless iterator, iter_end # while (more values)
39 entry = pop iterator # get an entry
44 =head2 iterate over a hash
46 .local pmc iterator, hash, key, entry
47 iterator = new 'Iterator', hash
49 unless iterator, iter_end # while (more values)
50 key = shift iterator # get the key..
64 #include "parrot/parrot.h"
66 pmclass Iterator no_ro {
70 /* Make the shift_pmc vtable function available as
71 * a method named "next" */
72 register_nci_method(INTERP, enum_class_Iterator,
73 F2DPTR(Parrot_Iterator_shift_pmc), "next", "PJO");
81 Raises an exception. Use C<init_pmc()>.
88 real_exception(INTERP, NULL, E_Exception,
89 "Iterator init without aggregate");
94 =item C<void init_pmc(PMC *initializer)>
96 Initializes the iterator with an aggregate PMC.
97 Defaults iteration mode to iterate from start.
103 VTABLE void init_pmc(PMC *aggregate) {
104 PMC_pmc_val(SELF) = aggregate;
105 PMC_struct_val(SELF) = NULL;
106 PObj_custom_mark_SET(SELF);
108 /* by default, iterate from start */
109 SELF.set_integer_native(ITERATE_FROM_START);
116 Marks the current idx/key and the aggregate as live.
124 if (PMC_struct_val(SELF))
125 pobject_lives(INTERP, (PObj *)PMC_struct_val(SELF));
128 if (PMC_pmc_val(SELF))
129 pobject_lives(INTERP, (PObj *)PMC_pmc_val(SELF));
134 =item C<PMC *clone()>
136 Make a clone of the iterator.
142 VTABLE PMC *clone() {
143 PMC * const key = (PMC *)PMC_struct_val(SELF);
144 PMC * const res = pmc_new_init(INTERP, SELF->vtable->base_type,
146 PMC_struct_val(res) = VTABLE_clone(interp, key);
152 =item C<INTVAL get_integer()>
154 Get number of remaining elements. Does not work for hashes yet.
155 TODO: keep track of current position and direction
161 VTABLE INTVAL get_integer() {
162 return SELF.elements();
167 =item C<STRING *get_string()>
169 Returns a textual representation of the iterator.
175 VTABLE STRING *get_string() {
176 PMC * const key = (PMC *)PMC_struct_val(SELF);
177 return string_from_int(INTERP, key_integer(INTERP, key));
182 =item C<INTVAL get_integer_keyed(PMC *key)>
188 VTABLE INTVAL get_integer_keyed(PMC *key) {
189 return VTABLE_get_integer_keyed(INTERP, PMC_pmc_val(SELF), key);
194 =item C<INTVAL get_integer_keyed_int(INTVAL idx)>
196 Get integer value of current position plus idx.
202 VTABLE INTVAL get_integer_keyed_int(INTVAL idx) {
203 PMC * const key = (PMC *)PMC_struct_val(SELF);
204 PMC * const agg = PMC_pmc_val(SELF);
205 return VTABLE_get_integer_keyed_int(INTERP, agg, PMC_int_val(key) +idx);
210 =item C<FLOATVAL get_number_keyed(PMC *key)>
216 VTABLE FLOATVAL get_number_keyed(PMC *key) {
217 return VTABLE_get_number_keyed(INTERP, PMC_pmc_val(SELF), key);
222 =item C<FLOATVAL get_number_keyed_int(INTVAL idx)>
224 Get number value of current position plus idx.
230 VTABLE FLOATVAL get_number_keyed_int(INTVAL idx) {
231 PMC * const key = (PMC *)PMC_struct_val(SELF);
232 PMC * const agg = PMC_pmc_val(SELF);
233 return VTABLE_get_number_keyed_int(INTERP, agg, PMC_int_val(key) + idx);
240 =item C<STRING *get_string_keyed(PMC *key)>
246 VTABLE STRING *get_string_keyed(PMC *key) {
247 return VTABLE_get_string_keyed(INTERP, PMC_pmc_val(SELF), key);
252 =item C<STRING *get_string_keyed_int(INTVAL idx)>
254 Get string value of current position plus idx.
260 VTABLE STRING *get_string_keyed_int(INTVAL idx) {
261 PMC * const key = (PMC *)PMC_struct_val(SELF);
262 PMC * const agg = PMC_pmc_val(SELF);
263 return VTABLE_get_string_keyed_int(INTERP, agg, PMC_int_val(key) + idx);
268 =item C<INTVAL get_bool()>
270 Returns true if the idx/key is not C<-1>.
276 VTABLE INTVAL get_bool() {
277 PMC * const key = (PMC *)PMC_struct_val(SELF);
278 return key && PMC_int_val(key) != -1;
283 =item C<INTVAL elements()>
285 Returns the number of remaining elements in the aggregate. TODO.
291 VTABLE INTVAL elements() {
292 return VTABLE_elements(INTERP, PMC_pmc_val(SELF));
297 =item C<PMC *get_pmc_keyed(PMC *key)>
299 Returns the element for C<*key>.
305 VTABLE PMC *get_pmc_keyed(PMC *key) {
306 return VTABLE_get_pmc_keyed(INTERP, PMC_pmc_val(SELF), key);
311 =item C<PMC *get_pmc_keyed_int(INTVAL key)>
313 Returns the element for C<key>.
319 VTABLE PMC *get_pmc_keyed_int(INTVAL idx) {
320 PMC * const key = (PMC *)PMC_struct_val(SELF);
321 PMC * const agg = PMC_pmc_val(SELF);
322 return VTABLE_get_pmc_keyed_int(INTERP, agg, PMC_int_val(key) + idx);
327 =item C<void set_integer_native(INTVAL value)>
329 Reset the Iterator. C<value> must be one of
331 ITERATE_FROM_START ... Iterate from start
332 ITERATE_FROM_START_KEYS ... OrderedHash by keys
333 ITERATE_FROM_END ... Arrays and PerlString only
339 VTABLE void set_integer_native(INTVAL value) {
341 if (value < ITERATE_FROM_START || value > ITERATE_FROM_END)
342 real_exception(INTERP, NULL, E_TypeError,
343 "Illegal set_integer on iterator");
345 /* reset iterator on aggregate */
346 agg = PMC_pmc_val(SELF);
348 if (agg->vtable->base_type == enum_class_Slice) {
349 /* it's an xrange serving as its own aggregate */
350 PMC_struct_val(SELF) =
351 VTABLE_nextkey_keyed(INTERP, agg, NULL, value);
354 if (!PMC_struct_val(SELF))
355 key = key_new(INTERP);
357 key = (PMC *)PMC_struct_val(SELF);
359 PMC_struct_val(SELF) =
360 VTABLE_nextkey_keyed(INTERP, key, agg, value);
366 =item C<INTVAL pop_integer()>
372 VTABLE INTVAL pop_integer() {
373 PMC * const key = (PMC *)PMC_struct_val(SELF);
374 PMC * const agg = PMC_pmc_val(SELF);
375 const INTVAL ret = VTABLE_get_integer_keyed(INTERP, agg, key);
376 PMC_struct_val(SELF) =
377 VTABLE_nextkey_keyed(INTERP, key, agg, ITERATE_GET_PREV);
384 =item C<FLOATVAL pop_float()>
390 VTABLE FLOATVAL pop_float() {
391 PMC * const key = (PMC *)PMC_struct_val(SELF);
392 PMC * const agg = PMC_pmc_val(SELF);
393 const FLOATVAL ret = VTABLE_get_number_keyed(INTERP, agg, key);
394 PMC_struct_val(SELF) =
395 VTABLE_nextkey_keyed(INTERP, key, agg, ITERATE_GET_PREV);
402 =item C<STRING *pop_string()>
408 VTABLE STRING *pop_string() {
409 PMC * const key = (PMC *)PMC_struct_val(SELF);
410 PMC * const agg = PMC_pmc_val(SELF);
411 STRING * const ret = VTABLE_get_string_keyed(INTERP, agg, key);
412 PMC_struct_val(SELF) =
413 VTABLE_nextkey_keyed(INTERP, key, agg, ITERATE_GET_PREV);
419 =item C<PMC *pop_pmc()>
421 Returns the element for the current idx/key and sets the idx/key to
428 VTABLE PMC *pop_pmc() {
429 PMC * const key = (PMC *)PMC_struct_val(SELF);
430 PMC * const agg = PMC_pmc_val(SELF);
431 PMC * const ret = VTABLE_get_pmc_keyed(INTERP, agg, key);
432 PMC_struct_val(SELF) =
433 VTABLE_nextkey_keyed(INTERP, key, agg, ITERATE_GET_PREV);
440 =item C<INTVAL shift_integer()>
442 Returns the element for the current idx/key and sets the idx/key to
449 VTABLE INTVAL shift_integer() {
450 PMC * const key = (PMC *)PMC_struct_val(SELF);
451 PMC * const agg = PMC_pmc_val(SELF);
452 const INTVAL ret = VTABLE_get_integer_keyed(INTERP, agg, key);
453 PMC_struct_val(SELF) =
454 VTABLE_nextkey_keyed(INTERP, key, agg, ITERATE_GET_NEXT);
460 =item C<opcode_t *invoke(void *next)>
462 Return the next element of the aggregate. The return type may depend on
463 the aggregate. If there are no more items in the aggregate, I1 .. I4 are
466 See F<docs/pdds/pdd03_calling_conventions.pod>.
471 VTABLE opcode_t *invoke(void *next) {
474 /* iterator constructor */
475 if (REG_INT(interp, 3) == 1) {
476 PMC *arg = REG_PMC(interp, 5);
479 if (PObj_is_object_TEST(arg)) {
480 REG_PMC(interp, 5) = VTABLE_get_iter(INTERP, arg);
481 return (opcode_t *)next;
484 REG_PMC(interp, 5) = iter = pmc_new_init(INTERP,
485 enum_class_Iterator, arg);
486 VTABLE_set_integer_native(INTERP, iter, 0);
487 return (opcode_t *)next;
489 /* TODO function + sentinel */
490 else if (REG_INT(interp, 3) == 2)
491 real_exception(INTERP, NULL, E_AssertionError,
492 "Iterator: invoke 2 args");
497 REG_INT(interp, 4) = 0;
499 agg = PMC_pmc_val(SELF);
501 if (agg->vtable->base_type == enum_class_IntList) {
502 const INTVAL ires = SELF.shift_integer();
503 REG_INT(interp, 1) = 1;
504 REG_INT(interp, 5) = ires;
505 return (opcode_t *)next;
508 PMC * const res = SELF.shift_pmc();
509 REG_INT(interp, 3) = 1;
510 REG_PMC(interp, 5) = res;
511 return (opcode_t *)next;
517 =item C<FLOATVAL shift_float()>
523 VTABLE FLOATVAL shift_float() {
524 PMC * const key = (PMC *)PMC_struct_val(SELF);
525 PMC * const agg = PMC_pmc_val(SELF);
526 const FLOATVAL ret = VTABLE_get_number_keyed(INTERP, agg, key);
527 PMC_struct_val(SELF) =
528 VTABLE_nextkey_keyed(INTERP, key, agg, ITERATE_GET_NEXT);
535 =item C<STRING *shift_string()>
541 VTABLE STRING *shift_string() {
542 PMC * const key = (PMC *)PMC_struct_val(SELF);
543 PMC * const agg = PMC_pmc_val(SELF);
544 STRING * const ret = VTABLE_get_string_keyed(INTERP, agg, key);
545 PMC_struct_val(SELF) =
546 VTABLE_nextkey_keyed(INTERP, key, agg, ITERATE_GET_NEXT);
552 =item C<PMC *shift_pmc()>
554 Returns the element for the current idx/key and sets the idx/key to
561 VTABLE PMC *shift_pmc() {
562 PMC * const key = (PMC *)PMC_struct_val(SELF);
563 PMC * const agg = PMC_pmc_val(SELF);
566 if (PMC_int_val(key) == -1)
567 real_exception(INTERP, NULL, E_StopIteration, "StopIteration");
569 ret = VTABLE_get_pmc_keyed(INTERP, agg, key);
571 PMC_struct_val(SELF) =
572 VTABLE_nextkey_keyed(INTERP, key, agg, ITERATE_GET_NEXT);
579 =item C<INTVAL exists_keyed(PMC *key)>
581 Returns whether an element for C<*key> exists in the aggregate.
587 VTABLE INTVAL exists_keyed(PMC *key) {
588 return VTABLE_exists_keyed(INTERP, PMC_pmc_val(SELF), key);
593 =item C<INTVAL exists_keyed_int(INTVAL idx)>
595 Returns whether an element for C<idx> exists in the aggregate.
601 VTABLE INTVAL exists_keyed_int(INTVAL idx) {
602 PMC * const key = (PMC *)PMC_struct_val(SELF);
603 PMC * const agg = PMC_pmc_val(SELF);
604 return VTABLE_exists_keyed_int(INTERP, agg, PMC_int_val(key) + idx);
609 =item C<INTVAL defined()>
611 Returns whether the iterator contains an aggregate.
617 VTABLE INTVAL defined() {
618 return (INTVAL)(PMC_pmc_val(SELF) != 0);
623 =item C<INTVAL defined_keyed(PMC *key)>
629 VTABLE INTVAL defined_keyed(PMC *key) {
630 return VTABLE_defined_keyed(INTERP, PMC_pmc_val(SELF), key);
635 =item C<INTVAL defined_keyed_int(INTVAL key)>
637 Returns the result of calling C<defined_keyed(key)> on the aggregate.
643 VTABLE INTVAL defined_keyed_int(INTVAL idx) {
644 PMC * const key = (PMC *)PMC_struct_val(SELF);
645 PMC * const agg = PMC_pmc_val(SELF);
646 return VTABLE_defined_keyed_int(INTERP, agg, PMC_int_val(key) + idx);
651 =item C<INTVAL type_keyed(PMC *key)>
653 Returns the result of calling C<type_keyed(key)> on the aggregate.
659 VTABLE INTVAL type_keyed(PMC *key) {
660 return VTABLE_type_keyed(INTERP, PMC_pmc_val(SELF), key);
665 =item C<INTVAL type_keyed_int(PMC *idx)>
667 Returns the result of calling C<type_keyed(key)> on the aggregate.
673 VTABLE INTVAL type_keyed_int(INTVAL idx) {
674 PMC * const key = (PMC *)PMC_struct_val(SELF);
675 PMC * const agg = PMC_pmc_val(SELF);
676 return VTABLE_type_keyed_int(INTERP, agg, PMC_int_val(key) + idx);
679 VTABLE PMC *get_iter() {
694 * c-file-style: "parrot"
696 * vim: expandtab shiftwidth=4: