Commit | Line | Data |
60cda014 |
1 | package DX::State; |
2 | |
3 | use Moo; |
4 | |
5 | has next_op => (is => 'ro', required => 1); |
6 | |
7 | has return_stack => (is => 'ro', required => 1); |
8 | |
9 | has by_id => (is => 'ro', required => 1); |
10 | |
11 | has scope => (is => 'ro', required => 1); |
12 | |
13 | has last_choice => (is => 'ro', required => 1); |
14 | |
15 | sub scope_var { |
16 | my ($self, $name) = @_; |
17 | $self->by_id->{$self->scope->{$name}}; |
18 | } |
19 | |
20 | sub bind_stream_then { |
21 | my ($self, $var, $stream, $then) = @_; |
22 | warn "Binding ".$var->id." to $stream"; |
23 | my $bound = $var->with_stream($stream); |
24 | $self->new(%$self, |
25 | by_id => { %{$self->by_id}, $var->id => $bound }, |
26 | next_op => $then |
27 | )->mark_choice($bound); |
28 | } |
29 | |
30 | sub mark_choice { |
31 | my ($self, $var) = @_; |
32 | $self->new(%$self, |
33 | last_choice => [ $self, $var ] |
34 | ); |
35 | } |
36 | |
37 | sub backtrack { |
38 | my ($self) = @_; |
39 | while (my ($state, $var) = @{$self->last_choice}) { |
40 | $var->bound_value; $var->clear_bound_value; |
41 | return $state unless $var->bound_stream->is_exhausted; |
42 | } |
43 | die "Out of options"; |
44 | } |
45 | |
46 | sub then { |
47 | my ($self, $then) = @_; |
48 | $self->new(%$self, next_op => $then); |
49 | } |
50 | |
51 | 1; |