# all sub postcircumfix [;] candidates here please proto sub postcircumfix:<[; ]>($, $, Mu $?, *%) is nodal {*} sub MD-ARRAY-SLICE-ONE-POSITION( \SELF, \indices, \idx, int $dim, \target ) is raw is implementation-detail { my int $next-dim = $dim + 1; if $next-dim < indices.elems { if nqp::istype(idx, Iterable) && !nqp::iscont(idx) { for idx { MD-ARRAY-SLICE-ONE-POSITION(SELF, indices, $_, $dim, target) } } elsif nqp::istype(idx, Int) { MD-ARRAY-SLICE-ONE-POSITION(SELF.AT-POS(idx), indices, indices.AT-POS($next-dim), $next-dim, target) } elsif nqp::istype(idx, Whatever) { for ^SELF.elems { MD-ARRAY-SLICE-ONE-POSITION(SELF.AT-POS($_), indices, indices.AT-POS($next-dim), $next-dim, target) } } elsif nqp::istype(idx, Callable) { MD-ARRAY-SLICE-ONE-POSITION(SELF, indices, idx.(|(SELF.elems xx (idx.count == Inf ?? 1 !! idx.count))), $dim, target); } else { MD-ARRAY-SLICE-ONE-POSITION(SELF.AT-POS(idx.Int), indices, indices.AT-POS($next-dim), $next-dim, target) } } else { if nqp::istype(idx, Iterable) && !nqp::iscont(idx) { for idx { MD-ARRAY-SLICE-ONE-POSITION(SELF, indices, $_, $dim, target) } } elsif nqp::istype(idx, Int) { nqp::push(target, SELF.AT-POS(idx)) } elsif nqp::istype(idx, Whatever) { for ^SELF.elems { nqp::push(target, SELF.AT-POS($_)) } } elsif nqp::istype(idx, Callable) { nqp::push(target, SELF.AT-POS(idx.(|(SELF.elems xx (idx.count == Inf ?? 1 !! idx.count))))) } else { nqp::push(target, SELF.AT-POS(idx.Int)) } } } sub MD-ARRAY-SLICE(\SELF, @indices) is raw is implementation-detail { my \target = nqp::create(IterationBuffer); MD-ARRAY-SLICE-ONE-POSITION(SELF, @indices, @indices.AT-POS(0), 0, target); target.List } multi sub postcircumfix:<[; ]>(\SELF, @indices) is raw { my \indices := nqp::getattr(@indices,List,'$!reified'); my int $elems = nqp::elems(indices); my int $i = -1; my \idxs := nqp::list_i; nqp::while( nqp::islt_i(++$i,$elems), nqp::if( nqp::istype((my $index = nqp::atpos(indices,$i)),Int), nqp::push_i(idxs,$index), # it's an Int, use that nqp::if( nqp::istype($index,Numeric), nqp::push_i(idxs,$index.Int), # can be safely coerced to Int nqp::if( nqp::istype($index,Str), nqp::if( nqp::istype((my \coerced := $index.Int),Failure), coerced.throw, # alas, not numeric, bye! nqp::push_i(idxs,coerced) # could be coerced to Int ), (return-rw MD-ARRAY-SLICE(SELF,@indices)) # alas, slow path needed ) ) ) ); nqp::if( # we have all Ints nqp::iseq_i($elems,2), SELF.AT-POS( # fast pathing [n;n] nqp::atpos_i(idxs,0), nqp::atpos_i(idxs,1) ), nqp::if( nqp::iseq_i($elems,3), SELF.AT-POS( # fast pathing [n;n;n] nqp::atpos_i(idxs,0), nqp::atpos_i(idxs,1), nqp::atpos_i(idxs,2) ), SELF.AT-POS(|@indices) # alas >3 dims, slow path ) ) } multi sub postcircumfix:<[; ]>(\SELF, @indices, Mu \assignee) is raw { my int $elems = @indices.elems; # reifies my \indices := nqp::getattr(@indices,List,'$!reified'); my int $i = -1; nqp::while( nqp::islt_i(++$i,$elems) && nqp::istype(nqp::atpos(indices,$i),Int), nqp::null ); nqp::if( nqp::islt_i($i,$elems), (MD-ARRAY-SLICE(SELF,@indices) = assignee), nqp::if( nqp::iseq_i($elems,2), SELF.ASSIGN-POS( nqp::atpos(indices,0), nqp::atpos(indices,1), assignee ), nqp::if( nqp::iseq_i($elems,3), SELF.ASSIGN-POS( nqp::atpos(indices,0), nqp::atpos(indices,1), nqp::atpos(indices,2), assignee ), SELF.ASSIGN-POS(|@indices,assignee) ) ) ) } multi sub postcircumfix:<[; ]>(\SELF, @indices, :$BIND!) is raw { my int $elems = @indices.elems; # reifies my \indices := nqp::getattr(@indices,List,'$!reified'); my int $i = -1; nqp::while( nqp::islt_i(++$i,$elems) && nqp::istype(nqp::atpos(indices,$i),Int), nqp::null ); nqp::if( nqp::islt_i($i,$elems), X::Bind::Slice.new(type => SELF.WHAT).throw, nqp::if( nqp::iseq_i($elems,2), SELF.BIND-POS( nqp::atpos(indices,0), nqp::atpos(indices,1), $BIND ), nqp::if( nqp::iseq_i($elems,3), SELF.BIND-POS( nqp::atpos(indices,0), nqp::atpos(indices,1), nqp::atpos(indices,2), $BIND ), SELF.BIND-POS(|@indices, $BIND) ) ) ) } multi sub postcircumfix:<[; ]>(\SELF, @indices, :$delete!) is raw { nqp::if( $delete, nqp::stmts( (my int $elems = @indices.elems), # reifies (my \indices := nqp::getattr(@indices,List,'$!reified')), (my int $i = -1), nqp::while( nqp::islt_i(++$i,$elems) && nqp::istype(nqp::atpos(indices,$i),Int), nqp::null ), nqp::if( nqp::islt_i($i,$elems), NYI(':delete on multi-dimensional slices'), nqp::if( nqp::iseq_i($elems,2), SELF.DELETE-POS( nqp::atpos(indices,0), nqp::atpos(indices,1) ), nqp::if( nqp::iseq_i($elems,3), SELF.DELETE-POS( nqp::atpos(indices,0), nqp::atpos(indices,1), nqp::atpos(indices,2) ), SELF.DELETE-POS(|@indices) ) ) ) ), postcircumfix:<[; ]>(SELF, @indices) ) } multi sub postcircumfix:<[; ]>(\SELF, @indices, :$exists!) is raw { nqp::if( $exists, nqp::stmts( (my int $elems = @indices.elems), # reifies (my \indices := nqp::getattr(@indices,List,'$!reified')), (my int $i = -1), nqp::while( nqp::islt_i(++$i,$elems) && nqp::istype(nqp::atpos(indices,$i),Int), nqp::null ), nqp::if( nqp::islt_i($i,$elems), NYI(':exists on multi-dimensional slices'), nqp::if( nqp::iseq_i($elems,2), SELF.EXISTS-POS( nqp::atpos(indices,0), nqp::atpos(indices,1) ), nqp::if( nqp::iseq_i($elems,3), SELF.EXISTS-POS( nqp::atpos(indices,0), nqp::atpos(indices,1), nqp::atpos(indices,2) ), SELF.EXISTS-POS(|@indices) ) ) ) ), postcircumfix:<[; ]>(SELF, @indices) ) } multi sub postcircumfix:<[; ]>(\SELF, @indices, :$kv!) is raw { nqp::if( $kv, nqp::stmts( (my int $elems = @indices.elems), # reifies (my \indices := nqp::getattr(@indices,List,'$!reified')), (my int $i = -1), nqp::while( nqp::islt_i(++$i,$elems) && nqp::istype(nqp::atpos(indices,$i),Int), nqp::null ), nqp::if( nqp::islt_i($i,$elems), NYI(':kv on multi-dimensional slices'), nqp::if( nqp::iseq_i($elems,2), nqp::if( SELF.EXISTS-POS( nqp::atpos(indices,0), nqp::atpos(indices,1) ), (@indices, SELF.AT-POS( nqp::atpos(indices,0), nqp::atpos(indices,1) )), () ), nqp::if( nqp::iseq_i($elems,3), nqp::if( SELF.EXISTS-POS( nqp::atpos(indices,0), nqp::atpos(indices,1), nqp::atpos(indices,2) ), (@indices, SELF.AT-POS( nqp::atpos(indices,0), nqp::atpos(indices,1), nqp::atpos(indices,2) )), () ), nqp::if( SELF.EXISTS-POS(|@indices), (@indices, SELF.AT-POS(|@indices)), () ) ) ) ) ), postcircumfix:<[; ]>(SELF, @indices) ) } multi sub postcircumfix:<[; ]>(\SELF, @indices, :$p!) is raw { nqp::if( $p, nqp::stmts( (my int $elems = @indices.elems), # reifies (my \indices := nqp::getattr(@indices,List,'$!reified')), (my int $i = -1), nqp::while( nqp::islt_i(++$i,$elems) && nqp::istype(nqp::atpos(indices,$i),Int), nqp::null ), nqp::if( nqp::islt_i($i,$elems), NYI(':p on multi-dimensional slices'), nqp::if( nqp::iseq_i($elems,2), nqp::if( SELF.EXISTS-POS( nqp::atpos(indices,0), nqp::atpos(indices,1) ), Pair.new(@indices, SELF.AT-POS( nqp::atpos(indices,0), nqp::atpos(indices,1) )), () ), nqp::if( nqp::iseq_i($elems,3), nqp::if( SELF.EXISTS-POS( nqp::atpos(indices,0), nqp::atpos(indices,1), nqp::atpos(indices,2) ), Pair.new(@indices, SELF.AT-POS( nqp::atpos(indices,0), nqp::atpos(indices,1), nqp::atpos(indices,2) )), () ), nqp::if( SELF.EXISTS-POS(|@indices), Pair.new(@indices, SELF.AT-POS(|@indices)), () ) ) ) ) ), postcircumfix:<[; ]>(SELF, @indices) ) } multi sub postcircumfix:<[; ]>(\SELF, @indices, :$k!) is raw { nqp::if( $k, nqp::stmts( (my int $elems = @indices.elems), # reifies (my \indices := nqp::getattr(@indices,List,'$!reified')), (my int $i = -1), nqp::while( nqp::islt_i(++$i,$elems) && nqp::istype(nqp::atpos(indices,$i),Int), nqp::null ), nqp::if( nqp::islt_i($i,$elems), NYI(':k on multi-dimensional slices'), nqp::if( nqp::iseq_i($elems,2), nqp::if( SELF.EXISTS-POS( nqp::atpos(indices,0), nqp::atpos(indices,1) ), @indices, () ), nqp::if( nqp::iseq_i($elems,3), nqp::if( SELF.EXISTS-POS( nqp::atpos(indices,0), nqp::atpos(indices,1), nqp::atpos(indices,2) ), @indices, () ), nqp::if( SELF.EXISTS-POS(|@indices), @indices, () ) ) ) ) ), postcircumfix:<[; ]>(SELF, @indices) ) } multi sub postcircumfix:<[; ]>(\SELF, @indices, :$v!) is raw { nqp::if( $v, nqp::stmts( (my int $elems = @indices.elems), # reifies (my \indices := nqp::getattr(@indices,List,'$!reified')), (my int $i = -1), nqp::while( nqp::islt_i(++$i,$elems) && nqp::istype(nqp::atpos(indices,$i),Int), nqp::null ), nqp::if( nqp::islt_i($i,$elems), NYI(':v on multi-dimensional slices'), nqp::if( nqp::iseq_i($elems,2), nqp::if( SELF.EXISTS-POS( nqp::atpos(indices,0), nqp::atpos(indices,1) ), nqp::decont(SELF.AT-POS( nqp::atpos(indices,0), nqp::atpos(indices,1) )), () ), nqp::if( nqp::iseq_i($elems,3), nqp::if( SELF.EXISTS-POS( nqp::atpos(indices,0), nqp::atpos(indices,1), nqp::atpos(indices,2) ), nqp::decont(SELF.AT-POS( nqp::atpos(indices,0), nqp::atpos(indices,1), nqp::atpos(indices,2) )), () ), nqp::if( SELF.EXISTS-POS(|@indices), nqp::decont(SELF.AT-POS(|@indices)), () ) ) ) ) ), postcircumfix:<[; ]>(SELF, @indices) ) } # vim: expandtab shiftwidth=4