execution_deferred_plan.bend
bendvy-ecs-core@0.1.0.3 · 115 lines · 32 definitions
1import Base
2
3
4
5type Node is Data:
6 Node{id:U32,hasDeferred:Bool,explicit:Bool,conditional:Bool,exclusive:Bool}
7type Edge is Data:
8 Edge{before:U32,after:U32,ignoreDeferred:Bool}
9type Position is Data:
10 Position{id:U32,distance:Nat,pending:Bool}
11type Explicit is Data:
12 Explicit{distance:Nat,id:U32}
13type State is Data:
14 State{positions:List<&2,Position>,explicit:List<&2,Explicit>}
15type Boundary is Data:
16 Boundary{before:U32,after:U32,distance:Nat,reuse:Maybe<&2,U32>}
17
18def node_id(node:Node) -> U32:
19 match node:
20 case Node{id,_,_,_,_}:id
21def explicit(node:Node) -> Bool:
22 match node:
23 case Node{_,_,isExplicit,conditional,_}:Bool.and(isExplicit,Bool.not(conditional))
24def exclusive(node:Node) -> Bool:
25 match node:
26 case Node{_,_,_,_,isExclusive}:isExclusive
27def deferred(node:Node) -> Bool:
28 match node:
29 case Node{_,hasDeferred,_,_,_}:hasDeferred
30def find_choice(same:Bool,node:Node,rest:Node) -> Node:
31 match same:
32 case True{}:node
33 case False{}:rest
34def find(nodes:List<&2,Node>,+id:U32) -> Node:
35 match nodes:
36 case []:Node{id,False{},False{},False{},False{}}
37 case +node <> rest:find_choice(U32.is_eq(node_id(node),id),node,find(rest,id))
38def position_choice(same:Bool,value:Position,rest:Position) -> Position:
39 match same:
40 case True{}:value
41 case False{}:rest
42def position(positions:List<&2,Position>,+id:U32) -> Position:
43 match positions:
44 case []:Position{id,0n,False{}}
45 case Position{+other,distance,pending} <> rest:position_choice(U32.is_eq(other,id),Position{other,distance,pending},position(rest,id))
46def keep_position(same:Bool,value:Position,rest:List<&2,Position>) -> List<&2,Position>:
47 match same:
48 case True{}:rest
49 case False{}:value <> rest
50def without(positions:List<&2,Position>,+id:U32) -> List<&2,Position>:
51 match positions:
52 case []:[]
53 case Position{+other,distance,pending} <> rest:keep_position(U32.is_eq(other,id),Position{other,distance,pending},without(rest,id))
54def update(positions:List<&2,Position>,value:Position) -> List<&2,Position>:
55 match value:
56 case Position{+id,distance,pending}:Position{id,distance,pending} <> without(positions,id)
57def weight(needsSync:Bool,target:Node) -> Nat:
58 match needsSync:
59 case True{}:1n
60 case False{}:Bool.pick(Nat,explicit(target),1n,0n)
61def target_updated(positions:List<&2,Position>,+distance:Nat,+needsSync:Bool,+ignored:Bool,target:Node,current:Position) -> List<&2,Position>:
62 match current:
63 case Position{id,oldDistance,pending}:update(positions,Position{id,Nat.max(oldDistance,Nat.add(distance,weight(Bool.and(needsSync,Bool.not(ignored)),target))),Bool.or(pending,Bool.and(needsSync,ignored))})
64def outgoing_edge(positions:List<&2,Position>,distance:Nat,needsSync:Bool,ignoreDeferred:Bool,+target:Node,current:Position) -> List<&2,Position>:
65 target_updated(positions,distance,needsSync,Bool.and(ignoreDeferred,Bool.not(exclusive(target))),target,current)
66def selected_edge(positions:List<&2,Position>,distance:Nat,needsSync:Bool,ignoreDeferred:Bool,target:Node,current:Position,matches:Bool) -> List<&2,Position>:
67 match matches:
68 case False{}:positions
69 case True{}:outgoing_edge(positions,distance,needsSync,ignoreDeferred,target,current)
70def outgoing(edges:List<&2,Edge>,+nodes:List<&2,Node>,+id:U32,+distance:Nat,+needsSync:Bool,+positions:List<&2,Position>) -> List<&2,Position>:
71 match edges:
72 case []:positions
73 case Edge{before,+after,ignoreDeferred} <> rest:outgoing(rest,nodes,id,distance,needsSync,selected_edge(positions,distance,needsSync,ignoreDeferred,find(nodes,after),position(positions,after),U32.is_eq(before,id)))
74def syncs(isExplicit:Bool,id:U32,distance:Nat,explicitNodes:List<&2,Explicit>) -> List<&2,Explicit>:
75 match isExplicit:
76 case True{}:Explicit{distance,id} <> explicitNodes
77 case False{}:explicitNodes
78def visit_position(+node:Node,edges:List<&2,Edge>,nodes:List<&2,Node>,positions:List<&2,Position>,explicitNodes:List<&2,Explicit>,current:Position) -> State:
79 match current:
80 case Position{+id,+distance,pending}:State{outgoing(edges,nodes,id,distance,Bool.and(Bool.not(explicit(node)),Bool.or(pending,deferred(node))),positions),syncs(explicit(node),id,distance,explicitNodes)}
81def visit(+node:Node,edges:List<&2,Edge>,nodes:List<&2,Node>,state:State) -> State:
82 match state:
83 case State{+positions,explicitNodes}:visit_position(node,edges,nodes,positions,explicitNodes,position(positions,node_id(node)))
84def distances(order:List<&2,Node>,+nodes:List<&2,Node>,+edges:List<&2,Edge>,state:State) -> State:
85 match order:
86 case []:state
87 case node <> rest:distances(rest,nodes,edges,visit(node,edges,nodes,state))
88def explicit_choice(same:Bool,id:U32,rest:Maybe<&2,U32>) -> Maybe<&2,U32>:
89 match same:
90 case True{}:Some{id}
91 case False{}:rest
92def reuse(explicitNodes:List<&2,Explicit>,+distance:Nat) -> Maybe<&2,U32>:
93 match explicitNodes:
94 case []:None{}
95 case Explicit{other,id} <> rest:explicit_choice(Nat.is_eq(other,distance),id,reuse(rest,distance))
96def boundary_step(before:U32,after:U32,from:Position,to:Position,target:Node,explicitNodes:List<&2,Explicit>,+rest:List<&2,Boundary>) -> List<&2,Boundary>:
97 match from to target:
98 case Position{_,distance,_} Position{_,+next,_} Node{_,_,isExplicit,_,_}:Bool.pick(List<&2,Boundary>,Bool.or(Nat.is_eq(distance,next),isExplicit),rest,Boundary{before,after,next,reuse(explicitNodes,next)} <> rest)
99def boundaries(edges:List<&2,Edge>,+nodes:List<&2,Node>,+positions:List<&2,Position>,+explicitNodes:List<&2,Explicit>) -> List<&2,Boundary>:
100 match edges:
101 case []:[]
102 case Edge{+before,+after,_} <> rest:boundary_step(before,after,position(positions,before),position(positions,after),find(nodes,after),explicitNodes,boundaries(rest,nodes,positions,explicitNodes))
103def planned(nodes:List<&2,Node>,edges:List<&2,Edge>,state:State) -> List<&2,Boundary>:
104 match state:
105 case State{positions,explicitNodes}:boundaries(edges,nodes,positions,explicitNodes)
106
107
108
109
110
111
112def plan(enabled:Bool,+order:List<&2,Node>,+edges:List<&2,Edge>) -> List<&2,Boundary>:
113 match enabled:
114 case False{}:[]
115 case True{}:planned(order,edges,distances(order,order,edges,State{[],[]}))