slightly janky attempt at show all solutions
[scpubgit/DX.git] / lib / DX / QueryState.pm
1 package DX::QueryState;
2
3 use Types::Standard qw(HashRef);
4 use DX::Scope;
5 use DX::Hypothesis;
6 use DX::SearchState;
7 use DX::ResolvedPropositionSet;
8 use DX::Value::Unset;
9 use DX::ActionBuilder::UnsetValue;
10 use DX::ActionPolicy::Allow;
11 use DX::Utils qw(:builders);
12 use DX::Class;
13
14 has predicates => (is => 'ro', isa => HashRef[Predicate], required => 1);
15
16 has globals => (is => 'ro', isa => DictValue, required => 1);
17
18 has proposition_sequence => (
19   is => 'ro', isa => PropositionSequence, required => 1
20 );
21
22 has search_state => (
23   is => 'lazy', builder => sub {
24     $_[0]->new_search_state_for($_[0]->proposition_sequence)
25   },
26 );
27
28 sub new_search_state_for {
29   my ($self, $prop_seq) = @_;
30   my @local_names = map { keys %{$_->introduced_names} }
31                       @{$prop_seq->members};
32   my $scope = DX::Scope->new(
33     predicates => $self->predicates,
34     globals => $self->globals,
35     locals => [
36       dict(
37         map +($_ => DX::Value::Unset->new(
38                       identity_path => [ 0, $_ ],
39                       action_builder => DX::ActionBuilder::UnsetValue->new(
40                         target_path => [ 0, $_ ],
41                       )
42                     )
43         ), @local_names
44       )
45     ]
46   );
47   my $hyp = DX::Hypothesis->new(
48     scope => $scope,
49     resolved_propositions => DX::ResolvedPropositionSet->new_empty,
50     outstanding_propositions => $prop_seq->members,
51     actions => [],
52     action_applications => [],
53     action_policy => DX::ActionPolicy::Allow->new,
54   );
55   return DX::SearchState->new(
56     current_hypothesis => $hyp,
57     alternatives => [],
58   );
59 }
60
61 sub with_additional_proposition {
62   my ($self, $prop) = @_;
63   my $prop_seq = $self->proposition_sequence
64                       ->with_additional_proposition($prop);
65   my $sol_ss = $self->new_search_state_for($prop_seq)
66                     ->find_solution;
67   die "No solution\n" unless $sol_ss;
68   $self->but(
69     proposition_sequence => $prop_seq,
70     search_state => $sol_ss,
71   );
72 }
73
74 sub with_forced_backtrack {
75   my ($self) = @_;
76   my $next_ss = $self->search_state->find_next_solution;
77   die "No next solution\n" unless $next_ss;
78   $self->but(search_state => $next_ss);
79 }
80
81 1;