1 import Base 2 import ./persistence_declaration.bend as Decl 3 import ./snapshot_gate.bend as Gate 4 import ./decode_data.bend as D 5 import ./column.bend as Col 6 import ./ordinary_declaration.bend as Canonical 7 8 # Ordinary leaf stores retain the recipe used for admission and export together. 9 type Component<-S:Data,-P:Type,-identity:Canonical.Declaration,-project:P -> P & D.Raw> is Type: 10 Component{column:Col.Column,declaration:Decl.Constructed} 11 type TransientComponent<-S:Data,-P:Type,-identity:Canonical.Declaration> is Type: 12 TransientComponent{column:Col.Column,declaration:Decl.Transient} 13 type Resource<-S:Data,-P:Type,-identity:Canonical.Declaration,-project:P -> P & D.Raw> is Type: 14 Resource{owner:P,declaration:Decl.Constructed} 15 type TransientResource<-S:Data,-P:Type,-identity:Canonical.Declaration> is Type: 16 TransientResource{owner:P,declaration:Decl.Transient} 17 def factory(~S:Data,~P:Type,~identity:Canonical.Declaration,~project:P -> P & D.Raw,declaration:Decl.Constructed) -> Gate.Gate: 18 Gate.persisted(~S,~P,~identity,Decl.codec(~S,~P,~identity,~project,declaration),project) 19 def fields(field:Gate.Field) -> List<&2,D.Field>: 20 match field: 21 case Gate.Omitted{_}:[] 22 case Gate.Saved{name,value}:[D.Field{name,value}] 23 def component_restored(~S:Data,~P:Type,~identity:Canonical.Declaration,~project:P -> P & D.Raw,declaration:Decl.Constructed,observed:Col.Column & Maybe<&2,Gate.Field>) -> Component & List<&2,D.Field>: 24 match observed: 25 case (column,None{}):(Component{column,declaration},[]) 26 case (column,Some{field}):(Component{column,declaration},fields(field)) 27 def component_taken(~S:Data,~P:Type,~identity:Canonical.Declaration,~project:P -> P & D.Raw,+id:U32,+declaration:Decl.Constructed,outcome:Col.SwapOutcome) -> Component & List<&2,D.Field>: 28 match outcome: 29 case Col.Rejected{column,_}:(Component{column,declaration},[]) 30 case Col.Accepted{column,None{}}:(Component{column,declaration},[]) 31 case Col.Accepted{column,Some{owner}}:component_restored(~S,~P,~identity,~project,declaration,Col.viewed(~S,~P,~Gate.Field,Gate.export_owner(~S,~P,~identity,factory(~S,~P,~identity,~project,declaration),owner),column,id)) 32 def component_fields_owned(~S:Data,~P:Type,~identity:Canonical.Declaration,~project:P -> P & D.Raw,+id:U32,value:Component) -> Component & List<&2,D.Field>: 33 match value: 34 case Component{column,declaration}:component_taken(~S,~P,~identity,~project,id,declaration,Col.swap(~S,~P,column,id,None{})) 35 def component_fields(~S:Data,~P:Type,~identity:Canonical.Declaration,~project:P -> P & D.Raw,id:U32,value:Component) -> Component & List<&2,D.Field>: 36 component_fields_owned(~S,~P,~identity,~project,id,value) 37 def transient_component_fields(~S:Data,~P:Type,~identity:Canonical.Declaration,id:U32,value:TransientComponent) -> TransientComponent & List<&2,D.Field>: 38 (value,[]) 39 def resource_restored(~S:Data,~P:Type,~identity:Canonical.Declaration,~project:P -> P & D.Raw,declaration:Decl.Constructed,observed:P & Gate.Field) -> Resource & List<&2,D.Field>: 40 match observed: 41 case (owner,field):(Resource{owner,declaration},fields(field)) 42 def resource_fields(~S:Data,~P:Type,~identity:Canonical.Declaration,~project:P -> P & D.Raw,value:Resource) -> Resource & List<&2,D.Field>: 43 match value: 44 case Resource{owner,+declaration}:resource_restored(~S,~P,~identity,~project,declaration,Gate.export_owner(~S,~P,~identity,factory(~S,~P,~identity,~project,declaration),owner)) 45 def transient_resource_fields(~S:Data,~P:Type,~identity:Canonical.Declaration,value:TransientResource) -> TransientResource & List<&2,D.Field>: 46 (value,[])