execution_lifetime_scope_cleanup.bend

bendvy-ecs-core@0.1.0.3 · 111 lines · 25 definitions

1import Base
2import bendvy-ecs-core@0.1.0.3/world.bend as W
3import bendvy-ecs-core@0.1.0.3/entity_key.bend as Key
4import bendvy-ecs-core@0.1.0.3/entity_allocator.bend as Allocator
5import bendvy-ecs-core@0.1.0.3/execution_relation_world_publication.bend as WorldFrame
6import bendvy-ecs-core@0.1.0.3/relation_types.bend as T
7import bendvy-ecs-core@0.1.0.3/relation_graph.bend as Graph
8import bendvy-ecs-core@0.1.0.3/relation_cleanup_control.bend as Control
9import bendvy-ecs-core@0.1.0.3/relation_cleanup_engine.bend as Engine
10import bendvy-ecs-core@0.1.0.3/execution_composer_layout.bend as Layout
11import bendvy-ecs-core@0.1.0.3/execution_command_buffer.bend as Buffer
12import bendvy-ecs-core@0.1.0.3/execution_command_permission.bend as Permission
13import bendvy-ecs-core@0.1.0.3/execution_relation_buffer.bend as Relation
14import bendvy-ecs-core@0.1.0.3/execution_relation_operation.bend as Operation
15import bendvy-ecs-core@0.1.0.3/execution_relation_context.bend as Context
16import bendvy-ecs-core@0.1.0.3/execution_relation_resource_snapshot.bend as Snapshot
17import bendvy-ecs-core@0.1.0.3/execution_lifetime_scope_world_access.bend as Access
18import bendvy-ecs-core@0.1.0.3/execution_lifetime_scope_store.bend as Store
19import bendvy-ecs-core@0.1.0.3/execution_lifetime_scope_resource_dispatch.bend as Dispatch
20import bendvy-ecs-core@0.1.0.3/change_tick.bend as Tick
21
22# Bevy ad678262ce53b5d142fe49ee5e08caff6f00ab60 hierarchy.rs:50 deletes
23# linked descendants. This adapter also returns each actual affine owner.
24type AfterDespawn is Data:
25  KeepMembership{}
26  ForgetMembership{routes:List<&2,Layout.Route>}
27type State<-S:Data,-C:Type,-R:Type,-E:Data,-P:Type,-D:Type> is Type:
28  State{world:W.World<S,C,R,E>,receipts:List<Buffer.Receipt<S,P,D>>,after:AfterDespawn,tick:Tick.Tick,blocked:Bool}
29def Dispose(~S:Data,~C:Type,~R:Type,~E:Data,~P:Type,~D:Type) -> Type:
30  W.World<S,C,R,E> -> W.Handle<S> -> Tick.Tick -> W.World<S,C,R,E> & Buffer.Receipt<S,P,D>
31def live_returned(-S:Data,-C:Type,-R:Type,-E:Data,same:Bool,resource:R,frame:WorldFrame.Frame<S,C,R,E>,result:Allocator.Allocator & Bool) -> W.World<S,C,R,E> & Bool:
32  match frame result:
33    case WorldFrame.Frame{namespace,columns,events,pending,registrations,nextSystem,clock,lifecycle}, (allocator,live):(W.World{namespace,allocator,columns,resource,events,pending,registrations,nextSystem,clock,lifecycle},Bool.and(same,live))
34def live(-S:Data,-C:Type,-R:Type,-E:Data,world:W.World<S,C,R,E>,handle:W.Handle<S>) -> W.World<S,C,R,E> & Bool:
35  match world handle:
36    case W.World{+namespace,allocator,columns,resource,events,pending,registrations,nextSystem,clock,lifecycle} W.Handle{handleNamespace,key}:live_returned(S,C,R,E,U32.is_eq(namespace,handleNamespace),resource,WorldFrame.Frame{namespace,columns,events,pending,registrations,nextSystem,clock,lifecycle},Allocator.checked(allocator,key,1))
37def find(-S:Data,+descriptor:T.Descriptor<S>,views:List<&2,Snapshot.GraphView<S>>) -> Maybe<&2,Snapshot.GraphView<S>>:
38  match views:
39    case []:None{}
40    case Snapshot.GraphView{route,+other,namespace,graph} <> rest:Bool.pick(Maybe<&2,Snapshot.GraphView<S>>,Permission.same_descriptor(S,descriptor,other),Some{Snapshot.GraphView{route,other,namespace,graph}},find(S,descriptor,rest))
41def children_selected(-S:Data,key:Key.Key,found:Maybe<&2,Snapshot.GraphView<S>>) -> List<&2,Key.Key>:
42  match found:
43    case None{}:[]
44    case Some{Snapshot.GraphView{_,descriptor,_,graph}}:Graph.inverse_erased(S,graph,descriptor,key)
45def children(-S:Data,descriptor:T.Descriptor<S>,key:Key.Key,views:List<&2,Snapshot.GraphView<S>>) -> List<&2,Key.Key>:
46  children_selected(S,key,find(S,descriptor,views))
47def descriptors(-S:Data,views:List<&2,Snapshot.GraphView<S>>) -> List<&2,T.Descriptor<S>>:
48  match views:
49    case []:[]
50    case Snapshot.GraphView{_,descriptor,_,_} <> rest:descriptor <> descriptors(S,rest)
51def edges(-S:Data,views:List<&2,Snapshot.GraphView<S>>) -> List<&2,T.Edge<S>>:
52  match views:
53    case []:[]
54    case Snapshot.GraphView{_,_,_,T.Graph{found,_}} <> rest:List.append(&2,T.Edge<S>,found,edges(S,rest))
55def checked(-S:Data,-C:Type,-R:Type,-E:Data,-P:Type,-D:Type,receipts:List<Buffer.Receipt<S,P,D>>,after:AfterDespawn,tick:Tick.Tick,key:Key.Key,descriptors:List<&2,T.Descriptor<S>>,frames:List<&2,T.CleanupFrame<S>>,result:W.World<S,C,R,E> & Bool) -> State<S,C,R,E,P,D> & List<&2,T.CleanupFrame<S>>:
56  match result:
57    case (world,False{}):(State{world,receipts,after,tick,False{}},frames)
58    case (world,True{}):(State{world,receipts,after,tick,False{}},T.CleanupDescriptors{key,descriptors} <> frames)
59def observed(-S:Data,-C:Type,-R:Type,-E:Data,-P:Type,-D:Type,receipts:List<Buffer.Receipt<S,P,D>>,after:AfterDespawn,tick:Tick.Tick,+key:Key.Key,+descriptor:T.Descriptor<S>,remaining:List<&2,T.Descriptor<S>>,frames:List<&2,T.CleanupFrame<S>>,result:W.World<S,C,R,E> & List<&2,Snapshot.GraphView<S>>) -> State<S,C,R,E,P,D> & List<&2,T.CleanupFrame<S>>:
60  match result:
61    case (world,views):(State{world,receipts,after,tick,False{}},T.CleanupChildren{key,descriptor,remaining,children(S,descriptor,key,views)} <> frames)
62def recorded(-S:Data,-C:Type,-R:Type,-E:Data,-P:Type,-D:Type,receipts:List<Buffer.Receipt<S,P,D>>,after:AfterDespawn,tick:Tick.Tick,frames:List<&2,T.CleanupFrame<S>>,result:W.World<S,C,R,E> & Buffer.Receipt<S,P,D>) -> State<S,C,R,E,P,D> & List<&2,T.CleanupFrame<S>>:
63  match result:
64    case (world,receipt):(State{world,receipt <> receipts,after,tick,False{}},frames)
65def forgotten(-S:Data,-C:Type,-R:Type,-E:Data,-P:Type,-D:Type,route:Layout.Route,handle:W.Handle<S>,receipts:List<Buffer.Receipt<S,P,D>>,next:W.World<S,C,R,E> -> List<Buffer.Receipt<S,P,D>> -> State<S,C,R,E,P,D> & List<&2,T.CleanupFrame<S>>,result:W.World<S,C,R,E> & Dispatch.Outcome<S>) -> State<S,C,R,E,P,D> & List<&2,T.CleanupFrame<S>>:
66  match result:
67    case (world,result):next(world,Buffer.ScopeStoreApplied{route,Store.Forget{handle},result} <> receipts)
68def forget_routes(~S:Data,~C:Type,~R:Type,~E:Data,~P:Type,~D:Type,~resources:Layout.Layout,~same:{R == Layout.resources(~S,resources) : Type},~selection:Permission.Selection<S,resources>,+namespace:U32,+after:AfterDespawn,+tick:Tick.Tick,+handle:W.Handle<S>,+frames:List<&2,T.CleanupFrame<S>>,routes:List<&2,Layout.Route>,receipts:List<Buffer.Receipt<S,P,D>>,world:W.World<S,C,R,E>) -> State<S,C,R,E,P,D> & List<&2,T.CleanupFrame<S>>:
69  match routes:
70    case []:(State{world,receipts,after,tick,False{}},frames)
71    case +route <> rest:forgotten(S,C,R,E,P,D,route,handle,receipts,world => receipts => forget_routes(~S,~C,~R,~E,~P,~D,~resources,~same,~selection,namespace,after,tick,handle,frames,rest,receipts,world),Access.apply(~S,~C,~R,~E,~resources,~same,~selection,Context.Context{namespace},route,Store.Forget{handle},world,tick))
72def post_dispose(~S:Data,~C:Type,~R:Type,~E:Data,~P:Type,~D:Type,~resources:Layout.Layout,~same:{R == Layout.resources(~S,resources) : Type},~selection:Permission.Selection<S,resources>,namespace:U32,receipts:List<Buffer.Receipt<S,P,D>>,after:AfterDespawn,tick:Tick.Tick,handle:W.Handle<S>,frames:List<&2,T.CleanupFrame<S>>,world:W.World<S,C,R,E>) -> State<S,C,R,E,P,D> & List<&2,T.CleanupFrame<S>>:
73  match after:
74    case KeepMembership{}:(State{world,receipts,KeepMembership{},tick,False{}},frames)
75    case ForgetMembership{+routes}:forget_routes(~S,~C,~R,~E,~P,~D,~resources,~same,~selection,namespace,ForgetMembership{routes},tick,handle,frames,routes,receipts,world)
76def disposed(~S:Data,~C:Type,~R:Type,~E:Data,~P:Type,~D:Type,~resources:Layout.Layout,~same:{R == Layout.resources(~S,resources) : Type},~selection:Permission.Selection<S,resources>,namespace:U32,receipts:List<Buffer.Receipt<S,P,D>>,after:AfterDespawn,tick:Tick.Tick,frames:List<&2,T.CleanupFrame<S>>,result:W.World<S,C,R,E> & Buffer.Receipt<S,P,D>) -> State<S,C,R,E,P,D> & List<&2,T.CleanupFrame<S>>:
77  match result:
78    case (world,Buffer.Despawned{+handle,removed}):post_dispose(~S,~C,~R,~E,~P,~D,~resources,~same,~selection,namespace,Buffer.Despawned{handle,removed} <> receipts,after,tick,handle,frames,world)
79    case (world,receipt):recorded(S,C,R,E,P,D,receipts,after,tick,frames,(world,receipt))
80def unlink_selected(~S:Data,~C:Type,~R:Type,~E:Data,~P:Type,~D:Type,~resources:Layout.Layout,~same:{R == Layout.resources(~S,resources) : Type},~selection:Permission.Selection<S,resources>,+namespace:U32,receipts:List<Buffer.Receipt<S,P,D>>,after:AfterDespawn,+tick:Tick.Tick,key:Key.Key,original:T.CleanupFrame<S>,frames:List<&2,T.CleanupFrame<S>>,world:W.World<S,C,R,E>,found:Maybe<&2,Snapshot.GraphView<S>>) -> State<S,C,R,E,P,D> & List<&2,T.CleanupFrame<S>>:
81  match found:
82    case None{}:(State{world,receipts,after,tick,True{}},original <> frames)
83    case Some{Snapshot.GraphView{route,_,_,_}}:recorded(S,C,R,E,P,D,receipts,after,tick,frames,Relation.apply(~S,~C,~R,~E,~P,~D,~resources,~same,~selection,Context.Context{namespace},route,Operation.Unrelate{W.Handle{namespace,key}},world,tick))
84def unlinked(~S:Data,~C:Type,~R:Type,~E:Data,~P:Type,~D:Type,~resources:Layout.Layout,~same:{R == Layout.resources(~S,resources) : Type},~selection:Permission.Selection<S,resources>,namespace:U32,receipts:List<Buffer.Receipt<S,P,D>>,after:AfterDespawn,+tick:Tick.Tick,key:Key.Key,descriptor:T.Descriptor<S>,original:T.CleanupFrame<S>,frames:List<&2,T.CleanupFrame<S>>,result:W.World<S,C,R,E> & List<&2,Snapshot.GraphView<S>>) -> State<S,C,R,E,P,D> & List<&2,T.CleanupFrame<S>>:
85  match result:
86    case (world,views):unlink_selected(~S,~C,~R,~E,~P,~D,~resources,~same,~selection,namespace,receipts,after,tick,key,original,frames,world,find(S,descriptor,views))
87def interpreted(~S:Data,~C:Type,~R:Type,~E:Data,~P:Type,~D:Type,~resources:Layout.Layout,~same:{R == Layout.resources(~S,resources) : Type},~selection:Permission.Selection<S,resources>,~dispose:Dispose(~S,~C,~R,~E,~P,~D),intent:Control.Intent<S>,original:T.CleanupFrame<S>,world:W.World<S,C,R,E>,receipts:List<Buffer.Receipt<S,P,D>>,after:AfterDespawn,+tick:Tick.Tick,+namespace:U32) -> State<S,C,R,E,P,D> & List<&2,T.CleanupFrame<S>>:
88  match intent:
89    case Control.Check{+key,descriptors,frames}:checked(S,C,R,E,P,D,receipts,after,tick,key,descriptors,frames,live(S,C,R,E,world,W.Handle{namespace,key}))
90    case Control.Observe{key,descriptor,remaining,frames}:observed(S,C,R,E,P,D,receipts,after,tick,key,descriptor,remaining,frames,Access.graphs(~S,~C,~R,~E,~resources,~same,~selection,world))
91    case Control.Unrelate{key,descriptor,frames}:unlinked(~S,~C,~R,~E,~P,~D,~resources,~same,~selection,namespace,receipts,after,tick,key,descriptor,original,frames,Access.graphs(~S,~C,~R,~E,~resources,~same,~selection,world))
92    case Control.Finish{key,frames}:disposed(~S,~C,~R,~E,~P,~D,~resources,~same,~selection,namespace,receipts,after,tick,frames,dispose(world,W.Handle{namespace,key},tick))
93    case Control.Continue{frames}:(State{world,receipts,after,tick,False{}},frames)
94def step_shared(~S:Data,~C:Type,~R:Type,~E:Data,~P:Type,~D:Type,~resources:Layout.Layout,~same:{R == Layout.resources(~S,resources) : Type},~selection:Permission.Selection<S,resources>,~dispose:Dispose(~S,~C,~R,~E,~P,~D),frame:T.CleanupFrame<S>,state:State<S,C,R,E,P,D>,+namespace:U32,descriptors:List<&2,T.Descriptor<S>>,frames:List<&2,T.CleanupFrame<S>>) -> State<S,C,R,E,P,D> & List<&2,T.CleanupFrame<S>>:
95  match frame state:
96    case frame State{world,receipts,after,tick,True{}}:(State{world,receipts,after,tick,True{}},frame <> frames)
97    case +frame State{world,receipts,after,tick,False{}}:interpreted(~S,~C,~R,~E,~P,~D,~resources,~same,~selection,~dispose,Control.next(S,frame,descriptors,frames),frame,world,receipts,after,tick,namespace)
98def step(~S:Data,~C:Type,~R:Type,~E:Data,~P:Type,~D:Type,~resources:Layout.Layout,~same:{R == Layout.resources(~S,resources) : Type},~selection:Permission.Selection<S,resources>,~dispose:Dispose(~S,~C,~R,~E,~P,~D),frame:T.CleanupFrame<S>,state:State<S,C,R,E,P,D>,+namespace:U32,descriptors:List<&2,T.Descriptor<S>>,frames:List<&2,T.CleanupFrame<S>>) -> State<S,C,R,E,P,D> & List<&2,T.CleanupFrame<S>>:
99  step_shared(~S,~C,~R,~E,~P,~D,~resources,~same,~selection,~dispose,frame,state,namespace,descriptors,frames)
100def member_frames(~S:Data,members:List<&2,Key.Key>) -> List<&2,T.CleanupFrame<S>>:
101  match members:
102    case []:[]
103    case key <> rest:T.CleanupEnter{key} <> member_frames(~S,rest)
104def continued(~S:Data,~C:Type,~R:Type,~E:Data,~P:Type,~D:Type,members:List<&2,Key.Key>,result:Engine.Progress<S,State<S,C,R,E,P,D>>,next:State<S,C,R,E,P,D> -> Engine.Progress<S,State<S,C,R,E,P,D>>) -> Engine.Progress<S,State<S,C,R,E,P,D>>:
105  match result:
106    case Engine.Incomplete{state,frames}:Engine.Incomplete{state,List.append(&2,T.CleanupFrame<S>,frames,member_frames(~S,members))}
107    case Engine.Complete{state}:next(state)
108def members_step(~S:Data,~C:Type,~R:Type,~E:Data,~P:Type,~D:Type,~resources:Layout.Layout,~same:{R == Layout.resources(~S,resources) : Type},~selection:Permission.Selection<S,resources>,~dispose:Dispose(~S,~C,~R,~E,~P,~D),+nodes:Nat,+originalEdges:List<&2,T.Edge<S>>,+namespace:U32,+descriptors:List<&2,T.Descriptor<S>>,members:List<&2,Key.Key>,state:State<S,C,R,E,P,D>) -> Engine.Progress<S,State<S,C,R,E,P,D>>:
109  match members:
110    case []:Engine.Complete{state}
111    case key <> +rest:continued(~S,~C,~R,~E,~P,~D,rest,Engine.automatic(~S,~State<S,C,R,E,P,D>,~step_shared(~S,~C,~R,~E,~P,~D,~resources,~same,~selection,~dispose),state,nodes,originalEdges,namespace,key,descriptors),state => members_step(~S,~C,~R,~E,~P,~D,~resources,~same,~selection,~dispose,nodes,originalEdges,namespace,descriptors,rest,state))