execution_save_layout_field.bend
bendvy-ecs-core@0.1.0.3 · 91 lines · 22 definitions
1import Base
2import bendvy-ecs-core@0.1.0.3/execution_save_data.bend as Saved
3import bendvy-ecs-core@0.1.0.3/execution_save_recipe.bend as Recipe
4import bendvy-ecs-core@0.1.0.3/execution_composer_layout.bend as Layout
5import bendvy-ecs-core@0.1.0.3/chunk_column.bend as Column
6import bendvy-ecs-core@0.1.0.3/chunk_shape.bend as Part
7import bendvy-ecs-core@0.1.0.3/execution_query_identity.bend as Index
8import bendvy-ecs-core@0.1.0.3/lifecycle.bend as Life
9import bendvy-ecs-core@0.1.0.3/decode_data.bend as D
10import bendvy-ecs-core@0.1.0.3/decode_size.bend as Size
11
12type Mode is Data:
13 Plain{}
14 Transient{}
15 Constructed{codec:D.Codec}
16def field(+key:String,stamp:Maybe<&2,Life.Stamp>,value:Maybe<&2,Recipe.Field>) -> Saved.Fields:
17 match value:
18 case None{}:Saved.Fields{[Saved.Field{key,False{},Saved.Absent{},stamp}],None{}}
19 case Some{Recipe.Omitted{}}:Saved.Fields{[Saved.Field{key,True{},Saved.Omitted{},stamp}],None{}}
20 case Some{Recipe.Saved{D.Field{_,raw}}}:Saved.Fields{[Saved.Field{key,True{},Saved.Persisted{raw},stamp}],None{}}
21 case Some{Recipe.Refused{reason}}:Saved.error(reason)
22def checked(-P:Type,owner:P,key:String,+codec:D.Codec,+fuel:Nat,checked:D.Checked) -> P & Recipe.Field:
23 match checked:
24 case D.Accepted{raw}:(owner,Recipe.Saved{D.Field{key,D.canonical(fuel,codec,raw)}})
25 case D.Rejected{error}:(owner,Recipe.Refused{Recipe.InvalidProjection{key,error}})
26def budgeted(-P:Type,owner:P,key:String,+codec:D.Codec,+raw:D.Raw,+fuel:Nat) -> P & Recipe.Field:
27 checked(P,owner,key,codec,fuel,D.validate(fuel,D.Continue{[D.Work{codec,raw,"$"}]},raw))
28def projected(-P:Type,key:String,+codec:D.Codec,result:P & D.Raw) -> P & Recipe.Field:
29 match result:
30 case (owner,+raw):budgeted(P,owner,key,codec,raw,Size.budget(codec,raw))
31def describe(-P:Type,mode:Mode,key:String,project:P -> P & D.Raw,owner:P) -> P & Recipe.Field:
32 match mode:
33 case Plain{}:(owner,Recipe.Refused{Recipe.PlainUnserializable{key}})
34 case Transient{}:(owner,Recipe.Omitted{})
35 case Constructed{codec}:projected(P,key,codec,project(owner))
36def viewed_returned(-P:Type,-V:Data,view:V,result:P & Recipe.Field) -> Layout.Viewed<P,V> & Recipe.Field:
37 match result:
38 case (owner,field):(Layout.Viewed{owner,view},field)
39def viewed(-P:Type,-V:Data,mode:Mode,key:String,project:P -> P & D.Raw,stored:Layout.Viewed<P,V>) -> Layout.Viewed<P,V> & Recipe.Field:
40 match stored:
41 case Layout.Viewed{owner,view}:viewed_returned(P,V,view,describe(P,mode,key,project,owner))
42def restored_value(-S:Data,-P:Type,values:Array<Maybe<&1,P>>,stamps:Array<Life.Stamp>,index:U32,stamp:Life.Stamp,result:P & Recipe.Field) -> Column.Column<S,P> & (Maybe<&2,Recipe.Field> & Maybe<&2,Life.Stamp>):
43 match result:
44 case (owner,field):(Column.Leaf{Array.set(Maybe<&1,P>,values,index,Some{owner}),stamps},(Some{field},Some{stamp}))
45def taken(-S:Data,-P:Type,project:P -> P & Recipe.Field,stamps:Array<Life.Stamp>,index:U32,stamp:Life.Stamp,result:Array<Maybe<&1,P>> & Maybe<&1,P>) -> Column.Column<S,P> & (Maybe<&2,Recipe.Field> & Maybe<&2,Life.Stamp>):
46 match result:
47 case (values,None{}):(Column.Leaf{values,stamps},(None{},Some{stamp}))
48 case (values,Some{owner}):restored_value(S,P,values,stamps,index,stamp,project(owner))
49def stamp_read(-S:Data,-P:Type,project:P -> P & Recipe.Field,values:Array<Maybe<&1,P>>,+index:U32,result:Array<Life.Stamp> & Life.Stamp) -> Column.Column<S,P> & (Maybe<&2,Recipe.Field> & Maybe<&2,Life.Stamp>):
50 match result:
51 case (stamps,stamp):taken(S,P,project,stamps,index,stamp,Array.swap(Maybe<&1,P>,values,index,None{}))
52def leaf(-S:Data,-P:Type,project:P -> P & Recipe.Field,values:Array<Maybe<&1,P>>,stamps:Array<Life.Stamp>,+index:U32,allowed:Bool) -> Column.Column<S,P> & (Maybe<&2,Recipe.Field> & Maybe<&2,Life.Stamp>):
53 match allowed:
54 case False{}:(Column.Leaf{values,stamps},(None{},None{}))
55 case True{}:stamp_read(S,P,project,values,index,Array.get(Life.Stamp,stamps,index))
56def branches(-S:Data,-P:Type,half:U32,leftResult:Column.Column<S,P> & (Maybe<&2,Recipe.Field> & Maybe<&2,Life.Stamp>),rightResult:Column.Column<S,P> & (Maybe<&2,Recipe.Field> & Maybe<&2,Life.Stamp>),first:Bool) -> Column.Column<S,P> & (Maybe<&2,Recipe.Field> & Maybe<&2,Life.Stamp>):
57 match leftResult rightResult first:
58 case (left,value), (right,_), True{}:(Column.Branch{half,left,right},value)
59 case (left,_), (right,value), False{}:(Column.Branch{half,left,right},value)
60def branch(-S:Data,-P:Type,left:Maybe<&1,P -> P & Recipe.Field> -> Column.Column<S,P> & (Maybe<&2,Recipe.Field> & Maybe<&2,Life.Stamp>),right:Maybe<&1,P -> P & Recipe.Field> -> Column.Column<S,P> & (Maybe<&2,Recipe.Field> & Maybe<&2,Life.Stamp>),half:U32,project:P -> P & Recipe.Field,first:Bool) -> Column.Column<S,P> & (Maybe<&2,Recipe.Field> & Maybe<&2,Life.Stamp>):
61 match first:
62 case True{}:branches(S,P,half,left(Some{project}),right(None{}),True{})
63 case False{}:branches(S,P,half,left(None{}),right(Some{project}),False{})
64def project_column(-S:Data,-P:Type,column:Column.Column<S,P>,+index:U32,project:Maybe<&1,P -> P & Recipe.Field>) -> Column.Column<S,P> & (Maybe<&2,Recipe.Field> & Maybe<&2,Life.Stamp>):
65 match column project:
66 case column None{}:(column,(None{},None{}))
67 case Column.Leaf{values,stamps} Some{project}:leaf(S,P,project,values,stamps,index,U32.is_lt(index,8))
68 case Column.Branch{+half,left,right} Some{project}:branch(S,P,project_column(S,P,left,index),project_column(S,P,right,U32.sub(index,half)),half,project,U32.is_lt(index,half))
69def component_returned(-S:Data,-P:Type,-V:Data,+key:String,-origin:Layout.Layout,result:Column.Column<S,Layout.Viewed<P,V>> & (Maybe<&2,Recipe.Field> & Maybe<&2,Life.Stamp>)) -> Layout.ColumnSlot<S,Layout.Viewed<P,V>,key,origin> & Saved.Fields:
70 match result:
71 case (column,(value,stamp)):(Layout.ColumnSlot{column},field(key,stamp,value))
72def component_offset(-S:Data,-P:Type,-V:Data,+key:String,-origin:Layout.Layout,mode:Mode,project:P -> P & D.Raw,column:Column.Column<S,Layout.Viewed<P,V>>,offset:Maybe<&2,U32>) -> Layout.ColumnSlot<S,Layout.Viewed<P,V>,key,origin> & Saved.Fields:
73 match offset:
74 case None{}:(Layout.ColumnSlot{column},Saved.error(Recipe.MalformedColumn{key}))
75 case Some{index}:component_returned(S,P,V,key,origin,project_column(S,Layout.Viewed<P,V>,column,index,Some{stored => viewed(P,V,mode,key,project,stored)}))
76def component_valid(-S:Data,-P:Type,-V:Data,+key:String,-origin:Layout.Layout,mode:Mode,project:P -> P & D.Raw,column:Column.Column<S,Layout.Viewed<P,V>>,logical:U32,valid:Bool) -> Layout.ColumnSlot<S,Layout.Viewed<P,V>,key,origin> & Saved.Fields:
77 match valid:
78 case False{}:(Layout.ColumnSlot{column},Saved.error(Recipe.MalformedColumn{key}))
79 case True{}:component_offset(S,P,V,key,origin,mode,project,column,Index.physical_index(logical))
80def component_inspected(-S:Data,-P:Type,-V:Data,+key:String,-origin:Layout.Layout,mode:Mode,project:P -> P & D.Raw,logical:U32,result:Column.Column<S,Layout.Viewed<P,V>> & Part.Inspection) -> Layout.ColumnSlot<S,Layout.Viewed<P,V>,key,origin> & Saved.Fields:
81 match result:
82 case (column,Part.Inspection{_,capacity,valid}):component_valid(S,P,V,key,origin,mode,project,column,logical,Bool.and(valid,U32.is_le(capacity,Column.maximum_capacity())))
83def component(-S:Data,-P:Type,-V:Data,+key:String,-origin:Layout.Layout,mode:Mode,project:P -> P & D.Raw,slot:Layout.ColumnSlot<S,Layout.Viewed<P,V>,key,origin>,logical:U32) -> Layout.ColumnSlot<S,Layout.Viewed<P,V>,key,origin> & Saved.Fields:
84 match slot:
85 case Layout.ColumnSlot{column}:component_inspected(S,P,V,key,origin,mode,project,logical,Part.inspect(S,Layout.Viewed<P,V>,column))
86def resource_returned(-S:Data,-P:Type,-V:Data,+key:String,-origin:Layout.Layout,view:V,+stamp:Life.Stamp,result:P & Recipe.Field) -> Layout.ResourceSlot<S,Layout.Viewed<P,V>,key,origin> & Saved.Fields:
87 match result:
88 case (owner,value):(Layout.ResourceSlot{Layout.Viewed{owner,view},stamp},field(key,Some{stamp},Some{value}))
89def resource(-S:Data,-P:Type,-V:Data,+key:String,-origin:Layout.Layout,mode:Mode,project:P -> P & D.Raw,slot:Layout.ResourceSlot<S,Layout.Viewed<P,V>,key,origin>) -> Layout.ResourceSlot<S,Layout.Viewed<P,V>,key,origin> & Saved.Fields:
90 match slot:
91 case Layout.ResourceSlot{Layout.Viewed{owner,view},stamp}:resource_returned(S,P,V,key,origin,view,stamp,describe(P,mode,key,project,owner))