1) Aggregates and Strings implement the nextkey_keyed vtable method/function respectively.
This gets one additional parameter: INTVAL what (e.g. 0=first, 1=next, 2=prev, 3=last) to reset the iterator and allow scan in both directions.
(Note Pxxx below should indicate the usage of the P-reg)
2) The iterator is a new PMC class which implements these vtables:
new PIter, .PIter, PAggregate // create a new iterator and attach the aggregate to it
set PIter, 0 // reset iterator, prepare from first
shift PVal, PIter // get first value from front
This doesn't actually change the aggregate, but should simulate to to so, i.e. PVal is the first value, *and* PIter has the semantics of the aggregate, as if the first value has been shifted off. This should reflect a (car, cdr) which could be handy for functional programming stuff.
shift PVal, PIter // get second value
set PIter, 3 // reset, prepare from last
pop PVal, PIter // pop last val
Now, the iterator itself should have the same sematics as the aggregate it points to:
assign PIter, PIntArray // attach a different array to iter? set PIter, 0 // reset shift I0, Piter // get PIntArrray[0] set I1, PIter[0] // == PIntArrary[1] set I2, PIter[1] // == PIntArrary[2]
This is probably not very meaningful for hashes, but arrays can do it simply.
So, the iterator also has all get_<x>_keyed_* methods implemented, which are passed on to the aggregate, but no set_<x>_keyed methods, iterators are readonly. This could also catch common errors, where the aggregate is changed during iteration. OTOH perl always gave you enough rope, to shoot yourself in the foot :)
3) The iterator PMC
It would need 2 pointers: a KEY * having the state of the current index and the data * pointer to the aggregate. This ought to be enough to implement this functionality.
4) Iterating over strings
Should work the same. The iterator holds the COWed substring and the offset in the KEY, the COWed substring should be reused on iterations.
Comments welcome leo