# No MMD yet. method exists (Hash|Pair|Array $self: $idx) { if $self.isa("Hash") { JS::inline('new PIL2JS.Box.Constant(function (args) { var hash = args[1].FETCH(), key = args[2], cc = args.pop(); cc(new PIL2JS.Box.Constant(hash.exists(key))); })')(%$self, $idx); } elsif $self.isa("Pair") { $self.key eq $idx; } elsif $self.isa("Array") { JS::inline('new PIL2JS.Box.Constant(function (args) { var array = args[1].FETCH(), idx = Number(args[2].toNative()), cc = args.pop(); cc(new PIL2JS.Box.Constant( array[idx >= 0 ? idx : array.length + idx] != undefined )); })')(@$self, $idx); } else { die ".exists does not work on objects of type {$self.ref}!"; } } method delete (Hash|Array $self: *@idx) { if $self.isa("Hash") { JS::inline('new PIL2JS.Box.Constant(function (args) { var hash = args[1].FETCH(), keys = args[2].FETCH(), cc = args.pop(); var ret = []; for(var i = 0; i < keys.length; i++) { var deleted = hash.delete_key(keys[i]); ret.push(deleted == undefined ? new PIL2JS.Box.Constant(undefined) : deleted); } cc(new PIL2JS.Box.Constant(ret)); })')(%$self, @idx); } elsif $self.isa("Array") { JS::inline('new PIL2JS.Box.Constant(function (args) { var array = args[1].FETCH(), idxs = args[2].toNative(), cc = args.pop(); var ret = []; for(var i = 0; i < idxs.length; i++) { var idx = Number(idxs[i]) >= 0 ? Number(idxs[i]) : array.length + Number(idxs[i]); ret.push(array[idx] == undefined ? new PIL2JS.Box.Constant(undefined) : array[idx]); delete array[idx]; if(idx == array.length - 1) array.length--; } cc(new PIL2JS.Box.Constant(ret)); })')(@$self, @idx); } else { die ".delete does not work on objects of type {$self.ref}!"; } } method keys (Hash|Pair|Array $self:) { if $self.isa("Hash") { JS::inline('new PIL2JS.Box.Constant(function (args) { var hash = args[1].FETCH(); var cc = args.pop(); var keys = hash.keys(); cc(new PIL2JS.Box.Constant(keys)); })')(%$self); } elsif $self.isa("Pair") { ($self.key,); } elsif $self.isa("Array") { JS::inline('new PIL2JS.Box.Constant(function (args) { var array = args[1].FETCH(); var cc = args.pop(); var ret = []; for(var i = 0; i < array.length; i++) { ret.push(new PIL2JS.Box.Constant(i)); } cc(new PIL2JS.Box.Constant(ret)); })')(@$self); } else { die ".keys does not work on objects of type {$self.ref}!"; } } method values (Hash|Pair|Array|Junction $self:) { if $self.isa("Junction") { JS::inline('new PIL2JS.Box.Constant(function (args) { var junc = args[1].FETCH(), cc = args.pop(); cc(new PIL2JS.Box.Constant(junc.values)); })')($self); } elsif $self.isa("Hash") { # $self.keys.map:{ $self{$_} } can't work, as map returns new containers. # (I think.) my @res; @res[+@res] := $self{$_} for $self.keys; @res; } elsif $self.isa("Pair") { ($self.value,); } elsif $self.isa("Array") { @$self; } else { die ".values does not work on objects of type {$self.ref}!"; } } method kv (Hash|Pair|Array $self:) { if $self.isa("Hash") { my @res; for $self.keys { push @res, $_, undef; @res[-1] := $self{$_}; } @res; } elsif $self.isa("Pair") { ($self.key, $self.value); } elsif $self.isa("Array") { my @res; for $self.keys { push @res, $_, undef; @res[-1] := $self[$_]; } @res; } else { die ".kv does not work on objects of type {$self.ref}!"; } } method pairs (Hash|Pair|Array $self:) { my sub make_pair ($key, $value is rw) is primitive is rw { my $pair = ($key => $value); $pair.value := $value; $pair; } if $self.isa("Hash") { $self.keys.map:{ make_pair($_, $self{$_}) }; } elsif $self.isa("Pair") { ($self,); } elsif $self.isa("Array") { $self.keys.map:{ make_pair($_, $self[$_]) }; } else { die ".pairs does not work on objects of type {$self.ref}!"; } } method pick (Hash|Pair|Array|Junction $self:) { if $self.isa("Junction") { my @vals = $self.values; @vals[int rand @vals]; } elsif $self.isa("Hash") { any($self.pairs).pick; } elsif $self.isa("Pair") { $self; } elsif $self.isa("Array") { any(@$self).pick; } }