compose.bend
bendvy-ecs-core@0.1.0.0 · 368 lines · 0 definitions
1import Base
2import bendvy-ecs-core@0.1.0.0/change_tick.bend as Tick
3import bendvy-ecs-core@0.1.0.0/deferred_command.bend as Deferred
4import bendvy-ecs-core@0.1.0.0/trace_facts.bend as TraceFacts
5import world.bend as W
6import column.bend as Col
7import component.bend as Cmp
8import transaction.bend as T
9import resource.bend as Res
10import commands.bend as Cmd
11import capabilities.bend as Cap
12import lifecycle.bend as L
13
14# Trusted engine row carrier: affine Tx, current handle, first recorded operation
15# error and invocation cursor. Ordinary gameplay receives opaque H instead of raw
16# Frame fields; constructing one does not establish handle validity or authority.
17type Frame<-S: Data,-Store: Type,-R: Type,-E: Data> is Type:
18 Frame{tx: T.Tx<W.World<S,Store,R,E>,E>,handle: W.Handle<S>,error: Maybe<&2,W.WorldError>,cursor: Maybe<&2,Tick.Tick>}
19# Execution error separates user-declared failure from a recorded World access
20# refusal. A recorded access error takes precedence over the returned user outcome.
21type Error<U: Data> is Data:
22 UserError{error: U}
23 AccessError{error: W.WorldError}
24# Trusted closed declaration: capability and membership choices travel together.
25# Trusted setup combines grants and membership predicate for one Ops shape.
26# Canonical ordinary declarations derive this pair together; raw Plan construction
27# does not validate arbitrary callbacks or infer capabilities from metadata.
28type Plan<-S: Data,-Store: Type,-R: Type,-E: Data,-Ops: Type -> Type> is Type:
29 Plan{caps: Ops(Frame<S,Store,R,E>),select: Frame<S,Store,R,E> -> Frame<S,Store,R,E> & Bool}
30# Returned World and traversal outcome with ordered detached Data row outputs.
31# Failure returns the rolled-back World and an empty output list, including when
32# earlier rows produced values. This is not an affine payload recovery receipt.
33type Executed<-World: Type,Error: Data,Out: Data> is Type:
34 Executed{world: World,outcome: T.Outcome<Error>,values: List<&2,Out>}
35# Family membership modes: Required/Present require Found, Absent requires a live
36# entity without the component, Optional admits either live presence state. Invalid
37# or foreign/stale handles never satisfy these family selectors.
38type Selection is Data:
39 Required{}
40 Present{}
41 Absent{}
42 Optional{}
43
44def first_error(previous: Maybe<&2,W.WorldError>,error: W.WorldError) -> Maybe<&2,W.WorldError>:
45 match previous:
46 case None{}: Some{error}
47 case Some{previous}: Some{previous}
48
49def read_join(~S: Data,~Store: Type,~R: Type,~E: Data,~V: Data,+handle: W.Handle<S>,error: Maybe<&2,W.WorldError>,cursor: Maybe<&2,Tick.Tick>,observed: T.Tx<W.World<S,Store,R,E>,E> & Cmp.Access<V>) -> Frame<S,Store,R,E> & Cmp.Access<V>:
50 (tx,value) = observed
51 (Frame{tx,handle,error,cursor},value)
52# Advanced row operation: read the current handle through Cmp.tx_get, returning
53# Frame and detached Access<V>. Missing/absent remains an explicit Access result;
54# this read alone does not store a new Frame access error.
55def get(~S: Data,~Store: Type,~R: Type,~E: Data,~Rest: Type,~C: Type,~V: Data,~Token: Data,~take: Store -> Rest & Col.Column<S,C>,~put: Rest -> Col.Column<S,C> -> Store,~project: C -> C & V,~family: Cmp.Family<S,Store,Rest,C,V,Token,take,put,project>,frame: Frame<S,Store,R,E>) -> Frame<S,Store,R,E> & Cmp.Access<V>:
56 match frame:
57 case Frame{tx,+handle,error,cursor}: read_join(~S,~Store,~R,~E,~V,handle,error,cursor,Cmp.tx_get(~S,~Store,~R,~E,~Rest,~C,~V,~Token,~take,~put,~project,family,tx,handle))
58def written(~S: Data,~Store: Type,~R: Type,~E: Data,~C: Type,handle: W.Handle<S>,error: Maybe<&2,W.WorldError>,cursor: Maybe<&2,Tick.Tick>,result: Cmp.SetResult<T.Tx<W.World<S,Store,R,E>,E>,C>) -> Frame<S,Store,R,E>:
59 match result:
60 case Cmp.Written{tx}: Frame{tx,handle,error,cursor}
61 case Cmp.WriteRejected{tx,_,reason}: Frame{tx,handle,first_error(error,reason),cursor}
62 case Cmp.WriteFailure{tx,reason}: Frame{tx,handle,first_error(error,reason),cursor}
63# Advanced row write consuming actual C and returning Frame. Refusal records the
64# first access error and consumes rejected incoming C without returning a receipt.
65# Successful writes journal displaced payload/stamp for transaction rollback.
66def set(~S: Data,~Store: Type,~R: Type,~E: Data,~Rest: Type,~C: Type,~V: Data,~Token: Data,~take: Store -> Rest & Col.Column<S,C>,~put: Rest -> Col.Column<S,C> -> Store,~project: C -> C & V,~family: Cmp.Family<S,Store,Rest,C,V,Token,take,put,project>,frame: Frame<S,Store,R,E>,replacement: C) -> Frame<S,Store,R,E>:
67 match frame:
68 case Frame{tx,+handle,error,cursor}: written(~S,~Store,~R,~E,~C,handle,error,cursor,Cmp.tx_set(~S,~Store,~R,~E,~Rest,~C,~V,~Token,~take,~put,~project,family,tx,handle,replacement))
69# Build a canonical component read grant for the current row. Trusted family
70# lenses/projector return their owners; gameplay sees only detached Access<V>.
71def read_family(~S: Data,~Store: Type,~R: Type,~E: Data,~Rest: Type,~C: Type,~V: Data,~Token: Data,~take: Store -> Rest & Col.Column<S,C>,~put: Rest -> Col.Column<S,C> -> Store,~project: C -> C & V,~family: Cmp.Family<S,Store,Rest,C,V,Token,take,put,project>) -> Cap.Read<Frame<S,Store,R,E>,V>:
72 Cap.Read{get(~S,~Store,~R,~E,~Rest,~C,~V,~Token,~take,~put,~project,~family)}
73# Build current-row component read/write grants. The setter consumes Type C and
74# records refusal on Frame; enclosing execution finishes the transaction. No
75# automatic incoming-owner recovery is added to the capability signature.
76def write_family(~S: Data,~Store: Type,~R: Type,~E: Data,~Rest: Type,~C: Type,~V: Data,~Token: Data,~take: Store -> Rest & Col.Column<S,C>,~put: Rest -> Col.Column<S,C> -> Store,~project: C -> C & V,~family: Cmp.Family<S,Store,Rest,C,V,Token,take,put,project>) -> Cap.Write<Frame<S,Store,R,E>,C,V>:
77 Cap.Write{get(~S,~Store,~R,~E,~Rest,~C,~V,~Token,~take,~put,~project,~family),set(~S,~Store,~R,~E,~Rest,~C,~V,~Token,~take,~put,~project,~family)}
78
79def value_join(~S: Data,~Store: Type,~R: Type,~E: Data,~V: Data,handle: W.Handle<S>,error: Maybe<&2,W.WorldError>,cursor: Maybe<&2,Tick.Tick>,observed: T.Tx<W.World<S,Store,R,E>,E> & V) -> Frame<S,Store,R,E> & V:
80 (tx,value) = observed
81 (Frame{tx,handle,error,cursor},value)
82# Advanced whole-resource read through its owner-returning detached projection.
83# Preserves the current handle/error/cursor; the projector is trusted provisioning.
84def resource_get(~S: Data,~Store: Type,~R: Type,~E: Data,~V: Data,~project: R -> R & V,frame: Frame<S,Store,R,E>) -> Frame<S,Store,R,E> & V:
85 match frame:
86 case Frame{tx,handle,error,cursor}: value_join(~S,~Store,~R,~E,~V,handle,error,cursor,Res.tx_get(~S,~Store,~R,~E,~V,~project,tx))
87# Advanced whole-R replacement, journaling the old owner for rollback. Consumes
88# replacement R and returns Frame; selected-field authority needs a narrower grant.
89def resource_set(~S: Data,~Store: Type,~R: Type,~E: Data,frame: Frame<S,Store,R,E>,replacement: R) -> Frame<S,Store,R,E>:
90 match frame:
91 case Frame{tx,handle,error,cursor}: Frame{Res.tx_replace(~S,~Store,~R,~E,tx,replacement),handle,error,cursor}
92# Build a detached resource read grant using a trusted owner-returning projector.
93def resource_read(~S: Data,~Store: Type,~R: Type,~E: Data,~V: Data,~project: R -> R & V) -> Cap.ValueRead<Frame<S,Store,R,E>,V>:
94 Cap.ValueRead{resource_get(~S,~Store,~R,~E,~V,~project)}
95# Build whole-resource read/replacement grants, not a selected-field permission.
96# Type R remains owned by the transaction or inverse journal, not copied to V.
97def resource_write(~S: Data,~Store: Type,~R: Type,~E: Data,~V: Data,~project: R -> R & V) -> Cap.ValueWrite<Frame<S,Store,R,E>,R,V>:
98 Cap.ValueWrite{resource_get(~S,~Store,~R,~E,~V,~project),resource_set(~S,~Store,~R,~E)}
99# Return the current detached handle with Frame. This is an identity projection,
100# not a fresh liveness validation or permission to access another entity.
101def handle_get(~S: Data,~Store: Type,~R: Type,~E: Data,frame: Frame<S,Store,R,E>) -> Frame<S,Store,R,E> & W.Handle<S>:
102 match frame:
103 case Frame{tx,+handle,error,cursor}: (Frame{tx,handle,error,cursor},handle)
104# Build the current-handle read grant without exposing raw Frame or World.
105def handle_read(~S: Data,~Store: Type,~R: Type,~E: Data) -> Cap.ValueRead<Frame<S,Store,R,E>,W.Handle<S>>:
106 Cap.ValueRead{handle_get(~S,~Store,~R,~E)}
107# Advanced row operation staging a Data event in Tx; publication occurs only
108# after successful execution finish. This does not synchronize an event Runtime.
109def emit(~S: Data,~Store: Type,~R: Type,~E: Data,frame: Frame<S,Store,R,E>,event: E) -> Frame<S,Store,R,E>:
110 match frame:
111 case Frame{tx,handle,error,cursor}: Frame{T.emit(~W.World<S,Store,R,E>,~E,tx,event),handle,error,cursor}
112# Build a Data-event publication grant with transactional staging semantics.
113def event_write(~S: Data,~Store: Type,~R: Type,~E: Data) -> Cap.Send<Frame<S,Store,R,E>,E>:
114 Cap.Send{emit(~S,~Store,~R,~E)}
115def despawn_join(~S: Data,~Store: Type,~R: Type,~E: Data,handle: W.Handle<S>,error: Maybe<&2,W.WorldError>,cursor: Maybe<&2,Tick.Tick>,observed: T.Tx<W.World<S,Store,R,E>,E> & W.Status) -> Frame<S,Store,R,E>:
116 match observed:
117 case (tx,W.Accepted{}): Frame{tx,handle,error,cursor}
118 case (tx,W.Rejected{reason}): Frame{tx,handle,first_error(error,reason),cursor}
119# Advanced row operation staging schema-owned cleanup of the current handle.
120# Admission refusal records the first Frame error. Accepted staging is not visible
121# until successful finish and an explicit barrier; clear is trusted schema setup.
122def despawn(~S: Data,~Store: Type,~R: Type,~E: Data,~clear: Store -> W.Handle<S> -> Store,frame: Frame<S,Store,R,E>) -> Frame<S,Store,R,E>:
123 match frame:
124 case Frame{tx,+handle,error,cursor}: despawn_join(~S,~Store,~R,~E,handle,error,cursor,Cmd.tx_despawn_with(~S,~Store,~R,~E,~clear,tx,handle))
125# Build a current-row deferred despawn grant using complete schema-owned cleanup.
126def command_despawn(~S: Data,~Store: Type,~R: Type,~E: Data,~clear: Store -> W.Handle<S> -> Store) -> Cap.Action<Frame<S,Store,R,E>>:
127 Cap.Action{despawn(~S,~Store,~R,~E,~clear)}
128def spawn_join(~S: Data,~Store: Type,~R: Type,~E: Data,handle: W.Handle<S>,error: Maybe<&2,W.WorldError>,cursor: Maybe<&2,Tick.Tick>,observed: T.Tx<W.World<S,Store,R,E>,E> & W.Reservation<S>) -> Frame<S,Store,R,E> & W.Reservation<S>:
129 match observed:
130 case (tx,W.Reserved{+reserved}): (Frame{tx,handle,error,cursor},W.Reserved{reserved})
131 case (tx,W.ReservationRejected{+reason}): (Frame{tx,handle,first_error(error,reason),cursor},W.ReservationRejected{reason})
132# Advanced reservation/staging operation consuming possibly-affine Payload.
133# Returns Frame and Reservation; refusal records an access error but returns no
134# payload receipt. Reserved handles are Pending, not yet live/readable; populate
135# runs at the barrier after successful finish, with reserved-id progress retained
136# under the ordinary command rollback policy.
137def spawn(~S: Data,~Store: Type,~R: Type,~E: Data,~Payload: Type,~populate: W.World<S,Store,R,E> -> W.Handle<S> -> Payload -> W.World<S,Store,R,E>,frame: Frame<S,Store,R,E>,payload: Payload) -> Frame<S,Store,R,E> & W.Reservation<S>:
138 match frame:
139 case Frame{tx,handle,error,cursor}: spawn_join(~S,~Store,~R,~E,handle,error,cursor,Cmd.tx_spawn(~S,~Store,~R,~E,~Payload,~populate,tx,payload))
140# Build a deferred spawn request grant. populate is trusted structural setup and
141# must consume the actual payload; the Reservation result is not payload recovery.
142def command_spawn(~S: Data,~Store: Type,~R: Type,~E: Data,~Payload: Type,~populate: W.World<S,Store,R,E> -> W.Handle<S> -> Payload -> W.World<S,Store,R,E>) -> Cap.Request<Frame<S,Store,R,E>,Payload,W.Reservation<S>>:
143 Cap.Request{spawn(~S,~Store,~R,~E,~Payload,~populate)}
144
145# Optional means a live entity with either family presence state.
146def selected_value(~V: Data,mode: Selection,value: Cmp.Access<V>) -> Bool:
147 match mode value:
148 case Required{} Cmp.Found{_}: True{}
149 case Present{} Cmp.Found{_}: True{}
150 case Absent{} Cmp.ComponentAbsent{}: True{}
151 case Optional{} Cmp.Found{_}: True{}
152 case Optional{} Cmp.ComponentAbsent{}: True{}
153 case _ _: False{}
154
155def selected_join(~S: Data,~Store: Type,~R: Type,~E: Data,~V: Data,mode: Selection,observed: Frame<S,Store,R,E> & Cmp.Access<V>) -> Frame<S,Store,R,E> & Bool:
156 (frame,value) = observed
157 (frame,selected_value(~V,mode,value))
158# Select current-row membership through the canonical component read. Projectors
159# may run for present components; the returned Frame owner is threaded onward.
160# Selection does not add a write grant or treat MissingEntity as optional absence.
161def family_match(~S: Data,~Store: Type,~R: Type,~E: Data,~Rest: Type,~C: Type,~V: Data,~Token: Data,~take: Store -> Rest & Col.Column<S,C>,~put: Rest -> Col.Column<S,C> -> Store,~project: C -> C & V,~family: Cmp.Family<S,Store,Rest,C,V,Token,take,put,project>,~mode: Selection,frame: Frame<S,Store,R,E>) -> Frame<S,Store,R,E> & Bool:
162 selected_join(~S,~Store,~R,~E,~V,mode,get(~S,~Store,~R,~E,~Rest,~C,~V,~Token,~take,~put,~project,~family,frame))
163# Always select and return Frame unchanged; this predicate itself validates no
164# handle. each supplies a live-handle snapshot, unlike a forged raw Frame.
165def all(~S: Data,~Store: Type,~R: Type,~E: Data,frame: Frame<S,Store,R,E>) -> Frame<S,Store,R,E> & Bool:
166 (frame,True{})
167def and_join(~S: Data,~Store: Type,~R: Type,~E: Data,~right: Frame<S,Store,R,E> -> Frame<S,Store,R,E> & Bool,observed: Frame<S,Store,R,E> & Bool) -> Frame<S,Store,R,E> & Bool:
168 match observed:
169 case (frame,False{}): (frame,False{})
170 case (frame,True{}): right(frame)
171# Conjoin predicates left before right, passing the actual returned Frame onward.
172# False short-circuits right and preserves the owner returned by left; True passes
173# that owner to right. See examples/query-composition/declarations.bend.
174def both(~S: Data,~Store: Type,~R: Type,~E: Data,~left: Frame<S,Store,R,E> -> Frame<S,Store,R,E> & Bool,~right: Frame<S,Store,R,E> -> Frame<S,Store,R,E> & Bool,frame: Frame<S,Store,R,E>) -> Frame<S,Store,R,E> & Bool:
175 and_join(~S,~Store,~R,~E,~right,left(frame))
176
177# Advanced closed engine projection of stored grants; consumes Plan without
178# invoking operations. This is declaration plumbing, not a gameplay grant builder.
179def plan_caps(~S: Data,~Store: Type,~R: Type,~E: Data,~Ops: Type -> Type,plan: Plan<S,Store,R,E,Ops>) -> Ops(Frame<S,Store,R,E>):
180 match plan:
181 case Plan{caps,_}: caps
182# Advanced closed engine projection of the stored predicate. It does not run
183# selection or validate the caller-authored Plan.
184def plan_select(~S: Data,~Store: Type,~R: Type,~E: Data,~Ops: Type -> Type,plan: Plan<S,Store,R,E,Ops>) -> Frame<S,Store,R,E> -> Frame<S,Store,R,E> & Bool:
185 match plan:
186 case Plan{_,select}: select
187
188def outcome(~U: Data,internal: Maybe<&2,W.WorldError>,user: T.Outcome<U>) -> T.Outcome<Error<U>>:
189 match internal user:
190 case Some{error} _: T.Failure{AccessError{error}}
191 case None{} T.Failure{error}: T.Failure{UserError{error}}
192 case None{} T.Success{}: T.Success{}
193
194# Row outputs are committed only when the entire traversal succeeds.
195def prepend(~S: Data,~Store: Type,~R: Type,~E: Data,~U: Data,~Out: Data,value: Out,observed: T.Tx<W.World<S,Store,R,E>,E> & (T.Outcome<Error<U>> & List<&2,Out>)) -> T.Tx<W.World<S,Store,R,E>,E> & (T.Outcome<Error<U>> & List<&2,Out>):
196 (tx,result) = observed
197 (outcome,values) = result
198 (tx,(outcome,value <> values))
199def completed(~S: Data,~Store: Type,~R: Type,~E: Data,~U: Data,~Out: Data,next: T.Tx<W.World<S,Store,R,E>,E> -> T.Tx<W.World<S,Store,R,E>,E> & (T.Outcome<Error<U>> & List<&2,Out>),tx: T.Tx<W.World<S,Store,R,E>,E>,value: Out,result: T.Outcome<Error<U>>) -> T.Tx<W.World<S,Store,R,E>,E> & (T.Outcome<Error<U>> & List<&2,Out>):
200 match result:
201 case T.Success{}: prepend(~S,~Store,~R,~E,~U,~Out,value,next(tx))
202 case T.Failure{error}: (tx,(T.Failure{error},[]))
203def body_returned(~S: Data,~Store: Type,~R: Type,~E: Data,~U: Data,~Out: Data,next: T.Tx<W.World<S,Store,R,E>,E> -> T.Tx<W.World<S,Store,R,E>,E> & (T.Outcome<Error<U>> & List<&2,Out>),observed: Frame<S,Store,R,E> & (T.Outcome<U> & Out)) -> T.Tx<W.World<S,Store,R,E>,E> & (T.Outcome<Error<U>> & List<&2,Out>):
204 match observed:
205 case (Frame{tx,_,internal,_},(user,value)): completed(~S,~Store,~R,~E,~U,~Out,next,tx,value,outcome(~U,internal,user))
206def selected(~S: Data,~Store: Type,~R: Type,~E: Data,~Ops: Type -> Type,~A: Data,~U: Data,~Out: Data,~plan: Plan<S,Store,R,E,Ops>,~body: @-H: Type -> @-caps: Ops(H) -> A -> H -> H & (T.Outcome<U> & Out),args: A,next: T.Tx<W.World<S,Store,R,E>,E> -> T.Tx<W.World<S,Store,R,E>,E> & (T.Outcome<Error<U>> & List<&2,Out>),observed: Frame<S,Store,R,E> & Bool) -> T.Tx<W.World<S,Store,R,E>,E> & (T.Outcome<Error<U>> & List<&2,Out>):
207 match observed:
208 case (Frame{tx,_,_,_},False{}): next(tx)
209 case (frame,True{}): body_returned(~S,~Store,~R,~E,~U,~Out,next,Cap.invoke(~Ops,~A,~(T.Outcome<U> & Out),~body,~Frame<S,Store,R,E>,~plan_caps(~S,~Store,~R,~E,~Ops,plan),args,frame))
210type RowResult<U: Data,Out: Data> is Data:
211 Skipped{}
212 Passed{value: Out}
213 Failed{error: Error<U>}
214def row_completed(~S: Data,~Store: Type,~R: Type,~E: Data,~U: Data,~Out: Data,tx: T.Tx<W.World<S,Store,R,E>,E>,value: Out,result: T.Outcome<Error<U>>) -> T.Tx<W.World<S,Store,R,E>,E> & RowResult<U,Out>:
215 match result:
216 case T.Success{}: (tx,Passed{value})
217 case T.Failure{error}: (tx,Failed{error})
218def row_body_returned(~S: Data,~Store: Type,~R: Type,~E: Data,~U: Data,~Out: Data,observed: Frame<S,Store,R,E> & (T.Outcome<U> & Out)) -> T.Tx<W.World<S,Store,R,E>,E> & RowResult<U,Out>:
219 match observed:
220 case (Frame{tx,_,internal,_},(user,value)): row_completed(~S,~Store,~R,~E,~U,~Out,tx,value,outcome(~U,internal,user))
221def selected_row(~S: Data,~Store: Type,~R: Type,~E: Data,~Ops: Type -> Type,~A: Data,~U: Data,~Out: Data,~plan: Plan<S,Store,R,E,Ops>,~body: @-H: Type -> @-caps: Ops(H) -> A -> H -> H & (T.Outcome<U> & Out),args: A,observed: Frame<S,Store,R,E> & Bool) -> T.Tx<W.World<S,Store,R,E>,E> & RowResult<U,Out>:
222 match observed:
223 case (Frame{tx,_,_,_},False{}): (tx,Skipped{})
224 case (frame,True{}): row_body_returned(~S,~Store,~R,~E,~U,~Out,Cap.invoke(~Ops,~A,~(T.Outcome<U> & Out),~body,~Frame<S,Store,R,E>,~plan_caps(~S,~Store,~R,~E,~Ops,plan),args,frame))
225# Finish each row before the next; keep successful values in reverse order.
226def run_handles_acc(~S: Data,~Store: Type,~R: Type,~E: Data,~Ops: Type -> Type,~A: Data,~U: Data,~Out: Data,~plan: Plan<S,Store,R,E,Ops>,~body: @-H: Type -> @-caps: Ops(H) -> A -> H -> H & (T.Outcome<U> & Out),handles: List<&2,W.Handle<S>>,+args: A,+cursor: Maybe<&2,Tick.Tick>,values: List<&2,Out>,observed: T.Tx<W.World<S,Store,R,E>,E> & RowResult<U,Out>) -> T.Tx<W.World<S,Store,R,E>,E> & (T.Outcome<Error<U>> & List<&2,Out>):
227 match handles observed:
228 case _ Tuple{tx,Failed{error}}: (tx,(T.Failure{error},List.reverse(&2,Out,values)))
229 case Nil{} Tuple{tx,Skipped{}}: (tx,(T.Success{},List.reverse(&2,Out,values)))
230 case Nil{} Tuple{tx,Passed{value}}: (tx,(T.Success{},List.reverse(&2,Out,value <> values)))
231 case Con{handle,rest} Tuple{tx,Skipped{}}: run_handles_acc(~S,~Store,~R,~E,~Ops,~A,~U,~Out,~plan,~body,rest,args,cursor,values,selected_row(~S,~Store,~R,~E,~Ops,~A,~U,~Out,~plan,~body,args,plan_select(~S,~Store,~R,~E,~Ops,plan)(Frame{tx,handle,None{},cursor})))
232 case Con{handle,rest} Tuple{tx,Passed{value}}: run_handles_acc(~S,~Store,~R,~E,~Ops,~A,~U,~Out,~plan,~body,rest,args,cursor,value <> values,selected_row(~S,~Store,~R,~E,~Ops,~A,~U,~Out,~plan,~body,args,plan_select(~S,~Store,~R,~E,~Ops,plan)(Frame{tx,handle,None{},cursor})))
233# Internal owned traversal adapter for an already-open transaction. Execute the
234# supplied list in order and return Tx plus outcome/outputs; unlike each, this does
235# not enumerate handles or finish/commit. Ordinary callers use each/each_since.
236def run_handles(~S: Data,~Store: Type,~R: Type,~E: Data,~Ops: Type -> Type,~A: Data,~U: Data,~Out: Data,~plan: Plan<S,Store,R,E,Ops>,~body: @-H: Type -> @-caps: Ops(H) -> A -> H -> H & (T.Outcome<U> & Out),handles: List<&2,W.Handle<S>>,args: A,cursor: Maybe<&2,Tick.Tick>,tx: T.Tx<W.World<S,Store,R,E>,E>) -> T.Tx<W.World<S,Store,R,E>,E> & (T.Outcome<Error<U>> & List<&2,Out>):
237 run_handles_acc(~S,~Store,~R,~E,~Ops,~A,~U,~Out,~plan,~body,handles,args,cursor,[],(tx,Skipped{}))
238def finish_returned(~S: Data,~Store: Type,~R: Type,~E: Data,~U: Data,~Out: Data,values: List<&2,Out>,returned: T.Returned<W.World<S,Store,R,E>,Error<U>>) -> Executed<W.World<S,Store,R,E>,Error<U>,Out>:
239 match returned:
240 case T.Returned{world,T.Success{}}: Executed{world,T.Success{},values}
241 case T.Returned{world,T.Failure{error}}: Executed{world,T.Failure{error},[]}
242def finished(~S: Data,~Store: Type,~R: Type,~E: Data,~U: Data,~Out: Data,observed: T.Tx<W.World<S,Store,R,E>,E> & (T.Outcome<Error<U>> & List<&2,Out>)) -> Executed<W.World<S,Store,R,E>,Error<U>,Out>:
243 match observed:
244 case (tx,(result,values)): finish_returned(~S,~Store,~R,~E,~U,~Out,values,Cmd.tx_finish(~S,~Store,~R,~E,~Error<U>,tx,result))
245# Advanced engine adapter: execute a supplied handle list within one new Tx and
246# finish it, using cursor for every row. Preserves supplied order without itself
247# validating list provenance; hierarchy adapters perform their own live filtering.
248def scope_finished(~S:Data,~Store:Type,~R:Type,~E:Data,~U:Data,~Out:Data,owned:Bool,result:Executed<W.World<S,Store,R,E>,Error<U>,Out>) -> Executed<W.World<S,Store,R,E>,Error<U>,Out>:
249 match result:
250 case Executed{world,outcome,values}:Executed{W.finish_run(~S,~Store,~R,~E,owned,world),outcome,values}
251def reserved_scoped(~S: Data,~Store: Type,~R: Type,~E: Data,~Ops: Type -> Type,~A: Data,~U: Data,~Out: Data,~plan: Plan<S,Store,R,E,Ops>,~body: @-H: Type -> @-caps: Ops(H) -> A -> H -> H & (T.Outcome<U> & Out),args: A,cursor: Maybe<&2,Tick.Tick>,handles:List<&2,W.Handle<S>>,admitted:W.World<S,Store,R,E> & Bool) -> Executed<W.World<S,Store,R,E>,Error<U>,Out>:
252 (world,owned)=admitted
253 scope_finished(~S,~Store,~R,~E,~U,~Out,owned,finished(~S,~Store,~R,~E,~U,~Out,run_handles(~S,~Store,~R,~E,~Ops,~A,~U,~Out,~plan,~body,handles,args,cursor,T.begin(~W.World<S,Store,R,E>,~E,world))))
254def reserved(~S: Data,~Store: Type,~R: Type,~E: Data,~Ops: Type -> Type,~A: Data,~U: Data,~Out: Data,~plan: Plan<S,Store,R,E,Ops>,~body: @-H: Type -> @-caps: Ops(H) -> A -> H -> H & (T.Outcome<U> & Out),args: A,cursor: Maybe<&2,Tick.Tick>,observed: W.World<S,Store,R,E> & List<&2,W.Handle<S>>) -> Executed<W.World<S,Store,R,E>,Error<U>,Out>:
255 (world,handles)=observed
256 reserved_scoped(~S,~Store,~R,~E,~Ops,~A,~U,~Out,~plan,~body,args,cursor,handles,W.ensure_run(~S,~Store,~R,~E,world))
257# Snapshot live handles in allocator-visible order; deferred commands stay invisible.
258# Snapshot allocator-visible live handles, then select and execute rows in that
259# order within ONE enclosing transaction, with no prior cursor. Later reads observe
260# earlier immediate writes; stop after the first selected-row failure, rollback
261# recorded writes and suppress all outputs/staged publications/commands on failure.
262# Success returns ordered Data outputs and enqueues commands without applying a
263# barrier. User bodies receive only Ops(H), not raw World storage. Arbitrary trusted
264# selectors/projectors or external effects are outside universal rollback claims.
265# See examples/query-composition/declarations.bend and gameplay.bend.
266def each(~S: Data,~Store: Type,~R: Type,~E: Data,~Ops: Type -> Type,~A: Data,~U: Data,~Out: Data,~plan: Plan<S,Store,R,E,Ops>,~body: @-H: Type -> @-caps: Ops(H) -> A -> H -> H & (T.Outcome<U> & Out),args: A,world: W.World<S,Store,R,E>) -> Executed<W.World<S,Store,R,E>,Error<U>,Out>:
267 reserved(~S,~Store,~R,~E,~Ops,~A,~U,~Out,~plan,~body,args,None{},W.handles(~S,~Store,~R,~E,world))
268
269# Explicit schema-typed target and owned payload for a deferred insert grant.
270# Owned explicit-target request for a deferred component insert. The detached
271# handle plus actual Type C are consumed; the request is not itself admission.
272type Insert<-S: Data,-C: Type> is Type:
273 Insert{target: W.Handle<S>,value: C}
274
275def insert_apply(~S: Data,~Store: Type,~R: Type,~E: Data,~Rest: Type,~C: Type,~V: Data,~Token: Data,~take: Store -> Rest & Col.Column<S,C>,~put: Rest -> Col.Column<S,C> -> Store,~project: C -> C & V,~family: Cmp.Family<S,Store,Rest,C,V,Token,take,put,project>,+target: W.Handle<S>,value: C,world: W.World<S,Store,R,E>) -> W.World<S,Store,R,E>:
276 Cmp.restore_done(~S,~Store,~R,~E,~Rest,~C,~V,~Token,~take,~put,~project,Cmp.replace(~S,~Store,~R,~E,~Rest,~C,~V,~Token,~take,~put,~project,family,world,target,Some{value}))
277def insert_checked(~S: Data,~Store: Type,~R: Type,~E: Data,~Rest: Type,~C: Type,~V: Data,~Token: Data,~take: Store -> Rest & Col.Column<S,C>,~put: Rest -> Col.Column<S,C> -> Store,~project: C -> C & V,~family: Cmp.Family<S,Store,Rest,C,V,Token,take,put,project>,current: W.Handle<S>,error: Maybe<&2,W.WorldError>,cursor: Maybe<&2,Tick.Tick>,+target: W.Handle<S>,value: C,undo: List<(W.World<S,Store,R,E> -> W.World<S,Store,R,E>)>,commands:List<Deferred.Command<W.World<S,Store,R,E>>>,events: List<&2,E>,trace:TraceFacts.State,observed: W.World<S,Store,R,E> & Bool) -> Frame<S,Store,R,E>:
278 match observed:
279 case (world,False{}): Frame{T.Tx{world,undo,commands,events,trace},current,first_error(error,W.MissingEntity{}),cursor}
280 case (world,True{}): Frame{T.stage(~W.World<S,Store,R,E>,~E,T.Tx{world,undo,commands,events,trace},(world => insert_apply(~S,~Store,~R,~E,~Rest,~C,~V,~Token,~take,~put,~project,~family,target,value,world))),current,error,cursor}
281# Advanced deferred insertion for an explicitly supplied currently live target.
282# Invalid/foreign/stale admission records MissingEntity and consumes the payload.
283# Accepted work is staged, then rechecks live replacement at barrier application;
284# application refusal does not return an incoming-owner receipt through this API.
285def insert(~S: Data,~Store: Type,~R: Type,~E: Data,~Rest: Type,~C: Type,~V: Data,~Token: Data,~take: Store -> Rest & Col.Column<S,C>,~put: Rest -> Col.Column<S,C> -> Store,~project: C -> C & V,~family: Cmp.Family<S,Store,Rest,C,V,Token,take,put,project>,frame: Frame<S,Store,R,E>,request: Insert<S,C>) -> Frame<S,Store,R,E>:
286 match frame request:
287 case Frame{T.Tx{world,undo,commands,events,trace},current,error,cursor} Insert{+target,value}: insert_checked(~S,~Store,~R,~E,~Rest,~C,~V,~Token,~take,~put,~project,~family,current,error,cursor,target,value,undo,commands,events,trace,W.valid(~S,~Store,~R,~E,world,target))
288# Build a family-specific deferred insert grant. This does not grant arbitrary
289# family access or promise insertion into a merely Pending spawn handle.
290def command_insert(~S: Data,~Store: Type,~R: Type,~E: Data,~Rest: Type,~C: Type,~V: Data,~Token: Data,~take: Store -> Rest & Col.Column<S,C>,~put: Rest -> Col.Column<S,C> -> Store,~project: C -> C & V,~family: Cmp.Family<S,Store,Rest,C,V,Token,take,put,project>) -> Cap.Send<Frame<S,Store,R,E>,Insert<S,C>>:
291 Cap.Send{insert(~S,~Store,~R,~E,~Rest,~C,~V,~Token,~take,~put,~project,~family)}
292
293# As each, with an explicit invocation cursor used by lifecycle predicates.
294# This does not automatically advance a registered reader, and does not itself
295# filter rows unless Plan.select contains lifecycle_match or another predicate.
296def each_since(~S: Data,~Store: Type,~R: Type,~E: Data,~Ops: Type -> Type,~A: Data,~U: Data,~Out: Data,~plan: Plan<S,Store,R,E,Ops>,~body: @-H: Type -> @-caps: Ops(H) -> A -> H -> H & (T.Outcome<U> & Out),args: A,world: W.World<S,Store,R,E>,cursor: Maybe<&2,Tick.Tick>) -> Executed<W.World<S,Store,R,E>,Error<U>,Out>:
297 reserved(~S,~Store,~R,~E,~Ops,~A,~U,~Out,~plan,~body,args,cursor,W.handles(~S,~Store,~R,~E,world))
298
299# Since cursor is runtime reader state; it lives in the affine row frame.
300# Added/Changed select component lifecycle stamps relative to Frame.cursor.
301# They grant no additional access and are not automatic reader advancement.
302type LifecycleSelection is Data:
303 Added{}
304 Changed{}
305def lifecycle_selected(mode: LifecycleSelection,stamp: L.Stamp,cursor: Maybe<&2,Tick.Tick>,this:Tick.Tick) -> Bool:
306 match mode:
307 case Added{}: L.added(stamp,cursor,this)
308 case Changed{}: L.changed(stamp,cursor,this)
309def lifecycle_clocked(~S: Data,~Store: Type,~R: Type,~E: Data,~mode: LifecycleSelection,handle: W.Handle<S>,error: Maybe<&2,W.WorldError>,+cursor: Maybe<&2,Tick.Tick>,undo: List<(W.World<S,Store,R,E> -> W.World<S,Store,R,E>)>,commands:List<Deferred.Command<W.World<S,Store,R,E>>>,events: List<&2,E>,trace:TraceFacts.State,stamp:L.Stamp,observed: W.World<S,Store,R,E> & Tick.Tick) -> Frame<S,Store,R,E> & Bool:
310 (world,this)=observed
311 (Frame{T.Tx{world,undo,commands,events,trace},handle,error,cursor},lifecycle_selected(mode,stamp,cursor,this))
312def lifecycle_join(~S: Data,~Store: Type,~R: Type,~E: Data,~mode: LifecycleSelection,handle: W.Handle<S>,error: Maybe<&2,W.WorldError>,+cursor: Maybe<&2,Tick.Tick>,undo: List<(W.World<S,Store,R,E> -> W.World<S,Store,R,E>)>,commands:List<Deferred.Command<W.World<S,Store,R,E>>>,events: List<&2,E>,trace:TraceFacts.State,observed: W.World<S,Store,R,E> & L.Stamp) -> Frame<S,Store,R,E> & Bool:
313 (world,stamp)=observed
314 lifecycle_clocked(~S,~Store,~R,~E,~mode,handle,error,cursor,undo,commands,events,trace,stamp,W.execution_clock(~S,~Store,~R,~E,world))
315# Compare this family slot stamp against the supplied invocation cursor and
316# return Frame with Bool. Does not project the payload or create a gameplay grant;
317# combine with membership predicates when actual presence is required.
318def lifecycle_match(~S: Data,~Store: Type,~R: Type,~E: Data,~Rest: Type,~C: Type,~V: Data,~Token: Data,~take: Store -> Rest & Col.Column<S,C>,~put: Rest -> Col.Column<S,C> -> Store,~project: C -> C & V,~family: Cmp.Family<S,Store,Rest,C,V,Token,take,put,project>,~mode: LifecycleSelection,frame: Frame<S,Store,R,E>) -> Frame<S,Store,R,E> & Bool:
319 match frame:
320 case Frame{T.Tx{world,undo,commands,events,trace},+handle,error,cursor}: lifecycle_join(~S,~Store,~R,~E,~mode,handle,error,cursor,undo,commands,events,trace,Cmp.lifecycle(~S,~Store,~R,~E,~Rest,~C,~V,~Token,~take,~put,~project,family,world,handle))
321def clock_join(~S: Data,~Store: Type,~R: Type,~E: Data,handle: W.Handle<S>,error: Maybe<&2,W.WorldError>,cursor: Maybe<&2,Tick.Tick>,undo: List<(W.World<S,Store,R,E> -> W.World<S,Store,R,E>)>,commands:List<Deferred.Command<W.World<S,Store,R,E>>>,events: List<&2,E>,trace:TraceFacts.State,observed: W.World<S,Store,R,E> & Tick.Tick) -> Frame<S,Store,R,E> & Tick.Tick:
322 (world,clock) = observed
323 (Frame{T.Tx{world,undo,commands,events,trace},handle,error,cursor},clock)
324# Advanced detached read of the current transaction World tick; does not advance
325# it or change Frame.cursor.
326def clock_get(~S: Data,~Store: Type,~R: Type,~E: Data,frame: Frame<S,Store,R,E>) -> Frame<S,Store,R,E> & Tick.Tick:
327 match frame:
328 case Frame{T.Tx{world,undo,commands,events,trace},handle,error,cursor}: clock_join(~S,~Store,~R,~E,handle,error,cursor,undo,commands,events,trace,W.clock(~S,~Store,~R,~E,world))
329# Build a current-World tick read grant, not a clock-advance capability.
330def clock_read(~S: Data,~Store: Type,~R: Type,~E: Data) -> Cap.ValueRead<Frame<S,Store,R,E>,Tick.Tick>:
331 Cap.ValueRead{clock_get(~S,~Store,~R,~E)}
332
333# Trace-aware advanced setter with the same consumption/error behavior as set.
334# When tracing is enabled, trusted projection/rendering annotates before/after
335# Data views; disabled tracing skips that presentation work.
336def set_displayed(~S: Data,~Store: Type,~R: Type,~E: Data,~Rest: Type,~C: Type,~V: Data,~Token: Data,~take: Store -> Rest & Col.Column<S,C>,~put: Rest -> Col.Column<S,C> -> Store,~project: C -> C & V,~family: Cmp.Family<S,Store,Rest,C,V,Token,take,put,project>,~display:V -> String,frame: Frame<S,Store,R,E>,replacement: C) -> Frame<S,Store,R,E>:
337 match frame:
338 case Frame{tx,+handle,error,cursor}: written(~S,~Store,~R,~E,~C,handle,error,cursor,Cmp.tx_set_displayed(~S,~Store,~R,~E,~Rest,~C,~V,~Token,~take,~put,~project,~display,family,tx,handle,replacement))
339# Build component grants whose setter uses the supplied detached display function
340# for enabled tracing. This is presentation, not additional mutation authority.
341def write_family_displayed(~S: Data,~Store: Type,~R: Type,~E: Data,~Rest: Type,~C: Type,~V: Data,~Token: Data,~take: Store -> Rest & Col.Column<S,C>,~put: Rest -> Col.Column<S,C> -> Store,~project: C -> C & V,~family: Cmp.Family<S,Store,Rest,C,V,Token,take,put,project>,~display:V -> String) -> Cap.Write<Frame<S,Store,R,E>,C,V>:
342 Cap.Write{get(~S,~Store,~R,~E,~Rest,~C,~V,~Token,~take,~put,~project,~family),set_displayed(~S,~Store,~R,~E,~Rest,~C,~V,~Token,~take,~put,~project,~family,~display)}
343
344def finish_returned_observed(~S:Data,~Store:Type,~R:Type,~E:Data,~U:Data,~Out:Data,values:List<&2,Out>,result:T.Returned<W.World<S,Store,R,E>,Error<U>> & TraceFacts.State) -> Executed<W.World<S,Store,R,E>,Error<U>,Out> & TraceFacts.State:
345 match result:
346 case (returned,trace):(finish_returned(~S,~Store,~R,~E,~U,~Out,values,returned),trace)
347
348def finished_observed(~S: Data,~Store: Type,~R: Type,~E: Data,~U: Data,~Out: Data,observed: T.Tx<W.World<S,Store,R,E>,E> & (T.Outcome<Error<U>> & List<&2,Out>)) -> Executed<W.World<S,Store,R,E>,Error<U>,Out> & TraceFacts.State:
349 match observed:
350 case (tx,(result,values)): finish_returned_observed(~S,~Store,~R,~E,~U,~Out,values,T.finish_observed(~W.World<S,Store,R,E>,~E,~Error<U>,~Cmd.enqueue(~S,~Store,~R,~E),~Cmd.publish(~S,~Store,~R,~E),tx,result))
351# Trace-aware advanced supplied-list execution adapter. Retains the same one-Tx
352# finish and output-clearing behavior as reserved, returning actual trace state
353# separately; operation facts do not assert that failed writes committed.
354def scope_observed(~S:Data,~Store:Type,~R:Type,~E:Data,~U:Data,~Out:Data,owned:Bool,result:Executed<W.World<S,Store,R,E>,Error<U>,Out> & TraceFacts.State) -> Executed<W.World<S,Store,R,E>,Error<U>,Out> & TraceFacts.State:
355 (executed,trace)=result
356 (scope_finished(~S,~Store,~R,~E,~U,~Out,owned,executed),trace)
357def reserved_observed_scoped(~S: Data,~Store: Type,~R: Type,~E: Data,~Ops: Type -> Type,~A: Data,~U: Data,~Out: Data,~plan: Plan<S,Store,R,E,Ops>,~body: @-H: Type -> @-caps: Ops(H) -> A -> H -> H & (T.Outcome<U> & Out),trace:TraceFacts.State,args: A,cursor: Maybe<&2,Tick.Tick>,handles:List<&2,W.Handle<S>>,admitted:W.World<S,Store,R,E> & Bool) -> Executed<W.World<S,Store,R,E>,Error<U>,Out> & TraceFacts.State:
358 (world,owned)=admitted
359 scope_observed(~S,~Store,~R,~E,~U,~Out,owned,finished_observed(~S,~Store,~R,~E,~U,~Out,run_handles(~S,~Store,~R,~E,~Ops,~A,~U,~Out,~plan,~body,handles,args,cursor,T.begin_with_trace(~W.World<S,Store,R,E>,~E,world,trace))))
360def reserved_observed(~S: Data,~Store: Type,~R: Type,~E: Data,~Ops: Type -> Type,~A: Data,~U: Data,~Out: Data,~plan: Plan<S,Store,R,E,Ops>,~body: @-H: Type -> @-caps: Ops(H) -> A -> H -> H & (T.Outcome<U> & Out),trace:TraceFacts.State,args: A,cursor: Maybe<&2,Tick.Tick>,observed: W.World<S,Store,R,E> & List<&2,W.Handle<S>>) -> Executed<W.World<S,Store,R,E>,Error<U>,Out> & TraceFacts.State:
361 (world,handles)=observed
362 reserved_observed_scoped(~S,~Store,~R,~E,~Ops,~A,~U,~Out,~plan,~body,trace,args,cursor,handles,W.ensure_run(~S,~Store,~R,~E,world))
363# Snapshot live handles in allocator-visible order; deferred commands stay invisible.
364# As each_since with supplied operation trace state returned alongside Executed.
365# Tracing does not change capability authority or apply pending commands. Facts
366# may include attempted/refused operations; inspect execution outcome separately.
367def each_since_observed(~S: Data,~Store: Type,~R: Type,~E: Data,~Ops: Type -> Type,~A: Data,~U: Data,~Out: Data,~plan: Plan<S,Store,R,E,Ops>,~body: @-H: Type -> @-caps: Ops(H) -> A -> H -> H & (T.Outcome<U> & Out),trace:TraceFacts.State,args: A,world: W.World<S,Store,R,E>,cursor: Maybe<&2,Tick.Tick>) -> Executed<W.World<S,Store,R,E>,Error<U>,Out> & TraceFacts.State:
368 reserved_observed(~S,~Store,~R,~E,~Ops,~A,~U,~Out,~plan,~body,trace,args,cursor,W.handles(~S,~Store,~R,~E,world))