execution_machine_state.bend

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

1import Base
2import bendvy-ecs-core@0.1.0.3/machine.bend as M
3import bendvy-ecs-core@0.1.0.3/machine_queue.bend as Queue
4import bendvy-ecs-core@0.1.0.3/execution_machine_stream.bend as Stream
5import bendvy-ecs-core@0.1.0.3/change_tick.bend as Tick
6
7# The Cell is framework storage. Ordinary bodies receive declaration-derived ops.
8type Cell<-S:Data,-K:Data,-V:Data> is Type:
9  Cell{slot:M.Slot<S,K,V>,stream:Stream.Store<V>,revision:Nat,stamp:Maybe<&2,Tick.Tick>,nextStamp:Maybe<&2,Tick.Tick>,sequence:Nat,initialPending:Bool,namespace:Maybe<&2,U32>,intent:Intent<V>}
10type Intent<-V:Data> is Data:
11  Idle{}
12  Initial{value:V}
13  Transition{from:V,to:V,runExitEnter:Bool}
14type View<-S:Data,-K:Data,-V:Data> is Data:
15  View{current:M.CurrentView<S,K,V>,next:M.NextView<S,K,V>,revision:Nat,stamp:Maybe<&2,Tick.Tick>,nextStamp:Maybe<&2,Tick.Tick>,intent:Intent<V>}
16def empty(~S:Data,~K:Data,~V:Data) -> Cell<S,K,V>:
17  Cell{M.Missing{},Stream.empty(~V),0n,None{},None{},0n,False{},None{},Idle{}}
18def projected(-S:Data,-K:Data,-V:Data,cell:Cell<S,K,V>) -> Cell<S,K,V> & View<S,K,V>:
19  match cell:
20    case Cell{+slot,stream,+revision,+stamp,+nextStamp,sequence,initialPending,namespace,+intent}:(Cell{slot,stream,revision,stamp,nextStamp,sequence,initialPending,namespace,intent},View{M.current_view_generic(S,K,V,slot),M.next_view_generic(S,K,V,slot),revision,stamp,nextStamp,intent})
21def queue_generic(-S:Data,-K:Data,-V:Data,same:V -> V -> Bool,cell:Cell<S,K,V>,request:M.QueueInput<V>) -> Cell<S,K,V>:
22  match cell request:
23    case Cell{slot,stream,revision,stamp,nextStamp,sequence,initialPending,namespace,intent} M.Set{value,skipSame}:Cell{Queue.queue_generic(S,K,V,same,slot,value,skipSame),stream,revision,stamp,nextStamp,sequence,initialPending,namespace,intent}
24    case Cell{slot,stream,revision,stamp,nextStamp,sequence,initialPending,namespace,intent} M.Reset{}:Cell{M.reset_generic(S,K,V,slot),stream,revision,stamp,nextStamp,sequence,initialPending,namespace,intent}
25# Next setters and pending consumption have their own actual write stamp:
26# https://github.com/bevyengine/bevy/blob/ad678262ce53b5d142fe49ee5e08caff6f00ab60/crates/bevy_state/src/state/resources.rs#L197-L234
27def queue(~S:Data,~K:Data,~V:Data,~same:V -> V -> Bool,cell:Cell<S,K,V>,request:M.QueueInput<V>) -> Cell<S,K,V>:
28  queue_generic(S,K,V,same,cell,request)
29
30def request_stamped_generic(-S:Data,-K:Data,-V:Data,tick:Tick.Tick,cell:Cell<S,K,V>) -> Cell<S,K,V> & Unit:
31  match cell:
32    case Cell{M.Missing{},stream,revision,stamp,nextStamp,sequence,initialPending,namespace,intent}:(Cell{M.Missing{},stream,revision,stamp,nextStamp,sequence,initialPending,namespace,intent},Unit{})
33    case Cell{slot,stream,revision,stamp,_,sequence,initialPending,namespace,intent}:(Cell{slot,stream,revision,stamp,Some{tick},sequence,initialPending,namespace,intent},Unit{})
34def request_stamped(~S:Data,~K:Data,~V:Data,tick:Tick.Tick,cell:Cell<S,K,V>) -> Cell<S,K,V> & Unit:
35  request_stamped_generic(S,K,V,tick,cell)
36
37def queued_at_generic(-S:Data,-K:Data,-V:Data,same:V -> V -> Bool,request:M.QueueInput<V>,tick:Tick.Tick,cell:Cell<S,K,V>) -> Cell<S,K,V> & Unit:
38  request_stamped_generic(S,K,V,tick,queue_generic(S,K,V,same,cell,request))
39def queued_at(~S:Data,~K:Data,~V:Data,~same:V -> V -> Bool,request:M.QueueInput<V>,tick:Tick.Tick,cell:Cell<S,K,V>) -> Cell<S,K,V> & Unit:
40  queued_at_generic(S,K,V,same,request,tick,cell)
41
42def initialized(~S:Data,~K:Data,~V:Data,+value:V,+tick:Tick.Tick,stream:Stream.Store<V>,+sequence:Nat,namespace:Maybe<&2,U32>) -> Cell<S,K,V>:
43  Cell{M.Present{value,M.NoPending{},None{},True{}},Stream.publish(~V,stream,1n+sequence,M.Initial{value}),1n,Some{tick},Some{tick},1n+sequence,True{},namespace,Initial{value}}
44def initialize(~S:Data,~K:Data,~V:Data,cell:Cell<S,K,V>,value:V,tick:Tick.Tick) -> Cell<S,K,V>:
45  match cell:
46    case Cell{M.Missing{},stream,_,_,_,sequence,_,namespace,_}:initialized(~S,~K,~V,value,tick,stream,sequence,namespace)
47    case cell:cell
48def next_revision(same:Bool,revision:Nat) -> Nat:
49  match same:
50    case True{}:revision
51    case False{}:1n+revision
52def next_stamp(same:Bool,stamp:Maybe<&2,Tick.Tick>,tick:Tick.Tick) -> Maybe<&2,Tick.Tick>:
53  match same:
54    case True{}:stamp
55    case False{}:Some{tick}
56# Bevy commits State and emits StateTransitionEvent before phase schedules:
57# https://github.com/bevyengine/bevy/blob/ad678262ce53b5d142fe49ee5e08caff6f00ab60/crates/bevy_state/src/state/transitions.rs#L138-L205
58# Comparator equality retains actual Current; exited/Previous/event use the
59# requested value, including when equal values have different representations.
60def retained(~V:Data,equal:Bool,from:V,to:V) -> V:
61  match equal:
62    case True{}:from
63    case False{}:to
64def exited(~V:Data,equal:Bool,from:V,to:V) -> V:
65  match equal:
66    case True{}:to
67    case False{}:from
68def committed(~S:Data,~K:Data,~V:Data,+from:V,+to:V,skipSame:Bool,stream:Stream.Store<V>,revision:Nat,stamp:Maybe<&2,Tick.Tick>,+sequence:Nat,+tick:Tick.Tick,+equal:Bool,namespace:Maybe<&2,U32>) -> Cell<S,K,V>:
69  Cell{M.Present{retained(~V,equal,from,to),M.NoPending{},Some{exited(~V,equal,from,to)},Bool.not(equal)},Stream.publish(~V,stream,1n+sequence,M.Transition{exited(~V,equal,from,to),to}),next_revision(equal,revision),next_stamp(equal,stamp,tick),Some{tick},1n+sequence,False{},namespace,Transition{exited(~V,equal,from,to),to,Bool.or(Bool.not(skipSame),Bool.not(equal))}}
70def apply(~S:Data,~K:Data,~V:Data,~same:V -> V -> Bool,cell:Cell<S,K,V>,tick:Tick.Tick) -> Cell<S,K,V>:
71  match cell:
72    case Cell{M.Present{+current,M.Queued{+value,skipSame},_,_},stream,revision,stamp,nextStamp,sequence,_,namespace,_}:committed(~S,~K,~V,current,value,skipSame,stream,revision,stamp,sequence,tick,same(current,value),namespace)
73    case Cell{slot,stream,revision,stamp,nextStamp,sequence,True{},namespace,intent}:Cell{slot,stream,revision,stamp,nextStamp,sequence,False{},namespace,intent}
74    case Cell{slot,stream,revision,stamp,nextStamp,sequence,False{},namespace,_}:Cell{M.clear_changed(~S,~K,~V,slot),stream,revision,stamp,nextStamp,sequence,False{},namespace,Idle{}}
75def run_exit(-V:Data,intent:Intent<V>) -> Bool:
76  match intent:
77    case Transition{_,_,allowed}:allowed
78    case _:False{}
79def run_transition(-V:Data,intent:Intent<V>) -> Bool:
80  match intent:
81    case Transition{_,_,_}:True{}
82    case _:False{}
83def run_enter(-V:Data,intent:Intent<V>) -> Bool:
84  match intent:
85    case Initial{_}:True{}
86    case Transition{_,_,allowed}:allowed
87    case _:False{}
88def matches(~S:Data,~K:Data,~V:Data,~same:V -> V -> Bool,value:V,view:View<S,K,V>) -> Bool:
89  match view:
90    case View{current,_,_,_,_,_}:M.is_current(~S,~K,~V,~same,current,value)
91
92def bind(~S:Data,~K:Data,~V:Data,namespace:U32,cell:Cell<S,K,V>) -> Cell<S,K,V>:
93  match cell:
94    case Cell{slot,stream,revision,stamp,nextStamp,sequence,initialPending,None{},intent}:Cell{slot,stream,revision,stamp,nextStamp,sequence,initialPending,Some{namespace},intent}
95    case cell:cell
96def maintain(~S:Data,~K:Data,~V:Data,tick:Tick.Tick,cell:Cell<S,K,V>) -> Cell<S,K,V>:
97  match cell:
98    case Cell{slot,stream,revision,stamp,nextStamp,+sequence,initialPending,namespace,intent}:Cell{slot,Stream.maintain(~V,sequence,tick,stream),revision,stamp,nextStamp,sequence,initialPending,namespace,intent}