use List::Util qw(reduce);
use Moo;
-has rule_set => (is => 'lazy', handles => [ 'add_rule' ], builder => sub {
- DX::RuleSet->new
-});
+has rule_set => (
+ is => 'lazy',
+ handles => [ qw(add_predicate add_rule) ],
+ builder => sub {
+ DX::RuleSet->new
+ },
+);
-has facts => (is => 'ro', required => 1);
+has facts => (is => 'ro', default => sub { {} });
has observation_policy => (is => 'ro');
sub query {
- my ($self, $vars, @terms) = @_;
+ my ($self, @terms) = @_;
+ $self->_solve({ allow_actions => 0 }, @terms);
+}
+
+sub solve {
+ my ($self, @terms) = @_;
+ $self->_solve({ allow_actions => 1 }, @terms);
+}
+
+sub ensure {
+ my ($self, @terms) = @_;
+ my $rs = $self->_solve({ allow_actions => 1 }, @terms);
+ my $r = $rs->next;
+ while ($r and $r->actions and my @ind = $r->independent_actions) {
+ $self->run_action($_) for @ind;
+ $rs = $self->_solve({ allow_actions => 1 }, @terms);
+ $r = $rs->next;
+ }
+ return $r;
+}
+
+sub _solve {
+ my ($self, $attrs, @terms) = @_;
my $rule_set = $self->rule_set;
- push @terms, map +[ materialize => $_ ], @$vars;
- my $head = $rule_set->expand_and_link(undef, @terms);
+ my $head = $rule_set->expand_and_link(undef, @terms, [ 'materialize' ]);
my $state = DX::State->new(
next_op => $head,
return_stack => [],
last_choice => [],
facts => $self->facts,
rule_set => $rule_set,
- )->assign_vars(map +($_ => {}), @$vars);
+ %$attrs
+ );
return DX::ResultStream->new(
for_state => $state,
($self->observation_policy
);
}
+sub run_action {
+ my ($self, $action) = @_;
+ warn +(split('::', ref($action)))[-1]."\n";
+ my @invalidate = $action->run;
+ while (my ($type, $value) = splice @invalidate, 0, 2) {
+ $self->facts->{$type}->remove_value($value);
+ }
+}
+
1;