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