machine_queue.bend

bendvy-ecs-core@0.1.0.1 · 44 lines · 0 definitions

1import Base
2import bendvy-ecs-core@0.1.0.1/deferred_command.bend as Deferred
3import bendvy-ecs-core@0.1.0.1/trace_facts.bend as TraceFacts
4import bendvy-ecs-core@0.1.0.1/machine.bend as M
5import bendvy-ecs-core@0.1.0.1/transaction.bend as Tx
6
7# Bevy NextState::set_if_different preserves an existing forced same target.
8# Equality is the same closed erased V comparator used by apply/conditions.
9def forced_pending(~V:Data,same:Bool,prior:V,value:V) -> M.Pending<V>:
10  match same:
11    case True{}:M.Queued{prior,False{}}
12    case False{}:M.Queued{value,True{}}
13def conditional_pending(~V:Data,~same:V -> V -> Bool,pending:M.Pending<V>,+value:V) -> M.Pending<V>:
14  match pending:
15    case M.Queued{+prior,False{}}:forced_pending(~V,same(prior,value),prior,value)
16    case _:M.Queued{value,True{}}
17def conditional(~S:Data,~K:Data,~V:Data,~same:V -> V -> Bool,slot:M.Slot<S,K,V>,value:V) -> M.Slot<S,K,V>:
18  match slot:
19    case M.Missing{}:M.Missing{}
20    case M.Present{current,pending,previous,changed}:M.Present{current,conditional_pending(~V,~same,pending,value),previous,changed}
21def queue(~S:Data,~K:Data,~V:Data,~same:V -> V -> Bool,slot:M.Slot<S,K,V>,value:V,skipSame:Bool) -> M.Slot<S,K,V>:
22  match skipSame:
23    case False{}:M.queue(~S,~K,~V,slot,value,False{})
24    case True{}:conditional(~S,~K,~V,~same,slot,value)
25def write_taken(~S:Data,~K:Data,~V:Data,~W:Type,~E:Data,~put:W -> M.Slot<S,K,V> -> W,~same:V -> V -> Bool,pair:W & M.Slot<S,K,V>,undo:List<&1,(W -> W)>,commands:List<&1,Deferred.Command<W>>,events:List<&2,E>,trace:TraceFacts.State,value:V,skipSame:Bool) -> Tx.Tx<W,E>:
26  match pair:
27    case (world,+old):Tx.Tx{put(world,queue(~S,~K,~V,~same,old,value,skipSame)),(world => put(world,old)) <> undo,commands,events,trace}
28def write(~S:Data,~K:Data,~V:Data,~W:Type,~E:Data,~take:W -> W & M.Slot<S,K,V>,~put:W -> M.Slot<S,K,V> -> W,~same:V -> V -> Bool,tx:Tx.Tx<W,E>,value:V,skipSame:Bool) -> Tx.Tx<W,E>:
29  match tx:
30    case Tx.Tx{world,undo,commands,events,trace}:write_taken(~S,~K,~V,~W,~E,~put,~same,take(world),undo,commands,events,trace,value,skipSame)
31def next(~S:Data,~K:Data,~V:Data,~W:Type,~E:Data,~take:W -> W & M.Slot<S,K,V>,~put:W -> M.Slot<S,K,V> -> W,~same:V -> V -> Bool,tx:Tx.Tx<W,E>,request:M.QueueInput<V>) -> Tx.Tx<W,E>:
32  match request:
33    case M.Set{value,skipSame}:write(~S,~K,~V,~W,~E,~take,~put,~same,tx,value,skipSame)
34    case M.Reset{}:M.reset_tx(~S,~K,~V,~W,~E,~take,~put,tx)
35def declared_record(~W:Type,~E:Data,enabled:Bool,name:String,tx:Tx.Tx<W,E>) -> Tx.Tx<W,E>:
36  match enabled:
37    case False{}:tx
38    case True{}:Tx.record(~W,~E,tx,TraceFacts.Fact{TraceFacts.NextStateValue{},name,TraceFacts.StageOperation{},None{},TraceFacts.OpaqueValue{},TraceFacts.OpaqueValue{},TraceFacts.Attempted{}})
39def declared_named(~S:Data,~K:Data,~V:Data,~W:Type,~E:Data,~take:W -> W & M.Slot<S,K,V>,~put:W -> M.Slot<S,K,V> -> W,~same:V -> V -> Bool,name:String,request:M.QueueInput<V>,checked:Tx.Tx<W,E> & Bool) -> Tx.Tx<W,E>:
40  match checked:
41    case (tx,enabled):declared_record(~W,~E,enabled,name,next(~S,~K,~V,~W,~E,~take,~put,~same,tx,request))
42def next_declared(~S:Data,~K:Data,~V:Data,~W:Type,~E:Data,~take:W -> W & M.Slot<S,K,V>,~put:W -> M.Slot<S,K,V> -> W,~same:V -> V -> Bool,family:M.Family<S,K,V,W,take,put>,tx:Tx.Tx<W,E>,request:M.QueueInput<V>) -> Tx.Tx<W,E>:
43  match family:
44    case M.Family{name}:declared_named(~S,~K,~V,~W,~E,~take,~put,~same,name,request,Tx.trace_enabled(~W,~E,tx))