follow alternative rspace entries without backtracking, explicitly resolve
[scpubgit/DX.git] / lib / DX / Step / ResolveProposition.pm
1 package DX::Step::ResolveProposition;
2
3 use DX::Step::EnterRecheck;
4 use DX::Step::CompleteResolution;
5 use DX::Step::Backtrack;
6
7 use DX::Utils qw(expand_deps);
8
9 use DX::Class;
10
11 with 'DX::Role::Step';
12
13 has resolution_space => (is => 'ro', isa => ResolutionSpace);
14
15 sub resolves { shift->resolution_space->proposition }
16
17 sub current_resolution { shift->resolution_space->next_resolution }
18
19 sub actions { shift->current_resolution->actions }
20
21 sub depends_on { shift->current_resolution->veracity_depends_on }
22
23 sub but_first {
24   my ($self, @actions) = @_;
25   $self->but(actions => [ @actions, @{$self->actions} ]);
26 }
27
28 sub but_with_dependencies_on {
29   my ($self, @deps) = @_;
30   $self->but(depends_on => [ @{$self->depends_on}, @deps ]);
31 }
32
33 sub apply_to {
34   my ($self, $old_ss) = @_;
35   trace resolve => [ statement => [
36     [ symbol => 'resolve' ],
37     [ block => [
38       [ statement => [
39         [ symbol => 'proposition' ],
40         @{$self->resolves->for_deparse->[1]},
41       ] ],
42       (@{$self->actions}
43         ? [ statement => [
44             [ symbol => 'actions' ],
45             [ block => $self->actions ],
46           ] ]
47         : ()),
48       [ statement => [
49         [ symbol => 'depends_on' ],
50         [ block => [
51           map [ statement => [
52             [ symbol => (split '::', ${$_->[0]})[-1] ],
53             [ value_path => [ @{$_}[1..$#$_] ] ]
54           ] ], @{$self->depends_on}
55         ] ],
56       ] ],
57     ] ]
58   ] ];
59   my $rspace = $self->resolution_space;
60   my $ss = $old_ss->but(
61     next_step => DX::Step::CompleteResolution->new(
62       original_search_state => $old_ss,
63       resolution_space => $rspace,
64     )
65   );
66   my $old_hyp = $old_ss->current_hypothesis;
67   (my $hyp, my @recheck) = $old_hyp->with_resolution(
68     $self->resolves, $self->depends_on, $self->actions
69   );
70   return $ss->but(next_step => DX::Step::Backtrack->new) unless $hyp;
71   return $ss->but(current_hypothesis => $hyp) unless @recheck;
72   return $ss->but(
73     current_hypothesis => $hyp,
74     next_step => DX::Step::EnterRecheck->new(
75       proposition_list => \@recheck,
76       on_completion_step => $ss->next_step,
77       on_failure_step => $rspace->remaining_resolution_space->next_step,
78     ),
79   );
80 }
81
82 1;