From: Matt S Trout Date: Mon, 3 Feb 2014 02:40:55 +0000 (+0000) Subject: factor out arg handling X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=385fa95470eee7f352b6a3ef3a082f8fbbc2d174;p=scpubgit%2FDKit.git factor out arg handling --- diff --git a/lib/DX/Op/ApplyConstraint.pm b/lib/DX/Op/ApplyConstraint.pm index 1dfee28..093ede6 100644 --- a/lib/DX/Op/ApplyConstraint.pm +++ b/lib/DX/Op/ApplyConstraint.pm @@ -7,9 +7,16 @@ with 'DX::Role::Op'; has vars => (is => 'ro', required => 1); has constraint => (is => 'ro', required => 1); +has _arg_map => (is => 'lazy', builder => sub { + my ($self) = @_; + my $name = 'arg0'; + +{ map +($name++, $_), @{$self->vars} }; +}); + sub run { my ($self, $state) = @_; - my @vars = map $state->scope_var($_)->bound_value, @{$self->vars}; + ($state, my %args) = $self->_expand_args($state, %{$self->_arg_map}); + my @vars = map $_->bound_value, @args{sort keys %args}; if ($self->constraint->(@vars)) { return $state->then($self->next); } diff --git a/lib/DX/Op/CallRule.pm b/lib/DX/Op/CallRule.pm index f97d187..2cd8c74 100644 --- a/lib/DX/Op/CallRule.pm +++ b/lib/DX/Op/CallRule.pm @@ -17,19 +17,7 @@ has full_name => (is => 'lazy', builder => sub { sub run { my ($self, $state) = @_; - my @args = map { - if (!ref($_)) { - $state->scope_var($_) - } elsif (ref($_) eq 'ARRAY') { - if ($_->[0] eq 'value') { - +{ bound_value => $_->[1] }; - } else { - die "Arrayref in argspec is not value"; - } - } else { - die "Argspec incomprehensible"; - } - } @{$self->rule_args}; + my @args = map $self->_expand_argspec($state, $_), @{$self->rule_args}; my @rules = @{$state->rule_set->rules->{$self->full_name}||[]}; die "No rules for ${\$self->full_name}" unless @rules; my $var = DX::Var->new(id => 'OR') diff --git a/lib/DX/Op/MemberOf.pm b/lib/DX/Op/MemberOf.pm index 94eceb2..2ff460e 100644 --- a/lib/DX/Op/MemberOf.pm +++ b/lib/DX/Op/MemberOf.pm @@ -6,13 +6,17 @@ use Moo; with 'DX::Role::Op'; has member_var => (is => 'ro', required => 1); -has coll_name => (is => 'ro', required => 1); +has coll_var => (is => 'ro', required => 1); sub run { my ($self, $state) = @_; - my $member = $state->scope_var($self->member_var); + ($state, my %args) = $self->_expand_args($state, + member => $self->member_var, + of => $self->coll_var + ); + my ($member, $of) = @args{qw(member of)}; die "member bound" if $member->is_bound; - my $set = $state->facts->{$self->coll_name}; + my $set = $state->facts->{$of->bound_value}; my $stream = DX::ArrayStream->from_array(@{$set}{sort keys %$set}); return $state->bind_stream_then($member, $stream, $self->next); } diff --git a/lib/DX/Role/Op.pm b/lib/DX/Role/Op.pm index 11294d1..813cea7 100644 --- a/lib/DX/Role/Op.pm +++ b/lib/DX/Role/Op.pm @@ -11,4 +11,27 @@ sub but { $self->new(%$self, @but); } +sub _expand_args { + my ($self, $state, %spec) = @_; + my %args; + @args{keys %spec} = map $self->_expand_argspec($state, $_), values %spec; + return $state->expand_vars(%args); +} + +sub _expand_argspec { + my ($self, $state, $spec) = @_; + if (!ref($spec)) { + $state->scope_var($spec) + } elsif (ref($spec) eq 'ARRAY') { + if ($spec->[0] eq 'value') { + +{ bound_value => $spec->[1] }; + } else { + die "Arrayref in argspec is not value"; + } + } else { + die "Argspec incomprehensible"; + } +} + + 1; diff --git a/lib/DX/RuleSet.pm b/lib/DX/RuleSet.pm index b051306..897c317 100644 --- a/lib/DX/RuleSet.pm +++ b/lib/DX/RuleSet.pm @@ -38,10 +38,10 @@ sub _expand_call { } sub _expand_member_of { - my ($self, $member_var, $coll_name) = @_; + my ($self, $member_var, $coll_var) = @_; DX::Op::MemberOf->new( member_var => $member_var, - coll_name => $coll_name, + coll_var => $coll_var, ); } diff --git a/t/basic_rule.t b/t/basic_rule.t index 6c78c96..c6d6795 100644 --- a/t/basic_rule.t +++ b/t/basic_rule.t @@ -33,13 +33,16 @@ my $solver = DX::Solver->new( facts => { servers => \%servers, shells => \%shells } ); -$solver->add_rule(server => [ 'S' ] => [ member_of => qw(S servers) ]); +$solver->add_rule( + server => [ 'S' ] => [ member_of => S => [ value => 'servers' ] ] +); my $s = $solver->query([ 'S' ], [ call => server => 'S' ]); is_deeply([ map $_->{S}{name}, $s->results ], [ sort @servers ]); -$solver->add_rule(shell => [ 'S' ] => [ member_of => qw(S shells) ]) +$solver->add_rule( + shell => [ 'S' ] => [ member_of => S => [ value => 'shells' ] ]) ->add_rule(name => [ qw(T N) ], [ constrain => [ qw(T N) ], sub { $_[0]->{name} eq $_[1] } ]