execution_relation_store.bend

bendvy-ecs-core@0.1.0.3 · 61 lines · 16 definitions

1import Base
2import bendvy-ecs-core@0.1.0.3/entity_allocator.bend as A
3import bendvy-ecs-core@0.1.0.3/relation_types.bend as T
4import bendvy-ecs-core@0.1.0.3/execution_relation_operation.bend as O
5import bendvy-ecs-core@0.1.0.3/execution_relation_interpreter.bend as I
6import bendvy-ecs-core@0.1.0.3/execution_relation_failure_message.bend as Failure
7import bendvy-ecs-core@0.1.0.3/execution_relation_failure_channel.bend as Reader
8import bendvy-ecs-core@0.1.0.3/execution_stream_channel.bend as Channel
9import bendvy-ecs-core@0.1.0.3/execution_composer_layout.bend as Layout
10import bendvy-ecs-core@0.1.0.3/change_tick.bend as Tick
11
12# Constructors and mutation functions are trusted provisioning/barrier helpers.
13# Gameplay receives only operations over an abstract H, never this owner.
14type Store<-S:Data,-descriptor:T.Descriptor<S>> is Type:
15  Store{namespace:U32,graph:T.Graph<S>,failures:Channel.Store<Failure.Message<S,descriptor>>,sequence:Nat,nextReader:U32}
16type View<-S:Data,-descriptor:T.Descriptor<S>> is Data:
17  View{namespace:U32,graph:T.Graph<S>,failures:Channel.Store<Failure.Message<S,descriptor>>,sequence:Nat,nextReader:U32}
18type Reason is Data:
19  NamespaceMismatch{}
20  OperationRefused{reason:O.Reason}
21type Receipt<S:Data> is Data:
22  Applied{operation:O.Operation<S>}
23  Refused{operation:O.Operation<S>,reason:Reason}
24type Registration<-S:Data,-descriptor:T.Descriptor<S>,-origin:Layout.Layout,-route:Layout.Route> is Type:
25  Registered{store:Store<S,descriptor>,reader:Reader.Reader<S,descriptor,origin,route>}
26  RegistrationRefused{store:Store<S,descriptor>}
27def fresh(~S:Data,~descriptor:T.Descriptor<S>,namespace:U32) -> Store<S,descriptor>:
28  Store{namespace,T.Graph{[],[]},Channel.empty(~Failure.Message<S,descriptor>),0n,1}
29def project_generic(-S:Data,-descriptor:T.Descriptor<S>,store:Store<S,descriptor>) -> Store<S,descriptor> & View<S,descriptor>:
30  match store:
31    case Store{+namespace,+graph,+failures,+sequence,+nextReader}:(Store{namespace,graph,failures,sequence,nextReader},View{namespace,graph,failures,sequence,nextReader})
32def project(~S:Data,~descriptor:T.Descriptor<S>,store:Store<S,descriptor>) -> Store<S,descriptor> & View<S,descriptor>:
33  project_generic(S,descriptor,store)
34def published(~S:Data,~descriptor:T.Descriptor<S>,namespace:U32,graph:T.Graph<S>,nextReader:U32,allocator:A.Allocator,operation:O.Operation<S>,reason:O.Reason,result:Nat & Channel.Store<Failure.Message<S,descriptor>>) -> A.Allocator & (Store<S,descriptor> & Receipt<S>):
35  match result:
36    case (sequence,failures):(allocator,(Store{namespace,graph,failures,sequence,nextReader},Refused{operation,OperationRefused{reason}}))
37def publish(~S:Data,~descriptor:T.Descriptor<S>,namespace:U32,graph:T.Graph<S>,failures:Channel.Store<Failure.Message<S,descriptor>>,sequence:Nat,nextReader:U32,allocator:A.Allocator,operation:O.Operation<S>,reason:O.Reason,message:Maybe<&2,Failure.Message<S,descriptor>>) -> A.Allocator & (Store<S,descriptor> & Receipt<S>):
38  match message:
39    case None{}:(allocator,(Store{namespace,graph,failures,sequence,nextReader},Refused{operation,OperationRefused{reason}}))
40    case Some{message}:published(~S,~descriptor,namespace,graph,nextReader,allocator,operation,reason,Channel.push(~Failure.Message<S,descriptor>,sequence,failures,message))
41def interpreted(~S:Data,~descriptor:T.Descriptor<S>,namespace:U32,failures:Channel.Store<Failure.Message<S,descriptor>>,sequence:Nat,nextReader:U32,result:A.Allocator & O.Outcome<S>) -> A.Allocator & (Store<S,descriptor> & Receipt<S>):
42  match result:
43    case (allocator,O.Applied{graph,operation}):(allocator,(Store{namespace,graph,failures,sequence,nextReader},Applied{operation}))
44    case (allocator,O.Refused{graph,+operation,+reason}):publish(~S,~descriptor,namespace,graph,failures,sequence,nextReader,allocator,operation,reason,Failure.refused(~S,~descriptor,operation,reason))
45def admitted(~S:Data,~descriptor:T.Descriptor<S>,same:Bool,+namespace:U32,allocator:A.Allocator,store:Store<S,descriptor>,operation:O.Operation<S>) -> A.Allocator & (Store<S,descriptor> & Receipt<S>):
46  match same store:
47    case False{} store:(allocator,(store,Refused{operation,NamespaceMismatch{}}))
48    case True{} Store{_,graph,failures,sequence,nextReader}:interpreted(~S,~descriptor,namespace,failures,sequence,nextReader,I.apply(~S,~descriptor,namespace,allocator,graph,operation))
49def apply(~S:Data,~descriptor:T.Descriptor<S>,+namespace:U32,allocator:A.Allocator,store:Store<S,descriptor>,operation:O.Operation<S>) -> A.Allocator & (Store<S,descriptor> & Receipt<S>):
50  match store:
51    case Store{+storedNamespace,graph,failures,sequence,nextReader}:admitted(~S,~descriptor,U32.is_eq(namespace,storedNamespace),namespace,allocator,Store{storedNamespace,graph,failures,sequence,nextReader},operation)
52def register_checked(~S:Data,~descriptor:T.Descriptor<S>,~origin:Layout.Layout,~route:Layout.Route,available:Bool,store:Store<S,descriptor>) -> Registration<S,descriptor,origin,route>:
53  match available store:
54    case False{} store:RegistrationRefused{store}
55    case True{} Store{+namespace,graph,failures,sequence,+nextReader}:Registered{Store{namespace,graph,failures,sequence,(nextReader + 1 : U32)},Reader.Reader{namespace,nextReader,0n}}
56def register(~S:Data,~descriptor:T.Descriptor<S>,~origin:Layout.Layout,~route:Layout.Route,store:Store<S,descriptor>) -> Registration<S,descriptor,origin,route>:
57  match store:
58    case Store{namespace,graph,failures,sequence,+nextReader}:register_checked(~S,~descriptor,~origin,~route,U32.is_lt(nextReader,4294967295),Store{namespace,graph,failures,sequence,nextReader})
59def maintained(~S:Data,~descriptor:T.Descriptor<S>,tick:Tick.Tick,store:Store<S,descriptor>) -> Store<S,descriptor>:
60  match store:
61    case Store{namespace,graph,failures,+sequence,nextReader}:Store{namespace,graph,Channel.maintain(~Failure.Message<S,descriptor>,sequence,tick,failures),sequence,nextReader}