tighten up SearchState new() signature slightly
[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::Step::MarkAsSolution;
7 use DX::Class;
8
9 has current_hypothesis => (is => 'ro', isa => Hypothesis, required => 1);
10
11 has next_step => (is => 'ro', isa => Maybe[Step], required => 1);
12
13 has propositions => (is => 'ro', isa => PropositionSequence, required => 1);
14
15 has alternatives => (is => 'ro', isa => AlternativeList, required => 1);
16
17 has is_solution_state => (is => 'ro', required => 1);
18
19 has on_exhaustion_step => (is => 'ro', isa => Maybe[Step], required => 1);
20
21 has on_solution_step => (is => 'ro', isa => Maybe[Step], required => 1);
22
23 sub next_proposition {
24   my ($self, $hyp) = @_;
25   $hyp ||= $self->current_hypothesis;
26   $self->propositions->members->[
27     $hyp->resolved_propositions->resolved_count
28   ];
29 }
30
31 sub new_for {
32   my ($class, $hyp, $props) = @_;
33   $class->new(
34     current_hypothesis => $hyp,
35     alternatives => [],
36     propositions => $props,
37     (@{$props->members}
38       ? (
39           next_step => DX::Step::InvokeNextPredicate->new(
40             proposition => $props->members->[0],
41           ),
42           is_solution_state => 0,
43         )
44       : ( next_step => undef, is_solution_state => 1 )
45     ),
46     on_exhaustion_step => undef,
47     on_solution_step => DX::Step::MarkAsSolution->new,
48   );
49 }
50
51 sub with_one_step {
52   my ($self) = @_;
53   return undef unless my $step = $self->next_step;
54   return $step->apply_to($self);
55 }
56
57 sub force_backtrack {
58   my ($self) = @_;
59   my ($first_alt, @rest_alt) = @{$self->alternatives};
60   return undef unless $first_alt;
61   trace 'search.backtrack.forced' => $first_alt->[0];
62   return $self->but(
63     next_step => DX::Step::Backtrack->new,
64   )->with_one_step;
65 }
66
67 1;