1 import Base 2 import ./execution_lifecycle_notices.bend as Notice 3 import ./clock_state.bend as Clock 4 import entity_key.bend as Key 5 import entity_allocator.bend as Alloc 6 import ./world.bend as W 7 import ./decode_data.bend as D 8 import ./deferred_command.bend as Deferred 9 10 # Basic detached Data only; runtime checkpoint state is intentionally not encoded. 11 type Entity is Data: 12 Entity{key:Key.Key,components:List<&2,D.Field>} 13 type Snapshot is Data: 14 Snapshot{version:U32,nextEntity:U32,entities:List<&2,Entity>,resources:List<&2,D.Field>} 15 16 # Ordinary save either exports detached Data or refuses pending structural work. 17 # Refusal returns the same World separately; it does not execute or discard work. 18 type Outcome is Data: 19 Saved{snapshot:A} 20 RefusedPending{} 21 22 def pending_ready(~World:Type,pending:List>) -> List> & Bool: 23 match pending: 24 case []:([],True{}) 25 case command <> rest:(command <> rest,False{}) 26 def ready_joined(~S:Data,~C:Type,~R:Type,~E:Data,namespace:U32,allocator:Alloc.Allocator,store:C,resource:R,events:List<&2,E>,registrations:List<&2,W.RegistrationMeta>,nextSystemId:U32,clock:Clock.State,result:List>> & Bool,lifecycle:Notice.Journal) -> W.World & Bool: 27 match result: 28 case (pending,ready):(W.World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},ready) 29 # Internal constant-time structural admission, before any trusted projection. 30 def ready(~S:Data,~C:Type,~R:Type,~E:Data,world:W.World) -> W.World & Bool: 31 match world: 32 case W.World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle}:ready_joined(~S,~C,~R,~E,namespace,allocator,store,resource,events,registrations,nextSystemId,clock,pending_ready(~W.World,pending),lifecycle) 33 34 # Internal experimental accessor: exact actual allocator, no inferred live count. 35 # Rebuild the SAME owner with every field returned unchanged. 36 def allocator(~S:Data,~C:Type,~R:Type,~E:Data,world:W.World) -> W.World & U32: 37 match world: 38 case W.World{+namespace,Alloc.Allocator{+nextId,+high,slots,+capacity,+depth,+free,+order},store,resource,+events,pending,+registrations,+nextSystemId,+clock,lifecycle}: 39 (W.World{namespace,Alloc.Allocator{nextId,high,slots,capacity,depth,free,order},store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},nextId) 40 41 # Closed schema providers must return the actual store/resource owners. Their 42 # projections, transient omission and name bindings are trusted author inputs. 43 # This is NOT the still-missing public constructed-descriptor validation gate. 44 def finish(~S:Data,~C:Type,~R:Type,~E:Data,nextEntity:U32,entities:List<&2,Entity>,observed:W.World & List<&2,D.Field>) -> W.World & Snapshot: 45 match observed: 46 case (world,fields):(world,Snapshot{1,nextEntity,entities,fields}) 47 def with_entities(~S:Data,~C:Type,~R:Type,~E:Data,~resources:R -> R & List<&2,D.Field>,nextEntity:U32,observed:W.World & List<&2,Entity>) -> W.World & Snapshot: 48 match observed: 49 case (world,entities):finish(~S,~C,~R,~E,nextEntity,entities,W.observe_resource(~S,~C,~R,~E,~List<&2,D.Field>,~resources,world)) 50 def with_handles(~S:Data,~C:Type,~R:Type,~E:Data,~rows:List<&2,W.Handle> -> C -> C & List<&2,Entity>,~resources:R -> R & List<&2,D.Field>,nextEntity:U32,observed:W.World & List<&2,W.Handle>) -> W.World & Snapshot: 51 match observed: 52 case (world,handles):with_entities(~S,~C,~R,~E,~resources,nextEntity,W.with_store(~S,~C,~R,~E,~List<&2,Entity>,rows(handles),world)) 53 def with_allocator(~S:Data,~C:Type,~R:Type,~E:Data,~rows:List<&2,W.Handle> -> C -> C & List<&2,Entity>,~resources:R -> R & List<&2,D.Field>,observed:W.World & U32) -> W.World & Snapshot: 54 match observed: 55 case (world,nextEntity):with_handles(~S,~C,~R,~E,~rows,~resources,nextEntity,W.handles(~S,~C,~R,~E,world)) 56 def saved(~S:Data,~C:Type,~R:Type,~E:Data,result:W.World & Snapshot) -> W.World & Outcome: 57 match result: 58 case (world,snapshot):(world,Saved{snapshot}) 59 def basic_ready(~S:Data,~C:Type,~R:Type,~E:Data,~rows:List<&2,W.Handle> -> C -> C & List<&2,Entity>,~resources:R -> R & List<&2,D.Field>,result:W.World & Bool) -> W.World & Outcome: 60 match result: 61 case (world,False{}):(world,RefusedPending{}) 62 case (world,True{}):saved(~S,~C,~R,~E,with_allocator(~S,~C,~R,~E,~rows,~resources,allocator(~S,~C,~R,~E,world))) 63 def basic(~S:Data,~C:Type,~R:Type,~E:Data,~rows:List<&2,W.Handle> -> C -> C & List<&2,Entity>,~resources:R -> R & List<&2,D.Field>,world:W.World) -> W.World & Outcome: 64 basic_ready(~S,~C,~R,~E,~rows,~resources,ready(~S,~C,~R,~E,world))