AddBoundValue action
Matt S Trout [Sat, 12 Mar 2016 11:33:07 +0000 (11:33 +0000)]
fragments/bind
lib/DX/Action/AddBoundValue.pm [new file with mode: 0644]
lib/DX/Action/SetBoundValue.pm
lib/DX/ActionBuilder/BoundValue.pm
lib/DX/Deparse.pm
lib/DX/Role/BoundValueAction.pm [new file with mode: 0644]

index 88f77c5..de424d3 100644 (file)
@@ -5,3 +5,11 @@ qact
 eq Y {{ foo 1 }}
 qact
 .
+?
+dict ?X {{ foo {{ bar 1 }} }}
+member_at X 'foo' ?Y
+member_at Y 'bar' ?Z
+eq Z 2
+member_at Y 'baz' 4
+qact
+.
diff --git a/lib/DX/Action/AddBoundValue.pm b/lib/DX/Action/AddBoundValue.pm
new file mode 100644 (file)
index 0000000..54cd5fd
--- /dev/null
@@ -0,0 +1,10 @@
+package DX::Action::AddBoundValue;
+
+use DX::Update::AddValue;
+use DX::Class;
+
+with 'DX::Role::BoundValueAction';
+
+sub update_class { 'DX::Update::AddValue' }
+
+1;
index 614ec36..cd7dca2 100644 (file)
@@ -3,67 +3,8 @@ package DX::Action::SetBoundValue;
 use DX::Update::SetValue;
 use DX::Class;
 
-with 'DX::Role::Action';
+with 'DX::Role::BoundValueAction';
 
-has target_path => (is => 'ro', required => 1);
-
-has bound_to_path => (is => 'ro', required => 1);
-
-has rebind_path => (is => 'ro', required => 1);
-
-has new_value => (is => 'ro', required => 1);
-
-has inner_action => (is => 'ro', required => 1);
-
-sub dry_run {
-  my ($self, $hyp) = @_;
-  my ($outer_hyp, @inner_events) = $self->inner_action->dry_run(
-    $hyp->but(
-      action_applications => [ @{$hyp->action_applications}, $self ],
-    ),
-  );
-  my $new_bound_to = do {
-    my $targ = $outer_hyp->scope;
-    $targ = $targ->get_member_at($_) for @{$self->bound_to_path};
-    $targ;
-  };
-  my $new_ab = DX::ActionBuilder::BoundValue->new(
-    target_path => $self->target_path,
-    rebind_path => $self->rebind_path,
-    bound_to_path => $self->bound_to_path,
-    inner_action_builder => $new_bound_to->action_builder
-  );
-  my $value_with_ab = $new_ab->apply_to_value($self->new_value, $new_bound_to);
-  my ($scope, @events) = $outer_hyp->scope->apply_updates(
-                           DX::Update::SetValue->new(
-                             target_path => $self->target_path,
-                             new_value => $value_with_ab,
-                           )
-                         );
-  my $new_bound = do {
-    my $targ = $scope;
-    $targ = $targ->get_member_at($_) for @{$self->rebind_path};
-    $targ;
-  };
-  my @actions = @{$outer_hyp->actions};
-  foreach my $idx (0.. $#actions) {
-    my $act = $actions[$idx];
-    if (
-      $act->isa('DX::Action::BindValue')
-        and join("\0", @{$act->target_path})
-              eq join("\0", @{$self->rebind_path})
-    ) {
-      my $bind = splice @actions, $idx, 1;
-      push @actions, $bind->but(new_value => $new_bound);
-      last;
-    }
-  }
-  return (
-    $outer_hyp->but(scope => $scope, actions => \@actions),
-    @inner_events, @events
-  );
-}
-
-sub run { die }
+sub update_class { 'DX::Update::SetValue' }
 
 1;
index 9138dbe..35e4232 100644 (file)
@@ -1,7 +1,7 @@
 package DX::ActionBuilder::BoundValue;
 
 use DX::Action::SetBoundValue;
-#use DX::Action::AddBoundValue;
+use DX::Action::AddBoundValue;
 use DX::Class;
 
 with 'DX::Role::ActionBuilder';
@@ -27,6 +27,21 @@ sub action_for_set_value {
   )
 }
 
+sub action_for_add_member {
+  my ($self, $at, $value) = @_;
+  $at = $at->string_value if ref($at);
+  my $inner_action = $self->inner_action_builder
+                          ->action_for_add_member($at, $value);
+  return undef unless $inner_action;
+  DX::Action::AddBoundValue->new(
+    target_path => [ @{$self->target_path}, $at ],
+    bound_to_path => [ @{$self->bound_to_path}, $at ],
+    rebind_path => $self->rebind_path,
+    new_value => $value,
+    inner_action => $inner_action
+  );
+}
+
 sub apply_to_value {
   my ($self, $value, $inner_value) = @_;
   my $new_value = $value->but_set_action_builder($self)
index 8edfffd..2d3b2ac 100644 (file)
@@ -122,6 +122,11 @@ sub _fmt_action_bindvalue {
   join ' ', BindValue => $path, $bound_path;
 }
 
+sub _fmt_action_addboundvalue {
+  my ($self, $action, $meta) = @_;
+  $self->_fmt_action_generic(AddBoundValue => $action, $meta);
+}
+
 sub _fmt_action_setboundvalue {
   my ($self, $action, $meta) = @_;
   $self->_fmt_action_generic(SetBoundValue => $action, $meta);
diff --git a/lib/DX/Role/BoundValueAction.pm b/lib/DX/Role/BoundValueAction.pm
new file mode 100644 (file)
index 0000000..37b317b
--- /dev/null
@@ -0,0 +1,70 @@
+package DX::Role::BoundValueAction;
+
+use DX::Role;
+
+with 'DX::Role::Action';
+
+has target_path => (is => 'ro', required => 1);
+
+has bound_to_path => (is => 'ro', required => 1);
+
+has rebind_path => (is => 'ro', required => 1);
+
+has new_value => (is => 'ro', required => 1);
+
+has inner_action => (is => 'ro', required => 1);
+
+requires 'update_class';
+
+sub dry_run {
+  my ($self, $hyp) = @_;
+  my ($outer_hyp, @inner_events) = $self->inner_action->dry_run(
+    $hyp->but(
+      action_applications => [ @{$hyp->action_applications}, $self ],
+    ),
+  );
+  my $new_bound_to = do {
+    my $targ = $outer_hyp->scope;
+    $targ = $targ->get_member_at($_) for @{$self->bound_to_path};
+    $targ;
+  };
+  my $new_ab = DX::ActionBuilder::BoundValue->new(
+    target_path => $self->target_path,
+    rebind_path => $self->rebind_path,
+    bound_to_path => $self->bound_to_path,
+    inner_action_builder => $new_bound_to->action_builder
+  );
+  my $value_with_ab = $new_ab->apply_to_value($self->new_value, $new_bound_to);
+  my ($scope, @events) = $outer_hyp->scope->apply_updates(
+                           $self->update_class->new(
+                             target_path => $self->target_path,
+                             new_value => $value_with_ab,
+                           )
+                         );
+  my $new_bound = do {
+    my $targ = $scope;
+    $targ = $targ->get_member_at($_) for @{$self->rebind_path};
+    $targ;
+  };
+  my @actions = @{$outer_hyp->actions};
+  foreach my $idx (0.. $#actions) {
+    my $act = $actions[$idx];
+    if (
+      $act->isa('DX::Action::BindValue')
+        and join("\0", @{$act->target_path})
+              eq join("\0", @{$self->rebind_path})
+    ) {
+      my $bind = splice @actions, $idx, 1;
+      push @actions, $bind->but(new_value => $new_bound);
+      last;
+    }
+  }
+  return (
+    $outer_hyp->but(scope => $scope, actions => \@actions),
+    @inner_events, @events
+  );
+}
+
+sub run { die }
+
+1;