diff --git a/src/core/Array.pm b/src/core/Array.pm index a02624aaf56..041a66bbb86 100644 --- a/src/core/Array.pm +++ b/src/core/Array.pm @@ -2,7 +2,6 @@ my class X::TypeCheck { ... }; my class X::Subscript::Negative { ... }; my class X::NotEnoughDimensions { ... }; my class X::Assignment::ArrayShapeMismatch { ... }; -my class X::Assignment::ToShaped { ... }; # An Array is a List that ensures every item added to it is in a Scalar # container. It also supports push, pop, shift, unshift, splice, BIND-POS, @@ -252,28 +251,6 @@ my class Array { # declared in BOOTSTRAP multi method STORE(::?CLASS:D: Mu \item) { self.STORE((item,)) } - method !STORE-PATH(@path, @rest, \in) { - my int $cur-pos = 0; - if @rest.elems == 1 { - for in -> \item { - self.ASSIGN-POS(|@path, $cur-pos, item); - $cur-pos = $cur-pos + 1; - } - } - else { - my @nextrest = @rest[1..*]; - for in -> \item { - my @nextpath = flat @path, $cur-pos; - if nqp::istype(item, Iterable) && nqp::isconcrete(item) { - self!STORE-PATH(@nextpath, @nextrest, item) - } - else { - X::Assignment::ToShaped.new(shape => self.shape).throw; - } - $cur-pos = $cur-pos + 1; - } - } - } # A shaped array isn't lazy, we these methods don't need to go looking # into the "todo". diff --git a/src/core/Rakudo/Internals.pm b/src/core/Rakudo/Internals.pm index dcd08812e37..4efa54896b9 100644 --- a/src/core/Rakudo/Internals.pm +++ b/src/core/Rakudo/Internals.pm @@ -1,5 +1,6 @@ my class Seq { ... } my class X::IllegalOnFixedDimensionArray { ... }; +my class X::Assignment::ToShaped { ... }; my class Rakudo::Internals { @@ -489,6 +490,29 @@ my class Rakudo::Internals { ']' x (@path.elems > 0) } } + + method !STORE-PATH(@path, @rest, \in) { + my int $cur-pos = 0; + if @rest.elems == 1 { + for in -> \item { + self.ASSIGN-POS(|@path, $cur-pos, item); + $cur-pos = $cur-pos + 1; + } + } + else { + my @nextrest = @rest[1..@rest.elems]; + for in -> \item { + my @nextpath = flat @path, $cur-pos; + if nqp::istype(item, Iterable) && nqp::isconcrete(item) { + self!STORE-PATH(@nextpath, @nextrest, item) + } + else { + X::Assignment::ToShaped.new(shape => self.shape).throw; + } + $cur-pos = $cur-pos + 1; + } + } + } } } diff --git a/src/core/native_array.pm b/src/core/native_array.pm index d801bb9ccfb..681a7ec7380 100644 --- a/src/core/native_array.pm +++ b/src/core/native_array.pm @@ -447,6 +447,31 @@ my class array does Iterable is repr('VMArray') { False } } + + proto method STORE(|) { * } + multi method STORE(::?CLASS:D: Iterable:D \in) { + my \in-shape = nqp::can(in, 'shape') ?? in.shape !! Nil; + if in-shape && !nqp::istype(in-shape.AT-POS(0), Whatever) { + if self.shape eqv in-shape { + # Can do a VM-supported memcpy-like thing in the future + for self.keys { + self.ASSIGN-POS(|$_, in.AT-POS(|$_)) + } + } + else { + X::Assignment::ArrayShapeMismatch.new( + source-shape => in-shape, + target-shape => self.shape + ).throw + } + } + else { + self!STORE-PATH((), self.shape, in) + } + } + multi method STORE(::?CLASS:D: Mu \item) { + self.STORE((item,)) + } } role shapedintarray[::T] does shapedarray {