1 import Base 2 import ../change_tick.bend as Tick 3 import ../clock_state.bend as Clock 4 import ../world.bend as W 5 import ../entity_key.bend as K 6 import ../entity_allocator.bend as A 7 import ../component.bend as C 8 import ../column.bend as Col 9 import ../inspector.bend as I 10 import ../inspector_query.bend as IQ 11 import ../inspector_query_world.bend as IW 12 import ../inspector_query_projection.bend as P 13 import ../compose.bend as Q 14 import ../deferred_command.bend as Deferred 15 16 # A scan owns one Store; unrelated World owners remain outside its row loop. 17 type Owner<-S:Data,-Store:Type> is Type: 18 Owner{namespace:U32,allocator:A.Allocator,store:Store,cursor:Maybe<&2,Tick.Tick>} 19 20 def read_join(~S:Data,~Store:Type,~V:Data,namespace:U32,allocator:A.Allocator,cursor:Maybe<&2,Tick.Tick>,observed:Store & C.Access) -> Owner & C.Access: 21 (store,value)=observed 22 (Owner{namespace,allocator,store,cursor},value) 23 def read_valid(~S:Data,~Store:Type,~Rest:Type,~Payload:Type,~V:Data,~take:Store -> Rest & Col.Column,~put:Rest -> Col.Column -> Store,~view:Payload -> Payload & V,namespace:U32,store:Store,cursor:Maybe<&2,Tick.Tick>,key:K.Key,observed:A.Allocator & Bool) -> Owner & C.Access: 24 match key observed: 25 case _, (allocator,False{}):(Owner{namespace,allocator,store,cursor},C.MissingEntity{}) 26 case K.EntityKey{id,_}, (allocator,True{}):read_join(~S,~Store,~V,namespace,allocator,cursor,C.get_store(~S,~Store,~Unit,~Nat,~Rest,~Payload,~V,~Unit,~take,~put,~view,id,take(store))) 27 def read_namespace(~S:Data,~Store:Type,~Rest:Type,~Payload:Type,~V:Data,~take:Store -> Rest & Col.Column,~put:Rest -> Col.Column -> Store,~view:Payload -> Payload & V,allowed:Bool,namespace:U32,allocator:A.Allocator,store:Store,cursor:Maybe<&2,Tick.Tick>,+key:K.Key) -> Owner & C.Access: 28 match allowed: 29 case False{}:(Owner{namespace,allocator,store,cursor},C.MissingEntity{}) 30 case True{}:read_valid(~S,~Store,~Rest,~Payload,~V,~take,~put,~view,namespace,store,cursor,key,A.checked(allocator,key,1)) 31 def read(~S:Data,~Store:Type,~Rest:Type,~Payload:Type,~V:Data,~take:Store -> Rest & Col.Column,~put:Rest -> Col.Column -> Store,~view:Payload -> Payload & V,owner:Owner,target:W.Handle) -> Owner & C.Access: 32 match owner target: 33 case Owner{+namespace,allocator,store,cursor} W.Handle{ns,key}:read_namespace(~S,~Store,~Rest,~Payload,~V,~take,~put,~view,U32.is_eq(namespace,ns),namespace,allocator,store,cursor,key) 34 def matched(~S:Data,~Store:Type,mode:Q.Selection,observed:Owner & C.Access) -> Owner & Bool: 35 (owner,value)=observed 36 (owner,Q.selected_value(~Bool,mode,value)) 37 def matches(~S:Data,~Store:Type,~Rest:Type,~Payload:Type,~take:Store -> Rest & Col.Column,~put:Rest -> Col.Column -> Store,~mode:Q.Selection,owner:Owner,target:W.Handle) -> Owner & Bool: 38 matched(~S,~Store,mode,read(~S,~Store,~Rest,~Payload,~Bool,~take,~put,~Col.present(~Payload),owner,target)) 39 def slot(~S:Data,~Store:Type,~Rest:Type,~Payload:Type,~V:Data,~take:Store -> Rest & Col.Column,~put:Rest -> Col.Column -> Store,~view:Payload -> Payload & V,~mode:Q.Selection) -> P.DeclaredSelection,S,C.Access>: 40 P.DeclaredSelection{owner=>target=>matches(~S,~Store,~Rest,~Payload,~take,~put,~mode,owner,target),owner=>target=>read(~S,~Store,~Rest,~Payload,~V,~take,~put,~view,owner,target)} 41 42 def restore(~S:Data,~Store:Type,~R:Type,~E:Data,~V:Data,resource:R,events:List<&2,E>,pending:List>>,registrations:List<&2,W.RegistrationMeta>,nextSystemId:U32,clock:Clock.State,observed:Owner & List<&2,IQ.ProjectedRow>) -> I.Frame & List<&2,IQ.ProjectedRow>: 43 match observed: 44 case (Owner{namespace,allocator,store,cursor},rows):(I.Frame{W.World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock},cursor},rows) 45 def enter_world(~S:Data,~Store:Type,~R:Type,~E:Data,~V:Data,~selection:P.DeclaredSelection,S,V>,world:W.World,cursor:Maybe<&2,Tick.Tick>,targets:List<&2,W.Handle>) -> I.Frame & List<&2,IQ.ProjectedRow>: 46 match world: 47 case W.World{namespace,allocator,store,resource,events,pending,registrations,nextSystemId,clock}:restore(~S,~Store,~R,~E,~V,resource,events,pending,registrations,nextSystemId,clock,IQ.composed_scanned(~Owner,~S,~V,~selection,(Owner{namespace,allocator,store,cursor},targets))) 48 def enter(~S:Data,~Store:Type,~R:Type,~E:Data,~V:Data,~selection:P.DeclaredSelection,S,V>,observed:I.Frame & List<&2,W.Handle>) -> I.Frame & List<&2,IQ.ProjectedRow>: 49 match observed: 50 case (I.Frame{world,cursor},targets):enter_world(~S,~Store,~R,~E,~V,~selection,world,cursor,targets) 51 def enumerate(~S:Data,~Store:Type,~R:Type,~E:Data,~V:Data,~selection:P.DeclaredSelection,S,V>,frame:I.Frame) -> I.Frame & List<&2,IQ.ProjectedRow>: 52 enter(~S,~Store,~R,~E,~V,~selection,IQ.composed_handles_field(~I.Frame,~S,IW.inspect_world(~S,~Store,~R,~E))(frame))