lift some of the rspace handling into the Resolution* classes
[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(
82 geometry_depends_on => $deps,
83 members => \@members
84 );
85
86 }
87
88 return rspace(
89 geometry_depends_on => [
90 [ CONTENTS_OF ,=> $dict, $key->string_value ],
91 [ TYPE_OF ,=> $value ],
92 ],
93 members => [
94 res(
95 actions => [ $value->action_for_set_value($cur_val) ],
96 veracity_depends_on => $deps,
97 ),
98 ]
99 );
100
101 }
102
103 if ($dict->can_add_member) {
104
105 my $deps = [
106 [ EXISTENCE_OF ,=> $dict, $key->string_value ],
107 [ TYPE_OF ,=> $value ],
108 ];
109
110 if ($value->is_set) {
111
112 # If we get here, it means (currently) that we entered recheck
113 # due to the deletion of the key from the dict and should fail
114 # (or there's a bug in the compiler but let's hope not)
115 return rspace(
116 geometry_depends_on => $deps,
117 members => [],
118 );
119 }
120
121 my @path = (@{$dict->value_path}, $key->string_value);
122 my $ab = DX::ActionBuilder::ProxySetToAdd->new(
123 target_path => \@path,
124 proxy_to => $dict->action_builder,
125 );
126
127 return rspace(
128 geometry_depends_on => $deps,
129 members => [
130 res(
131 actions => [
132 $value->action_for_set_value(
133 $value->but(action_builder => $ab),
134 ),
135 ],
136 # Veracity only depends on EXISTENCE_OF at this stage - if the
137 # $value is later set, recheck will lead us down a different path
138 # that will update those dependencies to include CONTENTS_OF
139 veracity_depends_on => $deps,
140 ),
141 ],
142 );
143
144 }
145
146 # Dict doesn't allow adding keys and key doesn't exist, so
147 # the contents of the value is completely irrelevant to the failure
148 return rspace(
149 geometry_depends_on => [
150 [ EXISTENCE_OF ,=> $dict, $key->string_value ],
151 ],
152 members => [],
153 );
154
155 }
156
157 die "Fucked" if $value->is_set; # +D -K +V ? seriously ?
158
159 # Laaater we may need to look at autovivifying an additional key/index
160 # ala ProxySetToAdd but I'm not 100% sure how that will make sense and
161 # premature generalisation is the root of all eval.
162
163 my @cand = map [
164 [ $_ ],
165 [ $dict->get_member_at($_) ],
166 ], map string($_), $dict->index_list;
167
168 return rspace(
169 geometry_depends_on => [
170 [ INDICES_OF ,=> $dict ],
171 [ TYPE_OF ,=> $key ],
172 [ TYPE_OF ,=> $value ],
173 ],
174 members => [
175 rstrat(
176 action_prototypes => [
177 [ $key => 'set_value' ],
178 [ $value => 'set_value' ],
179 ],
180 veracity_depends_on_builder => sub {
1f3fa757 181 my ($this_key, $this_val) = map @$_, @_;
7f385fb2 182 return [
183 [ CONTENTS_OF ,=> $dict, $this_key->string_value ],
184 [ CONTENTS_OF ,=> $key ],
185 [ CONTENTS_OF ,=> $value ],
186 ];
187 },
188 implementation_candidates => \@cand,
189 ),
190 ],
191 );
192}
193
9d759b64 1941;