ordinary_schema_provision.bend

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

1import Base
2import entity_key.bend as Key
3import bendvy-ecs-core@0.1.0.0/persistence_declaration.bend as Persist
4import bendvy-ecs-core@0.1.0.0/decode_data.bend as D
5import bendvy-ecs-core@0.1.0.0/world.bend as W
6import bendvy-ecs-core@0.1.0.0/column.bend as Col
7import bendvy-ecs-core@0.1.0.0/ordinary_schema.bend as Schema
8import bendvy-ecs-core@0.1.0.0/ordinary_declaration.bend as Identity
9import bendvy-ecs-core@0.1.0.0/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.
15type Provision<-S:Data,-C:Type,-R:Type,-empty:Unit -> C,-count:C -> List<&2,W.Handle<S>> -> C & List<&2,Maybe<&2,U32>>> is Data:
16  Provision{schema:Schema.Schema<S,C,R>}
17def counted(~S:Data,~P:Type,total:U32,result:Col.Column<S,P> & Bool,ih:Col.Column<S,P> -> U32 -> Col.Column<S,P> & U32) -> Col.Column<S,P> & U32:
18  match result:
19    case (column,True{}):ih(column,(total + 1 : U32))
20    case (column,False{}):ih(column,total)
21def column_count(~S:Data,~P:Type,handles:List<&2,W.Handle<S>>,column:Col.Column<S,P>,total:U32) -> Col.Column<S,P> & 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))
25def component_counted(~S:Data,~P:Type,result:Col.Column<S,P> & U32) -> Col.Column<S,P> & List<&2,Maybe<&2,U32>>:
26  match result:
27    case (column,count):(column,[Some{count}])
28def component_count(~S:Data,~P:Type,column:Col.Column<S,P>,handles:List<&2,W.Handle<S>>) -> Col.Column<S,P> & List<&2,Maybe<&2,U32>>:
29  component_counted(~S,~P,column_count(~S,~P,handles,column,0))
30def component_empty(~S:Data,~P:Type,unit:Unit) -> Col.Column<S,P>:Col.empty(~S,~P)
31def resource_count(~S:Data,value:Unit,handles:List<&2,W.Handle<S>>) -> Unit & List<&2,Maybe<&2,U32>>:(value,[None{}])
32def 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.
36def component(~S:Data,~P:Type,declaration:Identity.Declaration<S,P>) -> Provision<S,Col.Column<S,P>,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.
40def resource(~S:Data,~P:Type,declaration:Schema.Resource<S,P>) -> Provision<S,Unit,P,resource_empty,resource_count(~S)>:
41  Provision{Schema.resource_schema(~S,~P,declaration)}
42def product_counted(~L:Type,~R:Type,left:L,before:List<&2,Maybe<&2,U32>>,right:R & List<&2,Maybe<&2,U32>>) -> Product.Owner<L,R> & List<&2,Maybe<&2,U32>>:
43  match right:
44    case (right,after):(Product.Owner{left,right},List.append(&2,Maybe<&2,U32>,before,after))
45def product_left(~S:Data,~L:Type,~R:Type,~rightCount:R -> List<&2,W.Handle<S>> -> R & List<&2,Maybe<&2,U32>>,right:R,handles:List<&2,W.Handle<S>>,left:L & List<&2,Maybe<&2,U32>>) -> Product.Owner<L,R> & List<&2,Maybe<&2,U32>>:
46  match left:
47    case (left,before):product_counted(~L,~R,left,before,rightCount(right,handles))
48def product_count(~S:Data,~L:Type,~R:Type,~leftCount:L -> List<&2,W.Handle<S>> -> L & List<&2,Maybe<&2,U32>>,~rightCount:R -> List<&2,W.Handle<S>> -> R & List<&2,Maybe<&2,U32>>,store:Product.Owner<L,R>,handles:List<&2,W.Handle<S>>) -> Product.Owner<L,R> & 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))
53def product_empty(~L:Type,~R:Type,~leftEmpty:Unit -> L,~rightEmpty:Unit -> R,unit:Unit) -> Product.Owner<L,R>:
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.
58def product(~S:Data,~LC:Type,~LR:Type,~RC:Type,~RR:Type,~leftEmpty:Unit -> LC,~leftCount:LC -> List<&2,W.Handle<S>> -> LC & List<&2,Maybe<&2,U32>>,~rightEmpty:Unit -> RC,~rightCount:RC -> List<&2,W.Handle<S>> -> RC & List<&2,Maybe<&2,U32>>,left:Provision<S,LC,LR,leftEmpty,leftCount>,right:Provision<S,RC,RR,rightEmpty,rightCount>) -> Provision<S,Product.Owner<LC,RC>,Product.Owner<LR,RR>,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.
65def create(~S:Data,~C:Type,~R:Type,~E:Data,~empty:Unit -> C,~count:C -> List<&2,W.Handle<S>> -> C & List<&2,Maybe<&2,U32>>,provision:Provision<S,C,R,empty,count>,factory:W.Factory,resource:R) -> Provision<S,C,R,empty,count> & W.Creation<S,C,R,E>:
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.
71def component_plain(~S:Data,~P:Type,~identity:Identity.Declaration<S,P>,extension:Persist.Plain<S,P,identity>) -> Provision<S,Col.Column<S,P>,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.
76def component_transient(~S:Data,~P:Type,~identity:Identity.Declaration<S,P>,extension:Persist.Transient<S,P,identity>) -> Provision<S,Col.Column<S,P>,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.
81def component_constructed(~S:Data,~P:Type,~identity:Identity.Declaration<S,P>,~project:P -> P & D.Raw,extension:Persist.Constructed<S,P,identity,project>) -> Provision<S,Col.Column<S,P>,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.
86def resource_plain(~S:Data,~P:Type,~identity:Identity.Declaration<S,P>,extension:Persist.Plain<S,P,identity>) -> Provision<S,Unit,P,resource_empty,resource_count(~S)>: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.
91def resource_transient(~S:Data,~P:Type,~identity:Identity.Declaration<S,P>,extension:Persist.Transient<S,P,identity>) -> Provision<S,Unit,P,resource_empty,resource_count(~S)>: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.
96def resource_constructed(~S:Data,~P:Type,~identity:Identity.Declaration<S,P>,~project:P -> P & D.Raw,extension:Persist.Constructed<S,P,identity,project>) -> Provision<S,Unit,P,resource_empty,resource_count(~S)>:Provision{Schema.resource_constructed(~S,~P,~identity,~project,extension)}