world.bend
bendvy-ecs-core@0.1.0.3 · 401 lines · 82 definitions
1import Base
2import bendvy-ecs-core@0.1.0.3/change_tick.bend as Tick
3import bendvy-ecs-core@0.1.0.3/clock_state.bend as Clock
4import bendvy-ecs-core@0.1.0.3/execution_lifecycle_notices.bend as Notice
5import bendvy-ecs-core@0.1.0.3/trace_facts.bend as TraceFacts
6import bendvy-ecs-core@0.1.0.3/deferred_command.bend as Deferred
7import string_equality.bend as SE
8import entity_key.bend as K
9import entity_allocator.bend as A
10
11
12
13
14
15type Handle<Schema: Data> is Data:
16 Handle{namespace: U32, key: K.Key}
17
18
19
20type Factory is Type:
21 Factory{nextNamespace: U32}
22
23
24type RegistrationMeta is Data:
25 RegistrationMeta{id: U32, name: String, access: List<&2,String>}
26
27
28type WorldError is Data:
29 ReservationUnauthorized{}
30 MissingEntity{}
31 CapacityExceeded{}
32 NamespaceExhausted{}
33 SystemIdExhausted{}
34
35
36
37type World<Schema: Data,Store: Type,Resource: Type,Event: Data> is Type:
38 World{namespace: U32,allocator: A.Allocator,store: Store,resource: Resource,events: List<&2,Event>,pending:List<Deferred.Command<World<Schema,Store,Resource,Event>>>,registrations: List<&2,RegistrationMeta>,nextSystemId: U32,clock: Clock.State,lifecycle:Notice.Journal<Schema>}
39
40
41type Creation<Schema: Data,Store: Type,Resource: Type,Event: Data> is Type:
42 Created{factory: Factory,world: World<Schema,Store,Resource,Event>}
43 CreateRejected{factory: Factory,resource: Resource}
44
45
46type Reservation<Schema: Data> is Data:
47 Reserved{handle: Handle<Schema>}
48 ReservationRejected{error: WorldError}
49
50
51type Status is Data:
52 Accepted{}
53 Rejected{error: WorldError}
54
55
56type Registration is Data:
57 Registered{id: U32}
58 RegistrationRejected{error: WorldError}
59
60
61def clock(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>) -> World<S,C,R,E> & Tick.Tick:
62 match world:
63 case World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,+clock,lifecycle}:(World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},Clock.now(clock))
64
65
66def execution_clock(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>) -> World<S,C,R,E> & Tick.Tick:
67 match world:
68 case World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,+clock,lifecycle}:(World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},Clock.current(clock))
69
70def clock_returned(~S:Data,~C:Type,~R:Type,~E:Data,namespace:U32,allocator:A.Allocator,store:C,resource:R,events:List<&2,E>,pending:List<Deferred.Command<World<S,C,R,E>>>,registrations:List<&2,RegistrationMeta>,nextSystemId:U32,changed:Clock.State & Tick.Tick,lifecycle:Notice.Journal<S>) -> World<S,C,R,E> & Tick.Tick:
71 (clock,tick)=changed
72 (World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},tick)
73
74
75def advance_clock(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>) -> World<S,C,R,E> & Tick.Tick:
76 match world:
77 case World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle}:clock_returned(~S,~C,~R,~E,namespace,allocator,store,resource,events,pending,registrations,nextSystemId,Clock.advance(clock),lifecycle)
78
79
80def write_clock(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>) -> World<S,C,R,E> & Tick.Tick:
81 match world:
82 case World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle}:clock_returned(~S,~C,~R,~E,namespace,allocator,store,resource,events,pending,registrations,nextSystemId,Clock.write(clock),lifecycle)
83
84
85def enter_run(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>) -> World<S,C,R,E> & Tick.Tick:
86 match world:
87 case World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle}:clock_returned(~S,~C,~R,~E,namespace,allocator,store,resource,events,pending,registrations,nextSystemId,Clock.enter(clock),lifecycle)
88
89
90def leave_run(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>) -> World<S,C,R,E>:
91 match world:
92 case World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle}:World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,Clock.leave(clock),lifecycle}
93
94def ensure_returned(~S:Data,~C:Type,~R:Type,~E:Data,namespace:U32,allocator:A.Allocator,store:C,resource:R,events:List<&2,E>,pending:List<Deferred.Command<World<S,C,R,E>>>,registrations:List<&2,RegistrationMeta>,nextSystemId:U32,result:Clock.State & Bool,lifecycle:Notice.Journal<S>) -> World<S,C,R,E> & Bool:
95 (clock,owned)=result
96 (World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},owned)
97
98def ensure_run(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>) -> World<S,C,R,E> & Bool:
99 match world:
100 case World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle}:ensure_returned(~S,~C,~R,~E,namespace,allocator,store,resource,events,pending,registrations,nextSystemId,Clock.ensure(clock),lifecycle)
101def finish_run(~S:Data,~C:Type,~R:Type,~E:Data,owned:Bool,world:World<S,C,R,E>) -> World<S,C,R,E>:
102 match world:
103 case World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle}:World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,Clock.finish(owned,clock),lifecycle}
104
105
106
107def handle_index(~S:Data,handle:Handle<S>) -> U32:
108 match handle:
109 case Handle{_,key}:K.index(key)
110
111def handle_key(~S:Data,handle:Handle<S>) -> K.Key:
112 match handle:
113 case Handle{_,key}:key
114
115
116
117def factory() -> Factory:
118 Factory{1}
119def create_checked(~S:Data,~C:Type,~R:Type,~E:Data,~empty:Unit -> C,available:Bool,+namespace:U32,resource:R) -> Creation<S,C,R,E>:
120 match available:
121 case False{}:CreateRejected{Factory{namespace},resource}
122 case True{}:Created{Factory{(namespace + 1 : U32)},World{namespace,A.empty(),empty(Unit{}),resource,[],[],[],1,Clock.empty(),Notice.empty(~S,namespace)}}
123
124
125
126def create(~S:Data,~C:Type,~R:Type,~E:Data,~empty:Unit -> C,factory:Factory,resource:R) -> Creation<S,C,R,E>:
127 match factory:
128 case Factory{+namespace}:create_checked(~S,~C,~R,~E,~empty,U32.is_lt(namespace,4294967295),namespace,resource)
129def reserve_result(~S:Data,~C:Type,~R:Type,~E:Data,+namespace:U32,store:C,resource:R,+events:List<&2,E>,pending:List<Deferred.Command<World<S,C,R,E>>>,+registrations:List<&2,RegistrationMeta>,+nextSystemId:U32,+clock:Clock.State,allocator:A.Allocator,reservation:A.Reservation,lifecycle:Notice.Journal<S>) -> World<S,C,R,E> & Reservation<S>:
130 match reservation:
131 case A.Exhausted{}:(World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},ReservationRejected{CapacityExceeded{}})
132 case A.Reserved{key}:(World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},Reserved{Handle{namespace,key}})
133def reserve_join(~S:Data,~C:Type,~R:Type,~E:Data,+namespace:U32,store:C,resource:R,+events:List<&2,E>,pending:List<Deferred.Command<World<S,C,R,E>>>,+registrations:List<&2,RegistrationMeta>,+nextSystemId:U32,+clock:Clock.State,reserved:A.Allocator & A.Reservation,lifecycle:Notice.Journal<S>) -> World<S,C,R,E> & Reservation<S>:
134 (allocator,reservation) = reserved
135 reserve_result(~S,~C,~R,~E,namespace,store,resource,events,pending,registrations,nextSystemId,clock,allocator,reservation,lifecycle)
136
137
138def reserve_id(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>) -> World<S,C,R,E> & Reservation<S>:
139 match world:
140 case World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle}:reserve_join(~S,~C,~R,~E,namespace,store,resource,events,pending,registrations,nextSystemId,clock,A.reserve(allocator),lifecycle)
141def checked_join(~S:Data,~C:Type,~R:Type,~E:Data,namespace:U32,store:C,resource:R,events:List<&2,E>,pending:List<Deferred.Command<World<S,C,R,E>>>,registrations:List<&2,RegistrationMeta>,nextSystemId:U32,clock:Clock.State,checked:A.Allocator & Bool,lifecycle:Notice.Journal<S>) -> World<S,C,R,E> & Bool:
142 match checked:
143 case (allocator,valid):(World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},valid)
144def checked_namespace(~S:Data,~C:Type,~R:Type,~E:Data,allowed:Bool,mode:U32,world:World<S,C,R,E>,key:K.Key) -> World<S,C,R,E> & Bool:
145 match allowed world:
146 case False{} world:(world,False{})
147 case True{} World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle}:checked_join(~S,~C,~R,~E,namespace,store,resource,events,pending,registrations,nextSystemId,clock,A.checked(allocator,key,mode),lifecycle)
148def checked(~S:Data,~C:Type,~R:Type,~E:Data,mode:U32,world:World<S,C,R,E>,handle:Handle<S>) -> World<S,C,R,E> & Bool:
149 match world handle:
150 case World{+namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle} Handle{ns,key}:checked_namespace(~S,~C,~R,~E,U32.is_eq(namespace,ns),mode,World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},key)
151
152
153def metadata_valid(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>,handle:Handle<S>) -> World<S,C,R,E> & Bool:
154 checked(~S,~C,~R,~E,0,world,handle)
155
156
157def valid(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>,handle:Handle<S>) -> World<S,C,R,E> & Bool:
158 checked(~S,~C,~R,~E,1,world,handle)
159
160
161def pending_valid(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>,handle:Handle<S>) -> World<S,C,R,E> & Bool:
162 checked(~S,~C,~R,~E,2,world,handle)
163def phase_checked(~S:Data,~C:Type,~R:Type,~E:Data,phase:A.Phase,key:K.Key,checked:World<S,C,R,E> & Bool) -> World<S,C,R,E> & Status:
164 match checked:
165 case (world,False{}):(world,Rejected{MissingEntity{}})
166 case (World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},True{}):(World{namespace,A.write_phase(allocator,key,phase),store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},Accepted{})
167
168
169def activate(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>,+handle:Handle<S>) -> World<S,C,R,E> & Status:
170 phase_checked(~S,~C,~R,~E,A.Live{},handle_key(~S,handle),metadata_valid(~S,~C,~R,~E,world,handle))
171
172
173
174def deactivate(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>,+handle:Handle<S>) -> World<S,C,R,E> & Status:
175 phase_checked(~S,~C,~R,~E,A.DeadRetained{},handle_key(~S,handle),metadata_valid(~S,~C,~R,~E,world,handle))
176def discard_status(~S:Data,~C:Type,~R:Type,~E:Data,observed:World<S,C,R,E> & Status) -> World<S,C,R,E>:
177 match observed:
178 case (world,_):world
179
180
181def mark_pending(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>,+handle:Handle<S>) -> World<S,C,R,E>:
182 discard_status(~S,~C,~R,~E,phase_checked(~S,~C,~R,~E,A.Pending{},handle_key(~S,handle),metadata_valid(~S,~C,~R,~E,world,handle)))
183def owner_change(~S:Data,~C:Type,~R:Type,~E:Data,release:Bool,+key:K.Key,checked:World<S,C,R,E> & Bool) -> World<S,C,R,E>:
184 match release checked:
185 case _, (world,False{}):world
186 case False{}, (World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},True{}):World{namespace,A.abandon(allocator,key),store,resource,events,pending,registrations,nextSystemId,clock,lifecycle}
187 case True{}, (World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},True{}):World{namespace,A.release(allocator,key),store,resource,events,pending,registrations,nextSystemId,clock,lifecycle}
188
189
190def clear_pending(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>,+handle:Handle<S>) -> World<S,C,R,E>:
191 owner_change(~S,~C,~R,~E,False{},handle_key(~S,handle),pending_valid(~S,~C,~R,~E,world,handle))
192
193
194
195def release_cleared(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>,+handle:Handle<S>) -> World<S,C,R,E>:
196 owner_change(~S,~C,~R,~E,True{},handle_key(~S,handle),metadata_valid(~S,~C,~R,~E,world,handle))
197def command_live(~S:Data,~C:Type,~R:Type,~E:Data,handle:Handle<S>,checked:World<S,C,R,E> & Bool) -> World<S,C,R,E> & Bool:
198 match checked:
199 case (world,True{}):(world,True{})
200 case (world,False{}):pending_valid(~S,~C,~R,~E,world,handle)
201
202
203
204def command_valid(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>,+handle:Handle<S>) -> World<S,C,R,E> & Bool:
205 command_live(~S,~C,~R,~E,handle,valid(~S,~C,~R,~E,world,handle))
206
207
208
209def enqueue_command(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>,command:Deferred.Command<World<S,C,R,E>>) -> World<S,C,R,E>:
210 match world:
211 case World{+namespace,allocator,store,resource,+events,pending,+registrations,+nextSystemId,+clock,lifecycle}:World{namespace,allocator,store,resource,events,command <> pending,registrations,nextSystemId,clock,lifecycle}
212
213
214def enqueue(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>,command:World<S,C,R,E> -> World<S,C,R,E>) -> World<S,C,R,E>:
215 enqueue_command(~S,~C,~R,~E,world,Deferred.Raw{command})
216def drain_fifo(~S:Data,~C:Type,~R:Type,~E:Data,commands:List<Deferred.Command<World<S,C,R,E>>>,world:World<S,C,R,E>) -> World<S,C,R,E>:
217 match commands:
218 case []:world
219 case command <> rest:Deferred.run_disabled(~World<S,C,R,E>,command,drain_fifo(~S,~C,~R,~E,rest,world))
220def drain_apply(~S:Data,~C:Type,~R:Type,~E:Data,command:Deferred.Command<World<S,C,R,E>>,result:World<S,C,R,E> & TraceFacts.State) -> World<S,C,R,E> & TraceFacts.State:
221 match result:
222 case (world,trace):Deferred.run(~World<S,C,R,E>,command,world,trace)
223def drain_fifo_traced(~S:Data,~C:Type,~R:Type,~E:Data,commands:List<Deferred.Command<World<S,C,R,E>>>,world:World<S,C,R,E>,trace:TraceFacts.State) -> World<S,C,R,E> & TraceFacts.State:
224 match commands:
225 case []:(world,trace)
226 case command <> rest:
227 drain_apply(~S,~C,~R,~E,command,drain_fifo_traced(~S,~C,~R,~E,rest,world,trace))
228
229
230
231def barrier_completed(~S:Data,~C:Type,~R:Type,~E:Data,result:World<S,C,R,E> & TraceFacts.State) -> World<S,C,R,E> & TraceFacts.State:
232 (world,trace)=result
233 (leave_run(~S,~C,~R,~E,world),trace)
234def barrier_entered(~S:Data,~C:Type,~R:Type,~E:Data,trace:TraceFacts.State,entered:World<S,C,R,E> & Tick.Tick) -> World<S,C,R,E> & TraceFacts.State:
235 match entered:
236 case (World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},_):barrier_completed(~S,~C,~R,~E,drain_fifo_traced(~S,~C,~R,~E,pending,World{namespace,allocator,store,resource,events,[],registrations,nextSystemId,clock,lifecycle},trace))
237
238def barrier_traced(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>,trace:TraceFacts.State) -> World<S,C,R,E> & TraceFacts.State:
239 barrier_entered(~S,~C,~R,~E,trace,enter_run(~S,~C,~R,~E,world))
240
241
242
243def barrier(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>) -> World<S,C,R,E>:
244 Deferred.world_only(~World<S,C,R,E>,barrier_traced(~S,~C,~R,~E,world,TraceFacts.Off{}))
245
246
247
248def replace_resource(~S: Data,~C: Type,~R: Type,~E: Data,world: World<S,C,R,E>,replacement: R) -> World<S,C,R,E> & R:
249 match world:
250 case World{+namespace,allocator,store,resource,+events,pending,+registrations,+nextSystemId,+clock,lifecycle}: (World{namespace,allocator,store,replacement,events,pending,registrations,nextSystemId,clock,lifecycle},resource)
251
252def event_append_loop(~E: Data,reversed: List<&2,E>,+output: List<&2,E>) -> List<&2,E>:
253 match reversed:
254 case []: output
255 case head <> rest: event_append_loop(~E,rest,head <> output)
256
257def event_append(~E: Data,+left: List<&2,E>,+right: List<&2,E>) -> List<&2,E>:
258 event_append_loop(~E,List.reverse(&2,E,left),right)
259
260def event_publish_nonempty(~S: Data,~C: Type,~R: Type,~E: Data,world: World<S,C,R,E>,+published: List<&2,E>) -> World<S,C,R,E>:
261 match world:
262 case World{+namespace,allocator,store,resource,+events,pending,+registrations,+nextSystemId,+clock,lifecycle}: World{namespace,allocator,store,resource,event_append(~E,events,published),pending,registrations,nextSystemId,clock,lifecycle}
263
264
265
266
267def event_publish(~S: Data,~C: Type,~R: Type,~E: Data,world: World<S,C,R,E>,+published: List<&2,E>) -> World<S,C,R,E>:
268 match published:
269 case []: world
270 case head <> rest: event_publish_nonempty(~S,~C,~R,~E,world,head <> rest)
271
272
273
274def events_view(~S: Data,~C: Type,~R: Type,~E: Data,world: World<S,C,R,E>) -> World<S,C,R,E> & List<&2,E>:
275 match world:
276 case World{+namespace,allocator,store,resource,+events,pending,+registrations,+nextSystemId,+clock,lifecycle}: (World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},events)
277
278def observe_resource_finish(~S: Data,~C: Type,~R: Type,~E: Data,~V: Type,observed: R & V,+namespace: U32,allocator: A.Allocator,store: C,+events: List<&2,E>,pending:List<Deferred.Command<World<S,C,R,E>>>,+registrations: List<&2,RegistrationMeta>,+nextSystemId: U32,+clock: Clock.State,lifecycle:Notice.Journal<S>) -> World<S,C,R,E> & V:
279 (resource,value) = observed
280 (World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},value)
281
282
283
284
285def observe_resource(~S: Data,~C: Type,~R: Type,~E: Data,~V: Type,~project: R -> R & V,world: World<S,C,R,E>) -> World<S,C,R,E> & V:
286 match world:
287 case World{+namespace,allocator,store,resource,+events,pending,+registrations,+nextSystemId,+clock,lifecycle}: observe_resource_finish(~S,~C,~R,~E,~V,project(resource),namespace,allocator,store,events,pending,registrations,nextSystemId,clock,lifecycle)
288
289def register_checked(~S: Data,~C: Type,~R: Type,~E: Data,available: Bool,world: World<S,C,R,E>,+name: String,+access: List<&2,String>) -> World<S,C,R,E> & Registration:
290 match available world:
291 case False{} world: (world,RegistrationRejected{SystemIdExhausted{}})
292 case True{} World{+namespace,allocator,store,resource,+events,pending,+registrations,+nextSystemId,+clock,lifecycle}: (World{namespace,allocator,store,resource,events,pending,RegistrationMeta{nextSystemId,name,access} <> registrations,(nextSystemId + 1 : U32),clock,lifecycle},Registered{nextSystemId})
293
294
295
296
297def register(~S: Data,~C: Type,~R: Type,~E: Data,world: World<S,C,R,E>,+name: String,+access: List<&2,String>) -> World<S,C,R,E> & Registration:
298 match world:
299 case World{+namespace,allocator,store,resource,+events,pending,+registrations,+nextSystemId,+clock,lifecycle}: register_checked(~S,~C,~R,~E,U32.is_lt(nextSystemId,4294967295),World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},name,access)
300
301
302def access_equal(xs: List<&2,String>,ys: List<&2,String>) -> Bool:
303 match xs ys:
304 case Nil{} Nil{}: True{}
305 case Nil{} Con{_,_}: False{}
306 case Con{_,_} Nil{}: False{}
307 case Con{x,xs} Con{y,ys}: Bool.and(SE.equal(x,y),access_equal(xs,ys))
308
309def matching_access(sameName: Bool,metaAccess: List<&2,String>,wantedAccess: List<&2,String>) -> Bool:
310 match sameName:
311 case False{}: False{}
312 case True{}: access_equal(metaAccess,wantedAccess)
313
314def matching_id(sameId: Bool,metaName: String,wantedName: String,metaAccess: List<&2,String>,wantedAccess: List<&2,String>) -> Bool:
315 match sameId:
316 case False{}: False{}
317 case True{}: matching_access(SE.equal(metaName,wantedName),metaAccess,wantedAccess)
318
319def registration_meta_matches(meta: RegistrationMeta,+id: U32,+name: String,+access: List<&2,String>) -> Bool:
320 match meta:
321 case RegistrationMeta{mid,mname,maccess}: matching_id(U32.is_eq(mid,id),mname,name,maccess,access)
322
323def registration_list_walk(registrations: List<&2,RegistrationMeta>,+id: U32,+name: String,+access: List<&2,String>,found: Bool) -> Bool:
324 match registrations found:
325 case _ True{}: True{}
326 case [] False{}: False{}
327 case meta <> rest False{}: registration_list_walk(rest,id,name,access,registration_meta_matches(meta,id,name,access))
328
329def registration_list_matches(registrations: List<&2,RegistrationMeta>,+id: U32,+name: String,+access: List<&2,String>) -> Bool:
330 registration_list_walk(registrations,id,name,access,False{})
331
332
333
334def namespace(~S: Data,~C: Type,~R: Type,~E: Data,world: World<S,C,R,E>) -> World<S,C,R,E> & U32:
335 match world:
336 case World{+namespace,allocator,store,resource,+events,pending,+registrations,+nextSystemId,+clock,lifecycle}: (World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},namespace)
337
338
339
340def registration_matches(~S: Data,~C: Type,~R: Type,~E: Data,world: World<S,C,R,E>,+id: U32,+name: String,+access: List<&2,String>) -> World<S,C,R,E> & Bool:
341 match world:
342 case World{+namespace,allocator,store,resource,+events,pending,+registrations,+nextSystemId,+clock,lifecycle}: (World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},registration_list_matches(registrations,id,name,access))
343
344def with_store_finish(~S: Data,~C: Type,~R: Type,~E: Data,~Out: Type,observed: C & Out,+namespace: U32,allocator: A.Allocator,resource: R,+events: List<&2,E>,pending:List<Deferred.Command<World<S,C,R,E>>>,+registrations: List<&2,RegistrationMeta>,+nextSystemId: U32,+clock: Clock.State,lifecycle:Notice.Journal<S>) -> World<S,C,R,E> & Out:
345 (store,value) = observed
346 (World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},value)
347
348
349
350def with_store(~S: Data,~C: Type,~R: Type,~E: Data,~Out: Type,effect: C -> C & Out,world: World<S,C,R,E>) -> World<S,C,R,E> & Out:
351 match world:
352 case World{+namespace,allocator,store,resource,+events,pending,+registrations,+nextSystemId,+clock,lifecycle}: with_store_finish(~S,~C,~R,~E,~Out,effect(store),namespace,allocator,resource,events,pending,registrations,nextSystemId,clock,lifecycle)
353
354def pending_prepend(~S: Data,~C: Type,~R: Type,~E: Data,command: World<S,C,R,E> -> World<S,C,R,E>,counted: List<(World<S,C,R,E> -> World<S,C,R,E>)> & U32) -> List<(World<S,C,R,E> -> World<S,C,R,E>)> & U32:
355 (commands,count) = counted
356 (command <> commands,(count + 1 : U32))
357
358def pending_length_acc(~S: Data,~C: Type,~R: Type,~E: Data,commands:List<Deferred.Command<World<S,C,R,E>>>,reversed: List<Deferred.Command<World<S,C,R,E>>>,count: U32) -> List<Deferred.Command<World<S,C,R,E>>> & U32:
359 match commands:
360 case []: (List.reverse(&1,Deferred.Command<World<S,C,R,E>>,reversed),count)
361 case command <> rest: pending_length_acc(~S,~C,~R,~E,rest,command <> reversed,(count + 1 : U32))
362
363def pending_length(~S: Data,~C: Type,~R: Type,~E: Data,commands:List<Deferred.Command<World<S,C,R,E>>>) -> List<Deferred.Command<World<S,C,R,E>>> & U32:
364 pending_length_acc(~S,~C,~R,~E,commands,[],0)
365
366def pending_count_join(~S: Data,~C: Type,~R: Type,~E: Data,+namespace: U32,allocator: A.Allocator,store: C,resource: R,+events: List<&2,E>,+registrations: List<&2,RegistrationMeta>,+nextSystemId: U32,+clock: Clock.State,counted: List<Deferred.Command<World<S,C,R,E>>> & U32,lifecycle:Notice.Journal<S>) -> World<S,C,R,E> & U32:
367 (pending,count) = counted
368 (World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},count)
369
370
371
372def pending_count(~S: Data,~C: Type,~R: Type,~E: Data,world: World<S,C,R,E>) -> World<S,C,R,E> & U32:
373 match world:
374 case World{+namespace,allocator,store,resource,+events,pending,+registrations,+nextSystemId,+clock,lifecycle}: pending_count_join(~S,~C,~R,~E,namespace,allocator,store,resource,events,registrations,nextSystemId,clock,pending_length(~S,~C,~R,~E,pending),lifecycle)
375
376
377
378
379def events_replace(~S: Data,~C: Type,~R: Type,~E: Data,world: World<S,C,R,E>,+retained: List<&2,E>) -> World<S,C,R,E>:
380 match world:
381 case World{+namespace,allocator,store,resource,_,pending,+registrations,+nextSystemId,+clock,lifecycle}: World{namespace,allocator,store,resource,retained,pending,registrations,nextSystemId,clock,lifecycle}
382
383def key_handles(~S:Data,+namespace:U32,keys:List<&2,K.Key>) -> List<&2,Handle<S>>:
384 match keys:
385 case []:[]
386 case key <> rest:Handle{namespace,key} <> key_handles(~S,namespace,rest)
387def handles_join(~S:Data,~C:Type,~R:Type,~E:Data,+namespace:U32,store:C,resource:R,events:List<&2,E>,pending:List<Deferred.Command<World<S,C,R,E>>>,registrations:List<&2,RegistrationMeta>,nextSystemId:U32,clock:Clock.State,observed:A.Allocator & List<&2,K.Key>,lifecycle:Notice.Journal<S>) -> World<S,C,R,E> & List<&2,Handle<S>>:
388 match observed:
389 case (allocator,keys):(World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle},key_handles(~S,namespace,keys))
390
391
392def handles(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>) -> World<S,C,R,E> & List<&2,Handle<S>>:
393 match world:
394 case World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle}:handles_join(~S,~C,~R,~E,namespace,store,resource,events,pending,registrations,nextSystemId,clock,A.visible(allocator),lifecycle)
395
396
397
398
399def maintain_lifecycle(~S:Data,~C:Type,~R:Type,~E:Data,world:World<S,C,R,E>) -> World<S,C,R,E>:
400 match world:
401 case World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,lifecycle}:World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock,Notice.maintain(~S,lifecycle)}