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
63
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