Commit | Line | Data |
9d759b64 |
1 | package DX::SearchState; |
2 | |
3 | use DX::Class; |
4 | |
5 | has current_hypothesis => (is => 'ro', required => 1); |
6 | |
7 | has resume_step => (is => 'ro'); |
8 | |
9 | has alternatives => (is => 'ro', required => 1); |
10 | |
11 | sub with_one_step { |
12 | my ($self) = @_; |
13 | my $hyp = $self->current_hypothesis; |
14 | my $step = $self->resume_step |
15 | || $hyp->head_proposition->resolve_for($hyp->scope); |
16 | my @alt = @{$self->alternatives}; |
17 | HYP: while ($hyp) { |
18 | STEP: while ($step) { |
19 | my ($new_hyp, $alt_step) = $step->apply_to($hyp); |
20 | if ($new_hyp) { |
efad53c4 |
21 | return $self->but( |
9d759b64 |
22 | current_hypothesis => $new_hyp, |
23 | ($alt_step |
24 | ? (alternatives => [ |
25 | [ $hyp, $alt_step ], |
26 | @alt |
27 | ]) |
28 | : ()) |
29 | ); |
30 | } |
31 | $step = $alt_step; |
32 | } |
33 | ($hyp, $step) = @{shift(@alt)||[]}; |
34 | } |
35 | return undef; |
36 | } |
37 | |
38 | sub find_solution { |
39 | my $state = $_[0]; |
40 | while ($state and @{$state->current_hypothesis->outstanding_propositions}) { |
41 | $state = $state->with_one_step; |
42 | } |
43 | return $state; |
44 | } |
45 | |
46 | sub force_backtrack { |
47 | my ($self) = @_; |
48 | my ($first_alt, @rest_alt) = $self->alternatives; |
49 | return ref($self)->new( |
50 | current_hypothesis => $first_alt->[0], |
51 | resume_step => $first_alt->[1], |
52 | alternatives => \@rest_alt |
53 | ); |
54 | } |
55 | |
56 | sub find_next_solution { |
57 | my ($self) = @_; |
58 | return undef unless my $bt = $self->force_backtrack; |
59 | return $bt->find_solution; |
60 | } |
61 | |
62 | 1; |