diff --git a/src/builtins/guts.pir b/src/builtins/guts.pir index 6b41c996372..ceacd68ceb5 100644 --- a/src/builtins/guts.pir +++ b/src/builtins/guts.pir @@ -148,6 +148,65 @@ Does an indirect method dispatch. .end +=item !dispatch_dispatcher_parallel + +Does a parallel method dispatch over an existing dispatcher. Just invokes the normal +dispatcher for each thingy we're dispatching over. + +=cut + +.sub '!dispatch_dispatcher_parallel' + .param pmc invocanty + .param string dispatcher + .param pmc pos_args :slurpy + .param pmc named_args :slurpy :named + + .local pmc it, result, disp + disp = find_name dispatcher + result = new ['Perl6Array'] + invocanty = invocanty.'list'() + it = iter invocanty + it_loop: + unless it goto it_loop_done + $P0 = shift it + $P0 = disp($P0, pos_args :flat, named_args :flat :named) + result.'push'($P0) + goto it_loop + it_loop_done: + + .return (result) +.end + + +=item !dispatch_method_parallel + +Does a parallel method dispatch. Invokes the method for each thing in the +array of invocants. + +=cut + +.sub '!dispatch_method_parallel' + .param pmc invocanty + .param string name + .param pmc pos_args :slurpy + .param pmc named_args :slurpy :named + + .local pmc it, result + result = new ['Perl6Array'] + invocanty = invocanty.'list'() + it = iter invocanty + it_loop: + unless it goto it_loop_done + $P0 = shift it + $P0 = $P0.name(pos_args :flat, named_args :flat :named) + result.'push'($P0) + goto it_loop + it_loop_done: + + .return (result) +.end + + =item !VAR Helper function for implementing the VAR and .VAR macros. diff --git a/src/parser/actions.pm b/src/parser/actions.pm index 1199806c3c6..370b1f465df 100644 --- a/src/parser/actions.pm +++ b/src/parser/actions.pm @@ -1200,7 +1200,24 @@ method expect_term($/, $key) { method post($/, $key) { - make $/{$key}.ast; + my $past := $/{$key}.ast; + + if $ { + if $past.isa(PAST::Op) && $past.pasttype() eq 'call' { + $past.unshift($past.name()); + $past.name('!dispatch_dispatcher_parallel'); + } + elsif $past.isa(PAST::Op) && $past.pasttype() eq 'callmethod' { + $past.unshift($past.name()); + $past.name('!dispatch_method_parallel'); + $past.pasttype('call'); + } + else { + $/.panic("Unimplemented or invalid use of parallel dispatch"); + } + } + + make $past; }