execution_recoverable_component.bend
bendvy-ecs-core@0.1.0.3 · 69 lines · 16 definitions
1import Base
2import bendvy-ecs-core@0.1.0.3/world.bend as W
3import bendvy-ecs-core@0.1.0.3/chunk_column.bend as Column
4import bendvy-ecs-core@0.1.0.3/execution_composer_layout.bend as Layout
5import bendvy-ecs-core@0.1.0.3/execution_layout_access.bend as Access
6import bendvy-ecs-core@0.1.0.3/execution_query_identity.bend as Identity
7import bendvy-ecs-core@0.1.0.3/execution_resource_policy.bend as Policy
8import bendvy-ecs-core@0.1.0.3/recoverable_component.bend as RC
9import bendvy-ecs-core@0.1.0.3/lifecycle.bend as Life
10import bendvy-ecs-core@0.1.0.3/change_tick.bend as Tick
11
12
13type Exchange<-P:Type> is Type:
14 Exchanged{stamp:Life.Stamp,previous:Maybe<P>}
15 ExchangeRefused{incoming:Maybe<P>}
16def packed(~layout:Layout.Layout,~route:Layout.Route,incoming:Maybe<Layout.payload(layout,route)>) -> Maybe<Layout.stored(layout,route)>:
17 match incoming:
18 case None{}:None{}
19 case Some{owner}:Some{Layout.initialize(layout,route,owner)}
20def unpacked(~P:Type,~V:Data,incoming:Maybe<Layout.Viewed<P,V>>) -> Maybe<P>:
21 match incoming:
22 case None{}:None{}
23 case Some{Layout.Viewed{owner,_}}:Some{owner}
24def restore_optional(~S:Data,~P:Type,column:Column.Column<S,P>,index:U32,saved:Maybe<&2,Life.Stamp>) -> Column.Column<S,P>:
25 match saved:
26 case None{}:column
27 case Some{stamp}:Column.restore_stamp(~S,~P,column,index,stamp)
28def swapped(~S:Data,~layout:Layout.Layout,~route:Layout.Route,index:U32,prior:Life.Stamp,saved:Maybe<&2,Life.Stamp>,result:Column.SwapOutcome<S,Layout.stored(layout,route)>) -> Column.Column<S,Layout.stored(layout,route)> & Exchange<Layout.payload(layout,route)>:
29 match result:
30 case Column.Accepted{column,previous}:(restore_optional(~S,~Layout.stored(layout,route),column,index,saved),Exchanged{prior,unpacked(~Layout.payload(layout,route),~Layout.view(layout,route),previous)})
31 case Column.Rejected{column,incoming}:(column,ExchangeRefused{unpacked(~Layout.payload(layout,route),~Layout.view(layout,route),incoming)})
32def observed(~S:Data,~layout:Layout.Layout,~route:Layout.Route,+index:U32,incoming:Maybe<Layout.payload(layout,route)>,tick:Tick.Tick,saved:Maybe<&2,Life.Stamp>,result:Column.Column<S,Layout.stored(layout,route)> & Maybe<&2,Life.Stamp>) -> Column.Column<S,Layout.stored(layout,route)> & Exchange<Layout.payload(layout,route)>:
33 match result:
34 case (column,None{}):(column,ExchangeRefused{incoming})
35 case (column,Some{prior}):swapped(~S,~layout,~route,index,prior,saved,Column.swap_at(~S,~Layout.stored(layout,route),column,index,packed(~layout,~route,incoming),tick))
36def column_returned(~S:Data,~C:Type,~layout:Layout.Layout,~route:Layout.Route,~same:{C == Layout.columns(~S,layout) : Type},rest:Layout.column_rest(~S,layout,route),result:Column.Column<S,Layout.stored(layout,route)> & Exchange<Layout.payload(layout,route)>) -> C & Exchange<Layout.payload(layout,route)>:
37 match result:
38 case (column,result):(Access.column_put(~S,~C,~layout,~route,~same,rest,column),result)
39def column_taken(~S:Data,~C:Type,~layout:Layout.Layout,~route:Layout.Route,~same:{C == Layout.columns(~S,layout) : Type},+index:U32,incoming:Maybe<Layout.payload(layout,route)>,tick:Tick.Tick,saved:Maybe<&2,Life.Stamp>,result:Layout.column_rest(~S,layout,route) & Column.Column<S,Layout.stored(layout,route)>) -> C & Exchange<Layout.payload(layout,route)>:
40 match result:
41 case (rest,column):column_returned(~S,~C,~layout,~route,~same,rest,observed(~S,~layout,~route,index,incoming,tick,saved,Column.lifecycle(~S,~Layout.stored(layout,route),column,index)))
42def exchange(~S:Data,~C:Type,~layout:Layout.Layout,~route:Layout.Route,~same:{C == Layout.columns(~S,layout) : Type},index:U32,incoming:Maybe<Layout.payload(layout,route)>,tick:Tick.Tick,saved:Maybe<&2,Life.Stamp>,columns:C) -> C & Exchange<Layout.payload(layout,route)>:
43 column_taken(~S,~C,~layout,~route,~same,index,incoming,tick,saved,Access.column_take(~S,~C,~layout,~route,~same,columns))
44def replaced(~S:Data,~C:Type,~R:Type,~E:Data,~P:Type,handle:W.Handle<S>,result:W.World<S,C,R,E> & Exchange<P>) -> RC.Replacement<W.World<S,C,R,E>,S,P>:
45 match result:
46 case (world,Exchanged{stamp,previous}):RC.Applied{world,RC.Record{handle,stamp,previous}}
47 case (world,ExchangeRefused{incoming}):RC.Refused{world,incoming,W.CapacityExceeded{}}
48def timed(~S:Data,~C:Type,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,~same:{C == Layout.columns(~S,layout) : Type},handle:W.Handle<S>,index:U32,incoming:Maybe<Layout.payload(layout,route)>,result:W.World<S,C,R,E> & Tick.Tick) -> RC.Replacement<W.World<S,C,R,E>,S,Layout.payload(layout,route)>:
49 match result:
50 case (world,tick):replaced(~S,~C,~R,~E,~Layout.payload(layout,route),handle,W.with_store(~S,~C,~R,~E,~Exchange<Layout.payload(layout,route)>,exchange(~S,~C,~layout,~route,~same,index,incoming,tick,None{}),world))
51def offset(~S:Data,~C:Type,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,~same:{C == Layout.columns(~S,layout) : Type},incoming:Maybe<Layout.payload(layout,route)>,result:W.World<S,C,R,E> & Identity.Offset<S>) -> RC.Replacement<W.World<S,C,R,E>,S,Layout.payload(layout,route)>:
52 match result:
53 case (world,Identity.Physical{handle,index}):timed(~S,~C,~R,~E,~layout,~route,~same,handle,index,incoming,W.write_clock(~S,~C,~R,~E,world))
54 case (world,Identity.MissingEntity{_}):RC.Refused{world,incoming,W.MissingEntity{}}
55 case (world,Identity.OutsideStorage{_,_}):RC.Refused{world,incoming,W.CapacityExceeded{}}
56def replace(~S:Data,~C:Type,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,~same:{C == Layout.columns(~S,layout) : Type},~valid:{Layout.grant_valid(~layout,~route) == True{} : Bool},~ordinary:{Layout.policy(layout,route) == Policy.Ordinary{} : Policy.Policy},world:W.World<S,C,R,E>,handle:W.Handle<S>,incoming:Maybe<Layout.payload(layout,route)>) -> RC.Replacement<W.World<S,C,R,E>,S,Layout.payload(layout,route)>:
57 offset(~S,~C,~R,~E,~layout,~route,~same,incoming,Identity.world_offset(~S,~C,~R,~E,world,Column.maximum_capacity(),handle))
58def undone(~S:Data,~C:Type,~R:Type,~E:Data,~P:Type,handle:W.Handle<S>,saved:Life.Stamp,result:W.World<S,C,R,E> & Exchange<P>) -> W.World<S,C,R,E> & RC.Record<S,P>:
59 match result:
60 case (world,Exchanged{stamp,previous}):(world,RC.Record{handle,stamp,previous})
61 case (world,ExchangeRefused{incoming}):(world,RC.Record{handle,saved,incoming})
62def undo_offset(~S:Data,~C:Type,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,~same:{C == Layout.columns(~S,layout) : Type},+stamp:Life.Stamp,payload:Maybe<Layout.payload(layout,route)>,result:W.World<S,C,R,E> & Identity.Offset<S>) -> W.World<S,C,R,E> & RC.Record<S,Layout.payload(layout,route)>:
63 match result:
64 case (world,Identity.Physical{+handle,index}):undone(~S,~C,~R,~E,~Layout.payload(layout,route),handle,stamp,W.with_store(~S,~C,~R,~E,~Exchange<Layout.payload(layout,route)>,exchange(~S,~C,~layout,~route,~same,index,payload,Tick.zero(),Some{stamp}),world))
65 case (world,Identity.MissingEntity{handle}):(world,RC.Record{handle,stamp,payload})
66 case (world,Identity.OutsideStorage{handle,_}):(world,RC.Record{handle,stamp,payload})
67def undo(~S:Data,~C:Type,~R:Type,~E:Data,~layout:Layout.Layout,~route:Layout.Route,~same:{C == Layout.columns(~S,layout) : Type},~valid:{Layout.grant_valid(~layout,~route) == True{} : Bool},~ordinary:{Layout.policy(layout,route) == Policy.Ordinary{} : Policy.Policy},record:RC.Record<S,Layout.payload(layout,route)>,world:W.World<S,C,R,E>) -> W.World<S,C,R,E> & RC.Record<S,Layout.payload(layout,route)>:
68 match record:
69 case RC.Record{handle,stamp,payload}:undo_offset(~S,~C,~R,~E,~layout,~route,~same,stamp,payload,Identity.world_offset(~S,~C,~R,~E,world,Column.maximum_capacity(),handle))