disturbingly, bound values appear to actually work
Matt S Trout [Sat, 5 Mar 2016 21:48:39 +0000 (21:48 +0000)]
fragments/bind [new file with mode: 0644]
lib/DX/Action/BindValue.pm [new file with mode: 0644]
lib/DX/Action/SetBoundValue.pm [new file with mode: 0644]
lib/DX/ActionBuilder/BoundValue.pm [new file with mode: 0644]
lib/DX/ActionBuilder/UnsetValue.pm
lib/DX/Deparse.pm
lib/DX/ShellSession.pm

diff --git a/fragments/bind b/fragments/bind
new file mode 100644 (file)
index 0000000..d3d9d24
--- /dev/null
@@ -0,0 +1,7 @@
+?
+is_dict ?X
+eq ?Y X
+qact
+eq Y {{ foo 1 }}
+qact
+.
diff --git a/lib/DX/Action/BindValue.pm b/lib/DX/Action/BindValue.pm
new file mode 100644 (file)
index 0000000..a355935
--- /dev/null
@@ -0,0 +1,20 @@
+package DX::Action::BindValue;
+
+use DX::Update::SetValue;
+use DX::ActionBuilder::BoundValue;
+use DX::Class;
+
+with 'DX::Role::SimpleAction';
+
+has new_value => (is => 'ro', required => 1);
+
+sub _build__updates {
+  my ($self) = @_;
+  DX::Update::SetValue->new(
+    target_path => $self->target_path,
+    new_value => $self->new_value,
+  );
+}
+
+1;
+
diff --git a/lib/DX/Action/SetBoundValue.pm b/lib/DX/Action/SetBoundValue.pm
new file mode 100644 (file)
index 0000000..dbc0d75
--- /dev/null
@@ -0,0 +1,51 @@
+package DX::Action::SetBoundValue;
+
+use DX::Update::SetValue;
+use DX::Class;
+
+with 'DX::Role::Action';
+
+has target_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);
+  my ($scope, @events) = $outer_hyp->scope->apply_updates(
+                           DX::Update::SetValue->new(
+                             target_path => $self->target_path,
+                             new_value => $self->new_value,
+                           )
+                         );
+  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;
diff --git a/lib/DX/ActionBuilder/BoundValue.pm b/lib/DX/ActionBuilder/BoundValue.pm
new file mode 100644 (file)
index 0000000..8454992
--- /dev/null
@@ -0,0 +1,30 @@
+package DX::ActionBuilder::BoundValue;
+
+use DX::Action::SetBoundValue;
+#use DX::Action::AddBoundValue;
+use DX::Class;
+
+with 'DX::Role::ActionBuilder';
+
+has target_path => (is => 'ro', required => 1);
+
+has rebind_path => (is => 'ro', required => 1);
+
+has bound_to_path => (is => 'ro', required => 1);
+
+has inner_action_builder => (is => 'ro', required => 1);
+
+sub action_for_set_value {
+  my ($self, $value) = @_;
+  my $inner_action = $self->inner_action_builder->action_for_set_value($value);
+  return undef unless $inner_action;
+  DX::Action::SetBoundValue->new(
+    target_path => $self->target_path,
+    rebind_path => $self->rebind_path,
+    new_value => $value->but_set_action_builder($self)
+                       ->but_set_identity_path($self->bound_to_path),
+    inner_action => $inner_action,
+  )
+}
+
+1;
index c00a7fb..acc9306 100644 (file)
@@ -2,6 +2,8 @@ package DX::ActionBuilder::UnsetValue;
 
 use DX::Action::SetValue;
 use DX::ActionBuilder::Normal;
+use DX::Action::BindValue;
+use DX::ActionBuilder::BoundValue;
 use DX::Class;
 
 with 'DX::Role::ActionBuilder';
@@ -10,8 +12,17 @@ has target_path => (is => 'ro', required => 1);
 
 sub action_for_set_value {
   my ($self, $value) = @_;
-  if (0) { # value_path / identity_path test
-    # bind value
+  if (my $p = $value->identity_path) {
+    my $ab = DX::ActionBuilder::BoundValue->new(
+      target_path => $self->target_path,
+      rebind_path => $self->target_path,
+      bound_to_path => $p,
+      inner_action_builder => $value->action_builder,
+    );
+    return DX::Action::BindValue->new(
+      target_path => $self->target_path,
+      new_value => $value->but_set_action_builder($ab),
+    )
   }
   my $ab = DX::ActionBuilder::Normal->new(
     target_path => $self->target_path,
index ff590f9..1096792 100644 (file)
@@ -110,6 +110,11 @@ sub _fmt_action_addvalue {
   $self->_fmt_action_generic(AddValue => $action, $meta);
 }
 
+sub _fmt_action_bindvalue {
+  my ($self, $action, $meta) = @_;
+  $self->_fmt_action_generic(BindValue => $action, $meta);
+}
+
 sub _fmt_action_generic {
   my ($self, $name, $action, $meta) = @_;
   my $path = join '.', map $self->_fmt($_, $meta), @{$action->target_path};
index adced53..d90117a 100644 (file)
@@ -47,6 +47,12 @@ has tcl => (is => 'lazy', builder => sub {
     push our @Result, [ output => $rps ];
     return;
   });
+  $tcl->CreateCommand(qact => sub {
+    my $act = $self->shell_state->current_query_state->search_state
+                   ->current_hypothesis->actions;
+    push our @Result, map [ output => $_ ], @$act;
+    return;
+  });
   foreach my $pred (
     keys %{$self->shell_state->template_query_state->predicates}
   ) {