switch force_backtrack to execute a backtrack step
[scpubgit/DX.git] / lib / DX / SearchState.pm
1 package DX::SearchState;
2
3 use Types::Standard qw(Maybe);
4 use DX::Step::Backtrack;
5 use DX::Step::InvokeNextPredicate;
6 use DX::Class;
7
8 has current_hypothesis => (is => 'ro', isa => Hypothesis, required => 1);
9
10 has next_step => (is => 'ro', isa => Maybe[Step]);
11
12 has propositions => (is => 'ro', isa => PropositionSequence, required => 1);
13
14 has alternatives => (is => 'ro', isa => AlternativeList, required => 1);
15
16 sub next_proposition {
17   my ($self, $hyp) = @_;
18   $hyp ||= $self->current_hypothesis;
19   $self->propositions->members->[
20     $hyp->resolved_propositions->resolved_count
21   ];
22 }
23
24 sub new_for {
25   my ($class, $hyp, $props) = @_;
26   $class->new(
27     current_hypothesis => $hyp,
28     alternatives => [],
29     next_step => DX::Step::InvokeNextPredicate->new(
30       proposition => $props->members->[0],
31     ),
32     propositions => $props,
33   );
34 }
35
36 sub with_one_step {
37   my ($self) = @_;
38   return undef unless my $step = $self->next_step;
39   return $step->apply_to($self);
40 }
41
42 sub force_backtrack {
43   my ($self) = @_;
44   my ($first_alt, @rest_alt) = @{$self->alternatives};
45   return undef unless $first_alt;
46   trace 'search.backtrack.forced' => $first_alt->[0];
47   return $self->but(
48     next_step => DX::Step::Backtrack->new,
49   )->with_one_step;
50 }
51
52 1;