tug firmly, and recursion pops out into iteration
[scpubgit/DX.git] / lib / DX / Step / EnterRecheck.pm
1 package DX::Step::EnterRecheck;
2
3 use DX::Step::CompleteRecheck;
4 use DX::Step::FailRecheck;
5
6 use DX::Class;
7
8 with 'DX::Role::Step';
9
10 has proposition_list => (is => 'ro', required => 1);
11
12 has on_completion_step => (is => 'ro', required => 1);
13
14 has on_failure_step => (is => 'ro', required => 1);
15
16 sub apply_to {
17   my ($self, $old_ss) = @_;
18
19   my ($prop, @rest) = @{$self->proposition_list};
20
21   my $old_hyp = $old_ss->current_hypothesis;
22
23   # we should probably be doing something about pruning the scope
24   # but that's completely pointless until we have rules (and also,
25   # the lock_to_depth arg needs to come from the proposition somehow)
26
27   my $ap = DX::ActionPolicy::LockScope->new(
28     lock_to_depth => $old_hyp->scope->depth,
29     next_policy => $old_hyp->action_policy,
30   );
31
32   my $hyp = ref($old_hyp)->new(
33     scope => $old_hyp->scope,
34     resolved_propositions => DX::ResolvedPropositionSet->new_empty,
35     actions => [],
36     action_applications => [],
37     action_policy => $ap,
38   );
39
40   my $pseq = DX::PropositionSequence->new(
41     members => [ $prop ],
42     external_names => {},
43     internal_names => {},
44   );
45
46   my $next_step = (@rest
47                     ? $self->but(proposition_list => \@rest)
48                     : $self->on_completion_step);
49
50   trace 'step.recheck.hyp' => $hyp;
51
52   my $ss = DX::SearchState->new(
53     current_hypothesis => $hyp,
54     alternatives => [],
55     propositions => $pseq,
56     next_step => DX::Step::ConsiderProposition->new(
57                    proposition => $prop,
58                  ),
59     is_solution_state => 0,
60     on_solution_step => DX::Step::CompleteRecheck->new(
61       resume_search_state => $old_ss->but(next_step => $next_step),
62       was_recheck_for => $prop,
63     ),
64     on_exhaustion_step => DX::Step::FailRecheck->new(
65       resume_search_state => $old_ss->but(next_step => $self->on_failure_step),
66     ),
67   );
68
69   return $ss;
70 }
71
72 1;