my role Array::Shaped1 does Array::Shaped { multi method AT-POS(::?CLASS:D: uint $one) is raw { nqp::ifnull( nqp::atpos( nqp::getattr(self,List,'$!reified'), $one), AT-POS-CONTAINER(self, $one) ) } multi method AT-POS(::?CLASS:D: Int:D $one) is raw { nqp::ifnull( nqp::atpos( nqp::getattr(self,List,'$!reified'), $one), AT-POS-CONTAINER(self, $one) ) } sub AT-POS-CONTAINER(\array, uint $one) is raw { nqp::p6scalarfromdesc( ContainerDescriptor::BindArrayPos.new( nqp::getattr(array,Array,'$!descriptor'), nqp::getattr(array,List,'$!reified'), $one ) ) } multi method ASSIGN-POS(::?CLASS:D: uint $one, \value) { my \reified := nqp::getattr(self,List,'$!reified'); nqp::ifnull( nqp::atpos(reified,$one), nqp::bindpos( reified, $one, nqp::p6scalarfromdesc(nqp::getattr(self,Array,'$!descriptor'))) ) = value } multi method ASSIGN-POS(::?CLASS:D: Int:D $one, \value) { my \reified := nqp::getattr(self,List,'$!reified'); nqp::ifnull( nqp::atpos(reified,$one), nqp::bindpos( reified, $one, nqp::p6scalarfromdesc(nqp::getattr(self,Array,'$!descriptor'))) ) = value } multi method EXISTS-POS(::?CLASS:D: uint $one --> Bool:D) { my \reified := nqp::getattr(self,List,'$!reified'); nqp::hllbool( nqp::islt_i($one,nqp::elems(reified)) && nqp::not_i(nqp::isnull(nqp::atpos(reified,$one))) ) } multi method EXISTS-POS(::?CLASS:D: Int:D $one --> Bool:D) { my \reified := nqp::getattr(self,List,'$!reified'); nqp::hllbool( nqp::islt_i($one,nqp::elems(reified)) && nqp::not_i(nqp::isnull(nqp::atpos(reified,$one))) ) } multi method DELETE-POS(::?CLASS:D: uint $one) is raw { my \reified := nqp::getattr(self,List,'$!reified'); nqp::if( nqp::isnull(my \value := nqp::atpos(reified,$one)), Nil, nqp::stmts( nqp::bindpos(reified,$one,nqp::null), value ) ) } multi method DELETE-POS(::?CLASS:D: Int:D $one) is raw { my \reified := nqp::getattr(self,List,'$!reified'); nqp::if( nqp::isnull(my \value := nqp::atpos(reified,$one)), Nil, nqp::stmts( nqp::bindpos(reified,$one,nqp::null), value ) ) } multi method BIND-POS(::?CLASS:D: uint $one, \value) { nqp::bindpos(nqp::getattr(self,List,'$!reified'),$one,value) } multi method BIND-POS(::?CLASS:D: Int:D $one, \value) { nqp::bindpos(nqp::getattr(self,List,'$!reified'),$one,value) } method !RE-INITIALIZE(::?CLASS:D:) { my \list := nqp::getattr(self,List,'$!reified'); nqp::bind( # rebind newly created list list, nqp::bindattr( self,List,'$!reified', nqp::setelems(nqp::create(list),nqp::elems(list)) ) ) } proto method STORE(::?CLASS:D: |) {*} multi method STORE(::?CLASS:D: ::?CLASS:D \from-array) { my \to := nqp::getattr(self,List,'$!reified'); my \from := nqp::getattr(from-array,List,'$!reified'); nqp::if( nqp::iseq_i( (my uint $elems = nqp::elems(to)),nqp::elems(from)), nqp::stmts( (my \desc := nqp::getattr(self,Array,'$!descriptor')), (my int $i = -1), nqp::while( nqp::islt_i(++$i,$elems), # always create a new container in case the from list # contains containers already existing in the to list # e.g. after having done a .reverse or .rotate nqp::bindpos(to,$i,nqp::p6scalarfromdesc(desc)) = nqp::atpos(from,$i) ), self ), X::Assignment::ArrayShapeMismatch.new( source-shape => from-array.shape, target-shape => self.shape ).throw ) } multi method STORE(::?CLASS:D: Iterable:D \in, :$INITIALIZE) { my \list := $INITIALIZE ?? nqp::getattr(self,List,'$!reified') !! self!RE-INITIALIZE; my \desc := nqp::getattr(self,Array,'$!descriptor'); my \iter := in.iterator; my int $i = -1; my uint $elems = nqp::elems(list); nqp::until( nqp::eqaddr((my \pulled := iter.pull-one),IterationEnd) || nqp::iseq_i(++$i,$elems), nqp::ifnull( nqp::atpos(list,$i), nqp::bindpos(list,$i,nqp::p6scalarfromdesc(desc)) ) = pulled ); nqp::atpos(list,$i) # too many values on non-lazy iter, error unless nqp::islt_i($i,$elems) || iter.is-lazy; self } multi method STORE(::?CLASS:D: Mu \item, :$INITIALIZE) { my \list := $INITIALIZE ?? nqp::getattr(self,List,'$!reified') !! self!RE-INITIALIZE; nqp::bindpos(list,0, nqp::p6scalarfromdesc(nqp::getattr(self,Array,'$!descriptor')) ) = item; self } multi method keys(::?CLASS:D:) { Seq.new(Rakudo::Iterator.IntRange(0,self.shape.AT-POS(0) - 1)) } multi method kv(::?CLASS:D:) { Seq.new(Rakudo::Iterator.KeyValue(self.iterator)) } multi method pairs(::?CLASS:D:) { Seq.new(Rakudo::Iterator.Pairs(self.iterator)) } multi method antipairs(::?CLASS:D:) { Seq.new(Rakudo::Iterator.AntiPair(self.iterator)) } my class Iterate does PredictiveIterator { has Mu $!reified; has Mu $!desc; has int $!pos; method !SET-SELF(Mu \list) { $!reified := nqp::getattr(list,List,'$!reified'); $!desc := nqp::getattr(list,Array,'$!descriptor'); $!pos = -1; self } method new(Mu \list) { nqp::create(self)!SET-SELF(list) } method pull-one() is raw { nqp::if( nqp::islt_i(++$!pos,nqp::elems($!reified)), nqp::ifnull( nqp::atpos($!reified,$!pos), nqp::p6scalarfromdesc(ContainerDescriptor::BindArrayPos.new( $!desc, $!reified, $!pos)) ), IterationEnd ) } method skip-one() { nqp::islt_i(++$!pos,nqp::elems($!reified)) } method push-all(\target --> IterationEnd) { my uint $elems = nqp::elems($!reified); my int $i = $!pos; nqp::while( nqp::islt_i(++$i,$elems), target.push( nqp::ifnull( nqp::atpos($!reified,$i), nqp::p6scalarfromdesc(ContainerDescriptor::BindArrayPos.new( $!desc, $!reified, $i)) ) ) ); $!pos = $i; # mark as done } method count-only(--> Int:D) { nqp::p6box_i( nqp::elems($!reified) - $!pos - nqp::islt_i($!pos,nqp::elems($!reified) ) ) } method sink-all(--> IterationEnd) { $!pos = nqp::elems($!reified) } } method iterator(::?CLASS:D: --> Iterator:D) { Iterate.new(self) } method reverse(::?CLASS:D: --> Seq:D) is nodal { Seq.new: nqp::elems(nqp::getattr(self,List,'$!reified')) ?? Rakudo::Iterator.ReifiedReverse( self, nqp::getattr(self,Array,'$!descriptor')) !! Rakudo::Iterator.Empty } method rotate(::?CLASS:D: Int(Cool) $rotate = 1 --> Seq:D) is nodal { Seq.new: Rakudo::Iterator.ReifiedRotate( $rotate, self, nqp::getattr(self,Array,'$!descriptor') ) } multi method sum(::?CLASS:D:) { self.List::sum } } # vim: expandtab shiftwidth=4