prop op
[scpubgit/DKit.git] / lib / DX / RuleSet.pm
CommitLineData
b40e416a 1package DX::RuleSet;
2
3use Moo;
4use DX::Op::CallRule;
5use DX::Op::MemberOf;
b40e416a 6use DX::Op::ApplyConstraint;
7use DX::Op::Return;
734376d9 8use DX::Op::Cut;
71217e42 9use DX::Op::Backtrack;
5ef4d923 10use DX::Op::Observe;
71217e42 11use DX::Op::Not;
12use DX::Op::ProposeAction;
13use DX::Op::Materialize;
896fd92e 14use DX::Op::Prop;
b40e416a 15use List::Util qw(reduce);
16
17has rules => (is => 'ro', default => sub { {} });
18
19sub add_rule {
20 my ($self, $name, $vars, @body) = @_;
21 my $full_name = join('/', $name, scalar @$vars);
22 push @{$self->rules->{$full_name}}, $self->_make_rule($vars, @body);
23 return $self;
24}
25
26sub _make_rule {
27 my ($self, $vars, @body) = @_;
71217e42 28 my $head = $self->_expand_and_link(DX::Op::Return->new, @body);
b40e416a 29 [ $vars, $head ];
30}
31
71217e42 32sub _expand_and_link {
33 my ($self, $last, @body) = @_;
34 return reduce { $b->but(next => $a) }
35 $last,
36 reverse map $self->expand(@$_), @body;
37}
38
b40e416a 39sub expand {
40 my ($self, $type, @rest) = @_;
71217e42 41 if ($self->can(my $expand_meth = "_expand_op_${type}")) {
6d533c9d 42 return $self->$expand_meth(@rest);
43 }
44 return $self->_expand_call($type, @rest);
b40e416a 45}
46
47sub _expand_call {
48 my ($self, $name, @args) = @_;
49 DX::Op::CallRule->new(rule_name => $name, rule_args => \@args);
50}
51
71217e42 52sub _expand_op_cut { return DX::Op::Cut->new }
734376d9 53
71217e42 54sub _expand_op_fail { return DX::Op::Backtrack->new }
55
56sub _expand_op_not {
57 my ($self, @contents) = @_;
58 my $cut = DX::Op::Cut->new(next => DX::Op::Backtrack->new);
59 DX::Op::Not->new(
60 body => $self->_expand_and_link($cut, @contents)
61 );
62}
63
64sub _expand_op_member_of {
385fa954 65 my ($self, $member_var, $coll_var) = @_;
b40e416a 66 DX::Op::MemberOf->new(
67 member_var => $member_var,
385fa954 68 coll_var => $coll_var,
b40e416a 69 );
70}
71
71217e42 72sub _expand_op_constrain {
b40e416a 73 my ($self, $vars, $constraint) = @_;
74 DX::Op::ApplyConstraint->new(
75 vars => $vars,
76 constraint => $constraint
77 );
78}
79
71217e42 80sub _expand_op_observe {
5ef4d923 81 my ($self, $vars, $builder) = @_;
82 DX::Op::Observe->new(
83 vars => $vars,
84 builder => $builder,
85 );
86}
87
71217e42 88sub _expand_op_act {
89 my ($self, $vars, $builder) = @_;
90 DX::Op::ProposeAction->new(
91 vars => $vars,
92 builder => $builder,
93 );
94}
95
96sub _expand_op_materialize {
97 my ($self, $var_name) = @_;
98 DX::Op::Materialize->new(var_name => $var_name);
99}
100
896fd92e 101sub _expand_op_prop {
102 my ($self, @args) = @_;
103 my %new; @new{qw(of name value)} = @args;
104 DX::Op::Prop->new(%new);
105}
106
b40e416a 1071;