1 import Base 2 import ./world.bend as W 3 import ./check.bend as K 4 import ./capabilities.bend as Cap 5 import ./ordinary_schema.bend as Schema 6 import ./ordinary_optional_resource.bend as O 7 import ./optional_resource_binding.bend as B 8 import ./owner_product.bend as Product 9 10 # Metadata belongs to the same operational read; no caller-authored access list. 11 type ComponentSelection is Data: 12 Required{} 13 Optional{} 14 With{} 15 Without{} 16 type RelationKind is Data: 17 Ordinary{} 18 Hierarchy{} 19 type RelationDirection is Data: 20 Outgoing{} 21 Incoming{} 22 type RelationSelection is Data: 23 RelationRequired{} 24 RelationOptional{} 25 RelationPresent{} 26 RelationAbsent{} 27 type RelationIdentity is Data: 28 RelationIdentity{id:U32,name:String,inverseName:String,kind:RelationKind} 29 type Category is Data: 30 Resource{} 31 Component{selection:ComponentSelection} 32 Machine{} 33 Relation{identity:RelationIdentity,direction:RelationDirection,selection:RelationSelection,cellKey:Maybe<&2,String>} 34 type Mode is Data:Read{} 35 type Use is Data:Use{category:Category,key:String,mode:Mode,required:Bool} 36 type Declaration<-S:Data,-C:Type,-R:Type,-E:Data,-Ops:Type -> Type> is Type: 37 Declaration{plan:K.Plan,uses:List<&2,Use>} 38 type ResourceRead<-S:Data,-P:Type,-identity:Schema.Resource,-H:Type,-V:Data> is Type: 39 ResourceRead{read:Cap.ValueRead>} 40 def Ops(~S:Data,~P:Type,~identity:Schema.Resource,~V:Data,H:Type) -> Type:ResourceRead 41 def read_field(~S:Data,~P:Type,~identity:Schema.Resource,~H:Type,~V:Data,value:ResourceRead) -> H -> H & Maybe<&2,V>: 42 match value: 43 case ResourceRead{read}:Cap.value_read_field(~H,~Maybe<&2,V>,read) 44 def read(~S:Data,~P:Type,~identity:Schema.Resource,~H:Type,~V:Data,~value:ResourceRead,owner:H) -> H & Maybe<&2,V>: 45 read_field(~S,~P,~identity,~H,~V,value)(owner) 46 def provided(~S:Data,~C:Type,~R:Type,~E:Data,world:W.World) -> W.World & List<&2,String>:(world,[]) 47 def optional_resource(~S:Data,~C:Type,~R:Type,~E:Data,~P:Type,~Rest:Type,~V:Data,~identity:Schema.Resource,~lens:Product.Lens,Rest>,~binding:B.Binding,~view:P -> P & V) -> Declaration: 48 Declaration{K.Plan{provided(~S,~C,~R,~E),ResourceRead{O.condition(~S,~C,~R,~E,~P,~Rest,~V,~identity,~lens,~view,~O.Declaration{})}},[Use{Resource{},Schema.resource_key(~S,~P,identity),Read{},False{}}]} 49 def required_resource(~S:Data,~C:Type,~R:Type,~E:Data,~P:Type,~Rest:Type,~V:Data,~identity:Schema.Resource,~lens:Product.Lens,Rest>,~binding:B.Binding,~view:P -> P & V) -> Declaration: 50 Declaration{K.Plan{O.required(~S,~C,~R,~E,~P,~Rest,~V,~identity,~lens,~view,~O.Declaration{}),ResourceRead{O.condition(~S,~C,~R,~E,~P,~Rest,~V,~identity,~lens,~view,~O.Declaration{})}},[Use{Resource{},Schema.resource_key(~S,~P,identity),Read{},True{}}]} 51 def plan(~S:Data,~C:Type,~R:Type,~E:Data,~Ops:Type -> Type,value:Declaration) -> K.Plan: 52 match value: 53 case Declaration{plan,_}:plan 54 def uses(~S:Data,~C:Type,~R:Type,~E:Data,~Ops:Type -> Type,value:Declaration) -> List<&2,Use>: 55 match value: 56 case Declaration{_,uses}:uses 57 58 # A single reached predicate may request several declared reads. Validation 59 # threads the original World in authored order and retains each returned name. 60 def PairOps(~L:Type -> Type,~R:Type -> Type,H:Type) -> Type:Cap.Bundle 61 def required_join(~S:Data,~C:Type,~R:Type,~E:Data,before:List<&2,String>,observed:W.World & List<&2,String>) -> W.World & List<&2,String>: 62 match observed: 63 case (world,after):(world,List.append(&2,String,before,after)) 64 def required_right(~S:Data,~C:Type,~R:Type,~E:Data,~right:W.World -> W.World & List<&2,String>,observed:W.World & List<&2,String>) -> W.World & List<&2,String>: 65 match observed: 66 case (world,before):required_join(~S,~C,~R,~E,before,right(world)) 67 def required_pair(~S:Data,~C:Type,~R:Type,~E:Data,~left:W.World -> W.World & List<&2,String>,~right:W.World -> W.World & List<&2,String>,world:W.World) -> W.World & List<&2,String>:required_right(~S,~C,~R,~E,~right,left(world)) 68 def both(~S:Data,~C:Type,~R:Type,~E:Data,~LOps:Type -> Type,~ROps:Type -> Type,~left:Declaration,~right:Declaration) -> Declaration: 69 Declaration{K.Plan{required_pair(~S,~C,~R,~E,~K.required_field(~S,~C,~R,~E,~LOps,plan(~S,~C,~R,~E,~LOps,left)),~K.required_field(~S,~C,~R,~E,~ROps,plan(~S,~C,~R,~E,~ROps,right))),Cap.Bundle{K.caps_field(~S,~C,~R,~E,~LOps,plan(~S,~C,~R,~E,~LOps,left)),K.caps_field(~S,~C,~R,~E,~ROps,plan(~S,~C,~R,~E,~ROps,right))}},List.append(&2,Use,uses(~S,~C,~R,~E,~LOps,left),uses(~S,~C,~R,~E,~ROps,right))}