1 import Base 2 import ./world.bend as W 3 import ./restore_world.bend as Adapter 4 import ./restore_data.bend as R 5 import ./transaction.bend as T 6 import ./commands.bend as Cmd 7 8 def changes(~S:Data,~E:Data,~emit:R.Change -> E,values:List<&2,R.Change>) -> List<&2,E>: 9 match values: 10 case []:[] 11 case value <> rest:emit(value) <> changes(~S,~E,~emit,rest) 12 def clear_join(~S:Data,~C:Type,~E:Data,~emit:R.Change -> E,observed:C & List<&2,R.Change>) -> C & List<&2,E>: 13 match observed: 14 case (store,events):(store,changes(~S,~E,~emit,events)) 15 def clear_store(~S:Data,~C:Type,~E:Data,~clear:C -> W.Handle -> C & List<&2,R.Change>,~emit:R.Change -> E,store:C,handle:W.Handle) -> C & List<&2,E>: 16 clear_join(~S,~C,~E,~emit,clear(store,handle)) 17 def despawned(~S:Data,~E:Data,~emit:R.Change -> E,handle:W.Handle) -> E:emit(R.Despawned{handle}) 18 def queued(~S:Data,~C:Type,~Resources:Type,~E:Data,next:T.Tx,E> -> T.Tx,E>,observed:T.Tx,E> & W.Status) -> T.Tx,E>: 19 match observed: 20 case (tx,_):next(tx) 21 def queue(~S:Data,~C:Type,~Resources:Type,~E:Data,~clear:C -> W.Handle -> C & List<&2,R.Change>,~emit:R.Change -> E,handles:List<&2,W.Handle>,tx:T.Tx,E>) -> T.Tx,E>: 22 match handles: 23 case []:tx 24 case handle <> rest:queued(~S,~C,~Resources,~E,next => queue(~S,~C,~Resources,~E,~clear,~emit,rest,next),Cmd.tx_despawn_observed(~S,~C,~Resources,~E,~clear_store(~S,~C,~E,~clear,~emit),~despawned(~S,~E,~emit),tx,handle)) 25 def committed(~S:Data,~C:Type,~Resources:Type,~E:Data,observed:T.Returned,Unit>) -> W.World: 26 match observed: 27 case T.Returned{world,_}:W.barrier(~S,~C,~Resources,~E,world) 28 def clean(~S:Data,~C:Type,~Resources:Type,~E:Data,~clear:C -> W.Handle -> C & List<&2,R.Change>,~emit:R.Change -> E,handles:List<&2,W.Handle>,world:W.World) -> W.World: 29 committed(~S,~C,~Resources,~E,Cmd.tx_finish(~S,~C,~Resources,~E,~Unit,queue(~S,~C,~Resources,~E,~clear,~emit,handles,T.begin(~W.World,~E,Adapter.cancel_pending(~S,~C,~Resources,~E,world))),T.Success{})) 30 def populate(~S:Data,~C:Type,~Resources:Type,~E:Data,world:W.World,handle:W.Handle,unit:Unit) -> W.World: 31 world 32 def spawn_committed(~S:Data,~C:Type,~Resources:Type,~E:Data,reservation:W.Reservation,observed:T.Returned,Unit>) -> W.World & W.Reservation: 33 match observed: 34 case T.Returned{world,_}:(W.barrier(~S,~C,~Resources,~E,world),reservation) 35 def spawn_staged(~S:Data,~C:Type,~Resources:Type,~E:Data,observed:T.Tx,E> & W.Reservation) -> W.World & W.Reservation: 36 match observed: 37 case (tx,reservation):spawn_committed(~S,~C,~Resources,~E,reservation,Cmd.tx_finish(~S,~C,~Resources,~E,~Unit,tx,T.Success{})) 38 def spawn(~S:Data,~C:Type,~Resources:Type,~E:Data,world:W.World) -> W.World & W.Reservation: 39 spawn_staged(~S,~C,~Resources,~E,Cmd.tx_spawn(~S,~C,~Resources,~E,~Unit,~populate(~S,~C,~Resources,~E),T.begin(~W.World,~E,world),Unit{}))