1 import Base 2 import ./execution_resource_policy.bend as Policy 3 import ./chunk_column.bend as Column 4 import ./owner_product.bend as Product 5 import ./lifecycle.bend as Lifecycle 6 import ./change_tick.bend as Tick 7 import ./schema_fragments.bend as Fragment 8 9 type Viewed<-P:Type,-V:Data> is Type: 10 Viewed{owner:P,view:V} 11 def read(~P:Type,~V:Data,value:Viewed) -> Viewed & V: 12 match value: 13 case Viewed{owner,+view}:(Viewed{owner,view},view) 14 def initialized(-P:Type,-V:Data,result:P & V) -> Viewed: 15 match result: 16 case (owner,view):Viewed{owner,view} 17 18 type 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} 23 type Route is Data: 24 AtLeaf{} 25 InLeft{rest:Route} 26 InRight{rest:Route} 27 type ColumnSlot<-S:Data,-P:Type,-key:String,-origin:Layout> is Type: 28 ColumnSlot{column:Column.Column} 29 type ResourceSlot<-S:Data,-P:Type,-key:String,-origin:Layout> is Type: 30 ResourceSlot{owner:P,stamp:Lifecycle.Stamp} 31 def unknown_stamp() -> Lifecycle.Stamp:Lifecycle.Stamp{None{},None{}} 32 def 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 # Policy is part of the full canonical origin, independently of persistence. 40 def 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{} 47 def columns(~S:Data,layout:Layout) -> Type: 48 match layout: 49 case EmptyLayout{}:Unit 50 case LayoutLeaf{P,V,refresh,key,accessPolicy}:ColumnSlot,key,LayoutLeaf{P,V,refresh,key,accessPolicy}> 51 case ClassifiedLayoutLeaf{P,V,refresh,key,kind,accessPolicy}:ColumnSlot,key,ClassifiedLayoutLeaf{P,V,refresh,key,kind,accessPolicy}> 52 case LayoutPair{left,right}:Product.Owner 53 def resources_generic(-S:Data,layout:Layout) -> Type: 54 match layout: 55 case EmptyLayout{}:Unit 56 case LayoutLeaf{P,V,refresh,key,accessPolicy}:ResourceSlot,key,LayoutLeaf{P,V,refresh,key,accessPolicy}> 57 case ClassifiedLayoutLeaf{P,V,refresh,key,kind,accessPolicy}:ResourceSlot,key,ClassifiedLayoutLeaf{P,V,refresh,key,kind,accessPolicy}> 58 case LayoutPair{left,right}:Product.Owner 59 def resources(~S:Data,layout:Layout) -> Type: 60 resources_generic(S,layout) 61 62 def 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 69 def 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 76 def stored(layout:Layout,route:Route) -> Type:Viewed 77 def 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{}} 89 def 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) 92 def rewrite_view(-P:Type,-V:Data,-Out:Type,initialize:P -> Viewed,transform:P -> P & Out,value:Viewed) -> Viewed & Out: 93 match value: 94 case Viewed{owner,_}:rewritten(P,Viewed,Out,initialize,transform(owner)) 95 def 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) 97 def 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 _ _:"" 104 def 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{} 111 def empty_column(-S:Data,-P:Type) -> Column.Column: 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]} 113 def 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)} 117 case ClassifiedLayoutLeaf{P,V,_,key,_,_}:ColumnSlot{empty_column(S,Viewed)} 118 case LayoutPair{left,right}:Product.Owner{empty_columns(~S,left),empty_columns(~S,right)} 119 def 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) 126 def column_joined(~S:Data,-P:Type,-key:String,-origin:Layout,-Outer:Type,-Inner:Type,outer:Outer,result:Inner & ColumnSlot) -> (Outer & Inner) & ColumnSlot: 127 match result: 128 case (inner,slot):((outer,inner),slot) 129 def column_take(~S:Data,layout:Layout,route:Route,owner:columns(~S,layout)) -> column_rest(~S,layout,route) & ColumnSlot: 130 match layout route owner: 131 case EmptyLayout{} _ owner:(owner,ColumnSlot{Column.empty(~S,~Viewed)}) 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)}) 135 case ClassifiedLayoutLeaf{P,V,_,key,_,_} InLeft{_} owner:(owner,ColumnSlot{Column.empty(~S,~Viewed)}) 136 case LayoutLeaf{P,V,_,key,_} InRight{_} owner:(owner,ColumnSlot{Column.empty(~S,~Viewed)}) 137 case ClassifiedLayoutLeaf{P,V,_,key,_,_} InRight{_} owner:(owner,ColumnSlot{Column.empty(~S,~Viewed)}) 138 case LayoutPair{left,right} AtLeaf{} owner:(owner,ColumnSlot{Column.empty(~S,~Viewed)}) 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)) 141 def column_put(~S:Data,layout:Layout,route:Route,rest:column_rest(~S,layout,route),slot:ColumnSlot) -> 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)} 153 def 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) 160 def resource_rest(~S:Data,layout:Layout,route:Route) -> Type: 161 resource_rest_generic(S,layout,route) 162 163 def resource_joined_generic(-S:Data,-P:Type,-key:String,-origin:Layout,-Outer:Type,-Inner:Type,outer:Outer,result:Inner & ResourceSlot) -> (Outer & Inner) & ResourceSlot: 164 match result: 165 case (inner,slot):((outer,inner),slot) 166 def resource_joined(~S:Data,-P:Type,-key:String,-origin:Layout,-Outer:Type,-Inner:Type,outer:Outer,result:Inner & ResourceSlot) -> (Outer & Inner) & ResourceSlot: 167 resource_joined_generic(S,P,key,origin,Outer,Inner,outer,result) 168 def resource_take_generic(-S:Data,layout:Layout,route:Route,owner:resources_generic(S,layout)) -> resource_rest_generic(S,layout,route) & ResourceSlot: 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)) 180 def resource_take(~S:Data,layout:Layout,route:Route,owner:resources(~S,layout)) -> resource_rest(~S,layout,route) & ResourceSlot: 181 resource_take_generic(S,layout,route,owner) 182 def resource_put_generic(-S:Data,layout:Layout,route:Route,rest:resource_rest_generic(S,layout,route),slot:ResourceSlot) -> 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)} 194 def resource_put(~S:Data,layout:Layout,route:Route,rest:resource_rest(~S,layout,route),slot:ResourceSlot) -> resources(~S,layout): 195 resource_put_generic(S,layout,route,rest,slot) 196 def checked_owner(-A:Type,-B:Type,same:{A == B : Type},owner:A) -> B: 197 %same : _ 198 owner 199 def 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)) 205 def 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)) 209 def 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)) 213 def unique(layout:Layout) -> Bool:unique_names(names(layout)) 214 def grant_valid(~layout:Layout,~route:Route) -> Bool: 215 Bool.and(unique(layout),valid(layout,route)) 216 def resource_write_valid(~layout:Layout,~route:Route) -> Bool: 217 Bool.and(grant_valid(~layout,~route),Policy.generic_write(policy(layout,route))) 218 219 def 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{} 225 def 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) 231 def 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) 234 def 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)) 245 def 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)} 256 def 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 263 def 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 270 def 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{} 277 def query_view(layout:Layout,route:Route) -> Data:view(subtree(layout,route),InLeft{AtLeaf{}}) 278 def query_input(layout:Layout,route:Route) -> Type:payload(subtree(layout,route),InLeft{AtLeaf{}}) 279 def query_output(layout:Layout,route:Route) -> Type:payload(subtree(layout,route),InRight{AtLeaf{}}) 280 def query_read_key(layout:Layout,route:Route) -> String:key(subtree(layout,route),InLeft{AtLeaf{}}) 281 def query_write_key(layout:Layout,route:Route) -> String:key(subtree(layout,route),InRight{AtLeaf{}}) 282 def query_pair(~S:Data,~layout:Layout,~route:Route) -> Type: 283 Product.Owner,ColumnSlot> 284 def query_valid(~layout:Layout,~route:Route) -> Bool: 285 Bool.and(unique(layout),pair_leaves(subtree(layout,route))) 286 287 def 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 # Called only by a genuine ordinary World creation boundary, never by reads. 295 def 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)}