execution_relation_interpreter.bend

bendvy-ecs-core@0.1.0.3 · 57 lines · 12 definitions

1import Base
2import bendvy-ecs-core@0.1.0.3/entity_allocator.bend as A
3import bendvy-ecs-core@0.1.0.3/entity_key.bend as K
4import bendvy-ecs-core@0.1.0.3/world.bend as W
5import bendvy-ecs-core@0.1.0.3/relation_types.bend as T
6import bendvy-ecs-core@0.1.0.3/relation_graph.bend as Graph
7import bendvy-ecs-core@0.1.0.3/relation_reorder_core.bend as Reorder
8import bendvy-ecs-core@0.1.0.3/execution_relation_operation.bend as O
9
10# Trusted barrier seam. Namespace and allocator must come from the same actual
11# Administration owner; this module does not grant gameplay graph authority.
12def live_namespace(~S:Data,same:Bool,allocator:A.Allocator,handle:W.Handle<S>) -> A.Allocator & Bool:
13  match same:
14    case False{}:(allocator,False{})
15    case True{}:A.checked(allocator,W.handle_key(~S,handle),1)
16def live(~S:Data,+namespace:U32,allocator:A.Allocator,+handle:W.Handle<S>) -> A.Allocator & Bool:
17  match handle:
18    case W.Handle{ns,key}:live_namespace(~S,U32.is_eq(namespace,ns),allocator,W.Handle{ns,key})
19def result(~S:Data,operation:O.Operation<S>,checked:T.CoreResult<S>) -> O.Outcome<S>:
20  match checked:
21    case T.CoreResult{graph,None{}}:O.Applied{graph,operation}
22    case T.CoreResult{graph,Some{error}}:O.Refused{graph,operation,O.RelationError{error}}
23def relate_target(~S:Data,graph:T.Graph<S>,descriptor:T.Descriptor<S>,+source:W.Handle<S>,+target:W.Handle<S>,sourceLive:Bool,checked:A.Allocator & Bool) -> A.Allocator & O.Outcome<S>:
24  match checked:
25    case (allocator,targetLive):(allocator,result(~S,O.Relate{source,target},Graph.relate(~S,graph,descriptor,W.handle_key(~S,source),W.handle_key(~S,target),sourceLive,targetLive)))
26def relate_source(~S:Data,+namespace:U32,graph:T.Graph<S>,descriptor:T.Descriptor<S>,source:W.Handle<S>,+target:W.Handle<S>,checked:A.Allocator & Bool) -> A.Allocator & O.Outcome<S>:
27  match checked:
28    case (allocator,sourceLive):relate_target(~S,graph,descriptor,source,target,sourceLive,live(~S,namespace,allocator,target))
29def unrelate_checked(~S:Data,graph:T.Graph<S>,descriptor:T.Descriptor<S>,+source:W.Handle<S>,checked:A.Allocator & Bool) -> A.Allocator & O.Outcome<S>:
30  match checked:
31    case (allocator,False{}):(allocator,O.Refused{graph,O.Unrelate{source},O.RelationError{T.MissingEntity{W.handle_key(~S,source)}}})
32    case (allocator,True{}):(allocator,O.Applied{Graph.unrelate(~S,graph,descriptor,W.handle_key(~S,source)),O.Unrelate{source}})
33def child_next(key:K.Key,reversed:List<&2,T.ChildStatus>,next:A.Allocator -> List<&2,T.ChildStatus> -> A.Allocator & List<&2,T.ChildStatus>,checked:A.Allocator & Bool) -> A.Allocator & List<&2,T.ChildStatus>:
34  match checked:
35    case (allocator,isLive):next(allocator,T.ChildStatus{key,isLive} <> reversed)
36def children_checked(~S:Data,+namespace:U32,children:List<&2,W.Handle<S>>,allocator:A.Allocator,reversed:List<&2,T.ChildStatus>) -> A.Allocator & List<&2,T.ChildStatus>:
37  match children:
38    case []:(allocator,List.reverse(&2,T.ChildStatus,reversed))
39    case +child <> rest:child_next(W.handle_key(~S,child),reversed,allocator => reversed => children_checked(~S,namespace,rest,allocator,reversed),live(~S,namespace,allocator,child))
40def reorder_children(~S:Data,graph:T.Graph<S>,descriptor:T.Descriptor<S>,+parent:W.Handle<S>,+children:List<&2,W.Handle<S>>,parentLive:Bool,checked:A.Allocator & List<&2,T.ChildStatus>) -> A.Allocator & O.Outcome<S>:
41  match checked:
42    case (allocator,statuses):(allocator,result(~S,O.Reorder{parent,children},Reorder.reorder(~S,graph,descriptor,W.handle_key(~S,parent),statuses,parentLive)))
43def reorder_parent(~S:Data,namespace:U32,graph:T.Graph<S>,descriptor:T.Descriptor<S>,parent:W.Handle<S>,+children:List<&2,W.Handle<S>>,checked:A.Allocator & Bool) -> A.Allocator & O.Outcome<S>:
44  match checked:
45    case (allocator,parentLive):reorder_children(~S,graph,descriptor,parent,children,parentLive,children_checked(~S,namespace,children,allocator,[]))
46def reorder(~S:Data,+namespace:U32,allocator:A.Allocator,graph:T.Graph<S>,descriptor:T.Descriptor<S>,+parent:W.Handle<S>,children:List<&2,W.Handle<S>>) -> A.Allocator & O.Outcome<S>:
47  match descriptor:
48    case T.Descriptor{key,name,inverse,T.Ordinary{}}:(allocator,O.Refused{graph,O.Reorder{parent,children},O.HierarchyRequired{}})
49    case T.Descriptor{key,name,inverse,T.Hierarchy{}}:reorder_parent(~S,namespace,graph,T.Descriptor{key,name,inverse,T.Hierarchy{}},parent,children,live(~S,namespace,allocator,parent))
50# Bevy ad678262, relationship/mod.rs:28-36 makes the source relationship
51# authoritative and maintains its target collection. Existing Bend graph/reorder
52# algorithms implement that invariant; dispatch never accepts an inverse writer.
53def apply(~S:Data,~descriptor:T.Descriptor<S>,+namespace:U32,allocator:A.Allocator,graph:T.Graph<S>,operation:O.Operation<S>) -> A.Allocator & O.Outcome<S>:
54  match operation:
55    case O.Relate{+source,target}:relate_source(~S,namespace,graph,descriptor,source,target,live(~S,namespace,allocator,source))
56    case O.Unrelate{+source}:unrelate_checked(~S,graph,descriptor,source,live(~S,namespace,allocator,source))
57    case O.Reorder{parent,children}:reorder(~S,namespace,allocator,graph,descriptor,parent,children)