move dep expansion into step() and clean up ResolveProposition.pm
[scpubgit/DX.git] / lib / DX / Step / ResolveProposition.pm
1 package DX::Step::ResolveProposition;
2
3 use DX::Step::EnterRecheck;
4 use DX::Step::Backtrack;
5
6 use Types::Standard qw(ArrayRef);
7 use DX::Utils qw(deparse);
8
9 use DX::Class;
10
11 with 'DX::Role::Step';
12
13 has actions => (is => 'ro', isa => ArrayRef[Action], required => 1);
14
15 has depends_on => (is => 'ro', isa => ArrayRef[DependencySpec], required => 1);
16
17 has resolves => (is => 'ro', isa => Proposition);
18
19 has alternative_step => (is => 'ro', isa => Step);
20
21 sub but_first {
22   my ($self, @actions) = @_;
23   $self->but(actions => [ @actions, @{$self->actions} ]);
24 }
25
26 sub but_with_dependencies_on {
27   my ($self, @deps) = @_;
28   $self->but(depends_on => [ @{$self->depends_on}, @deps ]);
29 }
30
31 sub apply_to {
32   my ($self, $old_ss) = @_;
33   my $ns = do {
34     if (my $prop = $old_ss->next_proposition) {
35       DX::Step::ConsiderProposition->new(
36         proposition => $prop
37       )
38     } else {
39       $old_ss->on_solution_step
40     }
41   };
42   my $alt_step = $self->alternative_step;
43   my $ss = $old_ss->but(
44     next_step => $ns,
45     (@{$self->actions}
46       ? (adjustments_made => [
47           [ $self, $old_ss ],
48           @{$old_ss->adjustments_made}
49         ])
50       : ()
51     ),
52   );
53   my $new_ss = $self->_apply_to_ss($ss);
54   return $ss->but(next_step => DX::Step::Backtrack->new) unless $new_ss;
55   return $new_ss;
56 }
57
58 sub _apply_to_ss {
59   my ($self, $old_ss) = @_;
60   my $old_hyp = $old_ss->current_hypothesis;
61   (my $hyp, my @recheck) = $old_hyp->with_resolution(
62     $self->resolves, $self->depends_on, $self->actions
63   );
64   return undef unless $hyp;
65   return $self->_recheck_for(
66     $old_ss->but(current_hypothesis => $hyp),
67     @recheck
68   );
69 }
70
71 sub _recheck_for {
72   my ($self, $old_ss, @recheck) = @_;
73
74   return $old_ss unless @recheck;
75
76   my $ss = $old_ss->but(
77     next_step => DX::Step::EnterRecheck->new(
78       proposition_list => \@recheck,
79       on_completion_step => $old_ss->next_step,
80       on_failure_step => DX::Step::Backtrack->new,
81     ),
82   );
83
84   return $ss;
85 }
86
87 1;