inspector_query.bend
bendvy-ecs-core@0.1.0.4 · 271 lines · 65 definitions
1import Base
2import entity_key.bend as Key
3import inspector.bend as I
4import inspector_query_projection.bend as Q
5import world.bend as W
6import component.bend as C
7import column.bend as Col
8import capabilities.bend as Cap
9
10
11
12
13
14
15
16type LookupError is Data:
17 MissingEntity{entityId:Key.Key}
18 QueryMismatch{entityId:Key.Key}
19
20
21type SingleError is Data:
22 NoEntities{}
23 MultipleEntities{count:Nat}
24
25
26
27type ReadQuery<-H:Type,-S:Data,-V:Data> is Type:
28 ReadQuery{rows:Cap.ValueRead<H,List<&2,Q.Row<S,V>>>,lookup:I.Lookup<H,S,V>,selection:Q.Selection}
29
30def rows_field(~H:Type,~S:Data,~V:Data,cap:ReadQuery<H,S,V>) -> Cap.ValueRead<H,List<&2,Q.Row<S,V>>>:
31 match cap:
32 case ReadQuery{rows,_,_}:rows
33def lookup_field(~H:Type,~S:Data,~V:Data,cap:ReadQuery<H,S,V>) -> I.Lookup<H,S,V>:
34 match cap:
35 case ReadQuery{_,lookup,_}:lookup
36def selection_field(~H:Type,~S:Data,~V:Data,cap:ReadQuery<H,S,V>) -> Q.Selection:
37 match cap:
38 case ReadQuery{_,_,selection}:selection
39
40
41def each(~H:Type,~S:Data,~V:Data,~cap:ReadQuery<H,S,V>,owner:H) -> H & List<&2,Q.Row<S,V>>:
42 Cap.value_read(~H,~List<&2,Q.Row<S,V>>,~rows_field(~H,~S,~V,cap),owner)
43
44def selected(~S:Data,~V:Data,accepted:Bool,+target:W.Handle<S>,value:I.Value<V>) -> Result<&2,&2,LookupError,Q.Row<S,V>>:
45 match accepted target:
46 case True{} target:Done{Q.Row{target,value}}
47 case False{} W.Handle{_,id}:Fail{QueryMismatch{id}}
48def resolved(~S:Data,~V:Data,selection:Q.Selection,+target:W.Handle<S>,value:I.Value<V>) -> Result<&2,&2,LookupError,Q.Row<S,V>>:
49 match target value:
50 case W.Handle{_,id} I.Value{C.MissingEntity{},_,_}:Fail{MissingEntity{id}}
51 case target +value:selected(~S,~V,Q.accepts(~V,selection,value),target,value)
52def got(~H:Type,~S:Data,~V:Data,selection:Q.Selection,target:W.Handle<S>,result:H & I.Value<V>) -> H & Result<&2,&2,LookupError,Q.Row<S,V>>:
53 (owner,value)=result
54 (owner,resolved(~S,~V,selection,target,value))
55
56
57
58def get(~H:Type,~S:Data,~V:Data,~cap:ReadQuery<H,S,V>,owner:H,+target:W.Handle<S>) -> H & Result<&2,&2,LookupError,Q.Row<S,V>>:
59 got(~H,~S,~V,selection_field(~H,~S,~V,cap),target,I.lookup(~H,~S,~V,~lookup_field(~H,~S,~V,cap),owner,target))
60
61def single_rows(~S:Data,~V:Data,rows:List<&2,Q.Row<S,V>>) -> Result<&2,&2,SingleError,Q.Row<S,V>>:
62 match rows:
63 case []:Fail{NoEntities{}}
64 case row <> []:Done{row}
65 case _ <> _ <> rest:Fail{MultipleEntities{Nat.add(2n,List.length(&2,Q.Row<S,V>,rest))}}
66def single_observed(~H:Type,~S:Data,~V:Data,result:H & List<&2,Q.Row<S,V>>) -> H & Result<&2,&2,SingleError,Q.Row<S,V>>:
67 (owner,rows)=result
68 (owner,single_rows(~S,~V,rows))
69
70
71def single(~H:Type,~S:Data,~V:Data,~cap:ReadQuery<H,S,V>,owner:H) -> H & Result<&2,&2,SingleError,Q.Row<S,V>>:
72 single_observed(~H,~S,~V,each(~H,~S,~V,~cap,owner))
73def optional_rows(~S:Data,~V:Data,rows:List<&2,Q.Row<S,V>>) -> Result<&2,&2,SingleError,Maybe<&2,Q.Row<S,V>>>:
74 match rows:
75 case []:Done{None{}}
76 case row <> []:Done{Some{row}}
77 case _ <> _ <> rest:Fail{MultipleEntities{Nat.add(2n,List.length(&2,Q.Row<S,V>,rest))}}
78def optional_observed(~H:Type,~S:Data,~V:Data,result:H & List<&2,Q.Row<S,V>>) -> H & Result<&2,&2,SingleError,Maybe<&2,Q.Row<S,V>>>:
79 (owner,rows)=result
80 (owner,optional_rows(~S,~V,rows))
81
82
83def single_optional(~H:Type,~S:Data,~V:Data,~cap:ReadQuery<H,S,V>,owner:H) -> H & Result<&2,&2,SingleError,Maybe<&2,Q.Row<S,V>>>:
84 optional_observed(~H,~S,~V,each(~H,~S,~V,~cap,owner))
85
86
87
88
89
90def grant(~S:Data,~Store:Type,~R:Type,~E:Data,~Rest:Type,~Payload:Type,~V:Data,~Token:Data,~take:Store -> Rest & Col.Column<S,Payload>,~put:Rest -> Col.Column<S,Payload> -> Store,~project:Payload -> Payload & V,~family:C.Family<S,Store,Rest,Payload,V,Token,take,put,project>,~mode:Q.Selection) -> ReadQuery<I.Frame<S,Store,R,E>,S,V>:
91 ReadQuery{Q.read_query(~S,~Store,~R,~E,~Rest,~Payload,~V,~Token,~take,~put,~project,~family,~mode),I.read_family(~S,~Store,~R,~E,~Rest,~Payload,~V,~Token,~take,~put,~project,~family),mode}
92
93
94
95
96type ProjectedRow<S:Data,V:Data> is Data:
97 ProjectedRow{entity:W.Handle<S>,data:V}
98
99
100
101type WorldRead<-H:Type,-S:Data> is Type:
102 WorldRead{handles:H -> H & List<&2,W.Handle<S>>,valid:H -> W.Handle<S> -> H & Bool}
103
104
105
106type ComposedReadQuery<-H:Type,-S:Data,-V:Data> is Type:
107 ComposedReadQuery{each_composed:H -> H & List<&2,ProjectedRow<S,V>>,get_composed:H -> W.Handle<S> -> H & Result<&2,&2,LookupError,ProjectedRow<S,V>>}
108def composed_handles_field(~H:Type,~S:Data,value:WorldRead<H,S>) -> H -> H & List<&2,W.Handle<S>>:
109 match value:
110 case WorldRead{handles,_}:handles
111def composed_valid_field(~H:Type,~S:Data,value:WorldRead<H,S>) -> H -> W.Handle<S> -> H & Bool:
112 match value:
113 case WorldRead{_,valid}:valid
114def composed_each_field(~H:Type,~S:Data,~V:Data,value:ComposedReadQuery<H,S,V>) -> H -> H & List<&2,ProjectedRow<S,V>>:
115 match value:
116 case ComposedReadQuery{each_composed,_}:each_composed
117def composed_get_field(~H:Type,~S:Data,~V:Data,value:ComposedReadQuery<H,S,V>) -> H -> W.Handle<S> -> H & Result<&2,&2,LookupError,ProjectedRow<S,V>>:
118 match value:
119 case ComposedReadQuery{_,get_composed}:get_composed
120
121
122def each_composed(~H:Type,~S:Data,~V:Data,~cap:ComposedReadQuery<H,S,V>,owner:H) -> H & List<&2,ProjectedRow<S,V>>:
123 composed_each_field(~H,~S,~V,cap)(owner)
124
125
126
127def get_composed(~H:Type,~S:Data,~V:Data,~cap:ComposedReadQuery<H,S,V>,owner:H,target:W.Handle<S>) -> H & Result<&2,&2,LookupError,ProjectedRow<S,V>>:
128 composed_get_field(~H,~S,~V,cap)(owner,target)
129def composed_single_rows(~S:Data,~V:Data,rows:List<&2,ProjectedRow<S,V>>) -> Result<&2,&2,SingleError,ProjectedRow<S,V>>:
130 match rows:
131 case []:Fail{NoEntities{}}
132 case row <> []:Done{row}
133 case _ <> _ <> rest:Fail{MultipleEntities{Nat.add(2n,List.length(&2,ProjectedRow<S,V>,rest))}}
134def composed_single_observed(~H:Type,~S:Data,~V:Data,observed:H & List<&2,ProjectedRow<S,V>>) -> H & Result<&2,&2,SingleError,ProjectedRow<S,V>>:
135 (owner,rows)=observed
136 (owner,composed_single_rows(~S,~V,rows))
137
138
139def single_composed(~H:Type,~S:Data,~V:Data,~cap:ComposedReadQuery<H,S,V>,owner:H) -> H & Result<&2,&2,SingleError,ProjectedRow<S,V>>:
140 composed_single_observed(~H,~S,~V,each_composed(~H,~S,~V,~cap,owner))
141def composed_optional_rows(~S:Data,~V:Data,rows:List<&2,ProjectedRow<S,V>>) -> Result<&2,&2,SingleError,Maybe<&2,ProjectedRow<S,V>>>:
142 match rows:
143 case []:Done{None{}}
144 case row <> []:Done{Some{row}}
145 case _ <> _ <> rest:Fail{MultipleEntities{Nat.add(2n,List.length(&2,ProjectedRow<S,V>,rest))}}
146def composed_optional_observed(~H:Type,~S:Data,~V:Data,observed:H & List<&2,ProjectedRow<S,V>>) -> H & Result<&2,&2,SingleError,Maybe<&2,ProjectedRow<S,V>>>:
147 (owner,rows)=observed
148 (owner,composed_optional_rows(~S,~V,rows))
149
150
151def single_optional_composed(~H:Type,~S:Data,~V:Data,~cap:ComposedReadQuery<H,S,V>,owner:H) -> H & Result<&2,&2,SingleError,Maybe<&2,ProjectedRow<S,V>>>:
152 composed_optional_observed(~H,~S,~V,each_composed(~H,~S,~V,~cap,owner))
153
154
155def composed_lookup_projected(~H:Type,~S:Data,~V:Data,target:W.Handle<S>,observed:H & V) -> H & Result<&2,&2,LookupError,ProjectedRow<S,V>>:
156 (owner,value)=observed
157 (owner,Done{ProjectedRow{target,value}})
158def composed_mismatched(~H:Type,~S:Data,~V:Data,target:W.Handle<S>,owner:H) -> H & Result<&2,&2,LookupError,ProjectedRow<S,V>>:
159 match target:
160 case W.Handle{_,id}:(owner,Fail{QueryMismatch{id}})
161def composed_missing(~H:Type,~S:Data,~V:Data,target:W.Handle<S>,owner:H) -> H & Result<&2,&2,LookupError,ProjectedRow<S,V>>:
162 match target:
163 case W.Handle{_,id}:(owner,Fail{MissingEntity{id}})
164def composed_lookup_matched(~H:Type,~S:Data,~V:Data,project:H -> W.Handle<S> -> H & V,+target:W.Handle<S>,observed:H & Bool) -> H & Result<&2,&2,LookupError,ProjectedRow<S,V>>:
165 match observed:
166 case (owner,False{}):composed_mismatched(~H,~S,~V,target,owner)
167 case (owner,True{}):composed_lookup_projected(~H,~S,~V,target,project(owner,target))
168def composed_lookup_valid(~H:Type,~S:Data,~V:Data,matches:H -> W.Handle<S> -> H & Bool,project:H -> W.Handle<S> -> H & V,+target:W.Handle<S>,observed:H & Bool) -> H & Result<&2,&2,LookupError,ProjectedRow<S,V>>:
169 match observed:
170 case (owner,False{}):composed_missing(~H,~S,~V,target,owner)
171 case (owner,True{}):composed_lookup_matched(~H,~S,~V,project,target,matches(owner,target))
172def composed_lookup_target(~H:Type,~S:Data,~V:Data,~selection:Q.DeclaredSelection<H,S,V>,~world:WorldRead<H,S>,owner:H,+target:W.Handle<S>) -> H & Result<&2,&2,LookupError,ProjectedRow<S,V>>:
173 composed_lookup_valid(~H,~S,~V,Q.matches_field(~H,~S,~V,selection),Q.project_field(~H,~S,~V,selection),target,composed_valid_field(~H,~S,world)(owner,target))
174def composed_lookup(~H:Type,~S:Data,~V:Data,~selection:Q.DeclaredSelection<H,S,V>,~world:WorldRead<H,S>,owner:H,target:W.Handle<S>) -> H & Result<&2,&2,LookupError,ProjectedRow<S,V>>:
175 composed_lookup_target(~H,~S,~V,~selection,~world,owner,target)
176
177
178
179
180type ScanResult<-H:Type,-S:Data,-V:Data> is Type:
181 ScanResult{owner:H,rows:List<&2,ProjectedRow<S,V>>}
182 ScanResultLink{next:ScanResult<H,S,V>}
183def composed_unwrap_scan(~H:Type,~S:Data,~V:Data,result:ScanResult<H,S,V>) -> H & List<&2,ProjectedRow<S,V>>:
184 match result:
185 case ScanResult{owner,rows}:(owner,rows)
186 case ScanResultLink{next}:composed_unwrap_scan(~H,~S,~V,next)
187
188def composed_fold_projected(~H:Type,~S:Data,~V:Data,target:W.Handle<S>,rows:List<&2,ProjectedRow<S,V>>,observed:H & V) -> H & List<&2,ProjectedRow<S,V>>:
189 (owner,value)=observed
190 (owner,ProjectedRow{target,value} <> rows)
191def composed_fold_matched(~H:Type,~S:Data,~V:Data,~project:H -> W.Handle<S> -> H & V,+target:W.Handle<S>,rows:List<&2,ProjectedRow<S,V>>,observed:H & Bool) -> H & List<&2,ProjectedRow<S,V>>:
192 match observed:
193 case (owner,False{}):(owner,rows)
194 case (owner,True{}):composed_fold_projected(~H,~S,~V,target,rows,project(owner,target))
195def composed_fold_step(~H:Type,~S:Data,~V:Data,~selection:Q.DeclaredSelection<H,S,V>,acc:H & List<&2,ProjectedRow<S,V>>,+target:W.Handle<S>) -> H & List<&2,ProjectedRow<S,V>>:
196 (owner,rows)=acc
197 composed_fold_matched(~H,~S,~V,~Q.project_field(~H,~S,~V,selection),target,rows,Q.matches_field(~H,~S,~V,selection)(owner,target))
198def composed_fold_done(~H:Type,~S:Data,~V:Data,observed:H & List<&2,ProjectedRow<S,V>>) -> ScanResult<H,S,V>:
199 (owner,rows)=observed
200 ScanResult{owner,List.reverse(&2,ProjectedRow<S,V>,rows)}
201
202
203
204
205def composed_scan(~H:Type,~S:Data,~V:Data,~selection:Q.DeclaredSelection<H,S,V>,targets:List<&2,W.Handle<S>>,owner:H,rows:List<&2,ProjectedRow<S,V>>) -> ScanResult<H,S,V>:
206 composed_fold_done(~H,~S,~V,List.foldl(~&2,~W.Handle<S>,~(H & List<&2,ProjectedRow<S,V>>),~(acc => target => composed_fold_step(~H,~S,~V,~selection,acc,target)),targets,(owner,rows)))
207def composed_scanned(~H:Type,~S:Data,~V:Data,~selection:Q.DeclaredSelection<H,S,V>,observed:H & List<&2,W.Handle<S>>) -> H & List<&2,ProjectedRow<S,V>>:
208 (owner,targets)=observed
209 composed_unwrap_scan(~H,~S,~V,composed_scan(~H,~S,~V,~selection,targets,owner,[]))
210def composed_enumerate(~H:Type,~S:Data,~V:Data,~selection:Q.DeclaredSelection<H,S,V>,~world:WorldRead<H,S>,owner:H) -> H & List<&2,ProjectedRow<S,V>>:
211 composed_scanned(~H,~S,~V,~selection,composed_handles_field(~H,~S,world)(owner))
212
213
214
215
216def grant_composed(~H:Type,~S:Data,~V:Data,~selection:Q.DeclaredSelection<H,S,V>,~world:WorldRead<H,S>) -> ComposedReadQuery<H,S,V>:
217 ComposedReadQuery{owner => composed_enumerate(~H,~S,~V,~selection,~world,owner),owner => target => composed_lookup(~H,~S,~V,~selection,~world,owner,target)}
218
219
220
221
222
223
224def composed_runtime_match_right(~H:Type,~S:Data,~A:Data,~Arg:Data,~relation_matches:Arg -> H -> W.Handle<S> -> H & Bool,+target:W.Handle<S>,argument:Arg,observed:H & Bool) -> H & Bool:
225 match observed:
226 case (owner,False{}):(owner,False{})
227 case (owner,True{}):relation_matches(argument,owner,target)
228def composed_runtime_matches_target(~H:Type,~S:Data,~A:Data,~Arg:Data,~component:Q.DeclaredSelection<H,S,A>,~relation_matches:Arg -> H -> W.Handle<S> -> H & Bool,+target:W.Handle<S>,argument:Arg,owner:H) -> H & Bool:
229 composed_runtime_match_right(~H,~S,~A,~Arg,~relation_matches,target,argument,Q.matches_field(~H,~S,~A,component)(owner,target))
230def composed_runtime_projected_right(~H:Type,~A:Data,~B:Data,left:A,observed:H & B) -> H & Q.Product<A,B>:
231 (owner,right)=observed
232 (owner,Q.Product{left,right})
233def composed_runtime_projected_left(~H:Type,~S:Data,~A:Data,~B:Data,~Arg:Data,~relation_project:Arg -> H -> W.Handle<S> -> H & B,+target:W.Handle<S>,argument:Arg,observed:H & A) -> H & Q.Product<A,B>:
234 (owner,left)=observed
235 composed_runtime_projected_right(~H,~A,~B,left,relation_project(argument,owner,target))
236def composed_runtime_project(~H:Type,~S:Data,~A:Data,~B:Data,~Arg:Data,~component:Q.DeclaredSelection<H,S,A>,~relation_project:Arg -> H -> W.Handle<S> -> H & B,+target:W.Handle<S>,argument:Arg,owner:H) -> H & Q.Product<A,B>:
237 composed_runtime_projected_left(~H,~S,~A,~B,~Arg,~relation_project,target,argument,Q.project_field(~H,~S,~A,component)(owner,target))
238def composed_runtime_scan_projected(~H:Type,~S:Data,~A:Data,~B:Data,+target:W.Handle<S>,rows:List<&2,ProjectedRow<S,Q.Product<A,B>>>,continue:H -> List<&2,ProjectedRow<S,Q.Product<A,B>>> -> ScanResult<H,S,Q.Product<A,B>>,observed:H & Q.Product<A,B>) -> ScanResult<H,S,Q.Product<A,B>>:
239 (owner,value)=observed
240 continue(owner,ProjectedRow{target,value} <> rows)
241def composed_runtime_scan_matched(~H:Type,~S:Data,~A:Data,~B:Data,~Arg:Data,~component:Q.DeclaredSelection<H,S,A>,~relation_matches:Arg -> H -> W.Handle<S> -> H & Bool,~relation_project:Arg -> H -> W.Handle<S> -> H & B,+target:W.Handle<S>,rows:List<&2,ProjectedRow<S,Q.Product<A,B>>>,continue:H -> List<&2,ProjectedRow<S,Q.Product<A,B>>> -> ScanResult<H,S,Q.Product<A,B>>,argument:Arg,observed:H & Bool) -> ScanResult<H,S,Q.Product<A,B>>:
242 match observed:
243 case (owner,False{}):continue(owner,rows)
244 case (owner,True{}):composed_runtime_scan_projected(~H,~S,~A,~B,target,rows,continue,composed_runtime_project(~H,~S,~A,~B,~Arg,~component,~relation_project,target,argument,owner))
245def composed_runtime_scan(~H:Type,~S:Data,~A:Data,~B:Data,~Arg:Data,~component:Q.DeclaredSelection<H,S,A>,~relation_matches:Arg -> H -> W.Handle<S> -> H & Bool,~relation_project:Arg -> H -> W.Handle<S> -> H & B,targets:List<&2,W.Handle<S>>,+argument:Arg,owner:H,rows:List<&2,ProjectedRow<S,Q.Product<A,B>>>) -> ScanResult<H,S,Q.Product<A,B>>:
246 match targets:
247 case []:ScanResult{owner,List.reverse(&2,ProjectedRow<S,Q.Product<A,B>>,rows)}
248 case +target <> rest:composed_runtime_scan_matched(~H,~S,~A,~B,~Arg,~component,~relation_matches,~relation_project,target,rows,(owner => rows => composed_runtime_scan(~H,~S,~A,~B,~Arg,~component,~relation_matches,~relation_project,rest,argument,owner,rows)),argument,composed_runtime_matches_target(~H,~S,~A,~Arg,~component,~relation_matches,target,argument,owner))
249def composed_runtime_scanned(~H:Type,~S:Data,~A:Data,~B:Data,~Arg:Data,~component:Q.DeclaredSelection<H,S,A>,~relation_matches:Arg -> H -> W.Handle<S> -> H & Bool,~relation_project:Arg -> H -> W.Handle<S> -> H & B,observed:H & List<&2,W.Handle<S>>,+argument:Arg) -> H & List<&2,ProjectedRow<S,Q.Product<A,B>>>:
250 (owner,targets)=observed
251 composed_unwrap_scan(~H,~S,~Q.Product<A,B>,composed_runtime_scan(~H,~S,~A,~B,~Arg,~component,~relation_matches,~relation_project,targets,argument,owner,[]))
252def composed_runtime_enumerate(~H:Type,~S:Data,~A:Data,~B:Data,~Arg:Data,~component:Q.DeclaredSelection<H,S,A>,~relation_matches:Arg -> H -> W.Handle<S> -> H & Bool,~relation_project:Arg -> H -> W.Handle<S> -> H & B,~world:WorldRead<H,S>,argument:Arg,owner:H) -> H & List<&2,ProjectedRow<S,Q.Product<A,B>>>:
253 composed_runtime_scanned(~H,~S,~A,~B,~Arg,~component,~relation_matches,~relation_project,composed_handles_field(~H,~S,world)(owner),argument)
254def composed_runtime_lookup_selected(~H:Type,~S:Data,~A:Data,~B:Data,~Arg:Data,~component:Q.DeclaredSelection<H,S,A>,~relation_project:Arg -> H -> W.Handle<S> -> H & B,+target:W.Handle<S>,argument:Arg,observed:H & Bool) -> H & Result<&2,&2,LookupError,ProjectedRow<S,Q.Product<A,B>>>:
255 match observed:
256 case (owner,False{}):composed_mismatched(~H,~S,~Q.Product<A,B>,target,owner)
257 case (owner,True{}):composed_lookup_projected(~H,~S,~Q.Product<A,B>,target,composed_runtime_project(~H,~S,~A,~B,~Arg,~component,~relation_project,target,argument,owner))
258def composed_runtime_lookup_valid(~H:Type,~S:Data,~A:Data,~B:Data,~Arg:Data,~component:Q.DeclaredSelection<H,S,A>,~relation_matches:Arg -> H -> W.Handle<S> -> H & Bool,~relation_project:Arg -> H -> W.Handle<S> -> H & B,+target:W.Handle<S>,+argument:Arg,observed:H & Bool) -> H & Result<&2,&2,LookupError,ProjectedRow<S,Q.Product<A,B>>>:
259 match observed:
260 case (owner,False{}):composed_missing(~H,~S,~Q.Product<A,B>,target,owner)
261 case (owner,True{}):composed_runtime_lookup_selected(~H,~S,~A,~B,~Arg,~component,~relation_project,target,argument,composed_runtime_matches_target(~H,~S,~A,~Arg,~component,~relation_matches,target,argument,owner))
262def composed_runtime_lookup_target(~H:Type,~S:Data,~A:Data,~B:Data,~Arg:Data,~component:Q.DeclaredSelection<H,S,A>,~relation_matches:Arg -> H -> W.Handle<S> -> H & Bool,~relation_project:Arg -> H -> W.Handle<S> -> H & B,~world:WorldRead<H,S>,owner:H,+target:W.Handle<S>,argument:Arg) -> H & Result<&2,&2,LookupError,ProjectedRow<S,Q.Product<A,B>>>:
263 composed_runtime_lookup_valid(~H,~S,~A,~B,~Arg,~component,~relation_matches,~relation_project,target,argument,composed_valid_field(~H,~S,world)(owner,target))
264def composed_runtime_lookup(~H:Type,~S:Data,~A:Data,~B:Data,~Arg:Data,~component:Q.DeclaredSelection<H,S,A>,~relation_matches:Arg -> H -> W.Handle<S> -> H & Bool,~relation_project:Arg -> H -> W.Handle<S> -> H & B,~world:WorldRead<H,S>,owner:H,target:W.Handle<S>,argument:Arg) -> H & Result<&2,&2,LookupError,ProjectedRow<S,Q.Product<A,B>>>:
265 composed_runtime_lookup_target(~H,~S,~A,~B,~Arg,~component,~relation_matches,~relation_project,~world,owner,target,argument)
266
267
268
269
270def grant_composed_runtime(~H:Type,~S:Data,~A:Data,~B:Data,~Arg:Data,~component:Q.DeclaredSelection<H,S,A>,~world:WorldRead<H,S>,~relation_matches:Arg -> H -> W.Handle<S> -> H & Bool,~relation_project:Arg -> H -> W.Handle<S> -> H & B,+argument:Arg) -> ComposedReadQuery<H,S,Q.Product<A,B>>:
271 ComposedReadQuery{owner => composed_runtime_enumerate(~H,~S,~A,~B,~Arg,~component,~relation_matches,~relation_project,~world,argument,owner),owner => target => composed_runtime_lookup(~H,~S,~A,~B,~Arg,~component,~relation_matches,~relation_project,~world,owner,target,argument)}