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# Framework storage for one declared component family. Payloads remain affine
14# until a whole-World barrier applies them or returns them in a refusal receipt.
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# Bevy ad678262, schedule/executor/single_threaded.rs: run_without_applying_deferred
48# keeps the system's authored buffer, including after a handled RunSystemError.
49# Enqueue here only transfers ownership; no component storage is available.
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# Admission returns the actual bundle if canonical reservation was refused.
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))