1 import Base 2 import ./execution_composer_layout.bend as Layout 3 import ./execution_reservation_bundle.bend as Bundle 4 import ./execution_reservation_materialization.bend as Materialize 5 import ./execution_command_permission.bend as Permission 6 import ./restore_data.bend as R 7 import ./entity_key.bend as Key 8 import ./world.bend as W 9 import ./change_tick.bend as Tick 10 11 type Row<-layout:Layout.Layout> is Type:Row{saved:Key.Key,bundle:Bundle.Payload(layout)} 12 type Receipt<-S:Data,-layout:Layout.Layout> is Type: 13 Materialized{saved:Key.Key,handle:W.Handle,previous:Bundle.Payload(layout)} 14 AllocationRefused{saved:Key.Key,bundle:Bundle.Payload(layout)} 15 PublicationRefused{saved:Key.Key,handle:W.Handle,bundle:Bundle.Payload(layout),reason:Bundle.Refusal} 16 type Published<-S:Data,-layout:Layout.Layout,-Resource:Type,-E:Data> is Type: 17 Published{world:W.World,mapping:List<&2,R.Binding>,receipts:List>,complete:Bool} 18 def materialized(~S:Data,~layout:Layout.Layout,~Resource:Type,~E:Data,saved:Key.Key,result:Bundle.Publication) -> W.World & Receipt: 19 match result: 20 case Bundle.Materialized{world,handle,previous}:(world,Materialized{saved,handle,previous}) 21 case Bundle.RefusedPublication{world,handle,bundle,reason}:(world,PublicationRefused{saved,handle,bundle,reason}) 22 def reserved(~S:Data,~layout:Layout.Layout,~Resource:Type,~E:Data,saved:Key.Key,bundle:Bundle.Payload(layout),tick:Tick.Tick,result:W.World & W.Reservation) -> W.World & Receipt: 23 match result: 24 case (world,W.ReservationRejected{_}):(world,AllocationRefused{saved,bundle}) 25 case (world,W.Reserved{+handle}):materialized(~S,~layout,~Resource,~E,saved,Materialize.apply_at(~S,~Resource,~E,~layout,Permission.EntityStructural{},W.mark_pending(~S,~Layout.columns(~S,layout),~Resource,~E,world,handle),handle,bundle,tick)) 26 def returned(~S:Data,~layout:Layout.Layout,~Resource:Type,~E:Data,next:W.World -> List<&2,R.Binding> -> List> -> Bool -> Published,mapping:List<&2,R.Binding>,receipts:List>,complete:Bool,result:W.World & Receipt) -> Published: 27 match result: 28 case (world,Materialized{+saved,+handle,previous}):next(world,R.Binding{saved,handle} <> mapping,Materialized{saved,handle,previous} <> receipts,complete) 29 case (world,receipt):next(world,mapping,receipt <> receipts,False{}) 30 def rows(~S:Data,~layout:Layout.Layout,~Resource:Type,~E:Data,values:List>,world:W.World,+tick:Tick.Tick,mapping:List<&2,R.Binding>,receipts:List>,complete:Bool) -> Published: 31 match values: 32 case []:Published{world,List.reverse(&2,R.Binding,mapping),List.reverse(&1,Receipt,receipts),complete} 33 case Row{saved,bundle} <> rest:returned(~S,~layout,~Resource,~E,nextWorld => nextMapping => nextReceipts => nextComplete => rows(~S,~layout,~Resource,~E,rest,nextWorld,tick,nextMapping,nextReceipts,nextComplete),mapping,receipts,complete,reserved(~S,~layout,~Resource,~E,saved,bundle,tick,W.reserve_id(~S,~Layout.columns(~S,layout),~Resource,~E,world))) 34 # All incoming owners finish either in the receiver or an explicit refusal 35 # receipt. A failed row marks the whole result partial; later rows are retained 36 # and attempted once. Only canonical fresh receiver handles enter the map. 37 def publish(~S:Data,~layout:Layout.Layout,~Resource:Type,~E:Data,values:List>,world:W.World,tick:Tick.Tick) -> Published: 38 rows(~S,~layout,~Resource,~E,values,world,tick,[],[],True{})