new Op::Predicate
[scpubgit/DKit.git] / lib / DX / Solver.pm
1 package DX::Solver;
2
3 use DX::RuleSet;
4 use DX::State;
5 use DX::ResultStream;
6 use List::Util qw(reduce);
7 use Moo;
8
9 has rule_set => (
10   is => 'lazy',
11   handles => [ qw(add_predicate add_rule) ],
12   builder => sub {
13     DX::RuleSet->new
14   },
15 );
16
17 has facts => (is => 'ro', required => 1);
18
19 has observation_policy => (is => 'ro');
20
21 sub query {
22   my ($self, $vars, @terms) = @_;
23   my $rule_set = $self->rule_set;
24   push @terms, map +[ materialize => $_ ], @$vars;
25   my $head = $rule_set->expand_and_link(undef, @terms);
26   my $state = DX::State->new(
27     next_op => $head,
28     return_stack => [],
29     by_id => {},
30     scope => {},
31     last_choice => [],
32     facts => $self->facts,
33     rule_set => $rule_set,
34   )->assign_vars(map +($_ => {}), @$vars);
35   return DX::ResultStream->new(
36     for_state => $state,
37     ($self->observation_policy
38       ? (observation_policy => $self->observation_policy)
39       : ()),
40   );
41 }
42
43 sub run_action {
44   my ($self, $action) = @_;
45   my @invalidate = $action->run;
46   while (my ($type, $value) = splice @invalidate, 0, 2) {
47     $self->facts->{$type}->remove_value($value);
48   }
49 }
50
51 1;