machine.bend
bendvy-ecs-core@0.1.0.3 · 185 lines · 39 definitions
1import Base
2
3
4
5
6type Pending<V: Data> is Data:
7 NoPending{}
8 Queued{value: V, skipSame: Bool}
9
10type Transition<V: Data> is Data:
11 Transition{from: V, to: V}
12 Initial{to: V}
13
14type Slot<S: Data, M: Data, V: Data> is Data:
15 Missing{}
16 Present{current: V, pending: Pending<V>, previous: Maybe<&2,V>, changed: Bool}
17
18
19type CurrentView<S: Data,M: Data,V: Data> is Data:
20 Unavailable{}
21 Current{value: V}
22type NextView<S: Data,M: Data,V: Data> is Data:
23 NoNext{}
24 Next{value: V}
25
26def current_view_generic(-S: Data,-M: Data,-V: Data,slot: Slot<S,M,V>) -> CurrentView<S,M,V>:
27 match slot:
28 case Missing{}: Unavailable{}
29 case Present{current,_,_,_}: Current{current}
30def current_view(~S: Data,~M: Data,~V: Data,slot: Slot<S,M,V>) -> CurrentView<S,M,V>:
31 current_view_generic(S,M,V,slot)
32
33def pending_view_generic(-S: Data,-M: Data,-V: Data,pending: Pending<V>) -> NextView<S,M,V>:
34 match pending:
35 case NoPending{}: NoNext{}
36 case Queued{value,_}: Next{value}
37def pending_view(~S: Data,~M: Data,~V: Data,pending: Pending<V>) -> NextView<S,M,V>:
38 pending_view_generic(S,M,V,pending)
39
40def next_view_generic(-S: Data,-M: Data,-V: Data,slot: Slot<S,M,V>) -> NextView<S,M,V>:
41 match slot:
42 case Missing{}: NoNext{}
43 case Present{_,pending,_,_}: pending_view_generic(S,M,V,pending)
44
45def next_view(~S: Data,~M: Data,~V: Data,slot: Slot<S,M,V>) -> NextView<S,M,V>:
46 next_view_generic(S,M,V,slot)
47
48def is_current(~S: Data,~M: Data,~V: Data,~same: V -> V -> Bool,view: CurrentView<S,M,V>,value: V) -> Bool:
49 match view:
50 case Unavailable{}: False{}
51 case Current{current}: same(current,value)
52
53type Family<S: Data,M: Data,V: Data,W: Type,
54 -take: W -> W & Slot<S,M,V>,-put: W -> Slot<S,M,V> -> W> is Data:
55 Family{name: String}
56
57type QueueInput<V: Data> is Data:
58 Set{value: V,skipSame: Bool}
59 Reset{}
60
61type Snapshot<V: Data> is Data:
62 Unscheduled{}
63 Scheduled{value: V, skipSame: Bool}
64
65type Applied<S: Data, M: Data, V: Data> is Data:
66 Applied{slot: Slot<S,M,V>, event: Maybe<&2,Transition<V>>}
67
68def queue_generic(-S: Data,-M: Data,-V: Data,slot: Slot<S,M,V>,value: V,skipSame: Bool) -> Slot<S,M,V>:
69 match slot:
70 case Missing{}: Missing{}
71 case Present{current,_,previous,changed}: Present{current,Queued{value,skipSame},previous,changed}
72
73def queue(~S: Data,~M: Data,~V: Data,slot: Slot<S,M,V>,value: V,skipSame: Bool) -> Slot<S,M,V>:
74 queue_generic(S,M,V,slot,value,skipSame)
75
76def reset_generic(-S: Data,-M: Data,-V: Data,slot: Slot<S,M,V>) -> Slot<S,M,V>:
77 match slot:
78 case Missing{}: Missing{}
79 case Present{current,_,previous,changed}: Present{current,NoPending{},previous,changed}
80
81def reset(~S: Data,~M: Data,~V: Data,slot: Slot<S,M,V>) -> Slot<S,M,V>:
82 reset_generic(S,M,V,slot)
83
84def clear_changed(~S: Data,~M: Data,~V: Data,slot: Slot<S,M,V>) -> Slot<S,M,V>:
85 match slot:
86 case Missing{}: Missing{}
87 case Present{current,pending,previous,_}: Present{current,pending,previous,False{}}
88
89def snapshot_pending(~V: Data,pending: Pending<V>) -> Snapshot<V>:
90 match pending:
91 case NoPending{}: Unscheduled{}
92 case Queued{value,skipSame}: Scheduled{value,skipSame}
93
94def snapshot(~S: Data,~M: Data,~V: Data,slot: Slot<S,M,V>) -> Snapshot<V>:
95 match slot:
96 case Missing{}: Unscheduled{}
97 case Present{_,pending,_,_}: snapshot_pending(~V,pending)
98
99def apply_decision(~S: Data,~M: Data,~V: Data,+current: V,+value: V,previous: Maybe<&2,V>,changed: Bool,skip: Bool) -> Applied<S,M,V>:
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
104def 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<S,M,V>:
105 apply_decision(~S,~M,~V,current,value,previous,changed,Bool.and(skipSame,same(current,value)))
106
107
108
109def apply_snapshot(~S: Data,~M: Data,~V: Data,~same: V -> V -> Bool,slot: Slot<S,M,V>,captured: Snapshot<V>) -> Applied<S,M,V>:
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
116type Condition<V: Data> is Data:
117 InState{value: V}
118 StateChanged{}
119 Not{inner: Condition<V>}
120 Constant{value: Bool}
121 And{left: Condition<V>,right: Condition<V>}
122 Or{left: Condition<V>,right: Condition<V>}
123
124def current_matches(~S: Data,~M: Data,~V: Data,~same: V -> V -> Bool,slot: Slot<S,M,V>,value: V) -> Bool:
125 match slot:
126 case Missing{}: False{}
127 case Present{current,_,_,_}: same(current,value)
128
129def changed(~S: Data,~M: Data,~V: Data,slot: Slot<S,M,V>) -> Bool:
130 match slot:
131 case Missing{}: False{}
132 case Present{_,_,_,flag}: flag
133
134
135
136def all(~V: Data,items: List<&2,Condition<V>>) -> Condition<V>:
137 match items:
138 case Nil{}: Constant{True{}}
139 case Con{head,tail}: And{head,all(~V,tail)}
140
141def any(~V: Data,items: List<&2,Condition<V>>) -> Condition<V>:
142 match items:
143 case Nil{}: Constant{False{}}
144 case Con{head,tail}: Or{head,any(~V,tail)}
145
146def evaluate(~S: Data,~M: Data,~V: Data,~same: V -> V -> Bool,condition: Condition<V>,+slot: Slot<S,M,V>) -> 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
156
157type Marker<S: Data,W: Type> is Type:
158 Marker{steps: List<&1,(W -> W)>}
159
160def 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
165def run_marker(~S: Data,~W: Type,marker: Marker<S,W>,world: W) -> W:
166 match marker:
167 case Marker{steps}: marker_steps(~W,steps,world)
168
169
170
171type OwnedMarker<S: Data,W: Type,H: Type> is Type:
172 OwnedMarker{steps: List<&1,(H -> W -> H & W)>}
173
174def 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
178def 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
183def run_owned_marker(~S: Data,~W: Type,~H: Type,marker: OwnedMarker<S,W,H>,owners: H,world: W) -> H & W:
184 match marker:
185 case OwnedMarker{steps}: owned_marker_steps(~W,~H,steps,owners,world)