execution_relation_access.bend

bendvy-ecs-core@0.1.0.3 · 71 lines · 19 definitions

1import Base
2import bendvy-ecs-core@0.1.0.3/world.bend as W
3import bendvy-ecs-core@0.1.0.3/entity_key.bend as K
4import bendvy-ecs-core@0.1.0.3/relation_types.bend as T
5import bendvy-ecs-core@0.1.0.3/relation_graph.bend as Graph
6import bendvy-ecs-core@0.1.0.3/execution_relation_store.bend as Store
7import bendvy-ecs-core@0.1.0.3/execution_state.bend as State
8import bendvy-ecs-core@0.1.0.3/execution_lifecycle_notices.bend as Notice
9
10type Lookup<V:Data> is Data:
11  Value{value:V}
12  MissingEntity{}
13  NamespaceRefused{}
14type Reader<-S:Data,-H:Type> is Type:
15  Reader{target:H -> W.Handle<S> -> H & Lookup<Maybe<&2,W.Handle<S>>>,inverse:H -> W.Handle<S> -> H & Lookup<List<&2,W.Handle<S>>>}
16def Reads(~S:Data,H:Type) -> Type:Reader<S,H>
17def namespace(~S:Data,view:Notice.View<S>) -> U32:
18  match view:
19    case Notice.View{namespace,_,_}:namespace
20def handle(~S:Data,namespace:U32,value:Maybe<&2,K.Key>) -> Maybe<&2,W.Handle<S>>:
21  match value:
22    case None{}:None{}
23    case Some{key}:Some{W.Handle{namespace,key}}
24def handles(~S:Data,+namespace:U32,keys:List<&2,K.Key>) -> List<&2,W.Handle<S>>:
25  match keys:
26    case []:[]
27    case key <> rest:W.Handle{namespace,key} <> handles(~S,namespace,rest)
28def target_namespace(~S:Data,same:Bool,namespace:U32,value:Maybe<&2,K.Key>) -> Lookup<Maybe<&2,W.Handle<S>>>:
29  match same:
30    case False{}:NamespaceRefused{}
31    case True{}:Value{handle(~S,namespace,value)}
32def target_view(~S:Data,~descriptor:T.Descriptor<S>,+expected:U32,source:W.Handle<S>,view:Store.View<S,descriptor>) -> Lookup<Maybe<&2,W.Handle<S>>>:
33  match view:
34    case Store.View{+actual,graph,_,_,_}:target_namespace(~S,U32.is_eq(expected,actual),actual,Graph.target(~S,graph,descriptor,W.handle_key(~S,source)))
35def inverse_namespace(~S:Data,same:Bool,namespace:U32,keys:List<&2,K.Key>) -> Lookup<List<&2,W.Handle<S>>>:
36  match same:
37    case False{}:NamespaceRefused{}
38    case True{}:Value{handles(~S,namespace,keys)}
39def inverse_view(~S:Data,~descriptor:T.Descriptor<S>,+expected:U32,target:W.Handle<S>,view:Store.View<S,descriptor>) -> Lookup<List<&2,W.Handle<S>>>:
40  match view:
41    case Store.View{+actual,graph,_,_,_}:inverse_namespace(~S,U32.is_eq(expected,actual),actual,Graph.inverse(~S,graph,descriptor,W.handle_key(~S,target)))
42def target_returned(~S:Data,~descriptor:T.Descriptor<S>,~H:Type,expected:U32,source:W.Handle<S>,result:H & Store.View<S,descriptor>) -> H & Lookup<Maybe<&2,W.Handle<S>>>:
43  match result:
44    case (owner,view):(owner,target_view(~S,~descriptor,expected,source,view))
45def inverse_returned(~S:Data,~descriptor:T.Descriptor<S>,~H:Type,expected:U32,target:W.Handle<S>,result:H & Store.View<S,descriptor>) -> H & Lookup<List<&2,W.Handle<S>>>:
46  match result:
47    case (owner,view):(owner,inverse_view(~S,~descriptor,expected,target,view))
48def target_checked(~S:Data,~descriptor:T.Descriptor<S>,~C:Type,~R:Type,~view:State.Scope<S,C,R> -> State.Scope<S,C,R> & Store.View<S,descriptor>,valid:Bool,expected:U32,scope:State.Scope<S,C,R>,source:W.Handle<S>) -> State.Scope<S,C,R> & Lookup<Maybe<&2,W.Handle<S>>>:
49  match valid:
50    case False{}:(scope,MissingEntity{})
51    case True{}:target_returned(~S,~descriptor,~State.Scope<S,C,R>,expected,source,view(scope))
52def inverse_checked(~S:Data,~descriptor:T.Descriptor<S>,~C:Type,~R:Type,~view:State.Scope<S,C,R> -> State.Scope<S,C,R> & Store.View<S,descriptor>,valid:Bool,expected:U32,scope:State.Scope<S,C,R>,target:W.Handle<S>) -> State.Scope<S,C,R> & Lookup<List<&2,W.Handle<S>>>:
53  match valid:
54    case False{}:(scope,MissingEntity{})
55    case True{}:inverse_returned(~S,~descriptor,~State.Scope<S,C,R>,expected,target,view(scope))
56def target(~S:Data,~descriptor:T.Descriptor<S>,~C:Type,~R:Type,~view:State.Scope<S,C,R> -> State.Scope<S,C,R> & Store.View<S,descriptor>,scope:State.Scope<S,C,R>,+source:W.Handle<S>) -> State.Scope<S,C,R> & Lookup<Maybe<&2,W.Handle<S>>>:
57  match scope:
58    case State.Scope{columns,resources,+live,tick,prior,+notice}:target_checked(~S,~descriptor,~C,~R,~view,State.member(~S,source,live),namespace(~S,notice),State.Scope{columns,resources,live,tick,prior,notice},source)
59def inverse(~S:Data,~descriptor:T.Descriptor<S>,~C:Type,~R:Type,~view:State.Scope<S,C,R> -> State.Scope<S,C,R> & Store.View<S,descriptor>,scope:State.Scope<S,C,R>,+target:W.Handle<S>) -> State.Scope<S,C,R> & Lookup<List<&2,W.Handle<S>>>:
60  match scope:
61    case State.Scope{columns,resources,+live,tick,prior,+notice}:inverse_checked(~S,~descriptor,~C,~R,~view,State.member(~S,target,live),namespace(~S,notice),State.Scope{columns,resources,live,tick,prior,notice},target)
62# Only the closed provider supplies view. Gameplay receives no store owner,
63# graph setter, payload transform, inverse mutation, or concrete Scope type.
64def reader(~S:Data,~descriptor:T.Descriptor<S>,~C:Type,~R:Type,~view:State.Scope<S,C,R> -> State.Scope<S,C,R> & Store.View<S,descriptor>) -> Reader<S,State.Scope<S,C,R>>:
65  Reader{scope => source => target(~S,~descriptor,~C,~R,~view,scope,source),scope => target => inverse(~S,~descriptor,~C,~R,~view,scope,target)}
66def target_field(~S:Data,~H:Type,cap:Reader<S,H>) -> H -> W.Handle<S> -> H & Lookup<Maybe<&2,W.Handle<S>>>:
67  match cap:
68    case Reader{target,_}:target
69def inverse_field(~S:Data,~H:Type,cap:Reader<S,H>) -> H -> W.Handle<S> -> H & Lookup<List<&2,W.Handle<S>>>:
70  match cap:
71    case Reader{_,inverse}:inverse