execution_state.bend

bendvy-ecs-core@0.1.0.3 · 61 lines · 16 definitions

1import Base
2import bendvy-ecs-core@0.1.0.3/execution_lifecycle_notices.bend as Notice
3import bendvy-ecs-core@0.1.0.3/world.bend as W
4import bendvy-ecs-core@0.1.0.3/entity_allocator.bend as A
5import bendvy-ecs-core@0.1.0.3/entity_key.bend as K
6import bendvy-ecs-core@0.1.0.3/clock_state.bend as Clock
7import bendvy-ecs-core@0.1.0.3/change_tick.bend as Tick
8import bendvy-ecs-core@0.1.0.3/deferred_command.bend as Deferred
9import bendvy-ecs-core@0.1.0.3/execution_reservation_authority.bend as Authority
10
11type Invocation<-S:Data> is Type:
12  Invocation{namespace:U32,allocator:A.Allocator,admitted:Maybe<&2,U32>,permit:Authority.Permit}
13type Scope<-S:Data,-C:Type,-R:Type> is Type:
14  Scope{store:C,resource:R,handles:List<&2,W.Handle<S>>,tick:Tick.Tick,prior:Maybe<&2,Tick.Tick>,lifecycleView:Notice.View<S>}
15type Administration<-S:Data,-C:Type,-R:Type,-E:Data> is Type:
16  Administration{events:List<&2,E>,pending:List<Deferred.Command<W.World<S,C,R,E>>>,registrations:List<&2,W.RegistrationMeta>,nextSystemId:U32,clock:Clock.State,lifecycle:Notice.Journal<S>}
17def separated_snapshot(~S:Data,~C:Type,~R:Type,~E:Data,namespace:U32,allocator:A.Allocator,store:C,resource:R,events:List<&2,E>,pending:List<Deferred.Command<W.World<S,C,R,E>>>,registrations:List<&2,W.RegistrationMeta>,nextSystemId:U32,clock:Clock.State,handles:List<&2,W.Handle<S>>,tick:Tick.Tick,snapshot:Notice.Journal<S> & Notice.View<S>) -> Administration<S,C,R,E> & (Invocation<S> & Scope<S,C,R>):
18  match snapshot:
19    case (lifecycle,lifecycleView):(Administration{events,pending,registrations,nextSystemId,clock,lifecycle},(Invocation{namespace,allocator,None{},Authority.Unauthorized{}},Scope{store,resource,handles,tick,None{},lifecycleView}))
20def separated(~S:Data,~C:Type,~R:Type,~E:Data,tick:Tick.Tick,observed:W.World<S,C,R,E> & List<&2,W.Handle<S>>) -> Administration<S,C,R,E> & (Invocation<S> & Scope<S,C,R>):
21  match observed:
22    case (W.World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},handles):separated_snapshot(~S,~C,~R,~E,namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,handles,tick,Notice.snapshot(~S,lifecycle))
23def separate(~S:Data,~C:Type,~R:Type,~E:Data,world:W.World<S,C,R,E>,tick:Tick.Tick) -> Administration<S,C,R,E> & (Invocation<S> & Scope<S,C,R>):
24  separated(~S,~C,~R,~E,tick,W.handles(~S,~C,~R,~E,world))
25def reassemble(~S:Data,~C:Type,~R:Type,~E:Data,admin:Administration<S,C,R,E>,invocation:Invocation<S>,scope:Scope<S,C,R>) -> W.World<S,C,R,E>:
26  match admin invocation scope:
27    case Administration{events,pending,registrations,nextSystemId,clock,lifecycle} Invocation{namespace,allocator,_,_} Scope{store,resource,_,_,_,+lifecycleView}:W.World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle}
28def same(~S:Data,left:W.Handle<S>,right:W.Handle<S>) -> Bool:
29  match left right:
30    case W.Handle{ln,lk} W.Handle{rn,rk}:Bool.and(U32.is_eq(ln,rn),K.equal(lk,rk))
31def member(~S:Data,+handle:W.Handle<S>,handles:List<&2,W.Handle<S>>) -> Bool:
32  match handles:
33    case []:False{}
34    case current <> rest:Bool.or(same(~S,handle,current),member(~S,handle,rest))
35
36# The cursor belongs to this admitted system, independently of the shared clock.
37def window(~S:Data,~C:Type,~R:Type,scope:Scope<S,C,R>,prior:Maybe<&2,Tick.Tick>) -> Scope<S,C,R>:
38  match scope:
39    case Scope{store,resource,handles,tick,_,+lifecycleView}:Scope{store,resource,handles,tick,prior,lifecycleView}
40
41def admit(~S:Data,+id:U32,grant:Authority.Grant,invocation:Invocation<S>) -> Invocation<S>:
42  match invocation:
43    case Invocation{+namespace,allocator,_,_}:Invocation{namespace,allocator,Some{id},Authority.qualified(Authority.Context{namespace,id,grant})}
44def reserved_pending(-S:Data,+namespace:U32,authorized:Maybe<&2,U32>,permit:Authority.Permit,handle:W.Handle<S>,result:A.Allocator & Bool) -> Invocation<S> & W.Reservation<S>:
45  match result:
46    case (allocator,True{}):(Invocation{namespace,allocator,authorized,permit},W.Reserved{handle})
47    case (allocator,False{}):(Invocation{namespace,allocator,authorized,permit},W.ReservationRejected{W.MissingEntity{}})
48def reserved(-S:Data,+namespace:U32,authorized:Maybe<&2,U32>,permit:Authority.Permit,result:A.Allocator & A.Reservation) -> Invocation<S> & W.Reservation<S>:
49  match result:
50    case (allocator,A.Exhausted{}):(Invocation{namespace,allocator,authorized,permit},W.ReservationRejected{W.CapacityExceeded{}})
51    case (allocator,A.Reserved{+key}):reserved_pending(S,namespace,authorized,permit,W.Handle{namespace,key},A.set(allocator,key,A.Pending{}))
52def reserve_allowed(-S:Data,allowed:Bool,invocation:Invocation<S>) -> Invocation<S> & W.Reservation<S>:
53  match allowed invocation:
54    case False{} invocation:(invocation,W.ReservationRejected{W.ReservationUnauthorized{}})
55    case True{} Invocation{namespace,allocator,authorized,permit}:reserved(S,namespace,authorized,permit,A.reserve(allocator))
56def reserve_invocation(-S:Data,invocation:Invocation<S>) -> Invocation<S> & W.Reservation<S>:
57  match invocation:
58    case Invocation{+namespace,allocator,+authorized,+permit}:reserve_allowed(S,Authority.admitted(permit,namespace,authorized),Invocation{namespace,allocator,authorized,permit})
59def request(~S:Data,token:Authority.Granted,invocation:Invocation<S>) -> Invocation<S> & W.Reservation<S>:
60  match token:
61    case Authority.Granted{}:reserve_invocation(S,invocation)