provide and preserve aperture information
[scpubgit/DX.git] / lib / DX / Predicate / MemberAt.pm
CommitLineData
9d759b64 1package DX::Predicate::MemberAt;
2
7f385fb2 3use DX::Utils qw(:builders :dep_types);
dcf2adc7 4use DX::ActionBuilder::ProxySetToAdd;
c35c4f36 5use DX::ActionBuilder::Null;
9d759b64 6use DX::Class;
7
8with 'DX::Role::Predicate';
9
7f385fb2 10# member_at Dict Key Value
11#
12# Dict must be set to a dict (later maybe also an array and Key -> Index)
13#
14# Key bound ->
15#
16# Key exists ->
17#
18# Value bound ->
19#
20# Dict.Key = Value ->
21#
22# Trivial resolution
23#
24# Dict.Key != Value ->
25#
26# Failure
27#
28# Value unbound ->
29#
30# Set value to Dict.Key
31#
32# Key does not exist ->
33#
34# Dict allows add ->
35#
36# Value bound ->
37#
38# Failure on (exists Dict.Key, Value)
39#
40# Value unbound ->
41#
42# Set value to ProxySetToAdd value
43#
44# Dict disallows add ->
45#
46# Failure on (exists Dict.Key)
47#
48# Key unbound ->
49#
50# Value must also be unbound, because seriously?
51#
52# Set [Key, Value] to each pair in turn
53
54sub _resolution_space_for {
55 my ($self, $dict, $key, $value) = @_;
56
57 die "Fucked" unless $dict->does('DX::Role::StructuredValue');
58
59 if ($key->is_set) {
60
61 if (my $cur_val = $dict->get_member_at($key)) {
62
63 my $deps = [
64 [ CONTENTS_OF ,=> $dict, $key->string_value ],
65 [ CONTENTS_OF ,=> $value ],
66 ];
67
68 if ($value->is_set) {
69
70 my @members = (
71 $cur_val->equals($value)
72 # Trivial resolution, D.K = V
73 ? res(
74 actions => [],
75 veracity_depends_on => $deps,
76 )
77 # Failure
78 : ()
79 );
80
81 return rspace(
6aa36401 82 aperture => [],
7f385fb2 83 geometry_depends_on => $deps,
84 members => \@members
85 );
86
87 }
88
89 return rspace(
90 geometry_depends_on => [
91 [ CONTENTS_OF ,=> $dict, $key->string_value ],
92 [ TYPE_OF ,=> $value ],
93 ],
6aa36401 94 aperture => $value->aperture_for_set_value,
7f385fb2 95 members => [
96 res(
97 actions => [ $value->action_for_set_value($cur_val) ],
98 veracity_depends_on => $deps,
99 ),
100 ]
101 );
102
103 }
104
105 if ($dict->can_add_member) {
106
107 my $deps = [
108 [ EXISTENCE_OF ,=> $dict, $key->string_value ],
109 [ TYPE_OF ,=> $value ],
110 ];
111
112 if ($value->is_set) {
113
114 # If we get here, it means (currently) that we entered recheck
115 # due to the deletion of the key from the dict and should fail
116 # (or there's a bug in the compiler but let's hope not)
117 return rspace(
118 geometry_depends_on => $deps,
119 members => [],
120 );
121 }
122
123 my @path = (@{$dict->value_path}, $key->string_value);
124 my $ab = DX::ActionBuilder::ProxySetToAdd->new(
125 target_path => \@path,
126 proxy_to => $dict->action_builder,
127 );
128
129 return rspace(
130 geometry_depends_on => $deps,
6aa36401 131 aperture => $value->aperture_for_set_value,
7f385fb2 132 members => [
133 res(
134 actions => [
135 $value->action_for_set_value(
136 $value->but(action_builder => $ab),
137 ),
138 ],
139 # Veracity only depends on EXISTENCE_OF at this stage - if the
140 # $value is later set, recheck will lead us down a different path
141 # that will update those dependencies to include CONTENTS_OF
142 veracity_depends_on => $deps,
143 ),
144 ],
145 );
146
147 }
148
149 # Dict doesn't allow adding keys and key doesn't exist, so
150 # the contents of the value is completely irrelevant to the failure
151 return rspace(
152 geometry_depends_on => [
153 [ EXISTENCE_OF ,=> $dict, $key->string_value ],
154 ],
6aa36401 155 aperture => [],
7f385fb2 156 members => [],
157 );
158
159 }
160
161 die "Fucked" if $value->is_set; # +D -K +V ? seriously ?
162
163 # Laaater we may need to look at autovivifying an additional key/index
164 # ala ProxySetToAdd but I'm not 100% sure how that will make sense and
165 # premature generalisation is the root of all eval.
166
167 my @cand = map [
168 [ $_ ],
169 [ $dict->get_member_at($_) ],
170 ], map string($_), $dict->index_list;
171
172 return rspace(
173 geometry_depends_on => [
174 [ INDICES_OF ,=> $dict ],
175 [ TYPE_OF ,=> $key ],
176 [ TYPE_OF ,=> $value ],
177 ],
6aa36401 178 aperture => [ map @{$_->aperture_for_set_value}, $key, $value ],
7f385fb2 179 members => [
180 rstrat(
181 action_prototypes => [
182 [ $key => 'set_value' ],
183 [ $value => 'set_value' ],
184 ],
185 veracity_depends_on_builder => sub {
1f3fa757 186 my ($this_key, $this_val) = map @$_, @_;
7f385fb2 187 return [
188 [ CONTENTS_OF ,=> $dict, $this_key->string_value ],
189 [ CONTENTS_OF ,=> $key ],
190 [ CONTENTS_OF ,=> $value ],
191 ];
192 },
193 implementation_candidates => \@cand,
194 ),
195 ],
196 );
197}
198
9d759b64 1991;