-
-
Save FROGGS/50d58158001696e89327 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/CREDITS b/CREDITS | |
index ef253f9..a04a224 100644 | |
--- a/CREDITS | |
+++ b/CREDITS | |
@@ -27,6 +27,11 @@ N: Alex Elsayed | |
U: eternaleye | |
E: eternaleye@gmail.com | |
+N: Alex Lyon | |
+U: Arcterus | |
+E: arcterus@mail.com | |
+D: Shaped arrays | |
+ | |
N: Allison Randal | |
D: Parrot Architect (0.4.6...) | |
E: allison@parrot.org | |
diff --git a/src/Perl6/Actions.nqp b/src/Perl6/Actions.nqp | |
index 53ad22d..095375f 100644 | |
--- a/src/Perl6/Actions.nqp | |
+++ b/src/Perl6/Actions.nqp | |
@@ -198,7 +198,29 @@ class Perl6::Actions is HLL::Actions does STDActions { | |
%info<default_value> := $*W.find_symbol(['Any']); | |
} | |
if $shape { | |
- $*W.throw($/, 'X::Comp::NYI', feature => 'Shaped arrays'); | |
+ my $shape_ast := $shape[0].ast; | |
+ if +@($shape_ast) == 1 { | |
+ my $sast_size := +@($shape_ast[0]); | |
+ if $sast_size > 1 { | |
+ my $map_ast := $shape_ast[0][$sast_size - 1]; | |
+ if nqp::istype($map_ast[1], QAST::Node) && | |
+ $map_ast[1].has_compile_time_value && | |
+ $map_ast[1].compile_time_value eq 'map' { | |
+ %info<container_index_map> := $shape_ast[0].pop[2]; | |
+ $shape_ast[0] := $shape_ast[0][0] if +@($shape_ast[0]) == 1; | |
+ } | |
+ } elsif $sast_size == 0 { | |
+ $*W.throw($/, 'X::Comp::AdHoc', | |
+ payload => 'empty shape definition'); | |
+ } | |
+ } else { | |
+ $*W.throw($/, 'X::Comp::NYI', | |
+ feature => 'multidimensional shaped arrays'); | |
+ } | |
+ %info<container_shape> := $shape_ast; | |
+ } else { | |
+ my $whatever := $*W.find_symbol(['Whatever']); | |
+ %info<container_shape> := nqp::create($whatever); | |
} | |
} | |
elsif $sigil eq '%' { | |
@@ -2204,11 +2226,27 @@ class Perl6::Actions is HLL::Actions does STDActions { | |
} | |
if $*SCOPE eq 'our' { | |
- $BLOCK[0].push(QAST::Op.new( | |
- :op('bind'), | |
- $past, | |
- $*W.symbol_lookup([$name], $/, :package_only(1), :lvalue(1)) | |
- )); | |
+ if $sigil == '@' && %cont_info<container_index_map> { | |
+ my @asts; | |
+ nqp::push(@asts, $BLOCK[0].pop); | |
+ if nqp::istype(%cont_info<container_shape>, QAST::Node) { | |
+ nqp::push(@asts, $BLOCK[0].pop); | |
+ } | |
+ $BLOCK[0].push(QAST::Op.new( | |
+ :op('bind'), | |
+ $past, | |
+ $*W.symbol_lookup([$name], $/, :package_only(1), :lvalue(1)) | |
+ )); | |
+ for @asts { | |
+ $BLOCK[0].push($_); | |
+ } | |
+ } else { | |
+ $BLOCK[0].push(QAST::Op.new( | |
+ :op('bind'), | |
+ $past, | |
+ $*W.symbol_lookup([$name], $/, :package_only(1), :lvalue(1)) | |
+ )); | |
+ } | |
} | |
} | |
diff --git a/src/Perl6/Grammar.nqp b/src/Perl6/Grammar.nqp | |
index 4e71bff..ce49840 100644 | |
--- a/src/Perl6/Grammar.nqp | |
+++ b/src/Perl6/Grammar.nqp | |
@@ -2199,9 +2199,9 @@ grammar Perl6::Grammar is HLL::Grammar does STD { | |
reserved => '() shape syntax in variable declarations'); | |
} | |
} | |
- | :dba('shape definition') '[' ~ ']' <semilist> <.NYI: "Shaped variable declarations"> | |
+ | :dba('shape definition') '[' ~ ']' <semilist> | |
| :dba('shape definition') '{' ~ '}' <semilist> | |
- | <?[<]> <postcircumfix> <.NYI: "Shaped variable declarations"> | |
+ | <?[<]> <postcircumfix> | |
]+ | |
]? | |
<.ws> | |
diff --git a/src/Perl6/Metamodel/BOOTSTRAP.nqp b/src/Perl6/Metamodel/BOOTSTRAP.nqp | |
index 6314bb4..e6954bc 100644 | |
--- a/src/Perl6/Metamodel/BOOTSTRAP.nqp | |
+++ b/src/Perl6/Metamodel/BOOTSTRAP.nqp | |
@@ -77,6 +77,7 @@ my stub Grammar metaclass Perl6::Metamodel::ClassHOW { ... }; | |
my stub Junction metaclass Perl6::Metamodel::ClassHOW { ... }; | |
my stub Metamodel metaclass Perl6::Metamodel::PackageHOW { ... }; | |
my stub ForeignCode metaclass Perl6::Metamodel::ClassHOW { ... }; | |
+my stub Whatever metaclass Perl6::Metamodel::ClassHOW { ... }; | |
# We stick all the declarative bits inside of a BEGIN, so they get | |
# serialized. | |
@@ -1573,8 +1574,12 @@ BEGIN { | |
# class Array is List { | |
# has Mu $!descriptor; | |
+ # has Mu $!shape; | |
+ # has Mu $!index_map; | |
Array.HOW.add_parent(Array, List); | |
Array.HOW.add_attribute(Array, BOOTSTRAPATTR.new(:name<$!descriptor>, :type(Mu), :package(Array))); | |
+ Array.HOW.add_attribute(Array, scalar_attr('$!shape', Mu, Array)); | |
+ Array.HOW.add_attribute(Array, scalar_attr('$!index_map', Mu, Array)); | |
Array.HOW.compose_repr(Array); | |
# class LoL is List { | |
@@ -1634,6 +1639,10 @@ BEGIN { | |
ForeignCode.HOW.set_invocation_attr(ForeignCode, ForeignCode, '$!do'); | |
ForeignCode.HOW.compose_invocation(ForeignCode); | |
+ # class Whatever { } | |
+ Whatever.HOW.add_parent(Whatever, Any); | |
+ Whatever.HOW.compose_repr(Whatever); | |
+ | |
# Set up Stash type, which is really just a hash. | |
# class Stash is Hash { | |
Stash.HOW.add_parent(Stash, Hash); | |
@@ -1671,6 +1680,7 @@ BEGIN { | |
Perl6::Metamodel::ClassHOW.add_stash(Hash); | |
Perl6::Metamodel::ClassHOW.add_stash(ObjAt); | |
Perl6::Metamodel::ClassHOW.add_stash(ForeignCode); | |
+ Perl6::Metamodel::ClassHOW.add_stash(Whatever); | |
# Default invocation behavior delegates off to postcircumfix:<( )>. | |
my $invoke_forwarder := | |
@@ -1764,6 +1774,7 @@ BEGIN { | |
EXPORT::DEFAULT.WHO<Bool> := Bool; | |
EXPORT::DEFAULT.WHO<False> := $false; | |
EXPORT::DEFAULT.WHO<True> := $true; | |
+ EXPORT::DEFAULT.WHO<Whatever> := Whatever; | |
EXPORT::DEFAULT.WHO<ContainerDescriptor> := Perl6::Metamodel::ContainerDescriptor; | |
EXPORT::DEFAULT.WHO<MethodDispatcher> := Perl6::Metamodel::MethodDispatcher; | |
EXPORT::DEFAULT.WHO<MultiDispatcher> := Perl6::Metamodel::MultiDispatcher; | |
@@ -1793,6 +1804,7 @@ Regex.HOW.publish_parrot_vtable_handler_mapping(Regex); | |
Regex.HOW.publish_parrot_vtable_mapping(Regex); | |
Stash.HOW.publish_parrot_vtable_handler_mapping(Stash); | |
Str.HOW.publish_parrot_vtable_handler_mapping(Str); | |
+Whatever.HOW.publish_parrot_vtable_mapping(Whatever); | |
#?endif | |
# Set up various type mappings. | |
diff --git a/src/Perl6/World.nqp b/src/Perl6/World.nqp | |
index b85a61c..45e0734 100644 | |
--- a/src/Perl6/World.nqp | |
+++ b/src/Perl6/World.nqp | |
@@ -223,7 +223,7 @@ class Perl6::World is HLL::World { | |
@!cleanup_tasks := []; | |
%!magical_cds := {}; | |
} | |
- | |
+ | |
# Creates a new lexical scope and puts it on top of the stack. | |
method push_lexpad($/) { | |
# Create pad, link to outer and add to stack. | |
@@ -626,6 +626,33 @@ class Perl6::World is HLL::World { | |
nqp::bindattr($cont, %cont_info<container_base>, '$!value', | |
%cont_info<scalar_value>); | |
} | |
+ if nqp::existskey(%cont_info, 'container_shape') { | |
+ if nqp::istype(%cont_info<container_shape>, QAST::Node) { | |
+ $block[0].push( | |
+ QAST::Op.new( | |
+ :op('bindattr'), | |
+ QAST::Var.new(:scope('lexical'), :name($name)), | |
+ QAST::WVal.new(:value(%cont_info<container_base>)), | |
+ QAST::SVal.new(:value('$!shape')), | |
+ %cont_info<container_shape> | |
+ ) | |
+ ); | |
+ } else { | |
+ nqp::bindattr($cont, %cont_info<container_base>, '$!shape', | |
+ %cont_info<container_shape>); | |
+ } | |
+ if nqp::existskey(%cont_info, 'container_index_map') { | |
+ $block[0].push( | |
+ QAST::Op.new( | |
+ :op('bindattr'), | |
+ QAST::Var.new(:scope('lexical'), :name($name)), | |
+ QAST::WVal.new(:value(%cont_info<container_base>)), | |
+ QAST::SVal.new(:value('$!index_map')), | |
+ %cont_info<container_index_map> | |
+ ) | |
+ ); | |
+ } | |
+ } | |
self.add_object($cont); | |
$block.symbol($name, :value($cont)); | |
self.install_package_symbol($package, $name, $cont) if $scope eq 'our'; | |
@@ -706,6 +733,32 @@ class Perl6::World is HLL::World { | |
QAST::SVal.new( :value('$!value') ), | |
QAST::WVal.new( :value(%cont_info<scalar_value>) ))); | |
} | |
+ | |
+ if nqp::existskey(%cont_info, 'container_shape') { | |
+ if !nqp::istype(%cont_info<container_shape>, QAST::Node) { | |
+ %cont_info<container_shape> := QAST::Op.new( | |
+ :op('callmethod'), | |
+ :name('new'), | |
+ QAST::WVal.new(:value(self.find_symbol(['Whatever']))) | |
+ ); | |
+ } | |
+ $cont_code.push(QAST::Op.new( | |
+ :op('bindattr'), | |
+ QAST::Var.new(:name($tmp), :scope('local')), | |
+ QAST::WVal.new(:value(%cont_info<container_base>)), | |
+ QAST::SVal.new(:value('$!shape')), | |
+ %cont_info<container_shape> | |
+ )); | |
+ if nqp::existskey(%cont_info, 'container_index_map') { | |
+ $cont_code.push(QAST::Op.new( | |
+ :op('bindattr'), | |
+ QAST::Var.new(:name($tmp), :scope('local')), | |
+ QAST::WVal.new(:value(%cont_info<container_base>)), | |
+ QAST::SVal.new(:value('$!index_map')), | |
+ %cont_info<container_index_map> | |
+ )); | |
+ } | |
+ } | |
$cont_code | |
} | |
@@ -1499,13 +1552,26 @@ class Perl6::World is HLL::World { | |
nqp::bindattr($cont, %cont_info<container_base>, '$!value', | |
%cont_info<scalar_value>); | |
} | |
- | |
+ if nqp::existskey(%cont_info, 'container_shape') { | |
+ if nqp::istype(%cont_info<container_shape>, QAST::Node) { | |
+ nqp::bindattr($cont, %cont_info<container_base>, '$!shape', | |
+ self.compile_time_evaluate($/, %cont_info<container_shape>)); | |
+ } else { | |
+ nqp::bindattr($cont, %cont_info<container_base>, '$!shape', | |
+ %cont_info<container_shape>); | |
+ } | |
+ if nqp::existskey(%cont_info, 'container_index_map') { | |
+ nqp::bindattr($cont, %cont_info<container_base>, '$!index_map', | |
+ self.compile_time_evaluate($/, %cont_info<container_index_map>)); | |
+ } | |
+ } | |
+ | |
# Create meta-attribute instance and add right away. Also add | |
# it to the SC. | |
my $attr := $meta_attr.new(:auto_viv_container($cont), |%lit_args, |%obj_args); | |
$obj.HOW.add_attribute($obj, $attr); | |
self.add_object($attr); | |
- | |
+ | |
# Return attribute that was built. | |
$attr | |
} | |
diff --git a/src/core/Array.pm b/src/core/Array.pm | |
index 4490fb0..713a580 100644 | |
--- a/src/core/Array.pm | |
+++ b/src/core/Array.pm | |
@@ -3,13 +3,18 @@ my class X::TypeCheck { ... }; | |
class Array { # declared in BOOTSTRAP | |
# class Array is List { | |
+ # has Mu $!shape; | |
+ # has Mu $!index_map; | |
# has Mu $!descriptor; | |
- method new(|) { | |
+ method new(:$shape = *, |) { | |
my Mu $args := nqp::p6argvmarray(); | |
nqp::shift($args); | |
- | |
- nqp::p6list($args, self.WHAT, Bool::True); | |
+ fail "Too many elements for this shaped array" | |
+ unless nqp::istype($shape, Whatever) or nqp::elems($args) < $shape; | |
+ my $array := nqp::p6list($args, self.WHAT, Bool::True); | |
+ nqp::bindattr($array, Array, '$!shape', $shape); | |
+ $array; | |
} | |
multi method at_pos(Array:D: $pos) is rw { | |
@@ -21,7 +26,9 @@ class Array { # declared in BOOTSTRAP | |
#?endif | |
X::Item.new(aggregate => self, index => $pos).throw; | |
} | |
- my int $p = nqp::unbox_i($pos.Int); | |
+ my int $p = self.map_index($pos.Int); | |
+ fail "Index $p is too large for this shaped array" | |
+ unless nqp::istype($!shape, Whatever) or $p < $!shape; | |
my Mu $items := nqp::p6listitems(self); | |
# hotpath check for element existence (RT #111848) | |
if nqp::existspos($items, $p) | |
@@ -38,7 +45,10 @@ class Array { # declared in BOOTSTRAP | |
); | |
} | |
} | |
- multi method at_pos(Array:D: int $pos) is rw { | |
+ multi method at_pos(Array:D: int $p) is rw { | |
+ my int $pos = self.map_index($p); | |
+ fail "Index $pos is too large for this shaped array" | |
+ unless nqp::istype($!shape, Whatever) or $pos < $!shape; | |
my Mu $items := nqp::p6listitems(self); | |
# hotpath check for element existence (RT #111848) | |
if nqp::existspos($items, $pos) | |
@@ -57,12 +67,17 @@ class Array { # declared in BOOTSTRAP | |
} | |
proto method bind_pos(|) { * } | |
- multi method bind_pos($pos is copy, Mu \bindval) is rw { | |
- $pos = $pos.Int; | |
+ multi method bind_pos($p is copy, Mu \bindval) is rw { | |
+ my int $pos = self.map_index($p.Int); | |
+ fail "Index $pos is too large for this shaped array" | |
+ unless nqp::istype($!shape, Whatever) or $pos < $!shape; | |
self.gimme($pos + 1); | |
- nqp::bindpos(nqp::getattr(self, List, '$!items'), nqp::unbox_i($pos), bindval); | |
+ nqp::bindpos(nqp::getattr(self, List, '$!items'), $pos, bindval); | |
} | |
- multi method bind_pos(int $pos, Mu \bindval) is rw { | |
+ multi method bind_pos(int $p, Mu \bindval) is rw { | |
+ my int $pos = self.map_index($p); | |
+ fail "Index $pos is too large for this shaped array" | |
+ unless nqp::istype($!shape, Whatever) or $pos < $!shape; | |
self.gimme($pos + 1); | |
nqp::bindpos(nqp::getattr(self, List, '$!items'), $pos, bindval) | |
} | |
@@ -72,6 +87,7 @@ class Array { # declared in BOOTSTRAP | |
self.delete_pos(pos); | |
} | |
method delete_pos(\pos) { | |
+ fail "Cannot delete from a shaped array" unless nqp::istype($!shape, Whatever); | |
fail "Cannot use negative index {pos} on {self.WHAT.perl}" if pos < 0; | |
my $value := self.at_pos(pos); # needed for reification | |
@@ -82,7 +98,7 @@ class Array { # declared in BOOTSTRAP | |
my $pos = pos; | |
nqp::pop($items); | |
nqp::pop($items) | |
- while --$pos >= 0 && nqp::isnull(nqp::atpos($items,$pos)); | |
+ while --$pos >= 0 && nqp::isnull(nqp::atpos($items, $pos)); | |
} | |
elsif pos < $end { | |
nqp::bindpos($items, pos, nqp::null()); | |
@@ -95,6 +111,48 @@ class Array { # declared in BOOTSTRAP | |
method flattens() { 1 } | |
+ method shape() { $!shape } | |
+ | |
+ # FIXME: this should probably be private | |
+ method map_index($pos --> int) { | |
+ return nqp::unbox_i(nqp::decont($!index_map)($pos).floor.Int) | |
+ if nqp::istype($!index_map, Code); | |
+ return nqp::unbox_i($!index_map) if nqp::istype($!index_map, Any); | |
+ nqp::unbox_i($pos) | |
+ } | |
+ | |
+ method pop() is parcel { | |
+ fail 'Cannot pop from a shaped array' unless nqp::istype($!shape, Whatever); | |
+ nqp::findmethod(List, 'pop')(self) | |
+ } | |
+ | |
+ multi method push(Array:D: *@values) { | |
+ fail 'Cannot push to a shaped array' unless nqp::istype($!shape, Whatever); | |
+ nqp::findmethod(List, 'push')(self, |@values) | |
+ } | |
+ | |
+ method shift() is parcel { | |
+ fail 'Cannot shift from a shaped array' unless nqp::istype($!shape, Whatever); | |
+ nqp::findmethod(List, 'shift')(self) | |
+ } | |
+ | |
+ multi method unshift(Array:D: *@values) { | |
+ fail 'Cannot unshift to a shaped array' unless nqp::istype($!shape, Whatever); | |
+ nqp::findmethod(List, 'unshift')(self, |@values); | |
+ } | |
+ | |
+ method exists(\pos) { | |
+ nqp::findmethod(List, 'exists')(self, self.map_index(pos)) | |
+ } | |
+ | |
+ method reverse() { | |
+ Array.new(:shape($!shape), nqp::findmethod(List, 'reverse')(self)) | |
+ } | |
+ | |
+ method rotate(Int $n = 1) { | |
+ Array.new(:shape($!shape), nqp::findmethod(List, 'rotate')(self, $n)) | |
+ } | |
+ | |
# introspection | |
method name() { | |
my $d := $!descriptor; | |
@@ -129,6 +187,13 @@ class Array { # declared in BOOTSTRAP | |
nqp::findmethod(List, 'REIFY')(self, parcel, nextiter) | |
} | |
+ method STORE_AT_POS(Int \p, Mu $v is copy) is rw { | |
+ my int $pos = self.map_index(p.Int); | |
+ fail "Index $pos is too large for this shaped array" | |
+ unless nqp::istype($!shape, Whatever) or $pos < $!shape; | |
+ nqp::bindpos(nqp::getattr(self, List, '$!items'), $pos, $v) | |
+ } | |
+ | |
method STORE(|) { | |
# get arguments, shift off invocant | |
my $args := nqp::p6argvmarray(); | |
@@ -136,22 +201,31 @@ class Array { # declared in BOOTSTRAP | |
# make an array from them (we can't just use ourself for this, | |
# or @a = @a will go terribly wrong); make it eager | |
my $list := nqp::p6list($args, Array, Mu); | |
+ $!shape = * if !nqp::istype($!shape, Mu); | |
+ nqp::bindattr($list, Array, '$!shape', $!shape); | |
nqp::bindattr($list, List, '$!flattens', True); | |
$list.eager; | |
# clear our items and set our next iterator to be one over | |
# the array we just created | |
nqp::bindattr(self, List, '$!items', Mu); | |
nqp::bindattr(self, List, '$!nextiter', nqp::p6listiter(nqp::list($list), self)); | |
+ self = self.splice(0, $!shape, self) | |
+ if not nqp::istype($!shape, Whatever) and (self.infinite or self.elems > $!shape); | |
self | |
} | |
my role TypedArray[::TValue] does Positional[TValue] { | |
- method new(|) { | |
+ method new(:$shape = *, |) { | |
my Mu $args := nqp::p6argvmarray(); | |
nqp::shift($args); | |
+ | |
+ fail "Too many elements for this shaped array" | |
+ unless nqp::istype($shape, Whatever) or nqp::elems($args) < $shape; | |
my $list := nqp::p6list($args, self.WHAT, Bool::True); | |
+ nqp::bindattr($list, Array, '$!shape', $shape); | |
+ | |
my $of = self.of; | |
if ( $of !=:= Mu ) { | |
for @$list { | |
@@ -167,11 +241,13 @@ class Array { # declared in BOOTSTRAP | |
$list; | |
} | |
- multi method at_pos($pos is copy) is rw { | |
- $pos = $pos.Int; | |
+ multi method at_pos($p is copy) is rw { | |
+ my int $pos = self.map_index($p.Int); | |
+ fail "Index $pos is too large for this shaped array" | |
+ unless nqp::istype(self.shape, Whatever) or $pos < self.shape; | |
if self.exists_pos($pos) { | |
nqp::atpos( | |
- nqp::getattr(self, List, '$!items'), nqp::unbox_i($pos) | |
+ nqp::getattr(self, List, '$!items'), $pos | |
); | |
} | |
else { | |
@@ -180,11 +256,14 @@ class Array { # declared in BOOTSTRAP | |
Scalar, | |
'$!whence', | |
-> { nqp::bindpos( | |
- nqp::getattr(self,List,'$!items'), nqp::unbox_i($pos), v) } | |
+ nqp::getattr(self,List,'$!items'), $pos, v) } | |
); | |
} | |
} | |
- multi method at_pos(int $pos, TValue $v? is copy) is rw { | |
+ multi method at_pos(int $p, TValue $v? is copy) is rw { | |
+ my int $pos = self.map_index($p); | |
+ fail "Index $pos is too large for this shaped array" | |
+ unless nqp::istype(self.shape, Whatever) or $pos < self.shape; | |
if self.exists_pos($pos) { | |
nqp::atpos(nqp::getattr(self, List, '$!items'), $pos); | |
} | |
@@ -197,12 +276,17 @@ class Array { # declared in BOOTSTRAP | |
); | |
} | |
} | |
- multi method bind_pos($pos is copy, TValue \bindval) is rw { | |
- $pos = $pos.Int; | |
+ multi method bind_pos($p is copy, TValue \bindval) is rw { | |
+ my int $pos = self.map_index($p.Int); | |
+ fail "Index $pos is too large for this shaped array" | |
+ unless nqp::istype(self.shape, Whatever) or $pos < self.shape; | |
self.gimme($pos + 1); | |
- nqp::bindpos(nqp::getattr(self, List, '$!items'), nqp::unbox_i($pos), bindval) | |
+ nqp::bindpos(nqp::getattr(self, List, '$!items'), $pos, bindval) | |
} | |
- multi method bind_pos(int $pos, TValue \bindval) is rw { | |
+ multi method bind_pos(int $p, TValue \bindval) is rw { | |
+ my int $pos = self.map_index($p); | |
+ fail "Index $pos is too large for this shaped array" | |
+ unless nqp::istype(self.shape, Whatever) or $pos < self.shape; | |
self.gimme($pos + 1); | |
nqp::bindpos(nqp::getattr(self, List, '$!items'), $pos, bindval) | |
} | |
diff --git a/src/vm/jvm/runtime/org/perl6/rakudo/RakOps.java b/src/vm/jvm/runtime/org/perl6/rakudo/RakOps.java | |
index 43dd996..26f9352 100644 | |
--- a/src/vm/jvm/runtime/org/perl6/rakudo/RakOps.java | |
+++ b/src/vm/jvm/runtime/org/perl6/rakudo/RakOps.java | |
@@ -47,6 +47,7 @@ public final class RakOps { | |
public SixModelObject ContainerDescriptor; | |
public SixModelObject False; | |
public SixModelObject True; | |
+ public SixModelObject Whatever; | |
public SixModelObject AutoThreader; | |
public SixModelObject EMPTYARR; | |
public SixModelObject EMPTYHASH; | |
@@ -79,6 +80,7 @@ public final class RakOps { | |
private static final int HINT_LISTITER_nextiter = 1; | |
private static final int HINT_LISTITER_rest = 2; | |
private static final int HINT_LISTITER_list = 3; | |
+ private static final int HINT_ARRAY_shape = 6; | |
public static SixModelObject p6init(ThreadContext tc) { | |
GlobalExt gcx = key.getGC(tc); | |
@@ -119,6 +121,7 @@ public final class RakOps { | |
gcx.ContainerDescriptor = conf.at_key_boxed(tc, "ContainerDescriptor"); | |
gcx.False = conf.at_key_boxed(tc, "False"); | |
gcx.True = conf.at_key_boxed(tc, "True"); | |
+ gcx.Whatever = conf.at_key_boxed(tc, "Whatever"); | |
gcx.JavaHOW = conf.at_key_boxed(tc, "Metamodel").st.WHO.at_key_boxed(tc, "JavaHOW"); | |
SixModelObject defCD = gcx.ContainerDescriptor.st.REPR.allocate(tc, | |
@@ -183,6 +186,9 @@ public final class RakOps { | |
list.bind_attribute_boxed(tc, gcx.List, "$!nextiter", HINT_LIST_nextiter, | |
p6listiter(arr, list, tc)); | |
list.bind_attribute_boxed(tc, gcx.List, "$!flattens", HINT_LIST_flattens, flattens); | |
+ if (type == gcx.Array) | |
+ list.bind_attribute_boxed(tc, gcx.Array, "$!shape", HINT_ARRAY_shape, | |
+ gcx.Whatever.st.REPR.allocate(tc, gcx.Whatever.st)); | |
return list; | |
} | |
diff --git a/src/vm/parrot/guts/bind.c b/src/vm/parrot/guts/bind.c | |
index 44bb2f8..347c3d9 100644 | |
--- a/src/vm/parrot/guts/bind.c | |
+++ b/src/vm/parrot/guts/bind.c | |
@@ -27,6 +27,7 @@ static STRING *REST_str = NULL; | |
static STRING *LIST_str = NULL; | |
static STRING *HASH_str = NULL; | |
static STRING *FLATTENS_str = NULL; | |
+static STRING *SHAPE_str = NULL; | |
static STRING *NEXTITER_str = NULL; | |
static STRING *HASH_SIGIL_str = NULL; | |
static STRING *ARRAY_SIGIL_str = NULL; | |
@@ -51,6 +52,7 @@ static void setup_binder_statics(PARROT_INTERP) { | |
LIST_str = Parrot_str_new_constant(interp, "$!list"); | |
HASH_str = Parrot_str_new_constant(interp, "$!hash"); | |
FLATTENS_str = Parrot_str_new_constant(interp, "$!flattens"); | |
+ SHAPE_str = Parrot_str_new_constant(interp, "$!shape"); | |
NEXTITER_str = Parrot_str_new_constant(interp, "$!nextiter"); | |
HASH_SIGIL_str = Parrot_str_new_constant(interp, "%"); | |
ARRAY_SIGIL_str = Parrot_str_new_constant(interp, "@"); | |
@@ -155,13 +157,18 @@ Rakudo_binding_list_from_rpa(PARROT_INTERP, PMC *rpa, PMC *type, PMC *flattens) | |
VTABLE_set_attr_keyed(interp, list, List, FLATTENS_str, flattens); | |
return list; | |
} | |
- | |
+ | |
/* Creates a Perl 6 Array. */ | |
static PMC * | |
Rakudo_binding_create_positional(PARROT_INTERP, PMC *rpa) { | |
- return Rakudo_binding_list_from_rpa(interp, rpa, Rakudo_types_array_get(), | |
- Rakudo_types_bool_true_get()); | |
+ PMC *Array = Rakudo_types_array_get(); | |
+ PMC *Whatever = Rakudo_types_whatever_get(); | |
+ PMC *list = Rakudo_binding_list_from_rpa(interp, rpa, Array, | |
+ Rakudo_types_bool_true_get()); | |
+ VTABLE_set_attr_keyed(interp, list, Array, SHAPE_str, | |
+ REPR(Whatever)->allocate(interp, STABLE(Whatever))); | |
+ return list; | |
} | |
diff --git a/src/vm/parrot/guts/types.c b/src/vm/parrot/guts/types.c | |
index 67c2f29..660dc5a 100644 | |
--- a/src/vm/parrot/guts/types.c | |
+++ b/src/vm/parrot/guts/types.c | |
@@ -27,6 +27,7 @@ static PMC * Capture = NULL; | |
static PMC * Code = NULL; | |
static PMC * BoolFalse = NULL; | |
static PMC * BoolTrue = NULL; | |
+static PMC * Whatever = NULL; | |
static PMC * JunctionThreader = NULL; | |
static INTVAL ownedhash_id = 0; | |
@@ -89,6 +90,9 @@ PMC * Rakudo_types_bool_false_get(void) { return BoolFalse; } | |
void Rakudo_types_bool_true_set(PMC * type) { BoolTrue = type; } | |
PMC * Rakudo_types_bool_true_get(void) { return BoolTrue; } | |
+void Rakudo_types_whatever_set(PMC * type) { Whatever = type; } | |
+PMC * Rakudo_types_whatever_get(void) { return Whatever; } | |
+ | |
void Rakudo_types_junction_threader_set(PMC * threader) { JunctionThreader = threader; } | |
PMC * Rakudo_types_junction_threader_get(void) { return JunctionThreader; } | |
diff --git a/src/vm/parrot/guts/types.h b/src/vm/parrot/guts/types.h | |
index e082e9f..166f0d3 100644 | |
--- a/src/vm/parrot/guts/types.h | |
+++ b/src/vm/parrot/guts/types.h | |
@@ -58,6 +58,9 @@ PMC * Rakudo_types_bool_false_get(void); | |
void Rakudo_types_bool_true_set(PMC * type); | |
PMC * Rakudo_types_bool_true_get(void); | |
+void Rakudo_types_whatever_set(PMC * type); | |
+PMC * Rakudo_types_whatever_get(void); | |
+ | |
void Rakudo_types_junction_threader_set(PMC * threader); | |
PMC * Rakudo_types_junction_threader_get(void); | |
diff --git a/src/vm/parrot/ops/perl6.ops b/src/vm/parrot/ops/perl6.ops | |
index 65a3214..8c40c5d 100644 | |
--- a/src/vm/parrot/ops/perl6.ops | |
+++ b/src/vm/parrot/ops/perl6.ops | |
@@ -656,6 +656,8 @@ inline op p6settypes(invar PMC) :base_core { | |
Parrot_str_new_constant(interp, "False"))); | |
Rakudo_types_bool_true_set(VTABLE_get_pmc_keyed_str(interp, $1, | |
Parrot_str_new_constant(interp, "True"))); | |
+ Rakudo_types_whatever_set(VTABLE_get_pmc_keyed_str(interp, $1, | |
+ Parrot_str_new_constant(interp, "Whatever"))); | |
Rakudo_types_junction_set(VTABLE_get_pmc_keyed_str(interp, $1, | |
Parrot_str_new_constant(interp, "Junction"))); | |
Rakudo_types_nil_set(VTABLE_get_pmc_keyed_str(interp, $1, |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment