1 import Base 2 import entity_key.bend as Key 3 import ./persistence_declaration.bend as Persist 4 import ./decode_data.bend as D 5 import ./world.bend as W 6 import ./column.bend as Col 7 import ./ordinary_schema.bend as Schema 8 import ./ordinary_declaration.bend as Identity 9 import ./owner_product.bend as Product 10 # The single ordinary Schema owns all keys. The erased traversal holds no keys, 11 # presenters or payloads. Ordinary builders generate matching leaf slots/order. 12 # Trusted ordinary schema setup indexed by matching storage construction 13 # and population counting. Contains one schema, not live World/resource owners. 14 # Raw construction must preserve entry/slot order; no lens laws are checked. 15 type Provision<-S:Data,-C:Type,-R:Type,-empty:Unit -> C,-count:C -> List<&2,W.Handle> -> C & List<&2,Maybe<&2,U32>>> is Data: 16 Provision{schema:Schema.Schema} 17 def counted(~S:Data,~P:Type,total:U32,result:Col.Column & Bool,ih:Col.Column -> U32 -> Col.Column & U32) -> Col.Column & U32: 18 match result: 19 case (column,True{}):ih(column,(total + 1 : U32)) 20 case (column,False{}):ih(column,total) 21 def column_count(~S:Data,~P:Type,handles:List<&2,W.Handle>,column:Col.Column,total:U32) -> Col.Column & U32: 22 match handles: 23 case []:(column,total) 24 case W.Handle{_,Key.EntityKey{id,_}} <> rest:counted(~S,~P,total,Col.has(~S,~P,column,id),column => total => column_count(~S,~P,rest,column,total)) 25 def component_counted(~S:Data,~P:Type,result:Col.Column & U32) -> Col.Column & List<&2,Maybe<&2,U32>>: 26 match result: 27 case (column,count):(column,[Some{count}]) 28 def component_count(~S:Data,~P:Type,column:Col.Column,handles:List<&2,W.Handle>) -> Col.Column & List<&2,Maybe<&2,U32>>: 29 component_counted(~S,~P,column_count(~S,~P,handles,column,0)) 30 def component_empty(~S:Data,~P:Type,unit:Unit) -> Col.Column:Col.empty(~S,~P) 31 def resource_count(~S:Data,value:Unit,handles:List<&2,W.Handle>) -> Unit & List<&2,Maybe<&2,U32>>:(value,[None{}]) 32 def resource_empty(unit:Unit) -> Unit:unit 33 # Declare a component with matching empty-column/counting operations. 34 # Does not allocate a World or consume a component payload; combines with 35 # product for heterogeneous affine schema storage. 36 def component(~S:Data,~P:Type,declaration:Identity.Declaration) -> Provision,Unit,component_empty(~S,~P),component_count(~S,~P)>: 37 Provision{Schema.component(~S,~P,declaration)} 38 # Declare a resource schema leaf. Its component-storage contribution is 39 # Unit and population slot is None; the caller supplies actual R on creation. 40 def resource(~S:Data,~P:Type,declaration:Schema.Resource) -> Provision: 41 Provision{Schema.resource_schema(~S,~P,declaration)} 42 def product_counted(~L:Type,~R:Type,left:L,before:List<&2,Maybe<&2,U32>>,right:R & List<&2,Maybe<&2,U32>>) -> Product.Owner & List<&2,Maybe<&2,U32>>: 43 match right: 44 case (right,after):(Product.Owner{left,right},List.append(&2,Maybe<&2,U32>,before,after)) 45 def product_left(~S:Data,~L:Type,~R:Type,~rightCount:R -> List<&2,W.Handle> -> R & List<&2,Maybe<&2,U32>>,right:R,handles:List<&2,W.Handle>,left:L & List<&2,Maybe<&2,U32>>) -> Product.Owner & List<&2,Maybe<&2,U32>>: 46 match left: 47 case (left,before):product_counted(~L,~R,left,before,rightCount(right,handles)) 48 def product_count(~S:Data,~L:Type,~R:Type,~leftCount:L -> List<&2,W.Handle> -> L & List<&2,Maybe<&2,U32>>,~rightCount:R -> List<&2,W.Handle> -> R & List<&2,Maybe<&2,U32>>,store:Product.Owner,handles:List<&2,W.Handle>) -> Product.Owner & List<&2,Maybe<&2,U32>>: 49 match store: 50 case Product.Owner{left,right}: 51 +handles=handles 52 product_left(~S,~L,~R,~rightCount,right,handles,leftCount(left,handles)) 53 def product_empty(~L:Type,~R:Type,~leftEmpty:Unit -> L,~rightEmpty:Unit -> R,unit:Unit) -> Product.Owner: 54 Product.Owner{leftEmpty(Unit{}),rightEmpty(Unit{})} 55 # Compose trusted provisions in left/right schema/storage/count-slot order. 56 # Payload types may be affine; this setup value contains no live payloads. 57 # Does not validate duplicate keys or build a World. 58 def product(~S:Data,~LC:Type,~LR:Type,~RC:Type,~RR:Type,~leftEmpty:Unit -> LC,~leftCount:LC -> List<&2,W.Handle> -> LC & List<&2,Maybe<&2,U32>>,~rightEmpty:Unit -> RC,~rightCount:RC -> List<&2,W.Handle> -> RC & List<&2,Maybe<&2,U32>>,left:Provision,right:Provision) -> Provision,Product.Owner,product_empty(~LC,~RC,~leftEmpty,~rightEmpty),product_count(~S,~LC,~RC,~leftCount,~rightCount)>: 59 match left right: 60 case Provision{left} Provision{right}:Provision{Schema.product(~S,~LC,~LR,~RC,~RR,left,right)} 61 # Trusted factory-based World creation returning provision and Creation. 62 # Refusal preserves caller resources through the Creation result. This uses 63 # the supplied pure Factory and does not allocate a process-unique namespace; 64 # prefer checked IO creation for independently created ordinary Worlds. 65 def create(~S:Data,~C:Type,~R:Type,~E:Data,~empty:Unit -> C,~count:C -> List<&2,W.Handle> -> C & List<&2,Maybe<&2,U32>>,provision:Provision,factory:W.Factory,resource:R) -> Provision & W.Creation: 66 (provision,W.create(~S,~C,~R,~E,~empty,factory,resource)) 67 68 # Declare a component provision with plain persistence classification 69 # from its identity-bound extension. Derives matching empty/count operations; 70 # does not execute codecs, validate saved input or construct payload values. 71 def component_plain(~S:Data,~P:Type,~identity:Identity.Declaration,extension:Persist.Plain) -> Provision,Unit,component_empty(~S,~P),component_count(~S,~P)>:Provision{Schema.component_plain(~S,~P,~identity,extension)} 72 73 # Declare a component provision with transient persistence classification 74 # from its identity-bound extension. Derives matching empty/count operations; 75 # does not execute codecs, validate saved input or construct payload values. 76 def component_transient(~S:Data,~P:Type,~identity:Identity.Declaration,extension:Persist.Transient) -> Provision,Unit,component_empty(~S,~P),component_count(~S,~P)>:Provision{Schema.component_transient(~S,~P,~identity,extension)} 77 78 # Declare a component provision with constructed persistence classification 79 # from its identity-bound extension. Derives matching empty/count operations; 80 # does not execute codecs, validate saved input or construct payload values. 81 def component_constructed(~S:Data,~P:Type,~identity:Identity.Declaration,~project:P -> P & D.Raw,extension:Persist.Constructed) -> Provision,Unit,component_empty(~S,~P),component_count(~S,~P)>:Provision{Schema.component_constructed(~S,~P,~identity,~project,extension)} 82 83 # Declare a resource provision with plain persistence classification 84 # from its identity-bound extension. Derives matching empty/count operations; 85 # does not execute codecs, validate saved input or construct payload values. 86 def resource_plain(~S:Data,~P:Type,~identity:Identity.Declaration,extension:Persist.Plain) -> Provision:Provision{Schema.resource_plain(~S,~P,~identity,extension)} 87 88 # Declare a resource provision with transient persistence classification 89 # from its identity-bound extension. Derives matching empty/count operations; 90 # does not execute codecs, validate saved input or construct payload values. 91 def resource_transient(~S:Data,~P:Type,~identity:Identity.Declaration,extension:Persist.Transient) -> Provision:Provision{Schema.resource_transient(~S,~P,~identity,extension)} 92 93 # Declare a resource provision with constructed persistence classification 94 # from its identity-bound extension. Derives matching empty/count operations; 95 # does not execute codecs, validate saved input or construct payload values. 96 def resource_constructed(~S:Data,~P:Type,~identity:Identity.Declaration,~project:P -> P & D.Raw,extension:Persist.Constructed) -> Provision:Provision{Schema.resource_constructed(~S,~P,~identity,~project,extension)}