ordinary_check_query.bend

bendvy-ecs-core@0.1.0.1 · 60 lines · 0 definitions

1import Base
2import bendvy-ecs-core@0.1.0.1/ordinary_check_declaration.bend as D
3import bendvy-ecs-core@0.1.0.1/ordinary_component_binding.bend as B
4import bendvy-ecs-core@0.1.0.1/ordinary_declaration.bend as Identity
5import bendvy-ecs-core@0.1.0.1/ordinary_query_selections.bend as Leaves
6import bendvy-ecs-core@0.1.0.1/inspector_query_families.bend as Families
7import bendvy-ecs-core@0.1.0.1/inspector_query_projection.bend as Q
8import bendvy-ecs-core@0.1.0.1/inspector_query.bend as Query
9import bendvy-ecs-core@0.1.0.1/inspector_query_world.bend as Traverse
10import bendvy-ecs-core@0.1.0.1/check.bend as K
11import bendvy-ecs-core@0.1.0.1/column.bend as Col
12import bendvy-ecs-core@0.1.0.1/component.bend as C
13import bendvy-ecs-core@0.1.0.1/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.
17type Selection<-H:Type,-S:Data,-V:Data> is Type:
18  Selection{selection:Q.DeclaredSelection<H,S,V>,uses:List<&2,D.Use>}
19type Predicate<-H:Type,-S:Data> is Type:
20  Predicate{predicate:Q.Predicate<H,S>,uses:List<&2,D.Use>}
21def selected(~H:Type,~S:Data,~V:Data,value:Selection<H,S,V>) -> Q.DeclaredSelection<H,S,V>:
22  match value:
23    case Selection{selection,_}:selection
24def uses(~H:Type,~S:Data,~V:Data,value:Selection<H,S,V>) -> List<&2,D.Use>:
25  match value:
26    case Selection{_,uses}:uses
27def predicate(~H:Type,~S:Data,value:Predicate<H,S>) -> Q.Predicate<H,S>:
28  match value:
29    case Predicate{predicate,_}:predicate
30def predicate_uses(~H:Type,~S:Data,value:Predicate<H,S>) -> List<&2,D.Use>:
31  match value:
32    case Predicate{_,uses}:uses
33def read(~S:Data,~Store:Type,~R:Type,~E:Data,~Rest:Type,~P:Type,~V:Data,~Token:Data,~take:Store -> Rest & Col.Column<S,P>,~put:Rest -> Col.Column<S,P> -> Store,~view:P -> P & V,~binding:B.Binding<S,Store,Rest,P,V,Token,take,put,view>) -> Selection<K.Frame<S,Store,R,E>,S,C.Access<V>>:
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{}}]}
35def optional(~S:Data,~Store:Type,~R:Type,~E:Data,~Rest:Type,~P:Type,~V:Data,~Token:Data,~take:Store -> Rest & Col.Column<S,P>,~put:Rest -> Col.Column<S,P> -> Store,~view:P -> P & V,~binding:B.Binding<S,Store,Rest,P,V,Token,take,put,view>) -> Selection<K.Frame<S,Store,R,E>,S,C.Access<V>>:
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{}}]}
37def with_component(~S:Data,~Store:Type,~R:Type,~E:Data,~Rest:Type,~P:Type,~V:Data,~Token:Data,~take:Store -> Rest & Col.Column<S,P>,~put:Rest -> Col.Column<S,P> -> Store,~view:P -> P & V,~binding:B.Binding<S,Store,Rest,P,V,Token,take,put,view>) -> Predicate<K.Frame<S,Store,R,E>,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{}}]}
39def without_component(~S:Data,~Store:Type,~R:Type,~E:Data,~Rest:Type,~P:Type,~V:Data,~Token:Data,~take:Store -> Rest & Col.Column<S,P>,~put:Rest -> Col.Column<S,P> -> Store,~view:P -> P & V,~binding:B.Binding<S,Store,Rest,P,V,Token,take,put,view>) -> Predicate<K.Frame<S,Store,R,E>,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{}}]}
41def empty(~H:Type,~S:Data) -> Selection<H,S,Unit>:Selection{Q.empty(~H,~S),[]}
42def pair(~H:Type,~S:Data,~A:Data,~B:Data,~left:Selection<H,S,A>,~right:Selection<H,S,B>) -> Selection<H,S,Q.Product<A,B>>:
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))}
44def both(~H:Type,~S:Data,~left:Predicate<H,S>,~right:Predicate<H,S>) -> Predicate<H,S>:
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))}
46def constrain(~H:Type,~S:Data,~V:Data,~source:Selection<H,S,V>,~filter:Predicate<H,S>) -> Selection<H,S,V>:
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))}
48def map(~H:Type,~S:Data,~A:Data,~B:Data,~source:Selection<H,S,A>,~view:A -> B) -> Selection<H,S,B>:
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.
51type Read<-S:Data,-V:Data,-H:Type> is Type:
52  Read{query:Query.ComposedReadQuery<H,S,V>}
53def Ops(~S:Data,~V:Data,H:Type) -> Type:Read<S,V,H>
54def query(~S:Data,~V:Data,~H:Type,value:Read<S,V,H>) -> Query.ComposedReadQuery<H,S,V>:
55  match value:
56    case Read{query}:query
57def each(~S:Data,~V:Data,~H:Type,~caps:Read<S,V,H>,owner:H) -> H & List<&2,Query.ProjectedRow<S,V>>:
58  Query.each_composed(~H,~S,~V,~query(~S,~V,~H,caps),owner)
59def declaration(~S:Data,~Store:Type,~R:Type,~E:Data,~V:Data,~source:Selection<K.Frame<S,Store,R,E>,S,V>) -> D.Declaration<S,Store,R,E,Ops(~S,~V)>:
60  D.Declaration{K.Plan{D.provided(~S,~Store,~R,~E),Read{Query.grant_composed(~K.Frame<S,Store,R,E>,~S,~V,~selected(~K.Frame<S,Store,R,E>,~S,~V,source),~Traverse.check_world(~S,~Store,~R,~E))}},uses(~K.Frame<S,Store,R,E>,~S,~V,source)}