1 package DX::QueryState;
6 use DX::ResolvedPropositionSet;
7 use DX::ActionPolicy::Allow;
8 use DX::Step::MarkAsExhaustion;
9 use DX::Utils qw(:builders);
12 has predicates => (is => 'ro', isa => HashRef[Predicate], required => 1);
14 has globals => (is => 'ro', isa => DictValue, required => 1);
16 has proposition_sequence => (
17 is => 'ro', isa => PropositionSequence, required => 1
20 has search_process => (
21 is => 'lazy', isa => SearchProcess, builder => sub {
22 $_[0]->new_search_process_for($_[0]->proposition_sequence)
23 }, handles => { search_state => 'current_search_state' },
26 sub new_search_process_for {
27 my ($self, $prop_seq) = @_;
28 my @local_names = map { keys %{$_->introduced_names} }
29 @{$prop_seq->members};
30 my $scope = DX::Scope->new(
31 predicates => $self->predicates,
32 globals => $self->globals,
36 my $hyp = DX::Hypothesis->new(
38 resolved_propositions => DX::ResolvedPropositionSet->new_empty,
40 action_applications => [],
41 action_policy => DX::ActionPolicy::Allow->new,
43 return DX::SearchProcess->new_for($hyp, $prop_seq);
46 sub with_additional_proposition {
47 my ($self, $new_prop) = @_;
48 my $old_prop_seq = $self->proposition_sequence;
49 my $new_prop_seq = $old_prop_seq->with_additional_proposition($new_prop);
50 my $old_ss = $self->search_process->current_search_state;
52 my $_munge; $_munge = sub {
54 return $seen{$ss} ||= do {
57 map [ $_->[0], $_->[1]->$_munge ], @{$ss->decisions_taken}
60 if ($ss->propositions eq $old_prop_seq) {
61 $but{propositions} = $new_prop_seq;
63 foreach my $type (qw(on_solution_step on_exhaustion_step)) {
64 my $step = $ss->$type;
65 if ($step and $step->can('resume_search_state')) {
69 resume_search_state => $step->resume_search_state->$_munge
76 my $munged_ss = $old_ss->$_munge;
79 my $new_ss = $munged_ss->but(
80 is_solution_state => 0,
81 next_step => DX::Step::ConsiderProposition->new(
82 proposition => $new_prop
86 my $sol_sp = $self->search_process
87 ->but(current_search_state => $new_ss)
89 die "No solution\n" unless $sol_sp;
91 proposition_sequence => $new_prop_seq,
92 search_process => $sol_sp,
96 sub with_forced_backtrack {
98 my $next_ss = $self->search_process->find_next_solution;
99 die "No next solution\n" unless $next_ss;
100 $self->but(search_process => $next_ss);