From: Matt S Trout Date: Mon, 20 Jan 2014 12:25:53 +0000 (+0000) Subject: basic return stack usage X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=71d2620902f686f9e1d8bd8d576ffe140f880924;p=scpubgit%2FDKit.git basic return stack usage --- diff --git a/lib/DX/State.pm b/lib/DX/State.pm index 4815ab2..66287dd 100644 --- a/lib/DX/State.pm +++ b/lib/DX/State.pm @@ -54,12 +54,28 @@ sub then { $self->new(%$self, next_op => $then); } +sub select_next_op { + my ($self) = @_; + return $self->next_op || do { + if (my @stack = @{$self->return_stack}) { + my $top = pop @stack; + DX::Op::FromCode->new( + code => sub { + $_[1]->new(%{$_[1]}, return_stack => \@stack, next_op => $top) + } + ); + } else { + undef; + } + }; +} + sub run { my ($state) = @_; with_return { my ($return) = @_; local our $No_Options_Handler = $return; - while (my $op = $state->next_op) { + while (my $op = $state->select_next_op) { $state = $op->run($state); } return $state; diff --git a/t/basic.t b/t/basic.t index 1655c85..d3c636a 100644 --- a/t/basic.t +++ b/t/basic.t @@ -105,4 +105,43 @@ is_deeply( 'Complex stream' ); +my $call_op = FromCode->new( + code => sub { + my ($self, $state) = @_; + my @rst = @{$state->return_stack}; + my $save_scope = $state->scope; + my %scope = (S => $save_scope->{S}); + my $ret_op = FromCode->new( + code => sub { $_[1]->new(%{$_[1]}, scope => $save_scope, next_op => $_[0]->next) }, + next => $self->next, + ); + $state->new(%$state, + scope => \%scope, + return_stack => [ @rst, $ret_op ], + next_op => $op + ); + }, + next => FromCode->new( + code => bind_array(P => \@shells), + next => FromCode->new( + code => test_values([ qw(S P) ], sub { $shells{$_[1]}{$_[0]} }), + ) + ) +); + +my $callstream = DX::ResultStream->new( + for_state => make_state([ qw(S P) ], $call_op) +); + +is_deeply( + [ $callstream->results ], + [ + { P => 'csh', S => 'jim.example.com' }, + { P => 'csh', S => 'joe.example.com' }, + { P => 'bash', S => 'joe.example.com' }, + { P => 'csh', S => 'bob.example.com' }, + ], + 'Call stream' +); + done_testing;