1 import Base 2 import ./execution_query_identity.bend as Index 3 import ./execution_lifecycle_notices.bend as Notice 4 import ./world.bend as W 5 import ./entity_allocator.bend as A 6 import ./entity_key.bend as Key 7 import ./clock_state.bend as Clock 8 import ./change_tick.bend as Tick 9 import ./deferred_command.bend as Deferred 10 import ./execution_composer_layout.bend as Layout 11 import ./chunk_column.bend as Column 12 import ./execution_command_buffer.bend as Buffer 13 import ./execution_command_removed.bend as Removed 14 import ./execution_command_permission.bend as Permission 15 import ./execution_reservation_materialization.bend as Spawn 16 import ./execution_reservation_bundle.bend as Bundle 17 import ./execution_relation_buffer.bend as Relation 18 import ./execution_relation_context.bend as Context 19 import ./execution_lifetime_scope_buffer.bend as LifetimeScope 20 import ./execution_relation_linked_despawn.bend as Linked 21 import ./execution_lifetime_scope_coverage.bend as Coverage 22 23 # The interpreter owns the complete World. Gameplay supplies only raw affine 24 # payloads to its hidden queue; schema initialization happens at publication. 25 type Remainder<-S:Data,-C:Type,-R:Type,-E:Data> is Type: 26 Remainder{namespace:U32,resource:R,events:List<&2,E>,pending:List>>,registrations:List<&2,W.RegistrationMeta>,nextSystemId:U32,clock:Clock.State,lifecycle:Notice.Journal} 27 type Applied<-S:Data,-layout:Layout.Layout,-route:Layout.Route> is Type: 28 Applied{allocator:A.Allocator,column:Column.Column,receipt:Buffer.Receipt,removed:Bool} 29 def handle_namespace(~S:Data,handle:W.Handle) -> U32: 30 match handle: 31 case W.Handle{namespace,_}:namespace 32 def unwrap(~P:Type,~V:Data,value:Maybe<&1,Layout.Viewed>) -> Maybe<&1,P>: 33 match value: 34 case None{}:None{} 35 case Some{Layout.Viewed{owner,_}}:Some{owner} 36 def identity(~S:Data,handle:W.Handle) -> Notice.Identity: 37 match handle: 38 case W.Handle{namespace,key}:Notice.Identity{namespace,key} 39 def removed_notice(~S:Data,selector:Notice.Selector,entity:Notice.Identity,tick:Tick.Tick,journal:Notice.Journal,removed:Bool) -> Notice.Journal: 40 match removed: 41 case False{}:journal 42 case True{}:Notice.append(~S,selector,entity,tick,journal) 43 def swapped_previous(~S:Data,~layout:Layout.Layout,~route:Layout.Route,allocator:A.Allocator,column:Column.Column,handle:W.Handle,removing:Bool,previous:Maybe<&1,Layout.payload(layout,route)>) -> Applied: 44 match previous: 45 case None{}:Applied{allocator,column,Buffer.Applied{handle,None{}},False{}} 46 case Some{owner}:Applied{allocator,column,Buffer.Applied{handle,Some{owner}},removing} 47 def swapped(~S:Data,~layout:Layout.Layout,~route:Layout.Route,allocator:A.Allocator,handle:W.Handle,result:Column.SwapOutcome,removing:Bool) -> Applied: 48 match result: 49 case Column.Accepted{column,previous}:swapped_previous(~S,~layout,~route,allocator,column,handle,removing,unwrap(~(Layout.payload(layout,route)),~(Layout.view(layout,route)),previous)) 50 case Column.Rejected{column,incoming}:Applied{allocator,column,Buffer.Refused{handle,unwrap(~(Layout.payload(layout,route)),~(Layout.view(layout,route)),incoming)},False{}} 51 def insert_offset(~S:Data,~layout:Layout.Layout,~route:Layout.Route,allocator:A.Allocator,column:Column.Column,+handle:W.Handle,incoming:Layout.payload(layout,route),tick:Tick.Tick,offset:Maybe<&2,U32>) -> Applied: 52 match offset: 53 case None{}:Applied{allocator,column,Buffer.Refused{handle,Some{incoming}},False{}} 54 case Some{+offset}:swapped(~S,~layout,~route,allocator,handle,Column.swap_at(~S,~(Layout.stored(layout,route)),Column.ensure(~S,~(Layout.stored(layout,route)),column,U32.add(offset,1)),offset,Some{Layout.initialize(layout,route,incoming)},tick),False{}) 55 def insert_bounded(~S:Data,~layout:Layout.Layout,~route:Layout.Route,allocator:A.Allocator,column:Column.Column,+handle:W.Handle,incoming:Layout.payload(layout,route),tick:Tick.Tick,allowed:Bool) -> Applied: 56 match handle allowed: 57 case handle False{}:Applied{allocator,column,Buffer.Refused{handle,Some{incoming}},False{}} 58 case +handle True{}:insert_offset(~S,~layout,~route,allocator,column,handle,incoming,tick,Index.physical_index(W.handle_index(~S,handle))) 59 def remove_offset(~S:Data,~layout:Layout.Layout,~route:Layout.Route,allocator:A.Allocator,column:Column.Column,+handle:W.Handle,tick:Tick.Tick,offset:Maybe<&2,U32>) -> Applied: 60 match offset: 61 case None{}:Applied{allocator,column,Buffer.Refused{handle,None{}},False{}} 62 case Some{offset}:swapped(~S,~layout,~route,allocator,handle,Column.swap_at(~S,~(Layout.stored(layout,route)),column,offset,None{},tick),True{}) 63 def remove_present(~S:Data,~layout:Layout.Layout,~route:Layout.Route,allocator:A.Allocator,column:Column.Column,+handle:W.Handle,tick:Tick.Tick,present:Bool) -> Applied: 64 match handle present: 65 case handle False{}:Applied{allocator,column,Buffer.Applied{handle,None{}},False{}} 66 case +handle True{}:remove_offset(~S,~layout,~route,allocator,column,handle,tick,Index.physical_index(W.handle_index(~S,handle))) 67 def remove_bounded(~S:Data,~layout:Layout.Layout,~route:Layout.Route,allocator:A.Allocator,+handle:W.Handle,tick:Tick.Tick,result:Column.Column & U32) -> Applied: 68 match handle result: 69 case W.Handle{+namespace,+key}, (column,capacity):remove_present(~S,~layout,~route,allocator,column,W.Handle{namespace,key},tick,U32.is_le(Key.index(key),capacity)) 70 def prepared(~S:Data,~layout:Layout.Layout,~route:Layout.Route,allocator:A.Allocator,column:Column.Column,+handle:W.Handle,incoming:Maybe<&1,Layout.payload(layout,route)>,tick:Tick.Tick) -> Applied: 71 match handle incoming: 72 case handle None{}:remove_bounded(~S,~layout,~route,allocator,handle,tick,Column.capacity(~S,~(Layout.stored(layout,route)),column)) 73 case W.Handle{+namespace,+key} Some{owner}:insert_bounded(~S,~layout,~route,allocator,column,W.Handle{namespace,key},owner,tick,U32.is_le(Key.index(key),Column.maximum_capacity())) 74 def admitted(~S:Data,~layout:Layout.Layout,~route:Layout.Route,column:Column.Column,handle:W.Handle,incoming:Maybe<&1,Layout.payload(layout,route)>,tick:Tick.Tick,result:A.Allocator & Bool) -> Applied: 75 match result: 76 case (allocator,False{}):Applied{allocator,column,Buffer.Refused{handle,incoming},False{}} 77 case (allocator,True{}):prepared(~S,~layout,~route,allocator,column,handle,incoming,tick) 78 def namespaced(~S:Data,~layout:Layout.Layout,~route:Layout.Route,allocator:A.Allocator,column:Column.Column,handle:W.Handle,incoming:Maybe<&1,Layout.payload(layout,route)>,tick:Tick.Tick,allowed:Bool) -> Applied: 79 match handle allowed: 80 case handle False{}:Applied{allocator,column,Buffer.Refused{handle,incoming},False{}} 81 case W.Handle{+namespace,+key} True{}:admitted(~S,~layout,~route,column,W.Handle{namespace,key},incoming,tick,A.checked(allocator,key,1)) 82 def family_restored(~S:Data,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,rest:Layout.column_rest(~S,layout,route),remainder:Remainder,result:Applied,tick:Tick.Tick,handle:W.Handle) -> W.World & Buffer.Receipt: 83 match remainder result: 84 case Remainder{namespace,resource,events,pending,registrations,nextSystemId,clock,lifecycle} Applied{allocator,column,receipt,removed}:(W.World{namespace,allocator,Layout.column_put(~S,layout,route,rest,Layout.ColumnSlot{column}),resource,events,pending,registrations,nextSystemId,clock,removed_notice(~S,Notice.Removed{Layout.key(layout,route)},identity(~S,handle),tick,lifecycle,removed)},receipt) 85 def family_selected(~S:Data,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,allocator:A.Allocator,remainder:Remainder,+handle:W.Handle,incoming:Maybe<&1,Layout.payload(layout,route)>,+tick:Tick.Tick,result:Layout.column_rest(~S,layout,route) & Layout.ColumnSlot) -> W.World & Buffer.Receipt: 86 match remainder result: 87 case Remainder{+namespace,resource,events,pending,registrations,nextSystemId,clock,lifecycle}, (rest,Layout.ColumnSlot{column}):family_restored(~S,~R,~E,~layout,~route,rest,Remainder{namespace,resource,events,pending,registrations,nextSystemId,clock,lifecycle},namespaced(~S,~layout,~route,allocator,column,handle,incoming,tick,U32.is_eq(namespace,handle_namespace(~S,handle))),tick,handle) 88 def family(~S:Data,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,world:W.World,handle:W.Handle,incoming:Maybe<&1,Layout.payload(layout,route)>,tick:Tick.Tick) -> W.World & Buffer.Receipt: 89 match world: 90 case W.World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle}:family_selected(~S,~R,~E,~layout,~route,allocator,Remainder{namespace,resource,events,pending,registrations,nextSystemId,clock,lifecycle},handle,incoming,tick,Layout.column_take(~S,layout,route,store)) 91 # Bevy ad678262 system/commands/mod.rs EntityCommands::despawn queues a handled 92 # entity command; world/mod.rs despawn_with_caller refuses a missing entity and 93 # despawn removes all components before freeing its index. This boundary also 94 # returns each actual affine payload instead of dropping it. 95 def despawn_returned(-S:Data,-C:Type,-R:Type,-E:Data,-P:Type,-D:Type,namespace:U32,resource:R,events:List<&2,E>,pending:List>>,registrations:List<&2,W.RegistrationMeta>,nextSystemId:U32,clock:Clock.State,allocator:A.Allocator,store:C,+handle:W.Handle,tick:Tick.Tick,despawned:Notice.Identity -> Tick.Tick -> Notice.Journal -> Notice.Journal,result:Notice.Journal & D) -> W.World & Buffer.Receipt: 96 match handle result: 97 case W.Handle{+handleNamespace,+key}, (journal,removed):(W.World{namespace,A.release(A.write_phase(allocator,key,A.DeadRetained{}),key),store,resource,events,pending,registrations,nextSystemId,clock,despawned(Notice.Identity{handleNamespace,key},tick,journal)},Buffer.Despawned{W.Handle{handleNamespace,key},removed}) 98 def despawn_collected(-S:Data,-C:Type,-R:Type,-E:Data,-P:Type,-D:Type,allocator:A.Allocator,remainder:Remainder,+handle:W.Handle,result:C & D,+tick:Tick.Tick,notices:Notice.Identity -> Tick.Tick -> Notice.Journal -> D -> Notice.Journal & D,despawned:Notice.Identity -> Tick.Tick -> Notice.Journal -> Notice.Journal) -> W.World & Buffer.Receipt: 99 match remainder handle result: 100 case Remainder{namespace,resource,events,pending,registrations,nextSystemId,clock,lifecycle} W.Handle{+handleNamespace,+key}, (store,removed):despawn_returned(S,C,R,E,P,D,namespace,resource,events,pending,registrations,nextSystemId,clock,allocator,store,W.Handle{handleNamespace,key},tick,despawned,notices(Notice.Identity{handleNamespace,key},tick,lifecycle,removed)) 101 def despawn_offset(~S:Data,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,store:Layout.columns(~S,layout),remainder:Remainder,+handle:W.Handle,allocator:A.Allocator,+tick:Tick.Tick,offset:Maybe<&2,U32>) -> W.World & Buffer.Receipt: 102 match remainder offset: 103 case Remainder{namespace,resource,events,pending,registrations,nextSystemId,clock,lifecycle} None{}:(W.World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},Buffer.DespawnRefused{handle}) 104 case remainder Some{offset}:despawn_collected(S,Layout.columns(~S,layout),R,E,Layout.payload(layout,route),Removed.Removed(layout),allocator,remainder,handle,Removed.take(~S,layout)(offset,store),tick,Removed.notices(~S,layout),Notice.append(~S,Notice.Despawned{})) 105 def despawn_live(~S:Data,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,store:Layout.columns(~S,layout),remainder:Remainder,+handle:W.Handle,result:A.Allocator & Bool,+tick:Tick.Tick) -> W.World & Buffer.Receipt: 106 match remainder result: 107 case Remainder{namespace,resource,events,pending,registrations,nextSystemId,clock,lifecycle}, (allocator,False{}):(W.World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},Buffer.DespawnRefused{handle}) 108 case remainder, (allocator,True{}):despawn_offset(~S,~R,~E,~layout,~route,store,remainder,handle,allocator,tick,Index.physical_index(W.handle_index(~S,handle))) 109 def despawn_allowed(~S:Data,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,world:W.World,+handle:W.Handle,allowed:Bool,+tick:Tick.Tick) -> W.World & Buffer.Receipt: 110 match world allowed: 111 case world False{}:(world,Buffer.DespawnRefused{handle}) 112 case W.World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle} True{}:despawn_live(~S,~R,~E,~layout,~route,store,Remainder{namespace,resource,events,pending,registrations,nextSystemId,clock,lifecycle},handle,A.checked(allocator,W.handle_key(~S,handle),1),tick) 113 def despawn_namespace(~S:Data,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,+handle:W.Handle,permission:Permission.Permission,result:W.World & U32,+tick:Tick.Tick) -> W.World & Buffer.Receipt: 114 match result: 115 case (world,namespace):despawn_allowed(~S,~R,~E,~layout,~route,world,handle,Bool.and(Permission.agrees(permission,Permission.EntityStructural{}),U32.is_eq(namespace,handle_namespace(~S,handle))),tick) 116 def spawn_returned(~S:Data,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,result:Bundle.Publication) -> W.World & Buffer.Receipt: 117 match result: 118 case Bundle.Materialized{world,handle,previous}:(world,Buffer.Spawned{handle,previous}) 119 case Bundle.RefusedPublication{world,handle,bundle,reason}:(world,Buffer.SpawnRefused{handle,bundle,reason}) 120 def namespaced_liveness(same:Bool,result:A.Allocator & Bool) -> A.Allocator & Bool: 121 match result: 122 case (allocator,live):(allocator,Bool.and(same,live)) 123 def scope_dispose(~S:Data,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,world:W.World,handle:W.Handle,tick:Tick.Tick) -> W.World & Buffer.Receipt: 124 match world handle: 125 case W.World{+namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle} W.Handle{+handleNamespace,+key}:despawn_live(~S,~R,~E,~layout,~route,store,Remainder{namespace,resource,events,pending,registrations,nextSystemId,clock,lifecycle},W.Handle{handleNamespace,key},namespaced_liveness(U32.is_eq(namespace,handleNamespace),A.checked(allocator,key,1)),tick) 126 def despawn_path(~S:Data,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,~resources:Layout.Layout,~sameWR:{R == Layout.resources(~S,resources) : Type},~selection:Permission.Selection,~relations:Permission.Relations,protected:Bool,context:Context.Context,permission:Permission.Permission,world:W.World,+handle:W.Handle,tick:Tick.Tick) -> W.World & Buffer.Receipt: 127 match protected: 128 case False{}:despawn_namespace(~S,~R,~E,~layout,~route,handle,permission,W.namespace(~S,~Layout.columns(~S,layout),~R,~E,world),tick) 129 case True{}:Linked.apply(~S,~Layout.columns(~S,layout),~R,~E,~Layout.payload(layout,route),~Removed.Removed(layout),~resources,~sameWR,~selection,~relations,~scope_dispose(~S,~R,~E,~layout,~route),context,permission,world,handle,tick) 130 def scope_interpreter(~S:Data,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,~resources:Layout.Layout,~sameWR:{R == Layout.resources(~S,resources) : Type},~selection:Permission.Selection,~relations:Permission.Relations) -> LifetimeScope.Interpreter(~S,~Layout.columns(~S,layout),~R,~E,~Layout.payload(layout,route),~Removed.Removed(layout),~resources,~sameWR): 131 LifetimeScope.interpreter(~S,~Layout.columns(~S,layout),~R,~E,~Layout.payload(layout,route),~Removed.Removed(layout),~resources,~sameWR,~selection,~relations,~scope_dispose(~S,~R,~E,~layout,~route),~Coverage.has_protected(resources)) 132 def entry_interpreted(~S:Data,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,~resources:Layout.Layout,~sameWR:{R == Layout.resources(~S,resources) : Type},~selection:Permission.Selection,~relations:Permission.Relations,~scopeInterpreter:LifetimeScope.Interpreter(~S,~Layout.columns(~S,layout),~R,~E,~Layout.payload(layout,route),~Removed.Removed(layout),~resources,~sameWR),+context:Context.Context,permission:Permission.Permission,world:W.World,value:Buffer.Entry,tick:Tick.Tick) -> W.World & Buffer.Receipt: 133 match value: 134 case Buffer.Relation{resourceRoute,operation}:Relation.apply(~S,~Layout.columns(~S,layout),~R,~E,~Layout.payload(layout,route),~Removed.Removed(layout),~resources,~sameWR,~selection,context,resourceRoute,operation,world,tick) 135 case Buffer.LifetimeScope{resourceRoute,operation}:scopeInterpreter(context,resourceRoute,operation,world,tick) 136 case Buffer.Entry{handle,incoming}:family(~S,~R,~E,~layout,~route,world,handle,incoming,tick) 137 case Buffer.Spawn{handle,bundle}:spawn_returned(~S,~R,~E,~layout,~route,Spawn.apply_at(~S,~R,~E,~layout,permission,world,handle,bundle,tick)) 138 case Buffer.Despawn{+handle}:despawn_path(~S,~R,~E,~layout,~route,~resources,~sameWR,~selection,~relations,Coverage.has_protected(resources),context,permission,world,handle,tick) 139 def recorded(~S:Data,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,receipts:List>,result:W.World & Buffer.Receipt) -> W.World & List>: 140 match result: 141 case (world,receipt):(world,receipt <> receipts) 142 def next_interpreted(~S:Data,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,~resources:Layout.Layout,~sameWR:{R == Layout.resources(~S,resources) : Type},~selection:Permission.Selection,~relations:Permission.Relations,~scopeInterpreter:LifetimeScope.Interpreter(~S,~Layout.columns(~S,layout),~R,~E,~Layout.payload(layout,route),~Removed.Removed(layout),~resources,~sameWR),+context:Context.Context,permission:Permission.Permission,value:Buffer.Entry,tick:Tick.Tick,result:W.World & List>) -> W.World & List>: 143 match result: 144 case (world,receipts):recorded(~S,~R,~E,~layout,~route,receipts,entry_interpreted(~S,~R,~E,~layout,~route,~resources,~sameWR,~selection,~relations,~scopeInterpreter,context,permission,world,value,tick)) 145 def drain_interpreted(~S:Data,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,~resources:Layout.Layout,~sameWR:{R == Layout.resources(~S,resources) : Type},~selection:Permission.Selection,~relations:Permission.Relations,~scopeInterpreter:LifetimeScope.Interpreter(~S,~Layout.columns(~S,layout),~R,~E,~Layout.payload(layout,route),~Removed.Removed(layout),~resources,~sameWR),+context:Context.Context,+permission:Permission.Permission,entries:List>,world:W.World,+tick:Tick.Tick,receipts:List>) -> W.World & List>: 146 match entries: 147 case []:(world,receipts) 148 case value <> rest:next_interpreted(~S,~R,~E,~layout,~route,~resources,~sameWR,~selection,~relations,~scopeInterpreter,context,permission,value,tick,drain_interpreted(~S,~R,~E,~layout,~route,~resources,~sameWR,~selection,~relations,~scopeInterpreter,context,permission,rest,world,tick,receipts)) 149 def restored(~S:Data,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,result:W.World & List>) -> W.World & Buffer.Buffer: 150 match result: 151 case (world,receipts):(world,Buffer.Buffer{[],receipts}) 152 # Bevy ad678262 single_threaded.rs apply_deferred publishes each system's queued 153 # mutations after a barrier, including commands from handled body errors. This 154 # interpreter additionally returns all displaced affine owners in receipts. 155 def apply_at_interpreted(~S:Data,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,~valid:{Layout.grant_valid(~layout,~route) == True{} : Bool},~resources:Layout.Layout,~sameWR:{R == Layout.resources(~S,resources) : Type},~selection:Permission.Selection,~relations:Permission.Relations,~scopeInterpreter:LifetimeScope.Interpreter(~S,~Layout.columns(~S,layout),~R,~E,~Layout.payload(layout,route),~Removed.Removed(layout),~resources,~sameWR),+context:Context.Context,permission:Permission.Permission,world:W.World,buffer:Buffer.Buffer,tick:Tick.Tick) -> W.World & Buffer.Buffer: 156 match buffer: 157 case Buffer.Buffer{entries,receipts}:restored(~S,~R,~E,~layout,~route,drain_interpreted(~S,~R,~E,~layout,~route,~resources,~sameWR,~selection,~relations,~scopeInterpreter,context,permission,entries,world,tick,receipts)) 158 159 def apply_at(~S:Data,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,~valid:{Layout.grant_valid(~layout,~route) == True{} : Bool},~resources:Layout.Layout,~sameWR:{R == Layout.resources(~S,resources) : Type},~selection:Permission.Selection,~relations:Permission.Relations,+context:Context.Context,permission:Permission.Permission,world:W.World,buffer:Buffer.Buffer,tick:Tick.Tick) -> W.World & Buffer.Buffer: 160 apply_at_interpreted(~S,~R,~E,~layout,~route,~valid,~resources,~sameWR,~selection,~relations,~LifetimeScope.apply(~S,~Layout.columns(~S,layout),~R,~E,~Layout.payload(layout,route),~Removed.Removed(layout),~resources,~sameWR,~selection,~relations,~scope_dispose(~S,~R,~E,~layout,~route)),context,permission,world,buffer,tick)