eliminate outstanding_propositions attribute
[scpubgit/DX.git] / lib / DX / Hypothesis.pm
1 package DX::Hypothesis;
2
3 use DX::ActionPolicy::LockScope;
4 use Types::Standard qw(ArrayRef);
5 use DX::Utils qw(deparse);
6 use DX::Class;
7
8 has scope => (is => 'ro', isa => Scope, required => 1);
9
10 has resolved_propositions => (
11   is => 'ro', isa => ResolvedPropositionSet, required => 1
12 );
13
14 has actions => (
15   is => 'ro', isa => ArrayRef[Action], required => 1
16 );
17
18 has action_applications => (
19   is => 'ro', isa => ArrayRef[Action], required => 1
20 );
21
22 has action_policy => (is => 'ro', isa => ActionPolicy, required => 1);
23
24 sub with_actions {
25   my ($self, @actions) = @_;
26   my $hyp = $self;
27   foreach my $act (@actions) {
28     return undef unless $self->action_policy->allows($act);
29     ($hyp, my @events) = $act->dry_run($hyp);
30     return undef unless $hyp;
31     $hyp = $hyp->but_recheck_for(@events);
32     return undef unless $hyp;
33   }
34   return $hyp;
35 }
36
37 sub but_recheck_for {
38   my ($self, @events) = @_;
39   my ($still_resolved, @recheck) = $self->resolved_propositions
40                                         ->but_expire_for(@events);
41   return $self unless @recheck;
42
43   my $ap = DX::ActionPolicy::LockScope->new(
44     lock_to_depth => $self->scope->depth,
45     next_policy => $self->action_policy,
46   );
47
48   # we should probably be doing something about pruning the scope
49   # but that's completely pointless until we have rules
50
51   my $hyp = ref($self)->new(
52     scope => $self->scope,
53     resolved_propositions => DX::ResolvedPropositionSet->new_empty,
54     actions => [],
55     action_applications => [],
56     action_policy => $ap,
57   );
58
59   my $pseq = DX::PropositionSequence->new(
60     members => \@recheck,
61     external_names => {},
62     internal_names => {},
63   );
64
65   trace 'step.recheck.hyp' => $hyp;
66
67   my $ss = DX::SearchState->new_for($hyp, $pseq);
68
69   my $sol_ss = $ss->find_solution;
70
71   unless ($sol_ss) {
72     trace 'step.recheck.fail' => 'argh';
73     return undef;
74   }
75
76   my $sol_rps = $sol_ss->current_hypothesis->resolved_propositions;
77
78   my $rps = $still_resolved;
79
80   $rps = $rps->with_updated_dependencies_for(
81     $_, $sol_rps->dependencies_for($_)
82   ) for @recheck;
83
84   trace 'step.recheck.done' => 'yay';
85
86   return $self->but(resolved_propositions => $rps);
87 }
88
89 sub with_resolution {
90   my ($self, $prop, $depends) = @_;
91   $self->but(
92     resolved_propositions => $self->resolved_propositions
93                                   ->with_resolution_for(
94                                       $prop,
95                                       $depends,
96                                     ),
97   );
98 }
99
100 1;