pervasive type constraints
[scpubgit/DX.git] / lib / DX / Role / BoundValueAction.pm
CommitLineData
5b066a1c 1package DX::Role::BoundValueAction;
2
3use DX::Role;
4
5with 'DX::Role::Action';
6
2548ce61 7has target_path => (is => 'ro', required => 1, isa => ValuePath);
5b066a1c 8
2548ce61 9has bound_to_path => (is => 'ro', required => 1, isa => ValuePath);
5b066a1c 10
2548ce61 11has rebind_path => (is => 'ro', required => 1, isa => ValuePath);
5b066a1c 12
2548ce61 13has new_value => (is => 'ro', required => 1, isa => Value);
5b066a1c 14
2548ce61 15has inner_action => (is => 'ro', required => 1, isa => Action);
5b066a1c 16
17requires 'update_class';
18
c25fbf05 19sub for_deparse {
20 my ($self) = @_;
21 [ statement => [
22 [ symbol => (split('::',ref($self)))[-1] ],
23 [ value_path => $self->target_path ],
24 $self->new_value,
25 ] ];
26}
27
5b066a1c 28sub dry_run {
29 my ($self, $hyp) = @_;
30 my ($outer_hyp, @inner_events) = $self->inner_action->dry_run(
31 $hyp->but(
32 action_applications => [ @{$hyp->action_applications}, $self ],
33 ),
34 );
35 my $new_bound_to = do {
36 my $targ = $outer_hyp->scope;
37 $targ = $targ->get_member_at($_) for @{$self->bound_to_path};
38 $targ;
39 };
40 my $new_ab = DX::ActionBuilder::BoundValue->new(
41 target_path => $self->target_path,
42 rebind_path => $self->rebind_path,
43 bound_to_path => $self->bound_to_path,
44 inner_action_builder => $new_bound_to->action_builder
45 );
46 my $value_with_ab = $new_ab->apply_to_value($self->new_value, $new_bound_to);
47 my ($scope, @events) = $outer_hyp->scope->apply_updates(
48 $self->update_class->new(
49 target_path => $self->target_path,
50 new_value => $value_with_ab,
51 )
52 );
53 my $new_bound = do {
54 my $targ = $scope;
55 $targ = $targ->get_member_at($_) for @{$self->rebind_path};
56 $targ;
57 };
58 my @actions = @{$outer_hyp->actions};
59 foreach my $idx (0.. $#actions) {
60 my $act = $actions[$idx];
61 if (
62 $act->isa('DX::Action::BindValue')
63 and join("\0", @{$act->target_path})
64 eq join("\0", @{$self->rebind_path})
65 ) {
66 my $bind = splice @actions, $idx, 1;
67 push @actions, $bind->but(new_value => $new_bound);
68 last;
69 }
70 }
71 return (
72 $outer_hyp->but(scope => $scope, actions => \@actions),
73 @inner_events, @events
74 );
75}
76
77sub run { die }
78
791;