1 import Base 2 import ./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. 6 type State is Data: 7 State{now:Tick.Tick,scopes:List<&2,Tick.Tick>} 8 9 def empty() -> State: 10 State{Tick.zero(),[]} 11 12 def now(state:State) -> Tick.Tick: 13 match state: 14 case State{tick,_}:tick 15 16 def entered(+tick:Tick.Tick,scopes:List<&2,Tick.Tick>) -> State & Tick.Tick: 17 (State{tick,tick <> scopes},tick) 18 19 # Every admitted system execution captures exactly one new change tick. 20 def enter(state:State) -> State & Tick.Tick: 21 match state: 22 case State{tick,scopes}:entered(Tick.next(tick),scopes) 23 24 def left(tick:Tick.Tick,scopes:List<&2,Tick.Tick>) -> State: 25 match scopes: 26 case []:State{tick,[]} 27 case _ <> rest:State{tick,rest} 28 29 # Complete an execution scope; administrative time is retained on failure too. 30 def leave(state:State) -> State: 31 match state: 32 case State{tick,scopes}:left(tick,scopes) 33 34 def advanced(+tick:Tick.Tick,scopes:List<&2,Tick.Tick>) -> State & Tick.Tick: 35 (State{tick,scopes},tick) 36 37 # Advance an explicit direct/deferred boundary without opening a system scope. 38 def advance(state:State) -> State & Tick.Tick: 39 match state: 40 case State{tick,scopes}:advanced(Tick.next(tick),scopes) 41 42 def write_scoped(tick:Tick.Tick,scopes:List<&2,Tick.Tick>) -> State & Tick.Tick: 43 match scopes: 44 case []:advanced(Tick.next(tick),[]) 45 case +active <> rest:(State{tick,active <> rest},active) 46 47 # Writes in a system reuse its captured tick; standalone writes get a new tick. 48 def write(state:State) -> State & Tick.Tick: 49 match state: 50 case State{tick,scopes}:write_scoped(tick,scopes) 51 52 # Captured tick of the enclosing execution, or administrative time outside a run. 53 def current_scoped(tick:Tick.Tick,scopes:List<&2,Tick.Tick>) -> Tick.Tick: 54 match scopes: 55 case []:tick 56 case active <> _:active 57 def current(state:State) -> Tick.Tick: 58 match state: 59 case State{tick,scopes}:current_scoped(tick,scopes) 60 61 # Lower query execution reuses an admitted scope, opening one only when direct. 62 def ensured(+tick:Tick.Tick,scopes:List<&2,Tick.Tick>) -> State & Bool: 63 match scopes: 64 case []:(State{Tick.next(tick),[Tick.next(tick)]},True{}) 65 case active <> rest:(State{tick,active <> rest},False{}) 66 def ensure(state:State) -> State & Bool: 67 match state: 68 case State{tick,scopes}:ensured(tick,scopes) 69 def finish(owned:Bool,state:State) -> State: 70 match owned: 71 case False{}:state 72 case True{}:leave(state)