1 import Base 2 3 # Experimental machine metadata. World and component owners remain arbitrary Type. 4 # This module follows the pinned reference marker snapshot semantics; that behavior 5 # is not approval of the disputed blanket next-marker retention requirement. 6 type Pending is Data: 7 NoPending{} 8 Queued{value: V, skipSame: Bool} 9 10 type Transition is Data: 11 Transition{from: V, to: V} 12 Initial{to: V} 13 14 type Slot is Data: 15 Missing{} 16 Present{current: V, pending: Pending, previous: Maybe<&2,V>, changed: Bool} 17 18 # Public capability projections intentionally expose less than debug metadata. 19 type CurrentView is Data: 20 Unavailable{} 21 Current{value: V} 22 type NextView is Data: 23 NoNext{} 24 Next{value: V} 25 26 def current_view_generic(-S: Data,-M: Data,-V: Data,slot: Slot) -> CurrentView: 27 match slot: 28 case Missing{}: Unavailable{} 29 case Present{current,_,_,_}: Current{current} 30 def current_view(~S: Data,~M: Data,~V: Data,slot: Slot) -> CurrentView: 31 current_view_generic(S,M,V,slot) 32 33 def pending_view_generic(-S: Data,-M: Data,-V: Data,pending: Pending) -> NextView: 34 match pending: 35 case NoPending{}: NoNext{} 36 case Queued{value,_}: Next{value} 37 def pending_view(~S: Data,~M: Data,~V: Data,pending: Pending) -> NextView: 38 pending_view_generic(S,M,V,pending) 39 40 def next_view_generic(-S: Data,-M: Data,-V: Data,slot: Slot) -> NextView: 41 match slot: 42 case Missing{}: NoNext{} 43 case Present{_,pending,_,_}: pending_view_generic(S,M,V,pending) 44 45 def next_view(~S: Data,~M: Data,~V: Data,slot: Slot) -> NextView: 46 next_view_generic(S,M,V,slot) 47 48 def is_current(~S: Data,~M: Data,~V: Data,~same: V -> V -> Bool,view: CurrentView,value: V) -> Bool: 49 match view: 50 case Unavailable{}: False{} 51 case Current{current}: same(current,value) 52 53 type Family W & Slot,-put: W -> Slot -> W> is Data: 55 Family{name: String} 56 57 type QueueInput is Data: 58 Set{value: V,skipSame: Bool} 59 Reset{} 60 61 type Snapshot is Data: 62 Unscheduled{} 63 Scheduled{value: V, skipSame: Bool} 64 65 type Applied is Data: 66 Applied{slot: Slot, event: Maybe<&2,Transition>} 67 68 def queue_generic(-S: Data,-M: Data,-V: Data,slot: Slot,value: V,skipSame: Bool) -> Slot: 69 match slot: 70 case Missing{}: Missing{} 71 case Present{current,_,previous,changed}: Present{current,Queued{value,skipSame},previous,changed} 72 73 def queue(~S: Data,~M: Data,~V: Data,slot: Slot,value: V,skipSame: Bool) -> Slot: 74 queue_generic(S,M,V,slot,value,skipSame) 75 76 def reset_generic(-S: Data,-M: Data,-V: Data,slot: Slot) -> Slot: 77 match slot: 78 case Missing{}: Missing{} 79 case Present{current,_,previous,changed}: Present{current,NoPending{},previous,changed} 80 81 def reset(~S: Data,~M: Data,~V: Data,slot: Slot) -> Slot: 82 reset_generic(S,M,V,slot) 83 84 def clear_changed(~S: Data,~M: Data,~V: Data,slot: Slot) -> Slot: 85 match slot: 86 case Missing{}: Missing{} 87 case Present{current,pending,previous,_}: Present{current,pending,previous,False{}} 88 89 def snapshot_pending(~V: Data,pending: Pending) -> Snapshot: 90 match pending: 91 case NoPending{}: Unscheduled{} 92 case Queued{value,skipSame}: Scheduled{value,skipSame} 93 94 def snapshot(~S: Data,~M: Data,~V: Data,slot: Slot) -> Snapshot: 95 match slot: 96 case Missing{}: Unscheduled{} 97 case Present{_,pending,_,_}: snapshot_pending(~V,pending) 98 99 def apply_decision(~S: Data,~M: Data,~V: Data,+current: V,+value: V,previous: Maybe<&2,V>,changed: Bool,skip: Bool) -> Applied: 100 match skip: 101 case True{}: Applied{Present{current,NoPending{},previous,changed},None{}} 102 case False{}: Applied{Present{value,NoPending{},Some{current},True{}},Some{Transition{current,value}}} 103 104 def apply_present(~S: Data,~M: Data,~V: Data,~same: V -> V -> Bool,+current: V,+value: V,previous: Maybe<&2,V>,changed: Bool,skipSame: Bool) -> Applied: 105 apply_decision(~S,~M,~V,current,value,previous,changed,Bool.and(skipSame,same(current,value))) 106 107 # Captured initial value is authoritative; current pending is deleted at the 108 # machine's turn, matching Runtime.ts:1534 even when an earlier hook overwrote it. 109 def apply_snapshot(~S: Data,~M: Data,~V: Data,~same: V -> V -> Bool,slot: Slot,captured: Snapshot) -> Applied: 110 match slot captured: 111 case slot Unscheduled{}: Applied{slot,None{}} 112 case Missing{} Scheduled{_,_}: Applied{Missing{},None{}} 113 case Present{current,_,previous,changed} Scheduled{value,skipSame}: 114 apply_present(~S,~M,~V,~same,current,value,previous,changed,skipSame) 115 116 type Condition is Data: 117 InState{value: V} 118 StateChanged{} 119 Not{inner: Condition} 120 Constant{value: Bool} 121 And{left: Condition,right: Condition} 122 Or{left: Condition,right: Condition} 123 124 def current_matches(~S: Data,~M: Data,~V: Data,~same: V -> V -> Bool,slot: Slot,value: V) -> Bool: 125 match slot: 126 case Missing{}: False{} 127 case Present{current,_,_,_}: same(current,value) 128 129 def changed(~S: Data,~M: Data,~V: Data,slot: Slot) -> Bool: 130 match slot: 131 case Missing{}: False{} 132 case Present{_,_,_,flag}: flag 133 134 # Arbitrary public variadic combinations become a structural Boolean tree. 135 # Empty and/or preserve the primary API identities. 136 def all(~V: Data,items: List<&2,Condition>) -> Condition: 137 match items: 138 case Nil{}: Constant{True{}} 139 case Con{head,tail}: And{head,all(~V,tail)} 140 141 def any(~V: Data,items: List<&2,Condition>) -> Condition: 142 match items: 143 case Nil{}: Constant{False{}} 144 case Con{head,tail}: Or{head,any(~V,tail)} 145 146 def evaluate(~S: Data,~M: Data,~V: Data,~same: V -> V -> Bool,condition: Condition,+slot: Slot) -> Bool: 147 match condition: 148 case InState{value}: current_matches(~S,~M,~V,~same,slot,value) 149 case StateChanged{}: changed(~S,~M,~V,slot) 150 case Not{inner}: Bool.not(evaluate(~S,~M,~V,~same,inner,slot)) 151 case Constant{value}: value 152 case And{left,right}: Bool.and(evaluate(~S,~M,~V,~same,left,slot),evaluate(~S,~M,~V,~same,right,slot)) 153 case Or{left,right}: Bool.or(evaluate(~S,~M,~V,~same,left,slot),evaluate(~S,~M,~V,~same,right,slot)) 154 155 # A heterogeneous marker snapshot owns each callback exactly once. Each callback 156 # captures a Data machine value and closed lenses, never a world/component owner. 157 type Marker is Type: 158 Marker{steps: List<&1,(W -> W)>} 159 160 def marker_steps(~W: Type,steps: List<&1,(W -> W)>,world: W) -> W: 161 match steps: 162 case Nil{}: world 163 case Con{step,rest}: marker_steps(~W,rest,step(world)) 164 165 def run_marker(~S: Data,~W: Type,marker: Marker,world: W) -> W: 166 match marker: 167 case Marker{steps}: marker_steps(~W,steps,world) 168 169 # Registered schedule/transition owners live alongside the world and are also 170 # threaded, rather than copied into one closure per machine. 171 type OwnedMarker is Type: 172 OwnedMarker{steps: List<&1,(H -> W -> H & W)>} 173 174 def marker_next(~W: Type,~H: Type,next: H -> W -> H & W,pair: H & W) -> H & W: 175 (owners,world)=pair 176 next(owners,world) 177 178 def owned_marker_steps(~W: Type,~H: Type,steps: List<&1,(H -> W -> H & W)>,owners: H,world: W) -> H & W: 179 match steps: 180 case Nil{}: (owners,world) 181 case Con{step,rest}: marker_next(~W,~H,h => w => owned_marker_steps(~W,~H,rest,h,w),step(owners,world)) 182 183 def run_owned_marker(~S: Data,~W: Type,~H: Type,marker: OwnedMarker,owners: H,world: W) -> H & W: 184 match marker: 185 case OwnedMarker{steps}: owned_marker_steps(~W,~H,steps,owners,world)