1 import Base 2 import ./ordinary_check_declaration.bend as D 3 import ./ordinary_component_binding.bend as B 4 import ./ordinary_declaration.bend as Identity 5 import ./ordinary_query_selections.bend as Leaves 6 import ./inspector_query_families.bend as Families 7 import ./inspector_query_projection.bend as Q 8 import ./inspector_query.bend as Query 9 import ./inspector_query_world.bend as Traverse 10 import ./check.bend as K 11 import ./column.bend as Col 12 import ./component.bend as C 13 import ./world.bend as W 14 15 # Operational selection and description are produced from the same bindings. 16 # Required component selection means row membership, never World admission. 17 type Selection<-H:Type,-S:Data,-V:Data> is Type: 18 Selection{selection:Q.DeclaredSelection,uses:List<&2,D.Use>} 19 type Predicate<-H:Type,-S:Data> is Type: 20 Predicate{predicate:Q.Predicate,uses:List<&2,D.Use>} 21 def selected(~H:Type,~S:Data,~V:Data,value:Selection) -> Q.DeclaredSelection: 22 match value: 23 case Selection{selection,_}:selection 24 def uses(~H:Type,~S:Data,~V:Data,value:Selection) -> List<&2,D.Use>: 25 match value: 26 case Selection{_,uses}:uses 27 def predicate(~H:Type,~S:Data,value:Predicate) -> Q.Predicate: 28 match value: 29 case Predicate{predicate,_}:predicate 30 def predicate_uses(~H:Type,~S:Data,value:Predicate) -> List<&2,D.Use>: 31 match value: 32 case Predicate{_,uses}:uses 33 def read(~S:Data,~Store:Type,~R:Type,~E:Data,~Rest:Type,~P:Type,~V:Data,~Token:Data,~take:Store -> Rest & Col.Column,~put:Rest -> Col.Column -> Store,~view:P -> P & V,~binding:B.Binding) -> Selection,S,C.Access>: 34 Selection{Leaves.check_slot(~S,~Store,~R,~E,~Rest,~P,~V,~Token,~take,~put,~view,~binding,~Families.Required{}),[D.Use{D.Component{D.Required{}},Identity.key(~S,~P,B.identity(~S,~Store,~Rest,~P,~V,~Token,~take,~put,~view,binding)),D.Read{},False{}}]} 35 def optional(~S:Data,~Store:Type,~R:Type,~E:Data,~Rest:Type,~P:Type,~V:Data,~Token:Data,~take:Store -> Rest & Col.Column,~put:Rest -> Col.Column -> Store,~view:P -> P & V,~binding:B.Binding) -> Selection,S,C.Access>: 36 Selection{Leaves.check_slot(~S,~Store,~R,~E,~Rest,~P,~V,~Token,~take,~put,~view,~binding,~Families.Optional{}),[D.Use{D.Component{D.Optional{}},Identity.key(~S,~P,B.identity(~S,~Store,~Rest,~P,~V,~Token,~take,~put,~view,binding)),D.Read{},False{}}]} 37 def with_component(~S:Data,~Store:Type,~R:Type,~E:Data,~Rest:Type,~P:Type,~V:Data,~Token:Data,~take:Store -> Rest & Col.Column,~put:Rest -> Col.Column -> Store,~view:P -> P & V,~binding:B.Binding) -> Predicate,S>: 38 Predicate{Leaves.check_with(~S,~Store,~R,~E,~Rest,~P,~V,~Token,~take,~put,~view,~binding),[D.Use{D.Component{D.With{}},Identity.key(~S,~P,B.identity(~S,~Store,~Rest,~P,~V,~Token,~take,~put,~view,binding)),D.Read{},False{}}]} 39 def without_component(~S:Data,~Store:Type,~R:Type,~E:Data,~Rest:Type,~P:Type,~V:Data,~Token:Data,~take:Store -> Rest & Col.Column,~put:Rest -> Col.Column -> Store,~view:P -> P & V,~binding:B.Binding) -> Predicate,S>: 40 Predicate{Leaves.check_without(~S,~Store,~R,~E,~Rest,~P,~V,~Token,~take,~put,~view,~binding),[D.Use{D.Component{D.Without{}},Identity.key(~S,~P,B.identity(~S,~Store,~Rest,~P,~V,~Token,~take,~put,~view,binding)),D.Read{},False{}}]} 41 def empty(~H:Type,~S:Data) -> Selection:Selection{Q.empty(~H,~S),[]} 42 def pair(~H:Type,~S:Data,~A:Data,~B:Data,~left:Selection,~right:Selection) -> Selection>: 43 Selection{Q.pair(~H,~S,~A,~B,~selected(~H,~S,~A,left),~selected(~H,~S,~B,right)),List.append(&2,D.Use,uses(~H,~S,~A,left),uses(~H,~S,~B,right))} 44 def both(~H:Type,~S:Data,~left:Predicate,~right:Predicate) -> Predicate: 45 Predicate{Q.both(~H,~S,~predicate(~H,~S,left),~predicate(~H,~S,right)),List.append(&2,D.Use,predicate_uses(~H,~S,left),predicate_uses(~H,~S,right))} 46 def constrain(~H:Type,~S:Data,~V:Data,~source:Selection,~filter:Predicate) -> Selection: 47 Selection{Q.constrain(~H,~S,~V,~selected(~H,~S,~V,source),~predicate(~H,~S,filter)),List.append(&2,D.Use,uses(~H,~S,~V,source),predicate_uses(~H,~S,filter))} 48 def map(~H:Type,~S:Data,~A:Data,~B:Data,~source:Selection,~view:A -> B) -> Selection: 49 Selection{Q.map(~H,~S,~A,~B,~selected(~H,~S,~A,source),~view),uses(~H,~S,~A,source)} 50 # The only gameplay-facing operation is the existing confined readonly query. 51 type Read<-S:Data,-V:Data,-H:Type> is Type: 52 Read{query:Query.ComposedReadQuery} 53 def Ops(~S:Data,~V:Data,H:Type) -> Type:Read 54 def query(~S:Data,~V:Data,~H:Type,value:Read) -> Query.ComposedReadQuery: 55 match value: 56 case Read{query}:query 57 def each(~S:Data,~V:Data,~H:Type,~caps:Read,owner:H) -> H & List<&2,Query.ProjectedRow>: 58 Query.each_composed(~H,~S,~V,~query(~S,~V,~H,caps),owner) 59 def declaration(~S:Data,~Store:Type,~R:Type,~E:Data,~V:Data,~source:Selection,S,V>) -> D.Declaration: 60 D.Declaration{K.Plan{D.provided(~S,~Store,~R,~E),Read{Query.grant_composed(~K.Frame,~S,~V,~selected(~K.Frame,~S,~V,source),~Traverse.check_world(~S,~Store,~R,~E))}},uses(~K.Frame,~S,~V,source)}