1 import Base 2 import ./execution_resource_policy.bend as Policy 3 import ./execution_lifecycle_notices.bend as Notice 4 import ./change_tick.bend as Tick 5 import ./execution_composer_layout.bend as Layout 6 import ./chunk_column.bend as Column 7 import ./owner_product.bend as Product 8 9 # Structural receipts retain each actual raw owner, including unlike affine 10 # families. Removing a cached row never invokes its refresher. 11 def Removed(layout:Layout.Layout) -> Type: 12 match layout: 13 case Layout.EmptyLayout{}:Unit 14 case Layout.LayoutLeaf{P,_,_,_,_}:Maybe<&1,P> 15 case Layout.ClassifiedLayoutLeaf{P,_,_,_,_,_}:Maybe<&1,P> 16 case Layout.LayoutPair{left,right}:Product.Owner 17 def raw(-P:Type,-V:Data,value:Maybe<&1,Layout.Viewed>) -> Maybe<&1,P>: 18 match value: 19 case None{}:None{} 20 case Some{Layout.Viewed{owner,_}}:Some{owner} 21 def leaf_done(~S:Data,-P:Type,-V:Data,-key:String,-origin:Layout.Layout,result:Column.Column> & Maybe<&1,Layout.Viewed>) -> Layout.ColumnSlot,key,origin> & Maybe<&1,P>: 22 match result: 23 case (column,previous):(Layout.ColumnSlot{column},raw(P,V,previous)) 24 def leaf(~S:Data,-P:Type,-V:Data,-key:String,-origin:Layout.Layout,index:U32,slot:Layout.ColumnSlot,key,origin>) -> Layout.ColumnSlot,key,origin> & Maybe<&1,P>: 25 match slot: 26 case Layout.ColumnSlot{column}:leaf_done(~S,P,V,key,origin,Column.take(S,Layout.Viewed,column,index)) 27 def joined(~S:Data,-left:Layout.Layout,-right:Layout.Layout,leftOwner:Layout.columns(~S,left),removed:Removed(left),result:Layout.columns(~S,right) & Removed(right)) -> Product.Owner & Product.Owner: 28 match result: 29 case (rightOwner,rightRemoved):(Product.Owner{leftOwner,rightOwner},Product.Owner{removed,rightRemoved}) 30 def took_left(~S:Data,-left:Layout.Layout,-right:Layout.Layout,takeRight:U32 -> Layout.columns(~S,right) -> Layout.columns(~S,right) & Removed(right),index:U32,rightOwner:Layout.columns(~S,right),result:Layout.columns(~S,left) & Removed(left)) -> Product.Owner & Product.Owner: 31 match result: 32 case (leftOwner,removed):joined(~S,left,right,leftOwner,removed,takeRight(index,rightOwner)) 33 def pair(~S:Data,-left:Layout.Layout,-right:Layout.Layout,takeLeft:U32 -> Layout.columns(~S,left) -> Layout.columns(~S,left) & Removed(left),takeRight:U32 -> Layout.columns(~S,right) -> Layout.columns(~S,right) & Removed(right),+index:U32,owner:Product.Owner) -> Product.Owner & Product.Owner: 34 match owner: 35 case Product.Owner{leftOwner,rightOwner}:took_left(~S,left,right,takeRight,index,rightOwner,takeLeft(index,leftOwner)) 36 def take(~S:Data,layout:Layout.Layout) -> U32 -> Layout.columns(~S,layout) -> Layout.columns(~S,layout) & Removed(layout): 37 match layout: 38 case Layout.EmptyLayout{}:index => owner => (owner,Unit{}) 39 case Layout.LayoutLeaf{P,V,refresh,key,accessPolicy}:leaf(~S,P,V,key,Layout.LayoutLeaf{P,V,refresh,key,accessPolicy}) 40 case Layout.ClassifiedLayoutLeaf{P,V,refresh,key,policy,accessPolicy}:leaf(~S,P,V,key,Layout.ClassifiedLayoutLeaf{P,V,refresh,key,policy,accessPolicy}) 41 case Layout.LayoutPair{left,right}:index => owner => pair(~S,left,right,take(~S,left),take(~S,right),index,owner) 42 43 # Inspect actual displaced owners once and return those same owners. No cached 44 # view or presence metadata can manufacture a removal notice or refresh payloads. 45 def noticed_leaf(~S:Data,-P:Type,key:String,entity:Notice.Identity,tick:Tick.Tick,journal:Notice.Journal,removed:Maybe<&1,P>) -> Notice.Journal & Maybe<&1,P>: 46 match removed: 47 case None{}:(journal,None{}) 48 case Some{owner}:(Notice.append(~S,Notice.Removed{key},entity,tick,journal),Some{owner}) 49 def noticed_right(~S:Data,-left:Layout.Layout,-right:Layout.Layout,leftOwner:Removed(left),result:Notice.Journal & Removed(right)) -> Notice.Journal & Removed(Layout.LayoutPair{left,right}): 50 match result: 51 case (journal,rightOwner):(journal,Product.Owner{leftOwner,rightOwner}) 52 def noticed_left(~S:Data,-left:Layout.Layout,-right:Layout.Layout,noticeRight:Notice.Identity -> Tick.Tick -> Notice.Journal -> Removed(right) -> Notice.Journal & Removed(right),entity:Notice.Identity,tick:Tick.Tick,rightOwner:Removed(right),result:Notice.Journal & Removed(left)) -> Notice.Journal & Removed(Layout.LayoutPair{left,right}): 53 match result: 54 case (journal,leftOwner):noticed_right(~S,left,right,leftOwner,noticeRight(entity,tick,journal,rightOwner)) 55 def noticed_pair(~S:Data,-left:Layout.Layout,-right:Layout.Layout,noticeLeft:Notice.Identity -> Tick.Tick -> Notice.Journal -> Removed(left) -> Notice.Journal & Removed(left),noticeRight:Notice.Identity -> Tick.Tick -> Notice.Journal -> Removed(right) -> Notice.Journal & Removed(right),+entity:Notice.Identity,+tick:Tick.Tick,journal:Notice.Journal,removed:Removed(Layout.LayoutPair{left,right})) -> Notice.Journal & Removed(Layout.LayoutPair{left,right}): 56 match removed: 57 case Product.Owner{leftOwner,rightOwner}:noticed_left(~S,left,right,noticeRight,entity,tick,rightOwner,noticeLeft(entity,tick,journal,leftOwner)) 58 def notices(~S:Data,layout:Layout.Layout) -> Notice.Identity -> Tick.Tick -> Notice.Journal -> Removed(layout) -> Notice.Journal & Removed(layout): 59 match layout: 60 case Layout.EmptyLayout{}:entity => tick => journal => removed => (journal,removed) 61 case Layout.LayoutLeaf{P,_,_,key,_}:noticed_leaf(~S,P,key) 62 case Layout.ClassifiedLayoutLeaf{P,_,_,key,_,_}:noticed_leaf(~S,P,key) 63 case Layout.LayoutPair{left,right}:entity => tick => journal => removed => noticed_pair(~S,left,right,notices(~S,left),notices(~S,right),entity,tick,journal,removed)