relation_query.bend

bendvy-ecs-core@0.1.0.0 · 121 lines · 0 definitions

1import Base
2import bendvy-ecs-core@0.1.0.0/deferred_command.bend as Deferred
3import bendvy-ecs-core@0.1.0.0/trace_facts.bend as TraceFacts
4import entity_key.bend as Key
5import relation_types.bend as G
6import relation_graph.bend as Graph
7import relation_commands.bend as A
8import world.bend as W
9import transaction.bend as X
10import query.bend as Q
11import component.bend as Cmp
12import capabilities.bend as Cap
13
14# Relation requirements have arbitrary declaration length. The application C
15# remains Type; only immutable relation handles/snapshots are Data.
16type End is Data:
17  Outgoing{}
18  Incoming{}
19type Requirement<S:Data> is Data:
20  Requirement{key:String,descriptor:G.Descriptor<S>,end:End,mode:Q.Selection,project:Bool}
21type Spec<S:Data> is Data:
22  Spec{requirements:List<&2,Requirement<S>>}
23type Value<S:Data> is Data:
24  Missing{}
25  Target{handle:W.Handle<S>}
26  Sources{handles:List<&2,W.Handle<S>>}
27type Cell<S:Data> is Data:
28  Cell{key:String,end:End,value:Value<S>}
29type Row<S:Data,V:Data> is Data:
30  Row{entity:W.Handle<S>,cells:List<&2,Cell<S>>,component:V}
31def read_relation(~S:Data,key:String,descriptor:G.Descriptor<S>) -> Requirement<S>:
32  Requirement{key,descriptor,Outgoing{},Q.Required{},True{}}
33def optional_relation(~S:Data,key:String,descriptor:G.Descriptor<S>) -> Requirement<S>:
34  Requirement{key,descriptor,Outgoing{},Q.Optional{},True{}}
35def read_related(~S:Data,key:String,descriptor:G.Descriptor<S>) -> Requirement<S>:
36  Requirement{key,descriptor,Incoming{},Q.Required{},True{}}
37def optional_related(~S:Data,key:String,descriptor:G.Descriptor<S>) -> Requirement<S>:
38  Requirement{key,descriptor,Incoming{},Q.Optional{},True{}}
39def with_relation(~S:Data,descriptor:G.Descriptor<S>) -> Requirement<S>:
40  Requirement{"",descriptor,Outgoing{},Q.Present{},False{}}
41def without_relation(~S:Data,descriptor:G.Descriptor<S>) -> Requirement<S>:
42  Requirement{"",descriptor,Outgoing{},Q.Absent{},False{}}
43def with_related(~S:Data,descriptor:G.Descriptor<S>) -> Requirement<S>:
44  Requirement{"",descriptor,Incoming{},Q.Present{},False{}}
45def without_related(~S:Data,descriptor:G.Descriptor<S>) -> Requirement<S>:
46  Requirement{"",descriptor,Incoming{},Q.Absent{},False{}}
47def handles_acc(~S:Data,ids:List<&2,Key.Key>,+namespace:U32,acc:List<&2,W.Handle<S>>) -> List<&2,W.Handle<S>>:
48  match ids:
49    case []: List.reverse(&2,W.Handle<S>,acc)
50    case id <> rest: handles_acc(~S,rest,namespace,W.Handle{namespace,id} <> acc)
51def outgoing_value(~S:Data,value:Maybe<&2,Key.Key>,namespace:U32) -> Value<S>:
52  match value:
53    case None{}: Missing{}
54    case Some{id}: Target{W.Handle{namespace,id}}
55def incoming_value(~S:Data,ids:List<&2,Key.Key>,namespace:U32) -> Value<S>:
56  match ids:
57    case []: Missing{}
58    case first <> rest: Sources{handles_acc(~S,first <> rest,namespace,[])}
59def value(~S:Data,graph:G.Graph<S>,descriptor:G.Descriptor<S>,end:End,+namespace:U32,id:Key.Key) -> Value<S>:
60  match end:
61    case Outgoing{}: outgoing_value(~S,Graph.target(~S,graph,descriptor,id),namespace)
62    case Incoming{}: incoming_value(~S,Graph.inverse(~S,graph,descriptor,id),namespace)
63def presence(~S:Data,value:Value<S>) -> Cmp.Access<Bool>:
64  match value:
65    case Missing{}: Cmp.ComponentAbsent{}
66    case _: Cmp.Found{True{}}
67def add_cell(~S:Data,project:Bool,key:String,end:End,value:Value<S>,cells:List<&2,Cell<S>>) -> List<&2,Cell<S>>:
68  match project:
69    case False{}: cells
70    case True{}: Cell{key,end,value} <> cells
71def requirements(~S:Data,remaining:List<&2,Requirement<S>>,+graph:G.Graph<S>,+namespace:U32,+id:Key.Key,selected:Bool,acc:List<&2,Cell<S>>) -> Bool & List<&2,Cell<S>>:
72  match remaining:
73    case []: (selected,List.reverse(&2,Cell<S>,acc))
74    case Requirement{key,descriptor,+end,mode,project} <> rest:
75      +observed = value(~S,graph,descriptor,end,namespace,id)
76      requirements(~S,rest,graph,namespace,id,selected && Q.selection_aux(~Bool,mode,presence(~S,observed)),add_cell(~S,project,key,end,observed,acc))
77def spec_rows_result(~S:Data,~V:Data,observed:Bool & List<&2,Cell<S>>,handle:W.Handle<S>,component:V) -> Bool & Row<S,V>:
78  (selected,cells) = observed
79  (selected,Row{handle,cells,component})
80def spec_rows(~S:Data,~V:Data,spec:Spec<S>,graph:G.Graph<S>,handle:W.Handle<S>,component:V) -> Bool & Row<S,V>:
81  match spec handle:
82    case Spec{items} W.Handle{+namespace,+id}: spec_rows_result(~S,~V,requirements(~S,items,graph,namespace,id,True{},[]),W.Handle{namespace,id},component)
83def graph_read(~S:Data,~C:Type,store:A.Store<S,C>) -> A.Store<S,C> & G.Graph<S>:
84  match store:
85    case A.Store{components,+graph}: (A.Store{components,graph},graph)
86def inspect_done(~S:Data,~V:Data,~C:Type,~R:Type,~E:Data,~spec:Spec<S>,observed:W.World<S,A.Store<S,C>,R,A.Notice<S,E>> & G.Graph<S>,handle:W.Handle<S>,component:V,undo:List<(W.World<S,A.Store<S,C>,R,A.Notice<S,E>> -> W.World<S,A.Store<S,C>,R,A.Notice<S,E>>)>,commands:List<Deferred.Command<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>>>,events:List<&2,A.Notice<S,E>>,trace:TraceFacts.State) -> X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> & (Bool & Row<S,V>):
87  (world,graph) = observed
88  (X.Tx{world,undo,commands,events,trace},spec_rows(~S,~V,spec,graph,handle,component))
89def inspect(~S:Data,~V:Data,~C:Type,~R:Type,~E:Data,~spec:Spec<S>,tx:X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>>,handle:W.Handle<S>,component:V) -> X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> & (Bool & Row<S,V>):
90  match tx:
91    case X.Tx{world,undo,commands,events,trace}: inspect_done(~S,~V,~C,~R,~E,~spec,W.with_store(~S,~A.Store<S,C>,~R,~A.Notice<S,E>,~G.Graph<S>,graph_read(~S,~C),world),handle,component,undo,commands,events,trace)
92def row_get(~S:Data,~V:Data,~H:Type,+row:Row<S,V>,owner:H) -> H & Row<S,V>:
93  (owner,row)
94def invoke(~S:Data,~V:Data,~C:Type,~R:Type,~E:Data,~Out:Data,~body:@-H:Type -> Cap.ValueRead<H,Row<S,V>> -> H -> H & Out,row:Row<S,V>,tx:X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>>) -> X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> & Out:
95  body(X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>>,Cap.ValueRead{row_get(~S,~V,~X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>>,row)},tx)
96def output_prepend(~S:Data,~C:Type,~R:Type,~E:Data,~Out:Data,value:Out,observed:X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> & List<&2,Out>) -> X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> & List<&2,Out>:
97  (tx,rest) = observed
98  (tx,value <> rest)
99def output_join(~S:Data,~V:Data,~C:Type,~R:Type,~E:Data,~Out:Data,observed:X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> & Out,next:X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> -> X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> & List<&2,Out>) -> X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> & List<&2,Out>:
100  (tx,value) = observed
101  output_prepend(~S,~C,~R,~E,~Out,value,next(tx))
102def selected_row(~S:Data,~V:Data,~C:Type,~R:Type,~E:Data,~Out:Data,~body:@-H:Type -> Cap.ValueRead<H,Row<S,V>> -> H -> H & Out,observed:X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> & (Bool & Row<S,V>),next:X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> -> X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> & List<&2,Out>) -> X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> & List<&2,Out>:
103  match observed:
104    case (tx,(False{},_)): next(tx)
105    case (tx,(True{},row)): output_join(~S,~V,~C,~R,~E,~Out,invoke(~S,~V,~C,~R,~E,~Out,~body,row,tx),next)
106def component_join(~S:Data,~V:Data,~C:Type,~R:Type,~E:Data,~Out:Data,~spec:Spec<S>,~body:@-H:Type -> Cap.ValueRead<H,Row<S,V>> -> H -> H & Out,handle:W.Handle<S>,observed:X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> & (Bool & V),next:X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> -> X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> & List<&2,Out>) -> X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> & List<&2,Out>:
107  match observed:
108    case (tx,(False{},_)): next(tx)
109    case (tx,(True{},component)): selected_row(~S,~V,~C,~R,~E,~Out,~body,inspect(~S,~V,~C,~R,~E,~spec,tx,handle,component),next)
110def scan(~S:Data,~V:Data,~C:Type,~R:Type,~E:Data,~Out:Data,~spec:Spec<S>,~component_selected:X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> -> W.Handle<S> -> X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> & (Bool & V),~body:@-H:Type -> Cap.ValueRead<H,Row<S,V>> -> H -> H & Out,handles:List<&2,W.Handle<S>>,tx:X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>>) -> X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> & List<&2,Out>:
111  match handles:
112    case []: (tx,[])
113    case +handle <> rest: component_join(~S,~V,~C,~R,~E,~Out,~spec,~body,handle,component_selected(tx,handle),tx => scan(~S,~V,~C,~R,~E,~Out,~spec,~component_selected,~body,rest,tx))
114def finish(~S:Data,~C:Type,~R:Type,~E:Data,~Out:Data,observed:X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> & List<&2,Out>) -> W.World<S,A.Store<S,C>,R,A.Notice<S,E>> & List<&2,Out>:
115  match observed:
116    case (X.Tx{world,_,_,_,_},values): (world,values)
117def reserved(~S:Data,~V:Data,~C:Type,~R:Type,~E:Data,~Out:Data,~spec:Spec<S>,~component_selected:X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> -> W.Handle<S> -> X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> & (Bool & V),~body:@-H:Type -> Cap.ValueRead<H,Row<S,V>> -> H -> H & Out,observed:W.World<S,A.Store<S,C>,R,A.Notice<S,E>> & List<&2,W.Handle<S>>) -> W.World<S,A.Store<S,C>,R,A.Notice<S,E>> & List<&2,Out>:
118  (world,handles) = observed
119  finish(~S,~C,~R,~E,~Out,scan(~S,~V,~C,~R,~E,~Out,~spec,~component_selected,~body,handles,X.begin(~W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,~A.Notice<S,E>,world)))
120def each(~S:Data,~V:Data,~C:Type,~R:Type,~E:Data,~Out:Data,~spec:Spec<S>,~component_selected:X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> -> W.Handle<S> -> X.Tx<W.World<S,A.Store<S,C>,R,A.Notice<S,E>>,A.Notice<S,E>> & (Bool & V),~body:@-H:Type -> Cap.ValueRead<H,Row<S,V>> -> H -> H & Out,world:W.World<S,A.Store<S,C>,R,A.Notice<S,E>>) -> W.World<S,A.Store<S,C>,R,A.Notice<S,E>> & List<&2,Out>:
121  reserved(~S,~V,~C,~R,~E,~Out,~spec,~component_selected,~body,W.handles(~S,~A.Store<S,C>,~R,~A.Notice<S,E>,world))