Skip to content

Commit

Permalink
Support assignment to native shaped arrays.
Browse files Browse the repository at this point in the history
  • Loading branch information
jnthn committed Nov 20, 2015
1 parent 5777a46 commit 67f8715
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 23 deletions.
23 changes: 0 additions & 23 deletions src/core/Array.pm
Expand Up @@ -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,
Expand Down Expand Up @@ -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".
Expand Down
24 changes: 24 additions & 0 deletions 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 {

Expand Down Expand Up @@ -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;
}
}
}
}
}

Expand Down
25 changes: 25 additions & 0 deletions src/core/native_array.pm
Expand Up @@ -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 {
Expand Down

0 comments on commit 67f8715

Please sign in to comment.