execution_composer_layout.bend
bendvy-ecs-core@0.1.0.3 · 300 lines · 60 definitions
1import Base
2import bendvy-ecs-core@0.1.0.3/execution_resource_policy.bend as Policy
3import bendvy-ecs-core@0.1.0.3/chunk_column.bend as Column
4import bendvy-ecs-core@0.1.0.3/owner_product.bend as Product
5import bendvy-ecs-core@0.1.0.3/lifecycle.bend as Lifecycle
6import bendvy-ecs-core@0.1.0.3/change_tick.bend as Tick
7import bendvy-ecs-core@0.1.0.3/schema_fragments.bend as Fragment
8
9type Viewed<-P:Type,-V:Data> is Type:
10 Viewed{owner:P,view:V}
11def read(~P:Type,~V:Data,value:Viewed<P,V>) -> Viewed<P,V> & V:
12 match value:
13 case Viewed{owner,+view}:(Viewed{owner,view},view)
14def initialized(-P:Type,-V:Data,result:P & V) -> Viewed<P,V>:
15 match result:
16 case (owner,view):Viewed{owner,view}
17
18type Layout is Type:
19 EmptyLayout{}
20 LayoutLeaf{P:Type,V:Data,refresh:P -> P & V,key:String,access:Policy.Policy}
21 ClassifiedLayoutLeaf{P:Type,V:Data,refresh:P -> P & V,key:String,persistence:Fragment.PersistenceKind,access:Policy.Policy}
22 LayoutPair{left:Layout,right:Layout}
23type Route is Data:
24 AtLeaf{}
25 InLeft{rest:Route}
26 InRight{rest:Route}
27type ColumnSlot<-S:Data,-P:Type,-key:String,-origin:Layout> is Type:
28 ColumnSlot{column:Column.Column<S,P>}
29type ResourceSlot<-S:Data,-P:Type,-key:String,-origin:Layout> is Type:
30 ResourceSlot{owner:P,stamp:Lifecycle.Stamp}
31def unknown_stamp() -> Lifecycle.Stamp:Lifecycle.Stamp{None{},None{}}
32def origin(layout:Layout,route:Route) -> Layout:
33 match layout route:
34 case LayoutLeaf{P,V,refresh,key,accessPolicy} AtLeaf{}:LayoutLeaf{P,V,refresh,key,accessPolicy}
35 case ClassifiedLayoutLeaf{P,V,refresh,key,kind,accessPolicy} AtLeaf{}:ClassifiedLayoutLeaf{P,V,refresh,key,kind,accessPolicy}
36 case LayoutPair{left,_} InLeft{rest}:origin(left,rest)
37 case LayoutPair{_,right} InRight{rest}:origin(right,rest)
38 case _ _:EmptyLayout{}
39
40def policy(layout:Layout,route:Route) -> Policy.Policy:
41 match layout route:
42 case LayoutLeaf{_,_,_,_,access} AtLeaf{}:access
43 case ClassifiedLayoutLeaf{_,_,_,_,_,access} AtLeaf{}:access
44 case LayoutPair{left,_} InLeft{rest}:policy(left,rest)
45 case LayoutPair{_,right} InRight{rest}:policy(right,rest)
46 case _ _:Policy.Ordinary{}
47def columns(~S:Data,layout:Layout) -> Type:
48 match layout:
49 case EmptyLayout{}:Unit
50 case LayoutLeaf{P,V,refresh,key,accessPolicy}:ColumnSlot<S,Viewed<P,V>,key,LayoutLeaf{P,V,refresh,key,accessPolicy}>
51 case ClassifiedLayoutLeaf{P,V,refresh,key,kind,accessPolicy}:ColumnSlot<S,Viewed<P,V>,key,ClassifiedLayoutLeaf{P,V,refresh,key,kind,accessPolicy}>
52 case LayoutPair{left,right}:Product.Owner<columns(~S,left),columns(~S,right)>
53def resources_generic(-S:Data,layout:Layout) -> Type:
54 match layout:
55 case EmptyLayout{}:Unit
56 case LayoutLeaf{P,V,refresh,key,accessPolicy}:ResourceSlot<S,Viewed<P,V>,key,LayoutLeaf{P,V,refresh,key,accessPolicy}>
57 case ClassifiedLayoutLeaf{P,V,refresh,key,kind,accessPolicy}:ResourceSlot<S,Viewed<P,V>,key,ClassifiedLayoutLeaf{P,V,refresh,key,kind,accessPolicy}>
58 case LayoutPair{left,right}:Product.Owner<resources_generic(S,left),resources_generic(S,right)>
59def resources(~S:Data,layout:Layout) -> Type:
60 resources_generic(S,layout)
61
62def payload(layout:Layout,route:Route) -> Type:
63 match layout route:
64 case LayoutLeaf{P,V,_,_,_} AtLeaf{}:P
65 case ClassifiedLayoutLeaf{P,V,_,_,_,_} AtLeaf{}:P
66 case LayoutPair{left,_} InLeft{rest}:payload(left,rest)
67 case LayoutPair{_,right} InRight{rest}:payload(right,rest)
68 case _ _:Unit
69def view(layout:Layout,route:Route) -> Data:
70 match layout route:
71 case LayoutLeaf{_,V,_,_,_} AtLeaf{}:V
72 case ClassifiedLayoutLeaf{_,V,_,_,_,_} AtLeaf{}:V
73 case LayoutPair{left,_} InLeft{rest}:view(left,rest)
74 case LayoutPair{_,right} InRight{rest}:view(right,rest)
75 case _ _:Unit
76def stored(layout:Layout,route:Route) -> Type:Viewed<payload(layout,route),view(layout,route)>
77def initialize(layout:Layout,route:Route,owner:payload(layout,route)) -> stored(layout,route):
78 match layout route owner:
79 case LayoutLeaf{P,V,refresh,_,_} AtLeaf{} owner:initialized(P,V,refresh(owner))
80 case ClassifiedLayoutLeaf{P,V,refresh,_,_,_} AtLeaf{} owner:initialized(P,V,refresh(owner))
81 case LayoutPair{left,_} InLeft{rest} owner:initialize(left,rest,owner)
82 case LayoutPair{_,right} InRight{rest} owner:initialize(right,rest,owner)
83 case EmptyLayout{} _ owner:Viewed{owner,Unit{}}
84 case LayoutLeaf{_,_,_,_,_} InLeft{_} owner:Viewed{owner,Unit{}}
85 case LayoutLeaf{_,_,_,_,_} InRight{_} owner:Viewed{owner,Unit{}}
86 case ClassifiedLayoutLeaf{_,_,_,_,_,_} InLeft{_} owner:Viewed{owner,Unit{}}
87 case ClassifiedLayoutLeaf{_,_,_,_,_,_} InRight{_} owner:Viewed{owner,Unit{}}
88 case LayoutPair{_,_} AtLeaf{} owner:Viewed{owner,Unit{}}
89def rewritten(-P:Type,-Stored:Type,-Out:Type,initialize:P -> Stored,result:P & Out) -> Stored & Out:
90 match result:
91 case (owner,out):(initialize(owner),out)
92def rewrite_view(-P:Type,-V:Data,-Out:Type,initialize:P -> Viewed<P,V>,transform:P -> P & Out,value:Viewed<P,V>) -> Viewed<P,V> & Out:
93 match value:
94 case Viewed{owner,_}:rewritten(P,Viewed<P,V>,Out,initialize,transform(owner))
95def rewrite(~layout:Layout,~route:Route,-Out:Type,transform:payload(layout,route) -> payload(layout,route) & Out,value:stored(layout,route)) -> stored(layout,route) & Out:
96 rewrite_view(payload(layout,route),view(layout,route),Out,initialize(layout,route),transform,value)
97def key(layout:Layout,route:Route) -> String:
98 match layout route:
99 case LayoutLeaf{_,V,_,key,_} AtLeaf{}:key
100 case ClassifiedLayoutLeaf{_,V,_,key,_,_} AtLeaf{}:key
101 case LayoutPair{left,_} InLeft{rest}:key(left,rest)
102 case LayoutPair{_,right} InRight{rest}:key(right,rest)
103 case _ _:""
104def valid(layout:Layout,route:Route) -> Bool:
105 match layout route:
106 case LayoutLeaf{_,V,_,_,_} AtLeaf{}:True{}
107 case ClassifiedLayoutLeaf{_,V,_,_,_,_} AtLeaf{}:True{}
108 case LayoutPair{left,_} InLeft{rest}:valid(left,rest)
109 case LayoutPair{_,right} InRight{rest}:valid(right,rest)
110 case _ _:False{}
111def empty_column(-S:Data,-P:Type) -> Column.Column<S,P>:
112 Column.Leaf{ANode{ANode{ANode{ALeaf{None{}},ALeaf{None{}}},ANode{ALeaf{None{}},ALeaf{None{}}}},ANode{ANode{ALeaf{None{}},ALeaf{None{}}},ANode{ALeaf{None{}},ALeaf{None{}}}}},[Lifecycle.Stamp{None{},None{}} : Lifecycle.Stamp^3n]}
113def empty_columns(~S:Data,layout:Layout) -> columns(~S,layout):
114 match layout:
115 case EmptyLayout{}:Unit{}
116 case LayoutLeaf{P,V,_,key,_}:ColumnSlot{empty_column(S,Viewed<P,V>)}
117 case ClassifiedLayoutLeaf{P,V,_,key,_,_}:ColumnSlot{empty_column(S,Viewed<P,V>)}
118 case LayoutPair{left,right}:Product.Owner{empty_columns(~S,left),empty_columns(~S,right)}
119def column_rest(~S:Data,layout:Layout,route:Route) -> Type:
120 match layout route:
121 case LayoutLeaf{_,V,_,_,_} AtLeaf{}:Unit
122 case ClassifiedLayoutLeaf{_,V,_,_,_,_} AtLeaf{}:Unit
123 case LayoutPair{left,right} InLeft{rest}:columns(~S,right) & column_rest(~S,left,rest)
124 case LayoutPair{left,right} InRight{rest}:columns(~S,left) & column_rest(~S,right,rest)
125 case layout _:columns(~S,layout)
126def column_joined(~S:Data,-P:Type,-key:String,-origin:Layout,-Outer:Type,-Inner:Type,outer:Outer,result:Inner & ColumnSlot<S,P,key,origin>) -> (Outer & Inner) & ColumnSlot<S,P,key,origin>:
127 match result:
128 case (inner,slot):((outer,inner),slot)
129def column_take(~S:Data,layout:Layout,route:Route,owner:columns(~S,layout)) -> column_rest(~S,layout,route) & ColumnSlot<S,stored(layout,route),key(layout,route),origin(layout,route)>:
130 match layout route owner:
131 case EmptyLayout{} _ owner:(owner,ColumnSlot{Column.empty(~S,~Viewed<Unit,Unit>)})
132 case LayoutLeaf{P,V,_,key,_} AtLeaf{} owner:(Unit{},owner)
133 case ClassifiedLayoutLeaf{P,V,_,key,_,_} AtLeaf{} owner:(Unit{},owner)
134 case LayoutLeaf{P,V,_,key,_} InLeft{_} owner:(owner,ColumnSlot{Column.empty(~S,~Viewed<Unit,Unit>)})
135 case ClassifiedLayoutLeaf{P,V,_,key,_,_} InLeft{_} owner:(owner,ColumnSlot{Column.empty(~S,~Viewed<Unit,Unit>)})
136 case LayoutLeaf{P,V,_,key,_} InRight{_} owner:(owner,ColumnSlot{Column.empty(~S,~Viewed<Unit,Unit>)})
137 case ClassifiedLayoutLeaf{P,V,_,key,_,_} InRight{_} owner:(owner,ColumnSlot{Column.empty(~S,~Viewed<Unit,Unit>)})
138 case LayoutPair{left,right} AtLeaf{} owner:(owner,ColumnSlot{Column.empty(~S,~Viewed<Unit,Unit>)})
139 case LayoutPair{left,right} InLeft{rest} Product.Owner{l,r}:column_joined(~S,stored(left,rest),key(left,rest),origin(left,rest),columns(~S,right),column_rest(~S,left,rest),r,column_take(~S,left,rest,l))
140 case LayoutPair{left,right} InRight{rest} Product.Owner{l,r}:column_joined(~S,stored(right,rest),key(right,rest),origin(right,rest),columns(~S,left),column_rest(~S,right,rest),l,column_take(~S,right,rest,r))
141def column_put(~S:Data,layout:Layout,route:Route,rest:column_rest(~S,layout,route),slot:ColumnSlot<S,stored(layout,route),key(layout,route),origin(layout,route)>) -> columns(~S,layout):
142 match layout route rest:
143 case EmptyLayout{} _ rest:rest
144 case LayoutLeaf{P,V,_,key,_} AtLeaf{} _:slot
145 case ClassifiedLayoutLeaf{P,V,_,key,_,_} AtLeaf{} _:slot
146 case LayoutLeaf{P,V,_,key,_} InLeft{_} rest:rest
147 case ClassifiedLayoutLeaf{P,V,_,key,_,_} InLeft{_} rest:rest
148 case LayoutLeaf{P,V,_,key,_} InRight{_} rest:rest
149 case ClassifiedLayoutLeaf{P,V,_,key,_,_} InRight{_} rest:rest
150 case LayoutPair{left,right} AtLeaf{} rest:rest
151 case LayoutPair{left,right} InLeft{path}, (outer,inner):Product.Owner{column_put(~S,left,path,inner,slot),outer}
152 case LayoutPair{left,right} InRight{path}, (outer,inner):Product.Owner{outer,column_put(~S,right,path,inner,slot)}
153def resource_rest_generic(-S:Data,layout:Layout,route:Route) -> Type:
154 match layout route:
155 case LayoutLeaf{_,V,_,_,_} AtLeaf{}:Unit
156 case ClassifiedLayoutLeaf{_,V,_,_,_,_} AtLeaf{}:Unit
157 case LayoutPair{left,right} InLeft{rest}:resources_generic(S,right) & resource_rest_generic(S,left,rest)
158 case LayoutPair{left,right} InRight{rest}:resources_generic(S,left) & resource_rest_generic(S,right,rest)
159 case layout _:resources_generic(S,layout)
160def resource_rest(~S:Data,layout:Layout,route:Route) -> Type:
161 resource_rest_generic(S,layout,route)
162
163def resource_joined_generic(-S:Data,-P:Type,-key:String,-origin:Layout,-Outer:Type,-Inner:Type,outer:Outer,result:Inner & ResourceSlot<S,P,key,origin>) -> (Outer & Inner) & ResourceSlot<S,P,key,origin>:
164 match result:
165 case (inner,slot):((outer,inner),slot)
166def resource_joined(~S:Data,-P:Type,-key:String,-origin:Layout,-Outer:Type,-Inner:Type,outer:Outer,result:Inner & ResourceSlot<S,P,key,origin>) -> (Outer & Inner) & ResourceSlot<S,P,key,origin>:
167 resource_joined_generic(S,P,key,origin,Outer,Inner,outer,result)
168def resource_take_generic(-S:Data,layout:Layout,route:Route,owner:resources_generic(S,layout)) -> resource_rest_generic(S,layout,route) & ResourceSlot<S,stored(layout,route),key(layout,route),origin(layout,route)>:
169 match layout route owner:
170 case EmptyLayout{} _ owner:(owner,ResourceSlot{Viewed{Unit{},Unit{}},unknown_stamp()})
171 case LayoutLeaf{P,V,_,key,_} AtLeaf{} owner:(Unit{},owner)
172 case ClassifiedLayoutLeaf{P,V,_,key,_,_} AtLeaf{} owner:(Unit{},owner)
173 case LayoutLeaf{P,V,_,key,_} InLeft{_} owner:(owner,ResourceSlot{Viewed{Unit{},Unit{}},unknown_stamp()})
174 case ClassifiedLayoutLeaf{P,V,_,key,_,_} InLeft{_} owner:(owner,ResourceSlot{Viewed{Unit{},Unit{}},unknown_stamp()})
175 case LayoutLeaf{P,V,_,key,_} InRight{_} owner:(owner,ResourceSlot{Viewed{Unit{},Unit{}},unknown_stamp()})
176 case ClassifiedLayoutLeaf{P,V,_,key,_,_} InRight{_} owner:(owner,ResourceSlot{Viewed{Unit{},Unit{}},unknown_stamp()})
177 case LayoutPair{left,right} AtLeaf{} owner:(owner,ResourceSlot{Viewed{Unit{},Unit{}},unknown_stamp()})
178 case LayoutPair{left,right} InLeft{rest} Product.Owner{l,r}:resource_joined_generic(S,stored(left,rest),key(left,rest),origin(left,rest),resources_generic(S,right),resource_rest_generic(S,left,rest),r,resource_take_generic(S,left,rest,l))
179 case LayoutPair{left,right} InRight{rest} Product.Owner{l,r}:resource_joined_generic(S,stored(right,rest),key(right,rest),origin(right,rest),resources_generic(S,left),resource_rest_generic(S,right,rest),l,resource_take_generic(S,right,rest,r))
180def resource_take(~S:Data,layout:Layout,route:Route,owner:resources(~S,layout)) -> resource_rest(~S,layout,route) & ResourceSlot<S,stored(layout,route),key(layout,route),origin(layout,route)>:
181 resource_take_generic(S,layout,route,owner)
182def resource_put_generic(-S:Data,layout:Layout,route:Route,rest:resource_rest_generic(S,layout,route),slot:ResourceSlot<S,stored(layout,route),key(layout,route),origin(layout,route)>) -> resources_generic(S,layout):
183 match layout route rest:
184 case EmptyLayout{} _ rest:rest
185 case LayoutLeaf{P,V,_,key,_} AtLeaf{} _:slot
186 case ClassifiedLayoutLeaf{P,V,_,key,_,_} AtLeaf{} _:slot
187 case LayoutLeaf{P,V,_,key,_} InLeft{_} rest:rest
188 case ClassifiedLayoutLeaf{P,V,_,key,_,_} InLeft{_} rest:rest
189 case LayoutLeaf{P,V,_,key,_} InRight{_} rest:rest
190 case ClassifiedLayoutLeaf{P,V,_,key,_,_} InRight{_} rest:rest
191 case LayoutPair{left,right} AtLeaf{} rest:rest
192 case LayoutPair{left,right} InLeft{path}, (outer,inner):Product.Owner{resource_put_generic(S,left,path,inner,slot),outer}
193 case LayoutPair{left,right} InRight{path}, (outer,inner):Product.Owner{outer,resource_put_generic(S,right,path,inner,slot)}
194def resource_put(~S:Data,layout:Layout,route:Route,rest:resource_rest(~S,layout,route),slot:ResourceSlot<S,stored(layout,route),key(layout,route),origin(layout,route)>) -> resources(~S,layout):
195 resource_put_generic(S,layout,route,rest,slot)
196def checked_owner(-A:Type,-B:Type,same:{A == B : Type},owner:A) -> B:
197 %same : _
198 owner
199def names(layout:Layout) -> List<&2,String>:
200 match layout:
201 case EmptyLayout{}:[]
202 case LayoutLeaf{_,V,_,name,_}:[name]
203 case ClassifiedLayoutLeaf{_,V,_,name,_,_}:[name]
204 case LayoutPair{left,right}:List.append(&2,String,names(left),names(right))
205def contains_name(values:List<&2,String>,+name:String) -> Bool:
206 match values:
207 case []:False{}
208 case current <> rest:Bool.or(String.eq(current,name),contains_name(rest,name))
209def unique_names(values:List<&2,String>) -> Bool:
210 match values:
211 case []:True{}
212 case +name <> +rest:Bool.and(Bool.not(contains_name(rest,name)),unique_names(rest))
213def unique(layout:Layout) -> Bool:unique_names(names(layout))
214def grant_valid(~layout:Layout,~route:Route) -> Bool:
215 Bool.and(unique(layout),valid(layout,route))
216def resource_write_valid(~layout:Layout,~route:Route) -> Bool:
217 Bool.and(grant_valid(~layout,~route),Policy.generic_write(policy(layout,route)))
218
219def subtree(layout:Layout,route:Route) -> Layout:
220 match layout route:
221 case layout AtLeaf{}:layout
222 case LayoutPair{left,_} InLeft{rest}:subtree(left,rest)
223 case LayoutPair{_,right} InRight{rest}:subtree(right,rest)
224 case _ _:EmptyLayout{}
225def subtree_rest(~S:Data,layout:Layout,route:Route) -> Type:
226 match layout route:
227 case _ AtLeaf{}:Unit
228 case LayoutPair{left,right} InLeft{rest}:columns(~S,right) & subtree_rest(~S,left,rest)
229 case LayoutPair{left,right} InRight{rest}:columns(~S,left) & subtree_rest(~S,right,rest)
230 case layout _:columns(~S,layout)
231def subtree_joined(-Outer:Type,-Inner:Type,-Selected:Type,outer:Outer,result:Inner & Selected) -> (Outer & Inner) & Selected:
232 match result:
233 case (inner,selected):((outer,inner),selected)
234def subtree_take(~S:Data,layout:Layout,route:Route,owner:columns(~S,layout)) -> subtree_rest(~S,layout,route) & columns(~S,subtree(layout,route)):
235 match layout route owner:
236 case layout AtLeaf{} owner:(Unit{},owner)
237 case EmptyLayout{} InLeft{_} owner:(owner,Unit{})
238 case EmptyLayout{} InRight{_} owner:(owner,Unit{})
239 case LayoutLeaf{_,V,_,_,_} InLeft{_} owner:(owner,Unit{})
240 case ClassifiedLayoutLeaf{_,V,_,_,_,_} InLeft{_} owner:(owner,Unit{})
241 case LayoutLeaf{_,V,_,_,_} InRight{_} owner:(owner,Unit{})
242 case ClassifiedLayoutLeaf{_,V,_,_,_,_} InRight{_} owner:(owner,Unit{})
243 case LayoutPair{left,right} InLeft{rest} Product.Owner{l,r}:subtree_joined(columns(~S,right),subtree_rest(~S,left,rest),columns(~S,subtree(left,rest)),r,subtree_take(~S,left,rest,l))
244 case LayoutPair{left,right} InRight{rest} Product.Owner{l,r}:subtree_joined(columns(~S,left),subtree_rest(~S,right,rest),columns(~S,subtree(right,rest)),l,subtree_take(~S,right,rest,r))
245def subtree_put(~S:Data,layout:Layout,route:Route,rest:subtree_rest(~S,layout,route),selected:columns(~S,subtree(layout,route))) -> columns(~S,layout):
246 match layout route rest:
247 case _ AtLeaf{} _:selected
248 case EmptyLayout{} InLeft{_} rest:rest
249 case EmptyLayout{} InRight{_} rest:rest
250 case LayoutLeaf{_,V,_,_,_} InLeft{_} rest:rest
251 case ClassifiedLayoutLeaf{_,V,_,_,_,_} InLeft{_} rest:rest
252 case LayoutLeaf{_,V,_,_,_} InRight{_} rest:rest
253 case ClassifiedLayoutLeaf{_,V,_,_,_,_} InRight{_} rest:rest
254 case LayoutPair{left,right} InLeft{path}, (outer,inner):Product.Owner{subtree_put(~S,left,path,inner,selected),outer}
255 case LayoutPair{left,right} InRight{path}, (outer,inner):Product.Owner{outer,subtree_put(~S,right,path,inner,selected)}
256def pair_input(layout:Layout) -> Type:
257 match layout:
258 case LayoutPair{LayoutLeaf{P,V,_,_,_},LayoutLeaf{_,V,_,_,_}}:P
259 case LayoutPair{LayoutLeaf{P,V,_,_,_},ClassifiedLayoutLeaf{_,V,_,_,_,_}}:P
260 case LayoutPair{ClassifiedLayoutLeaf{P,V,_,_,_,_},LayoutLeaf{_,V,_,_,_}}:P
261 case LayoutPair{ClassifiedLayoutLeaf{P,V,_,_,_,_},ClassifiedLayoutLeaf{_,V,_,_,_,_}}:P
262 case _:Unit
263def pair_output(layout:Layout) -> Type:
264 match layout:
265 case LayoutPair{LayoutLeaf{_,V,_,_,_},LayoutLeaf{P,V,_,_,_}}:P
266 case LayoutPair{LayoutLeaf{_,V,_,_,_},ClassifiedLayoutLeaf{P,V,_,_,_,_}}:P
267 case LayoutPair{ClassifiedLayoutLeaf{_,V,_,_,_,_},LayoutLeaf{P,V,_,_,_}}:P
268 case LayoutPair{ClassifiedLayoutLeaf{_,V,_,_,_,_},ClassifiedLayoutLeaf{P,V,_,_,_,_}}:P
269 case _:Unit
270def pair_leaves(layout:Layout) -> Bool:
271 match layout:
272 case LayoutPair{LayoutLeaf{_,V,_,_,_},LayoutLeaf{_,V,_,_,_}}:True{}
273 case LayoutPair{LayoutLeaf{_,V,_,_,_},ClassifiedLayoutLeaf{_,V,_,_,_,_}}:True{}
274 case LayoutPair{ClassifiedLayoutLeaf{_,V,_,_,_,_},LayoutLeaf{_,V,_,_,_}}:True{}
275 case LayoutPair{ClassifiedLayoutLeaf{_,V,_,_,_,_},ClassifiedLayoutLeaf{_,V,_,_,_,_}}:True{}
276 case _:False{}
277def query_view(layout:Layout,route:Route) -> Data:view(subtree(layout,route),InLeft{AtLeaf{}})
278def query_input(layout:Layout,route:Route) -> Type:payload(subtree(layout,route),InLeft{AtLeaf{}})
279def query_output(layout:Layout,route:Route) -> Type:payload(subtree(layout,route),InRight{AtLeaf{}})
280def query_read_key(layout:Layout,route:Route) -> String:key(subtree(layout,route),InLeft{AtLeaf{}})
281def query_write_key(layout:Layout,route:Route) -> String:key(subtree(layout,route),InRight{AtLeaf{}})
282def query_pair(~S:Data,~layout:Layout,~route:Route) -> Type:
283 Product.Owner<ColumnSlot<S,stored(subtree(layout,route),InLeft{AtLeaf{}}),query_read_key(layout,route),origin(subtree(layout,route),InLeft{AtLeaf{}})>,ColumnSlot<S,stored(subtree(layout,route),InRight{AtLeaf{}}),query_write_key(layout,route),origin(subtree(layout,route),InRight{AtLeaf{}})>>
284def query_valid(~layout:Layout,~route:Route) -> Bool:
285 Bool.and(unique(layout),pair_leaves(subtree(layout,route)))
286
287def normalize_resources(~S:Data,layout:Layout,owners:resources(~S,layout)) -> resources(~S,layout):
288 match layout owners:
289 case EmptyLayout{} owner:owner
290 case LayoutLeaf{P,V,refresh,key,accessPolicy} ResourceSlot{Viewed{owner,_},stamp}:ResourceSlot{initialized(P,V,refresh(owner)),stamp}
291 case ClassifiedLayoutLeaf{P,V,refresh,key,_,accessPolicy} ResourceSlot{Viewed{owner,_},stamp}:ResourceSlot{initialized(P,V,refresh(owner)),stamp}
292 case LayoutPair{left,right} Product.Owner{l,r}:Product.Owner{normalize_resources(~S,left,l),normalize_resources(~S,right,r)}
293
294
295def initialize_resources(~S:Data,layout:Layout,+tick:Tick.Tick,owners:resources(~S,layout)) -> resources(~S,layout):
296 match layout owners:
297 case EmptyLayout{} owner:owner
298 case LayoutLeaf{P,V,refresh,key,accessPolicy} ResourceSlot{Viewed{owner,_},_}:ResourceSlot{initialized(P,V,refresh(owner)),Lifecycle.Stamp{Some{tick},Some{tick}}}
299 case ClassifiedLayoutLeaf{P,V,refresh,key,_,accessPolicy} ResourceSlot{Viewed{owner,_},_}:ResourceSlot{initialized(P,V,refresh(owner)),Lifecycle.Stamp{Some{tick},Some{tick}}}
300 case LayoutPair{left,right} Product.Owner{l,r}:Product.Owner{initialize_resources(~S,left,tick,l),initialize_resources(~S,right,tick,r)}