diff --git a/src/core.c/Array.pm6 b/src/core.c/Array.pm6 index 9ea46664b87..ad92b1c1ccf 100644 --- a/src/core.c/Array.pm6 +++ b/src/core.c/Array.pm6 @@ -419,6 +419,14 @@ my class Array { # declared in BOOTSTRAP multi method flat(Array:U:) { self } multi method flat(Array:D:) { Seq.new(self.iterator) } + method reverse(Array:D: --> Seq:D) is nodal { + self.is-lazy # reifies + ?? Failure.new(X::Cannot::Lazy.new(:action)) + !! Seq.new: nqp::getattr(self,List,'$!reified') + ?? Rakudo::Iterator.ReifiedReverse(self, $!descriptor) + !! Rakudo::Iterator.Empty + } + multi method List(Array:D: :$view --> List:D) { nqp::if( self.is-lazy, # can't make a List diff --git a/src/core.c/List.pm6 b/src/core.c/List.pm6 index bc7a1ec112e..f4d266f3f4c 100644 --- a/src/core.c/List.pm6 +++ b/src/core.c/List.pm6 @@ -1132,7 +1132,7 @@ my class List does Iterable does Positional { # declared in BOOTSTRAP self.is-lazy # reifies ?? Failure.new(X::Cannot::Lazy.new(:action)) !! Seq.new: $!reified - ?? Rakudo::Iterator.ReifiedListReverse(self) + ?? Rakudo::Iterator.ReifiedReverse(self, Mu) !! Rakudo::Iterator.Empty } diff --git a/src/core.c/Rakudo/Iterator.pm6 b/src/core.c/Rakudo/Iterator.pm6 index e37f3f1e0e0..8dc5d1ff38d 100644 --- a/src/core.c/Rakudo/Iterator.pm6 +++ b/src/core.c/Rakudo/Iterator.pm6 @@ -2927,25 +2927,41 @@ class Rakudo::Iterator { ReifiedListIterator.new(list) } - # Return an iterator for a List that has been completely reified - # already, but that will produce values in reverse order. - my class ReifiedListReverseIterator does PredictiveIterator { + # Return an iterator for a List/Array that has been completely reified, + # or an IterationBuffer, that will produce values in reverse order. Takes + # a descriptor to create correct values for holes in the List/Array, use + # Mu to have holes returned as Nil. + my class ReifiedReverseIterator does PredictiveIterator { has $!reified; + has $!descriptor; has int $!i; - method !SET-SELF(\list) { + method !SET-SELF(\list, Mu \descriptor) { $!reified := nqp::istype(list,List) ?? nqp::getattr(list,List,'$!reified') !! list; + $!descriptor := nqp::eqaddr(descriptor,Mu) + ?? nqp::null() + !! descriptor; ($!i = nqp::elems($!reified)) ?? self !! Rakudo::Iterator.Empty } - method new(\list) { nqp::create(self)!SET-SELF(list) } + method new(\list, Mu \des) { nqp::create(self)!SET-SELF(list, des) } + + method !hole(int $i) is raw { + nqp::isnull($!descriptor) + ?? Nil + !! nqp::p6scalarfromdesc( + ContainerDescriptor::BindArrayPos.new( + $!descriptor, $!reified, $i + ) + ) + } method pull-one() is raw { nqp::isge_i(($!i = nqp::sub_i($!i,1)),0) - ?? nqp::ifnull(nqp::atpos($!reified,$!i),Nil) + ?? nqp::ifnull(nqp::atpos($!reified,$!i),self!hole($!i)) !! IterationEnd } method push-all(\target --> IterationEnd) { @@ -2953,7 +2969,7 @@ class Rakudo::Iterator { my int $i = $!i; nqp::while( # doesn't sink nqp::isge_i(($i = nqp::sub_i($i,1)),0), - target.push(nqp::ifnull(nqp::atpos($reified,$i),Nil)) + target.push(nqp::ifnull(nqp::atpos($reified,$i),self!hole($i))) ); $!i = $i; } @@ -2961,8 +2977,8 @@ class Rakudo::Iterator { method count-only(--> Int:D) { $!i + nqp::islt_i($!i,0) } method sink-all(--> IterationEnd) { $!i = -1 } } - method ReifiedListReverse(\list) { - ReifiedListReverseIterator.new(list) + method ReifiedReverse(\list, Mu \descriptor) { + ReifiedReverseIterator.new(list, descriptor) } # Return a lazy iterator that will repeat the values of a given diff --git a/src/core.c/Seq.pm6 b/src/core.c/Seq.pm6 index b001f98a802..6a7ee29d6fb 100644 --- a/src/core.c/Seq.pm6 +++ b/src/core.c/Seq.pm6 @@ -116,7 +116,7 @@ my class Seq is Cool does Iterable does Sequence { Failure.new(X::Cannot::Lazy.new(:action)), nqp::stmts( $iterator.push-all(my \buffer := nqp::create(IterationBuffer)), - Seq.new: Rakudo::Iterator.ReifiedListReverse(buffer) + Seq.new: Rakudo::Iterator.ReifiedReverse(buffer, Mu) ) ) }