execution_query_identity.bend

bendvy-ecs-core@0.1.0.3 · 83 lines · 21 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/execution_state.bend as State
5import bendvy-ecs-core@0.1.0.3/execution_query_domain.bend as D
6import bendvy-ecs-core@0.1.0.3/indexed_lifecycle.bend as Indexed
7import bendvy-ecs-core@0.1.0.3/chunk_column.bend as Column
8
9# Captured handles must originate from admitted actual World/Prepared state.
10# Comparing all namespace/key/generation fields precedes physical conversion.
11type Offset<-S:Data> is Data:
12  MissingEntity{handle:W.Handle<S>}
13  OutsideStorage{handle:W.Handle<S>,capacity:U32}
14  Physical{handle:W.Handle<S>,offset:U32}
15def checked_range(~S:Data,+handle:W.Handle<S>,+capacity:U32,+logical:U32,live:Bool,inRange:Bool) -> Offset<S>:
16  match live inRange:
17    case False{} _:MissingEntity{handle}
18    case True{} False{}:OutsideStorage{handle,capacity}
19    case True{} True{}:Physical{handle,U32.sub(logical,1)}
20def checked_logical(~S:Data,+namespace:U32,+handles:List<&2,W.Handle<S>>,+capacity:U32,+handle:W.Handle<S>,+handleNamespace:U32,+key:K.Key) -> Offset<S>:
21  checked_range(~S,handle,capacity,K.index(key),Bool.and(U32.is_eq(namespace,handleNamespace),State.member(~S,handle,handles)),Bool.and(Indexed.normal(K.index(key)),U32.is_le(K.index(key),capacity)))
22def checked_offset(~S:Data,namespace:U32,handles:List<&2,W.Handle<S>>,capacity:U32,handle:W.Handle<S>) -> Offset<S>:
23  match handle:
24    case W.Handle{+hn,+key}:checked_logical(~S,namespace,handles,capacity,W.Handle{hn,key},hn,key)
25type TargetCheck<-S:Data> is Data:
26  Targets{handles:List<&2,W.Handle<S>>,offsets:D.Domain}
27  Refused{handles:List<&2,W.Handle<S>>}
28def unique(~S:Data,handles:List<&2,W.Handle<S>>) -> Bool:
29  match handles:
30    case []:True{}
31    case +head <> +tail:Bool.and(Bool.not(State.member(~S,head,tail)),unique(~S,tail))
32
33def offset_handles(~S:Data,~C:Type,~R:Type,~E:Data,namespace:U32,capacity:U32,handle:W.Handle<S>,result:W.World<S,C,R,E> & List<&2,W.Handle<S>>) -> W.World<S,C,R,E> & Offset<S>:
34  match result:
35    case (world,handles):(world,checked_offset(~S,namespace,handles,capacity,handle))
36def offset_namespace(~S:Data,~C:Type,~R:Type,~E:Data,capacity:U32,handle:W.Handle<S>,result:W.World<S,C,R,E> & U32) -> W.World<S,C,R,E> & Offset<S>:
37  match result:
38    case (world,namespace):offset_handles(~S,~C,~R,~E,namespace,capacity,handle,W.handles(~S,~C,~R,~E,world))
39def offset_valid(~S:Data,~C:Type,~R:Type,~E:Data,capacity:U32,handle:W.Handle<S>,result:W.World<S,C,R,E> & Bool) -> W.World<S,C,R,E> & Offset<S>:
40  match result:
41    case (world,False{}):(world,MissingEntity{handle})
42    case (world,True{}):offset_namespace(~S,~C,~R,~E,capacity,handle,W.namespace(~S,~C,~R,~E,world))
43def world_offset(~S:Data,~C:Type,~R:Type,~E:Data,world:W.World<S,C,R,E>,capacity:U32,+handle:W.Handle<S>) -> W.World<S,C,R,E> & Offset<S>:
44  offset_valid(~S,~C,~R,~E,capacity,handle,W.valid(~S,~C,~R,~E,world,handle))
45
46def index_checked(+logical:U32,normal:Bool) -> Maybe<&2,U32>:
47  match normal:
48    case False{}:None{}
49    case True{}:Some{U32.sub(logical,1)}
50def physical_index(+logical:U32) -> Maybe<&2,U32>:
51  index_checked(logical,Indexed.normal(logical))
52def captured_offset(~S:Data,+handles:List<&2,W.Handle<S>>,handle:W.Handle<S>) -> Offset<S>:
53  match handles:
54    case []:MissingEntity{handle}
55    case W.Handle{+namespace,+key} <> +rest:checked_offset(~S,namespace,W.Handle{namespace,key} <> rest,Column.maximum_capacity(),handle)
56def physical_live(~S:Data,checked:Offset<S>) -> Bool:
57  match checked:
58    case Physical{_,_}:True{}
59    case _:False{}
60def captured_live(~S:Data,handles:List<&2,W.Handle<S>>,handle:W.Handle<S>) -> Bool:
61  physical_live(~S,captured_offset(~S,handles,handle))
62def prepend_offset(~S:Data,tail:Maybe<&2,List<&2,U32>>,checked:Offset<S>) -> Maybe<&2,List<&2,U32>>:
63  match tail checked:
64    case Some{tail} Physical{_,offset}:Some{offset <> tail}
65    case _ _:None{}
66def target_offsets(~S:Data,+namespace:U32,+all:List<&2,W.Handle<S>>,remaining:List<&2,W.Handle<S>>) -> Maybe<&2,List<&2,U32>>:
67  match remaining:
68    case []:Some{[]}
69    case +head <> tail:prepend_offset(~S,target_offsets(~S,namespace,all,tail),checked_offset(~S,namespace,all,Column.maximum_capacity(),head))
70def targets_valid(~S:Data,handles:List<&2,W.Handle<S>>,domain:D.Domain,valid:Bool) -> TargetCheck<S>:
71  match valid:
72    case False{}:Refused{handles}
73    case True{}:Targets{handles,domain}
74def targets_validation(~S:Data,+handles:List<&2,W.Handle<S>>,+domain:D.Domain,validation:D.Validation) -> TargetCheck<S>:
75  match validation:
76    case D.Valid{}:targets_valid(~S,handles,domain,unique(~S,handles))
77    case _:Refused{handles}
78def targets_offsets(~S:Data,handles:List<&2,W.Handle<S>>,offsets:Maybe<&2,List<&2,U32>>) -> TargetCheck<S>:
79  match offsets:
80    case None{}:Refused{handles}
81    case Some{+offsets}:targets_validation(~S,handles,D.Domain{offsets},D.validate(Column.maximum_capacity(),D.Domain{offsets}))
82def targets(~S:Data,namespace:U32,+handles:List<&2,W.Handle<S>>) -> TargetCheck<S>:
83  targets_offsets(~S,handles,target_offsets(~S,namespace,handles,handles))