execution_command_buffer.bend
bendvy-ecs-core@0.1.0.3 · 83 lines · 17 definitions
1import Base
2import bendvy-ecs-core@0.1.0.3/execution_effects.bend as Effects
3import bendvy-ecs-core@0.1.0.3/world.bend as W
4import bendvy-ecs-core@0.1.0.3/execution_reservation_bundle.bend as Bundle
5import bendvy-ecs-core@0.1.0.3/execution_composer_layout.bend as Layout
6import bendvy-ecs-core@0.1.0.3/execution_relation_operation.bend as Operation
7import bendvy-ecs-core@0.1.0.3/execution_relation_store.bend as RelationStore
8import bendvy-ecs-core@0.1.0.3/execution_lifetime_scope_command.bend as ScopeCommands
9import bendvy-ecs-core@0.1.0.3/execution_lifetime_scope_store.bend as ScopeStore
10import bendvy-ecs-core@0.1.0.3/execution_lifetime_scope_resource_dispatch.bend as ScopeDispatch
11import bendvy-ecs-core@0.1.0.3/relation_types.bend as Relation
12
13
14
15type Entry<-S:Data,-P:Type,-D:Type> is Type:
16 Entry{handle:W.Handle<S>,incoming:Maybe<&1,P>}
17 Despawn{handle:W.Handle<S>}
18 Spawn{handle:W.Handle<S>,bundle:D}
19 Relation{route:Layout.Route,operation:Operation.Operation<S>}
20 LifetimeScope{route:Layout.Route,operation:ScopeCommands.Operation<S>}
21type ScopeDenial is Data:
22 MissingAuthority{}
23 ForeignNamespace{}
24 ScopeStoreRefused{}
25type ScopeStatus is Data:
26 ScopeComplete{}
27 ScopePaused{}
28 ScopeDenied{reason:ScopeDenial}
29type LinkedStatus is Data:
30 LinkedComplete{}
31 LinkedPaused{}
32 LinkedDenied{reason:ScopeDenial}
33type Receipt<-S:Data,-P:Type,-D:Type> is Type:
34 Applied{handle:W.Handle<S>,previous:Maybe<&1,P>}
35 Refused{handle:W.Handle<S>,incoming:Maybe<&1,P>}
36 Despawned{handle:W.Handle<S>,removed:D}
37 DespawnRefused{handle:W.Handle<S>}
38 LinkedDespawn{handle:W.Handle<S>,status:LinkedStatus,receipts:List<Receipt<S,P,D>>,frames:List<&2,Relation.CleanupFrame<S>>}
39 Spawned{handle:W.Handle<S>,previous:D}
40 SpawnRefused{handle:W.Handle<S>,bundle:D,reason:Bundle.Refusal}
41 RelationPublished{route:Layout.Route,receipt:RelationStore.Receipt<S>}
42 RelationUndeclared{route:Layout.Route,operation:Operation.Operation<S>}
43 ScopePublished{route:Layout.Route,operation:ScopeCommands.Operation<S>,status:ScopeStatus,receipts:List<Receipt<S,P,D>>,frames:List<&2,Relation.CleanupFrame<S>>}
44 ScopeStoreApplied{route:Layout.Route,request:ScopeStore.Request<S>,result:ScopeDispatch.Outcome<S>}
45type Buffer<-S:Data,-P:Type,-D:Type> is Type:
46 Buffer{pending:List<Entry<S,P,D>>,receipts:List<Receipt<S,P,D>>}
47
48
49
50def empty(~S:Data,~P:Type,~D:Type) -> Buffer<S,P,D>:Buffer{[],[]}
51def relation(~S:Data,~P:Type,~D:Type,buffer:Buffer<S,P,D>,route:Layout.Route,operation:Operation.Operation<S>) -> Buffer<S,P,D>:
52 match buffer:
53 case Buffer{pending,receipts}:Buffer{Relation{route,operation} <> pending,receipts}
54def lifetime_scope(~S:Data,~P:Type,~D:Type,buffer:Buffer<S,P,D>,route:Layout.Route,operation:ScopeCommands.Operation<S>) -> Buffer<S,P,D>:
55 match buffer:
56 case Buffer{pending,receipts}:Buffer{LifetimeScope{route,operation} <> pending,receipts}
57def insert(~S:Data,~P:Type,~D:Type,buffer:Buffer<S,P,D>,handle:W.Handle<S>,incoming:P) -> Buffer<S,P,D>:
58 match buffer:
59 case Buffer{pending,receipts}:Buffer{Entry{handle,Some{incoming}} <> pending,receipts}
60def remove(~S:Data,~P:Type,~D:Type,buffer:Buffer<S,P,D>,handle:W.Handle<S>) -> Buffer<S,P,D>:
61 match buffer:
62 case Buffer{pending,receipts}:Buffer{Entry{handle,None{}} <> pending,receipts}
63def despawn(~S:Data,~P:Type,~D:Type,buffer:Buffer<S,P,D>,handle:W.Handle<S>) -> Buffer<S,P,D>:
64 match buffer:
65 case Buffer{pending,receipts}:Buffer{Despawn{handle} <> pending,receipts}
66def pending(~S:Data,~P:Type,~D:Type,buffer:Buffer<S,P,D>) -> Buffer<S,P,D> & Bool:
67 match buffer:
68 case Buffer{[],receipts}:(Buffer{[],receipts},False{})
69 case Buffer{head <> rest,receipts}:(Buffer{head <> rest,receipts},True{})
70def take_receipts(~S:Data,~P:Type,~D:Type,buffer:Buffer<S,P,D>) -> Buffer<S,P,D> & List<Receipt<S,P,D>>:
71 match buffer:
72 case Buffer{pending,receipts}:(Buffer{pending,[]},List.reverse(&1,Receipt<S,P,D>,receipts))
73
74
75type SpawnAdmission<-S:Data,-D:Type> is Type:
76 SpawnQueued{handle:W.Handle<S>}
77 SpawnRejected{bundle:D,error:W.WorldError}
78def stage(~S:Data,~P:Type,~D:Type,buffer:Buffer<S,P,D>,bundle:D,answer:W.Reservation<S>) -> Buffer<S,P,D> & SpawnAdmission<S,D>:
79 match buffer answer:
80 case Buffer{pending,receipts} W.ReservationRejected{error}:(Buffer{pending,receipts},SpawnRejected{bundle,error})
81 case Buffer{pending,receipts} W.Reserved{+handle}:(Buffer{Spawn{handle,bundle} <> pending,receipts},SpawnQueued{handle})
82def spawn(~S:Data,~P:Type,~D:Type,~Permit:Data,~F:Type -> Type,~effects:Effects.Effects<F>,~token:Permit,~request:Permit -> F(W.Reservation<S>),buffer:Buffer<S,P,D>,bundle:D) -> F(Buffer<S,P,D> & SpawnAdmission<S,D>):
83 Effects.map(~F,W.Reservation<S>,(Buffer<S,P,D> & SpawnAdmission<S,D>),effects,request(token),answer => stage(~S,~P,~D,buffer,bundle,answer))