1 import Base 2 import ./change_tick.bend as Tick 3 import ./world.bend as W 4 import ./compose.bend as Q 5 import ./capture_query.bend as Fold 6 import ./ordinary_query_declaration.bend as Decl 7 import ./ordinary_system.bend as Ordinary 8 import ./local.bend as Local 9 import ./captures.bend as Capture 10 import ./transaction.bend as T 11 # Capture lifecycle reuses Local; each completed run consumes its captured tick. 12 # Advanced lowering of the closed query declaration into its typed grant 13 # and membership predicate; it performs no traversal or capture mutation. 14 def plan(~S:Data,~C:Type,~R:Type,~E:Data,~L:Type,~Ops:Type -> Type,~A:Data,~U:Data,~Out:Data,~query:Decl.Declaration,Ops(Q.Frame)>,~body:@-H:Type -> @-caps:Ops(H) -> L -> A -> H -> H & (L & (T.Outcome & Out))) -> Q.Plan: 15 Q.Plan{Decl.grant(~S,~Q.Frame,~Ops(Q.Frame),query),Decl.selector(~S,~Q.Frame,~Ops(Q.Frame),query)} 16 def finished(~S:Data,~C:Type,~R:Type,~E:Data,~L:Type,~U:Data,~Out:Data,result:Fold.Executed,L,Q.Error,Out>) -> Local.Outcome,L,Q.Error,List<&2,Out>>: 17 match result: 18 case Fold.Executed{world,capture,T.Success{},values}:Local.Succeeded{world,capture,values} 19 case Fold.Executed{world,capture,T.Failure{error},_}:Local.Failed{world,capture,error} 20 # Advanced captured-query runner with explicit (args,cursor). Threads L 21 # through selected rows while the ECS transaction journals World changes. 22 # Failure retains returned capture but discards row outputs. Bypasses runtime 23 # registration checks; ordinary callers use define/run or App capture add. 24 def runner(~S:Data,~C:Type,~R:Type,~E:Data,~L:Type,~Ops:Type -> Type,~A:Data,~U:Data,~Out:Data,~query:Decl.Declaration,Ops(Q.Frame)>,~body:@-H:Type -> @-caps:Ops(H) -> L -> A -> H -> H & (L & (T.Outcome & Out)),world:W.World,capture:L,args:A & Maybe<&2,Tick.Tick>) -> Local.Outcome,L,Q.Error,List<&2,Out>>: 25 match args: 26 case (args,cursor):finished(~S,~C,~R,~E,~L,~U,~Out,Fold.each_since(~S,~C,~R,~E,~L,~U,~Out,~Ops,~A,~plan(~S,~C,~R,~E,~L,~Ops,~A,~U,~Out,~query,~body),~body,args,cursor,capture,world)) 27 # Runtime-bound captured-query owner: a Local instance owns affine capture L 28 # and a separate cursor tracks query lifecycle visibility. Keep both returned 29 # parts together across runs; raw constructors are trusted administration. 30 type Owner<-S:Data,-C:Type,-R:Type,-E:Data,-L:Type,-Ops:Type -> Type,-A:Data,-U:Data,-Out:Data,-query:Decl.Declaration,Ops(Q.Frame)>,-body:@-H:Type -> @-caps:Ops(H) -> L -> A -> H -> H & (L & (T.Outcome & Out))> is Type: 31 Owner{instance:Local.Instance,Q.Error,List<&2,Out>,runner(~S,~C,~R,~E,~L,~Ops,~A,~U,~Out,~query,~body)>,cursor:Maybe<&2,Tick.Tick>} 32 # Registered returns World and captured-query owner; Rejected returns 33 # World and initial capture L without invoking the query body. 34 type Registration is Type: 35 Registered{world:World,owner:Owned} 36 Rejected{world:World,capture:L} 37 # Completed returns World, retained capture owner and ordered row outputs 38 # or query error. Refused returns World/owner and original Data args before 39 # body execution. Capture state survives body failure; failed row outputs do not. 40 type Run is Type: 41 Completed{world:World,owner:Owned,result:Result>} 42 Refused{world:World,owner:Owned,args:A} 43 # Removed returns World and detached affine capture after deregistration. 44 # RemovalRejected returns World and original owner. No finalizer is invoked 45 # here: caller decides how to reuse or dispose the returned capture. 46 type Removal is Type: 47 Removed{world:World,capture:L} 48 RemovalRejected{world:World,owner:Owned} 49 def registered(~S:Data,~C:Type,~R:Type,~E:Data,~L:Type,~Ops:Type -> Type,~A:Data,~U:Data,~Out:Data,~query:Decl.Declaration,Ops(Q.Frame)>,~body:@-H:Type -> @-caps:Ops(H) -> L -> A -> H -> H & (L & (T.Outcome & Out)),result:Local.Registered,Q.Error,List<&2,Out>,runner(~S,~C,~R,~E,~L,~Ops,~A,~U,~Out,~query,~body)>) -> Registration,Owner,L>: 50 match result: 51 case Local.Registered{world,instance}:Registered{world,Owner{instance,None{}}} 52 case Local.RegistrationRejected{world,capture}:Rejected{world,capture} 53 # Register a captured query with access derived from the same declaration. 54 # Consumes capture; refusal returns it with World. Success owns a real Local 55 # registration and initializes an absent query cursor. No body runs at setup. 56 # Example: examples/captured-query/app.bend. 57 def define(~S:Data,~C:Type,~R:Type,~E:Data,~L:Type,~Ops:Type -> Type,~A:Data,~U:Data,~Out:Data,~query:Decl.Declaration,Ops(Q.Frame)>,~body:@-H:Type -> @-caps:Ops(H) -> L -> A -> H -> H & (L & (T.Outcome & Out)),world:W.World,name:String,capture:L) -> Registration,Owner,L>: 58 registered(~S,~C,~R,~E,~L,~Ops,~A,~U,~Out,~query,~body,Capture.register(~S,~C,~R,~E,~L,~(A & Maybe<&2,Tick.Tick>),~Q.Error,~List<&2,Out>,~runner(~S,~C,~R,~E,~L,~Ops,~A,~U,~Out,~query,~body),world,name,Ordinary.access(~S,Decl.clauses(~S,~Q.Frame,~Ops(Q.Frame),query)),capture)) 59 def returned(~S:Data,~C:Type,~R:Type,~E:Data,~L:Type,~Ops:Type -> Type,~A:Data,~U:Data,~Out:Data,~query:Decl.Declaration,Ops(Q.Frame)>,~body:@-H:Type -> @-caps:Ops(H) -> L -> A -> H -> H & (L & (T.Outcome & Out)),cursor:Maybe<&2,Tick.Tick>,result:Local.Run,Q.Error,List<&2,Out>,runner(~S,~C,~R,~E,~L,~Ops,~A,~U,~Out,~query,~body)>) -> Run,Owner,A,Q.Error,Out>: 60 match result: 61 case Local.Completed{world,instance,Done{values},tick}:Completed{world,Owner{instance,Some{tick}},Done{values}} 62 case Local.Completed{world,instance,Fail{error},tick}:Completed{world,Owner{instance,Some{tick}},Fail{error}} 63 case Local.Refused{world,instance,(args,_)}:Refused{world,Owner{instance,cursor},args} 64 # Execute the checked captured-query registration at its retained cursor. 65 # Completed success/error consume the captured execution tick; refusal preserves it. 66 # Query failure rolls back recorded World changes but retains capture changes; 67 # registration refusal returns original args without running body. Deferred 68 # commands remain invisible until explicit barriers. 69 def run(~S:Data,~C:Type,~R:Type,~E:Data,~L:Type,~Ops:Type -> Type,~A:Data,~U:Data,~Out:Data,~query:Decl.Declaration,Ops(Q.Frame)>,~body:@-H:Type -> @-caps:Ops(H) -> L -> A -> H -> H & (L & (T.Outcome & Out)),owner:Owner,world:W.World,args:A) -> Run,Owner,A,Q.Error,Out>: 70 match owner: 71 case Owner{instance,+cursor}:returned(~S,~C,~R,~E,~L,~Ops,~A,~U,~Out,~query,~body,cursor,Capture.run(~S,~C,~R,~E,~L,~(A & Maybe<&2,Tick.Tick>),~Q.Error,~List<&2,Out>,~runner(~S,~C,~R,~E,~L,~Ops,~A,~U,~Out,~query,~body),instance,world,(args,cursor))) 72 # No callback entry: preserve capture and the existing query reader cursor. 73 # Return the same captured owner and World without invoking the body. 74 # Both capture state and query cursor remain unchanged. 75 def skip(~S:Data,~C:Type,~R:Type,~E:Data,~L:Type,~Ops:Type -> Type,~A:Data,~U:Data,~Out:Data,~query:Decl.Declaration,Ops(Q.Frame)>,~body:@-H:Type -> @-caps:Ops(H) -> L -> A -> H -> H & (L & (T.Outcome & Out)),owner:Owner,world:W.World) -> Owner & W.World: 76 (owner,world) 77 def removed(~S:Data,~C:Type,~R:Type,~E:Data,~L:Type,~Ops:Type -> Type,~A:Data,~U:Data,~Out:Data,~query:Decl.Declaration,Ops(Q.Frame)>,~body:@-H:Type -> @-caps:Ops(H) -> L -> A -> H -> H & (L & (T.Outcome & Out)),cursor:Maybe<&2,Tick.Tick>,result:Local.Disposal,Q.Error,List<&2,Out>,runner(~S,~C,~R,~E,~L,~Ops,~A,~U,~Out,~query,~body),L>) -> Removal,Owner,L>: 78 match result: 79 case Local.Disposed{world,capture}:Removed{world,capture} 80 case Local.DisposalRejected{world,instance}:RemovalRejected{world,Owner{instance,cursor}} 81 # Remove the matching registration and return its actual affine capture. 82 # Refusal returns the original owner for retry; success returns Removed with 83 # World/capture. Does not invoke a user finalizer or reset unrelated systems. 84 def unregister(~S:Data,~C:Type,~R:Type,~E:Data,~L:Type,~Ops:Type -> Type,~A:Data,~U:Data,~Out:Data,~query:Decl.Declaration,Ops(Q.Frame)>,~body:@-H:Type -> @-caps:Ops(H) -> L -> A -> H -> H & (L & (T.Outcome & Out)),owner:Owner,world:W.World) -> Removal,Owner,L>: 85 match owner: 86 case Owner{instance,cursor}:removed(~S,~C,~R,~E,~L,~Ops,~A,~U,~Out,~query,~body,cursor,Capture.unregister(~S,~C,~R,~E,~L,~(A & Maybe<&2,Tick.Tick>),~Q.Error,~List<&2,Out>,~runner(~S,~C,~R,~E,~L,~Ops,~A,~U,~Out,~query,~body),instance,world))