From: Matt S Trout Date: Sat, 12 Mar 2016 11:13:37 +0000 (+0000) Subject: refactor action stuff to be recursive on dicts X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=3a630a54115b675facf8b0498b727b6a0de9d89b;p=scpubgit%2FDX.git refactor action stuff to be recursive on dicts --- diff --git a/lib/DX/Action/SetBoundValue.pm b/lib/DX/Action/SetBoundValue.pm index 5771eb7..614ec36 100644 --- a/lib/DX/Action/SetBoundValue.pm +++ b/lib/DX/Action/SetBoundValue.pm @@ -7,6 +7,8 @@ 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); @@ -20,10 +22,22 @@ sub dry_run { 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 => $self->new_value, + new_value => $value_with_ab, ) ); my $new_bound = do { diff --git a/lib/DX/ActionBuilder/BoundValue.pm b/lib/DX/ActionBuilder/BoundValue.pm index 8454992..9138dbe 100644 --- a/lib/DX/ActionBuilder/BoundValue.pm +++ b/lib/DX/ActionBuilder/BoundValue.pm @@ -20,11 +20,31 @@ sub action_for_set_value { return undef unless $inner_action; DX::Action::SetBoundValue->new( target_path => $self->target_path, + bound_to_path => $self->bound_to_path, rebind_path => $self->rebind_path, - new_value => $value->but_set_action_builder($self) - ->but_set_identity_path($self->bound_to_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) + ->but_set_identity_path($inner_value->identity_path); + return $new_value unless $new_value->isa('DX::Value::Dict'); + my %m = %{$new_value->members}; + return $new_value->but( + members => { + map { + my $this_inner = $inner_value->get_member_at($_); + ($_ => $self->but( + target_path => [ @{$self->target_path}, $_ ], + bound_to_path => [ @{$self->bound_to_path}, $_ ], + inner_action_builder => $this_inner->action_builder, + )->apply_to_value($m{$_}, $this_inner)) + } keys %m + }, + ); +} + 1; diff --git a/lib/DX/ActionBuilder/Normal.pm b/lib/DX/ActionBuilder/Normal.pm index c950758..45e5abd 100644 --- a/lib/DX/ActionBuilder/Normal.pm +++ b/lib/DX/ActionBuilder/Normal.pm @@ -12,22 +12,43 @@ sub action_for_set_value { my ($self, $value) = @_; DX::Action::SetValue->new( target_path => $self->target_path, - new_value => $value->but_set_action_builder($self) - ->but_set_identity_path($self->target_path) + new_value => $self->apply_to_value($value), ); } sub action_for_add_member { my ($self, $at, $value) = @_; - my @add_path = (@{$self->target_path}, ref($at) ? $at->string_value : $at); + my $ab = $self->specialize_for_member($at); DX::Action::AddValue->new( - target_path => \@add_path, - new_value => $value->but_set_action_builder( - $self->but(target_path => \@add_path) - )->but_set_identity_path(\@add_path) + target_path => $ab->target_path, + new_value => $ab->apply_to_value($value), ); } sub action_for_remove_member { die 'WHUT' } +sub apply_to_value { + my ($self, $value) = @_; + my $new_value = $value->but_set_action_builder($self) + ->but_set_identity_path($self->target_path); + return $new_value unless $new_value->isa('DX::Value::Dict'); + my %m = %{$new_value->members}; + return $new_value->but( + members => { + map +($_ => $self->specialize_for_member($_)->apply_to_value($m{$_})), + keys %m, + }, + ); +} + +sub specialize_for_member { + my ($self, $at) = @_; + $self->but( + target_path => [ + @{$self->target_path}, + (ref($at) ? $at->string_value : $at) + ], + ); +} + 1; diff --git a/lib/DX/ActionBuilder/UnsetValue.pm b/lib/DX/ActionBuilder/UnsetValue.pm index acc9306..95eecf5 100644 --- a/lib/DX/ActionBuilder/UnsetValue.pm +++ b/lib/DX/ActionBuilder/UnsetValue.pm @@ -21,17 +21,12 @@ sub action_for_set_value { ); return DX::Action::BindValue->new( target_path => $self->target_path, - new_value => $value->but_set_action_builder($ab), + new_value => $ab->apply_to_value($value, $value), ) } - my $ab = DX::ActionBuilder::Normal->new( + DX::ActionBuilder::Normal->new( target_path => $self->target_path, - ); - DX::Action::SetValue->new( - target_path => $self->target_path, - new_value => $value->but_set_action_builder($ab) - ->but_set_identity_path($self->target_path), - ); + )->action_for_set_value($value); } 1;