clock_state.bend

bendvy-ecs-core@0.1.0.3 · 84 lines · 18 definitions

1import Base
2import bendvy-ecs-core@0.1.0.3/change_tick.bend as Tick
3
4# Administrative time and captured execution ticks. Payloads never live here.
5# Nested execution restores its enclosing tick without rewinding World time.
6type State is Data:
7  State{now:Tick.Tick,scopes:List<&2,Tick.Tick>}
8
9def empty() -> State:
10  State{Tick.zero(),[]}
11
12def now(state:State) -> Tick.Tick:
13  match state:
14    case State{tick,_}:tick
15
16def floor_tick(ordered:Bool,current:Tick.Tick,minimum:Tick.Tick) -> Tick.Tick:
17  match ordered:
18    case True{}:minimum
19    case False{}:current
20
21# Trusted restore publication raises administrative time without rebasing any
22# retained reader cursor or captured scope. Admission requires quiescent scopes.
23# Elapsed receiver time is preserved; saved events are not replayed.
24def floor(state:State,+minimum:Tick.Tick) -> State:
25  match state:
26    case State{+current,scopes}:State{floor_tick(Tick.not_future(current,minimum),current,minimum),scopes}
27
28def entered(+tick:Tick.Tick,scopes:List<&2,Tick.Tick>) -> State & Tick.Tick:
29  (State{tick,tick <> scopes},tick)
30
31# Every admitted system execution captures exactly one new change tick.
32def enter(state:State) -> State & Tick.Tick:
33  match state:
34    case State{tick,scopes}:entered(Tick.next(tick),scopes)
35
36def left(tick:Tick.Tick,scopes:List<&2,Tick.Tick>) -> State:
37  match scopes:
38    case []:State{tick,[]}
39    case _ <> rest:State{tick,rest}
40
41# Complete an execution scope; administrative time is retained on failure too.
42def leave(state:State) -> State:
43  match state:
44    case State{tick,scopes}:left(tick,scopes)
45
46def advanced(+tick:Tick.Tick,scopes:List<&2,Tick.Tick>) -> State & Tick.Tick:
47  (State{tick,scopes},tick)
48
49# Advance an explicit direct/deferred boundary without opening a system scope.
50def advance(state:State) -> State & Tick.Tick:
51  match state:
52    case State{tick,scopes}:advanced(Tick.next(tick),scopes)
53
54def write_scoped(tick:Tick.Tick,scopes:List<&2,Tick.Tick>) -> State & Tick.Tick:
55  match scopes:
56    case []:advanced(Tick.next(tick),[])
57    case +active <> rest:(State{tick,active <> rest},active)
58
59# Writes in a system reuse its captured tick; standalone writes get a new tick.
60def write(state:State) -> State & Tick.Tick:
61  match state:
62    case State{tick,scopes}:write_scoped(tick,scopes)
63
64# Captured tick of the enclosing execution, or administrative time outside a run.
65def current_scoped(tick:Tick.Tick,scopes:List<&2,Tick.Tick>) -> Tick.Tick:
66  match scopes:
67    case []:tick
68    case active <> _:active
69def current(state:State) -> Tick.Tick:
70  match state:
71    case State{tick,scopes}:current_scoped(tick,scopes)
72
73# Lower query execution reuses an admitted scope, opening one only when direct.
74def ensured(+tick:Tick.Tick,scopes:List<&2,Tick.Tick>) -> State & Bool:
75  match scopes:
76    case []:(State{Tick.next(tick),[Tick.next(tick)]},True{})
77    case active <> rest:(State{tick,active <> rest},False{})
78def ensure(state:State) -> State & Bool:
79  match state:
80    case State{tick,scopes}:ensured(tick,scopes)
81def finish(owned:Bool,state:State) -> State:
82  match owned:
83    case False{}:state
84    case True{}:leave(state)