1 import Base 2 import ./deferred_command.bend as Deferred 3 import ./trace_facts.bend as TraceFacts 4 import ./commands.bend as Cmd 5 import ./lifetime_scope.bend as Sc 6 import ./world.bend as W 7 import ./transaction.bend as T 8 import ./relation_commands.bend as A 9 10 # Ordinary population receives the same full World context as Cmd.tx_spawn. 11 # Membership is assigned only after successful activation and population. 12 def assigned(~S:Data,~C:Type,~R:Type,~E:Data,seen:W.World>,R,A.Notice> & Unit) -> W.World>,R,A.Notice>: 13 match seen: 14 case (world,_):world 15 def assign(~S:Data,~C:Type,~R:Type,~E:Data,world:W.World>,R,A.Notice>,handle:W.Handle,name:String) -> W.World>,R,A.Notice>: 16 match handle: 17 case W.Handle{_,id}:assigned(~S,~C,~R,~E,W.with_store(~S,~A.Store>,~R,~A.Notice,~Unit,store => Sc.assigned(~S,~C,store,name,id),world)) 18 def activated(~S:Data,~C:Type,~R:Type,~E:Data,~P:Type,~populate:W.World>,R,A.Notice> -> W.Handle -> P -> W.World>,R,A.Notice>,seen:W.World>,R,A.Notice> & W.Status,+handle:W.Handle,payload:P,name:String) -> W.World>,R,A.Notice>: 19 match seen: 20 case (world,W.Accepted{}):assign(~S,~C,~R,~E,populate(world,handle,payload),handle,name) 21 case (world,W.Rejected{_}):world 22 def apply(~S:Data,~C:Type,~R:Type,~E:Data,~P:Type,~populate:W.World>,R,A.Notice> -> W.Handle -> P -> W.World>,R,A.Notice>,world:W.World>,R,A.Notice>,+handle:W.Handle,payload:P,name:String) -> W.World>,R,A.Notice>: 23 activated(~S,~C,~R,~E,~P,~populate,W.activate(~S,~A.Store>,~R,~A.Notice,world,handle),handle,payload,name) 24 def reserved(~S:Data,~C:Type,~R:Type,~E:Data,~P:Type,~populate:W.World>,R,A.Notice> -> W.Handle -> P -> W.World>,R,A.Notice>,seen:W.World>,R,A.Notice> & W.Reservation,undo:List<(W.World>,R,A.Notice> -> W.World>,R,A.Notice>)>,commands:List>,R,A.Notice>>>,events:List<&2,A.Notice>,trace:TraceFacts.State,payload:P,name:String) -> T.Tx>,R,A.Notice>,A.Notice> & Sc.SpawnResult: 25 match seen: 26 case (world,W.ReservationRejected{error}):(T.Tx{world,undo,commands,events,trace},Sc.SpawnRejected{payload,error}) 27 case (world,W.Reserved{+handle}):(Cmd.track_pending(~S,~A.Store>,~R,~A.Notice,T.Tx{world,undo,Deferred.Raw{(world => apply(~S,~C,~R,~E,~P,~populate,world,handle,payload,name))} <> commands,events,trace},handle),Sc.Spawned{handle}) 28 def checked(~S:Data,~C:Type,~R:Type,~E:Data,~P:Type,~populate:W.World>,R,A.Notice> -> W.Handle -> P -> W.World>,R,A.Notice>,same:Bool,world:W.World>,R,A.Notice>,undo:List<(W.World>,R,A.Notice> -> W.World>,R,A.Notice>)>,commands:List>,R,A.Notice>>>,events:List<&2,A.Notice>,trace:TraceFacts.State,payload:P,name:String) -> T.Tx>,R,A.Notice>,A.Notice> & Sc.SpawnResult: 29 match same: 30 case False{}:(T.Tx{world,undo,commands,events,trace},Sc.SpawnRejected{payload,W.MissingEntity{}}) 31 case True{}:reserved(~S,~C,~R,~E,~P,~populate,W.reserve_id(~S,~A.Store>,~R,~A.Notice,world),undo,commands,events,trace,payload,name) 32 def namespaced(~S:Data,~C:Type,~R:Type,~E:Data,~P:Type,~populate:W.World>,R,A.Notice> -> W.Handle -> P -> W.World>,R,A.Notice>,seen:W.World>,R,A.Notice> & U32,scope:Sc.Scope,undo:List<(W.World>,R,A.Notice> -> W.World>,R,A.Notice>)>,commands:List>,R,A.Notice>>>,events:List<&2,A.Notice>,trace:TraceFacts.State,payload:P) -> T.Tx>,R,A.Notice>,A.Notice> & Sc.SpawnResult: 33 match seen scope: 34 case (world,current) Sc.Scope{namespace,name}:checked(~S,~C,~R,~E,~P,~populate,U32.is_eq(current,namespace),world,undo,commands,events,trace,payload,name) 35 def tx_spawn_in(~S:Data,~C:Type,~R:Type,~E:Data,~P:Type,~populate:W.World>,R,A.Notice> -> W.Handle -> P -> W.World>,R,A.Notice>,tx:T.Tx>,R,A.Notice>,A.Notice>,scope:Sc.Scope,payload:P) -> T.Tx>,R,A.Notice>,A.Notice> & Sc.SpawnResult: 36 match tx: 37 case T.Tx{world,undo,commands,events,trace}:namespaced(~S,~C,~R,~E,~P,~populate,W.namespace(~S,~A.Store>,~R,~A.Notice,world),scope,undo,commands,events,trace,payload)