allocate new locals in consider instead of up-front
[scpubgit/DX.git] / lib / DX / QueryState.pm
1 package DX::QueryState;
2
3 use DX::Scope;
4 use DX::Hypothesis;
5 use DX::SearchProcess;
6 use DX::ResolvedPropositionSet;
7 use DX::Value::Unset;
8 use DX::ActionBuilder::UnsetValue;
9 use DX::ActionPolicy::Allow;
10 use DX::Utils qw(:builders);
11 use DX::Class;
12
13 has predicates => (is => 'ro', isa => HashRef[Predicate], required => 1);
14
15 has globals => (is => 'ro', isa => DictValue, required => 1);
16
17 has proposition_sequence => (
18   is => 'ro', isa => PropositionSequence, required => 1
19 );
20
21 has search_process => (
22   is => 'lazy', isa => SearchProcess, builder => sub {
23     $_[0]->new_search_process_for($_[0]->proposition_sequence)
24   }, handles => { search_state => 'current_search_state' },
25 );
26
27 sub new_search_process_for {
28   my ($self, $prop_seq) = @_;
29   my @local_names = map { keys %{$_->introduced_names} }
30                       @{$prop_seq->members};
31   my $scope = DX::Scope->new(
32     predicates => $self->predicates,
33     globals => $self->globals,
34     locals => [ dict() ],
35     lex_map => { }
36   );
37   my $hyp = DX::Hypothesis->new(
38     scope => $scope,
39     resolved_propositions => DX::ResolvedPropositionSet->new_empty,
40     actions => [],
41     action_applications => [],
42     action_policy => DX::ActionPolicy::Allow->new,
43   );
44   return DX::SearchProcess->new_for($hyp, $prop_seq);
45 }
46
47 sub with_additional_proposition {
48   my ($self, $prop) = @_;
49   my $prop_seq = $self->proposition_sequence
50                       ->with_additional_proposition($prop);
51   my $sol_ss = $self->new_search_process_for($prop_seq)
52                     ->find_solution;
53   die "No solution\n" unless $sol_ss;
54   $self->but(
55     proposition_sequence => $prop_seq,
56     search_process => $sol_ss,
57   );
58 }
59
60 sub with_forced_backtrack {
61   my ($self) = @_;
62   my $next_ss = $self->search_process->find_next_solution;
63   die "No next solution\n" unless $next_ss;
64   $self->but(search_process => $next_ss);
65 }
66
67 1;