# New Ticket Created by Cory Spencer
# Please include the string: [perl #61582]
# in the subject line of all future correspondence about this issue.
# <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=61582 >
This patch adds a .iterator method to Mapping.pir, allowing hashes to be
iterated over as in:
my %hash = (a => 1, b => 2); %hash.map: { .say }
The other methods in Mapping.pir were also rewritten in terms of .iterator
Index: src/classes/Mapping.pir
===================================================================
--- src/classes/Mapping.pir (revision 34219)
+++ src/classes/Mapping.pir (working copy)
@@ -39,20 +39,45 @@
.end
-.sub '' :vtable('get_string') :method
- .local string result
- result = ''
- $P0 = self.'pairs'()
+=item fmt
+
+ our Str multi Mapping::fmt ( Str $format, $separator = "\n" )
+
+Returns the invocant mapping formatted by an implicit call to C<.fmt> on
+every pair, joined by newlines or an explicitly given separator.
+
+=cut
+
+.sub 'fmt' :method :multi('Hash')
+ .param pmc format
+ .param string sep :optional
+ .param int has_sep :opt_flag
+
.local pmc it
- it = iter $P0
- it_loop:
- unless it goto it_done
- $S0 = shift it
- result .= $S0
- result .= "\n"
- goto it_loop
- it_done:
- .return (result)
+ .local pmc rv
+
+ if has_sep goto have_sep
+ sep = "\n"
+
+ have_sep:
+ it = self.'iterator'()
+ rv = new 'List'
+
+ loop:
+ .local pmc pairfmt
+ .local pmc pair
+
+ unless it goto end
+
+ pair = shift it
+ pairfmt = pair.'fmt'(format)
+
+ push rv, pairfmt
+ goto loop
+
+ end:
+ rv = 'join'(sep, rv)
+ .return(rv)
.end
@@ -63,206 +88,287 @@
=cut
.sub 'hash' :method
- .local pmc result, it
- result = new 'Perl6Hash'
- it = iter self
- iter_loop:
- unless it goto iter_end
- $S0 = shift it
- $P0 = self[$S0]
- result[$S0] = $P0
- goto iter_loop
- iter_end:
- .return (result)
-.end
+ .local pmc rv
+ .local pmc it
+ rv = new 'Perl6Hash'
+ it = self.'iterator'()
-=item list()
+ loop:
+ .local string key
+ .local pmc val
-Return invocant as a List of Pairs.
+ unless it goto end
+ key = shift it
+ val = self[$S0]
-=cut
+ rv[key] = val
+ goto loop
-.sub 'list' :method
- .tailcall self.'pairs'()
+ end:
+ .return (rv)
.end
-=item perl()
+=item iterator()
-Return perl representation of the invocant.
-
=cut
-.sub 'perl' :method
- .local string result
- .local pmc keys
- result = '{'
- keys = self.'keys'()
- unless keys goto iter_end
- iter_loop:
- .local pmc key, value
- key = shift keys
- value = self[key]
- $S0 = key.'perl'()
- result .= $S0
- result .= ' => '
- $S0 = value.'perl'()
- result .= $S0
- unless keys goto iter_end
- result .= ', '
- goto iter_loop
- iter_end:
- result .= '}'
- .return (result)
+.sub 'iterator' :method :multi('Hash')
+ .local pmc it
+ .local pmc rv
+
+ it = iter self
+ rv = new 'List'
+
+ loop:
+ .local string key
+ .local pmc pair
+ .local pmc val
+
+ unless it goto end
+ key = shift it
+ val = it[key]
+
+ pair = 'infix:=>'(key, val)
+ push rv, pair
+ goto loop
+
+ end:
+ .return (rv)
.end
-=item kv (method)
+=item keys()
-Returns elements of hash as array of C<Pair(key, value)>
+Returns keys of hash as a List
=cut
-.sub 'kv' :method :multi('Hash')
+.sub 'keys' :method :multi('Hash')
.local pmc it
.local pmc rv
- it = iter self
- rv = new 'List'
+
+ it = self.'iterator'()
+ rv = new 'List'
loop:
+ .local string key
+ .local pmc pair
+
unless it goto end
- $S1 = shift it
- push rv, $S1
- $P1 = it[$S1]
- push rv, $P1
+ pair = shift it
+ key = pair.'key'()
+
+ push rv, key
goto loop
+
end:
.return (rv)
.end
-=item pairs (method)
-Returns elements of hash as array of C<Pairs>
+=item kv (method)
+Returns elements of hash as array of C<Pair(key, value)>
+
=cut
-.sub 'pairs' :method :multi('Hash')
+.sub 'kv' :method :multi('Hash')
.local pmc it
.local pmc rv
- it = iter self
- $P0 = get_hll_global 'list'
- rv = $P0()
- $P3 = get_hll_global 'Perl6Pair'
+
+ it = self.'iterator'()
+ rv = new 'List'
+
loop:
+ .local string key
+ .local pmc pair
+ .local pmc val
+
unless it goto end
- $P1 = shift it
- $P2 = it[$P1]
- $P4 = $P3.'new'('key' => $P1, 'value' => $P2)
- push rv, $P4
+ pair = shift it
+ key = pair.'key'()
+ val = pair.'value'()
+
+ push rv, key
+ push rv, val
goto loop
+
end:
.return (rv)
.end
-=item fmt
+=item list()
- our Str multi Mapping::fmt ( Str $format, $separator = "\n" )
+Return invocant as a List of Pairs.
-Returns the invocant mapping formatted by an implicit call to C<.fmt> on
-every pair, joined by newlines or an explicitly given separator.
-
=cut
-.sub 'fmt' :method :multi('Hash')
- .param pmc format
- .param string sep :optional
- .param int has_sep :opt_flag
+.sub 'list' :method
+ .tailcall self.'iterator'()
+.end
- .local pmc pairs
- .local pmc res
- .local pmc iter
- .local pmc retv
- .local pmc elem
- .local pmc key
- .local pmc value
- .local pmc elemres
- if has_sep goto have_sep
- sep = "\n"
- have_sep:
- pairs = self.'pairs'()
- res = new 'List'
- iter = pairs.'iterator'()
- elem_loop:
- unless iter goto done
+=item pairs (method)
- invoke:
- elem = shift iter
- elemres = elem.'fmt'(format)
- push res, elemres
- goto elem_loop
+Returns elements of hash as array of C<Pairs>
- done:
- retv = 'join'(sep, res)
- .return(retv)
+=cut
+
+.sub 'pairs' :method :multi('Hash')
+ .tailcall self.'iterator'()
.end
-.sub 'keys' :method :multi('Hash')
+=item perl()
+
+Return perl representation of the invocant.
+
+=cut
+
+.sub 'perl' :method
+ .local string rv
.local pmc it
- .local pmc rv
- it = iter self
- rv = new 'List'
- loop:
+
+ rv = '{'
+ it = self.'iterator'()
+
+ loop:
+ .local string str
+ .local pmc pair
+ .local pmc key
+ .local pmc val
+
unless it goto end
- $S1 = shift it
- push rv, $S1
+
+ pair = shift it
+
+ key = pair.'key'()
+ val = pair.'value'()
+
+ str = key.'perl'()
+ rv .= str
+
+ rv .= ' => '
+
+ str = val.'perl'()
+ rv .= str
+
+ unless it goto end
+
+ rv .= ', '
goto loop
+
end:
+ rv .= '}'
.return (rv)
.end
+
=item reverse
=cut
.sub 'reverse' :method :multi('Hash')
- .local pmc result, it
- result = new 'Perl6Hash'
- it = iter self
- iter_loop:
- unless it goto iter_end
- $S0 = shift it
- $S1 = self[$S0]
- result[$S1] = $S0
- goto iter_loop
- iter_end:
- .return (result)
+ .local pmc it
+ .local pmc rv
+
+ rv = new 'Perl6Hash'
+ it = self.'iterator'()
+
+ loop:
+ .local string key
+ .local pmc pair
+ .local pmc val
+
+ unless it goto end
+ pair = shift it
+ key = pair.'key'()
+ val = pair.'value'()
+
+ rv[val] = key
+ goto loop
+
+ end:
+ .return (rv)
.end
+=item values()
+
+Returns values of hash as a List
+
+=cut
+
.sub 'values' :method :multi('Hash')
.local pmc it
.local pmc rv
- it = iter self
- rv = new 'List'
+
+ it = self.'iterator'()
+ rv = new 'List'
+
loop:
+ .local pmc pair
+ .local pmc val
+
unless it goto end
- $S1 = shift it
- $P1 = it[$S1]
- push rv, $P1
+ pair = shift it
+ val = pair.'value'()
+
+ push rv, val
goto loop
+
end:
.return (rv)
.end
+=head2 Private methods
+
+=over 4
+
+=item !flatten()
+
+Flatten the invocant, as in list context.
+
+=cut
+
.sub '!flatten' :method
- .tailcall self.'pairs'()
+ .tailcall self.'iterator'()
.end
+=back
+
+=head2 Vtable functions
+
+=over 4
+
+=item ''
+
+=cut
+
+.sub '' :vtable('get_string') :method
+ .local string rv
+ .local pmc it
+
+ it = self.'iterator'()
+ rv = ''
+
+ loop:
+ .local string str
+
+ unless it goto end
+ str = shift it
+ rv .= str
+ rv .= "\n"
+ goto loop
+
+ end:
+ .return (rv)
+.end
+
=back
=cut