1 import Base 2 import ./execution_composer_layout.bend as Layout 3 import ./ordinary_declaration.bend as C 4 import ./persistence_declaration.bend as Decl 5 import ./schema_fragments.bend as Fragment 6 import ./decode_data.bend as D 7 import ./owner_product.bend as Product 8 import ./execution_resource_policy.bend as Policy 9 10 # An ordinary persistence extension determines its canonical storage layout and 11 # retained declarations together. A separate route/key catalog is not accepted. 12 type Plan is Type: 13 Empty{} 14 Plain{P:Type,V:Data,refresh:P -> P & V,key:String,access:Policy.Policy} 15 Transient{P:Type,V:Data,refresh:P -> P & V,key:String,access:Policy.Policy} 16 Constructed{P:Type,V:Data,refresh:P -> P & V,key:String,project:P -> P & D.Raw,access:Policy.Policy} 17 Pair{left:Plan,right:Plan} 18 def layout(plan:Plan) -> Layout.Layout: 19 match plan: 20 case Empty{}:Layout.EmptyLayout{} 21 case Plain{P,V,refresh,key,access}:Layout.ClassifiedLayoutLeaf{P,V,refresh,key,Fragment.Plain{},access} 22 case Transient{P,V,refresh,key,access}:Layout.ClassifiedLayoutLeaf{P,V,refresh,key,Fragment.Transient{},access} 23 case Constructed{P,V,refresh,key,_,access}:Layout.ClassifiedLayoutLeaf{P,V,refresh,key,Fragment.Constructed{},access} 24 case Pair{left,right}:Layout.LayoutPair{layout(left),layout(right)} 25 def identity(~S:Data,~P:Type,key:String) -> C.Declaration:C.Declaration{key} 26 def unused(~P:Type,owner:P) -> P & D.Raw:(owner,D.Missing{}) 27 def Recipes(~S:Data,plan:Plan) -> Type: 28 match plan: 29 case Empty{}:Unit 30 case Plain{P,_,_,key,_}:Decl.Plain 31 case Transient{P,_,_,key,_}:Decl.Transient 32 case Constructed{P,_,_,key,project,_}:Decl.Constructed 33 case Pair{left,right}:Product.Owner 34 def first(left:Maybe<&2,String>,right:Maybe<&2,String>) -> Maybe<&2,String>: 35 match left: 36 case Some{key}:Some{key} 37 case None{}:right 38 def ineligible(plan:Plan) -> Maybe<&2,String>: 39 match plan: 40 case Empty{}:None{} 41 case Plain{_,_,_,key,_}:Some{key} 42 case Transient{_,_,_,_,_}:None{} 43 case Constructed{_,_,_,_,_,_}:None{} 44 case Pair{left,right}:first(ineligible(left),ineligible(right)) 45 type Schema<-S:Data,-components:Plan,-resources:Plan> is Type: 46 Schema{components:Recipes(~S,components),resources:Recipes(~S,resources)}