factor out arg handling
Matt S Trout [Mon, 3 Feb 2014 02:40:55 +0000 (02:40 +0000)]
lib/DX/Op/ApplyConstraint.pm
lib/DX/Op/CallRule.pm
lib/DX/Op/MemberOf.pm
lib/DX/Role/Op.pm
lib/DX/RuleSet.pm
t/basic_rule.t

index 1dfee28..093ede6 100644 (file)
@@ -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);
   }
index f97d187..2cd8c74 100644 (file)
@@ -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')
index 94eceb2..2ff460e 100644 (file)
@@ -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);
 }
index 11294d1..813cea7 100644 (file)
@@ -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;
index b051306..897c317 100644 (file)
@@ -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,
   );
 }
 
index 6c78c96..c6d6795 100644 (file)
@@ -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] } ]