pervasive type constraints
[scpubgit/DX.git] / lib / DX / SearchState.pm
1 package DX::SearchState;
2
3 use DX::Step::Backtrack;
4 use DX::Step::ConsiderProposition;
5 use DX::Step::MarkAsSolution;
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], required => 1);
11
12 has propositions => (is => 'ro', isa => PropositionSequence, required => 1);
13
14 has decisions_taken => (is => 'ro', isa => DecisionList, required => 1);
15
16 has is_solution_state => (is => 'ro', isa => Bool, required => 1);
17
18 has on_exhaustion_step => (is => 'ro', isa => Maybe[Step], required => 1);
19
20 has on_solution_step => (is => 'ro', isa => Maybe[Step], required => 1);
21
22 sub next_proposition {
23   my ($self) = @_;
24   my $hyp = $self->current_hypothesis;
25   $self->propositions->members->[
26     $hyp->resolved_propositions->resolved_count + 1
27   ];
28 }
29
30 sub new_for {
31   my ($class, $hyp, $props) = @_;
32   $class->new(
33     current_hypothesis => $hyp,
34     decisions_taken => [],
35     propositions => $props,
36     (@{$props->members}
37       ? (
38           next_step => DX::Step::ConsiderProposition->new(
39             proposition => $props->members->[0],
40           ),
41           is_solution_state => 0,
42         )
43       : ( next_step => undef, is_solution_state => 1 )
44     ),
45     on_exhaustion_step => undef,
46     on_solution_step => DX::Step::MarkAsSolution->new,
47   );
48 }
49
50 sub with_one_step {
51   my ($self) = @_;
52   return undef unless my $step = $self->next_step;
53   #trace step => $step;
54   return $step->apply_to($self);
55 }
56
57 sub force_backtrack {
58   my ($self) = @_;
59   return $self->but(
60     next_step => DX::Step::Backtrack->new,
61   )->with_one_step;
62 }
63
64 1;