execution_deferred_schedule.bend

bendvy-ecs-core@0.1.0.3 · 123 lines · 37 definitions

1import Base
2import bendvy-ecs-core@0.1.0.3/execution_deferred_settings.bend as Settings
3import bendvy-ecs-core@0.1.0.3/dependency_plan.bend as Plan
4import bendvy-ecs-core@0.1.0.3/dependency_executor.bend as Exec
5import bendvy-ecs-core@0.1.0.3/execution_publication_order.bend as Order
6
7type BoundaryKind is Data:
8  Sync{ids:List<&2,U32>}
9  Final{}
10type Boundary is Data:
11  ApplyEntered{kind:BoundaryKind,requested:List<&2,U32>}
12  ApplyReturned{kind:BoundaryKind,remaining:List<&2,U32>}
13type TraceState is Data:
14  Off{}
15  On{reverse:List<&2,Boundary>}
16type Metadata is Data:
17  Metadata{syncs:List<&2,U32>,publication:List<&2,U32>}
18type Context<-Actual:Type> is Type:
19  Context{state:Actual,unapplied:List<&2,U32>,metadata:Metadata,trace:TraceState}
20type Outcome<-Actual:Type,Error:Data,Out:Data> is Type:
21  Outcome{result:Exec.ExecutionResult<Actual,String,Error,Out>,unapplied:List<&2,U32>}
22type Observed<-Actual:Type,-Error:Data,-Out:Data> is Type:
23  Observed{outcome:Outcome<Actual,Error,Out>,boundaries:List<&2,Boundary>}
24def is_sync(metadata:Metadata,id:U32) -> Bool:
25  match metadata:
26    case Metadata{syncs,_}:Settings.member(id,syncs)
27def publication(metadata:Metadata) -> List<&2,U32>:
28  match metadata:
29    case Metadata{_,order}:order
30def sync_entered(state:TraceState,id:U32,unapplied:List<&2,U32>) -> TraceState:
31  match state:
32    case Off{}:Off{}
33    case On{reverse}:On{ApplyEntered{Sync{[id]},unapplied} <> reverse}
34def sync_returned(state:TraceState,id:U32,unapplied:List<&2,U32>) -> TraceState:
35  match state:
36    case Off{}:Off{}
37    case On{reverse}:On{ApplyReturned{Sync{[id]},unapplied} <> reverse}
38def final_entered(state:TraceState,unapplied:List<&2,U32>) -> TraceState:
39  match state:
40    case Off{}:Off{}
41    case On{reverse}:On{ApplyEntered{Final{},unapplied} <> reverse}
42def final_returned(state:TraceState,unapplied:List<&2,U32>) -> TraceState:
43  match state:
44    case Off{}:Off{}
45    case On{reverse}:On{ApplyReturned{Final{},unapplied} <> reverse}
46def boundaries(state:TraceState) -> List<&2,Boundary>:
47  match state:
48    case Off{}:[]
49    case On{reverse}:List.reverse(&2,Boundary,reverse)
50def include(+id:U32,+ids:List<&2,U32>) -> List<&2,U32>:
51  Bool.pick(List<&2,U32>,Settings.member(id,ids),ids,id <> ids)
52def admitted(~Error:Data,~Out:Data,+status:Exec.Invocation<Error,Out>,id:U32,ids:List<&2,U32>) -> List<&2,U32>:
53  match status:
54    case Exec.Completed{_}:include(id,ids)
55    case Exec.BodyError{_,_}:include(id,ids)
56    case Exec.AdmissionRefused{}:ids
57def condition_returned(~Actual:Type,~Error:Data,syncs:Metadata,unapplied:List<&2,U32>,trace:TraceState,result:Actual & Exec.Condition<Error>) -> Context<Actual> & Exec.Condition<Error>:
58  match result:
59    case (state,value):(Context{state,unapplied,syncs,trace},value)
60def condition_adapter(~Actual:Type,~Error:Data,~condition:Actual -> U32 -> Actual & Exec.Condition<Error>,context:Context<Actual>,id:U32) -> Context<Actual> & Exec.Condition<Error>:
61  match context:
62    case Context{state,unapplied,syncs,trace}:condition_returned(~Actual,~Error,syncs,unapplied,trace,condition(state,id))
63def dispatch_returned(~Actual:Type,~Error:Data,~Out:Data,syncs:Metadata,unapplied:List<&2,U32>,trace:TraceState,id:U32,result:Actual & Exec.Invocation<Error,Out>) -> Context<Actual> & Exec.Invocation<Error,Out>:
64  match result:
65    case (state,+status):(Context{state,admitted(~Error,~Out,status,id,unapplied),syncs,trace},status)
66def dispatch_id(~Actual:Type,~Error:Data,~Out:Data,~dispatch:Actual -> U32 -> Actual & Exec.Invocation<Error,Out>,context:Context<Actual>,+id:U32) -> Context<Actual> & Exec.Invocation<Error,Out>:
67  match context:
68    case Context{state,unapplied,syncs,trace}:dispatch_returned(~Actual,~Error,~Out,syncs,unapplied,trace,id,dispatch(state,id))
69def dispatch_adapter(~Actual:Type,~Error:Data,~Out:Data,~dispatch:Actual -> U32 -> Actual & Exec.Invocation<Error,Out>,context:Context<Actual>,id:U32) -> Context<Actual> & Exec.Invocation<Error,Out>:
70  dispatch_id(~Actual,~Error,~Out,~dispatch,context,id)
71def handled(~Actual:Type,syncs:Metadata,unapplied:List<&2,U32>,trace:TraceState,result:Actual & Exec.Handling) -> Context<Actual> & Exec.Handling:
72  match result:
73    case (state,handling):(Context{state,unapplied,syncs,trace},handling)
74def handler_adapter(~Actual:Type,~Error:Data,~handler:Actual -> Error -> Actual & Exec.Handling,context:Context<Actual>,error:Error) -> Context<Actual> & Exec.Handling:
75  match context:
76    case Context{state,unapplied,syncs,trace}:handled(~Actual,syncs,unapplied,trace,handler(state,error))
77def applied(~Actual:Type,syncs:Metadata,id:U32,trace:TraceState,result:Actual & List<&2,U32>) -> Context<Actual>:
78  match result:
79    case (state,+unapplied):Context{state,unapplied,syncs,sync_returned(trace,id,unapplied)}
80def synchronize(~Actual:Type,~apply:List<&2,U32> -> Actual -> Actual & List<&2,U32>,context:Context<Actual>,+id:U32) -> Context<Actual>:
81  match context:
82    case Context{state,+unapplied,+syncs,trace}:applied(~Actual,syncs,id,sync_entered(trace,id,unapplied),Order.apply(~Actual,~apply,publication(syncs),unapplied,state))
83
84def selected(~Actual:Type,~Error:Data,~Out:Data,~condition:Actual -> U32 -> Actual & Exec.Condition<Error>,~dispatch:Actual -> U32 -> Actual & Exec.Invocation<Error,Out>,~handler:Actual -> Error -> Actual & Exec.Handling,~apply:List<&2,U32> -> Actual -> Actual & List<&2,U32>,next:Context<Actual> -> List<&2,Exec.Observation<Error,Out>> -> Exec.ExecutionResult<Context<Actual>,String,Error,Out>,context:Context<Actual>,+id:U32,events:List<&2,Exec.Observation<Error,Out>>,isSync:Bool) -> Exec.ExecutionResult<Context<Actual>,String,Error,Out>:
85  match isSync:
86    case True{}:next(synchronize(~Actual,~apply,context,id),events)
87    case False{}:Exec.conditioned(~Context<Actual>,~String,~Error,~Out,~dispatch_adapter(~Actual,~Error,~Out,~dispatch),~handler_adapter(~Actual,~Error,~handler),next,condition_adapter(~Actual,~Error,~condition,context,id),id,events)
88def step(~Actual:Type,~Error:Data,~Out:Data,~condition:Actual -> U32 -> Actual & Exec.Condition<Error>,~dispatch:Actual -> U32 -> Actual & Exec.Invocation<Error,Out>,~handler:Actual -> Error -> Actual & Exec.Handling,~apply:List<&2,U32> -> Actual -> Actual & List<&2,U32>,next:Context<Actual> -> List<&2,Exec.Observation<Error,Out>> -> Exec.ExecutionResult<Context<Actual>,String,Error,Out>,context:Context<Actual>,+id:U32,events:List<&2,Exec.Observation<Error,Out>>) -> Exec.ExecutionResult<Context<Actual>,String,Error,Out>:
89  match context:
90    case Context{state,unapplied,+syncs,trace}:selected(~Actual,~Error,~Out,~condition,~dispatch,~handler,~apply,next,Context{state,unapplied,syncs,trace},id,events,is_sync(syncs,id))
91# Synthetic sync IDs apply buffers before the next condition and produce no body event.
92def execute(~Actual:Type,~Error:Data,~Out:Data,~condition:Actual -> U32 -> Actual & Exec.Condition<Error>,~dispatch:Actual -> U32 -> Actual & Exec.Invocation<Error,Out>,~handler:Actual -> Error -> Actual & Exec.Handling,~apply:List<&2,U32> -> Actual -> Actual & List<&2,U32>,order:List<&2,Plan.Node<String>>,context:Context<Actual>,events:List<&2,Exec.Observation<Error,Out>>) -> Exec.ExecutionResult<Context<Actual>,String,Error,Out>:
93  match order:
94    case []:Exec.Finished{context,events}
95    case Plan.Node{id,_} <> rest:step(~Actual,~Error,~Out,~condition,~dispatch,~handler,~apply,context => events => execute(~Actual,~Error,~Out,~condition,~dispatch,~handler,~apply,rest,context,events),context,id,events)
96def planned(~Actual:Type,~Error:Data,~Out:Data,~condition:Actual -> U32 -> Actual & Exec.Condition<Error>,~dispatch:Actual -> U32 -> Actual & Exec.Invocation<Error,Out>,~handler:Actual -> Error -> Actual & Exec.Handling,~apply:List<&2,U32> -> Actual -> Actual & List<&2,U32>,plan:Plan.Build<String>,context:Context<Actual>) -> Exec.ExecutionResult<Context<Actual>,String,Error,Out>:
97  match plan:
98    case Plan.Rejected{reason}:Exec.Invalid{context,reason}
99    case Plan.Planned{order,_}:execute(~Actual,~Error,~Out,~condition,~dispatch,~handler,~apply,order,context,[])
100def final_applied(~Actual:Type,~Error:Data,~Out:Data,trace:TraceState,events:List<&2,Exec.Observation<Error,Out>>,result:Actual & List<&2,U32>) -> Observed<Actual,Error,Out>:
101  match result:
102    case (state,+unapplied):Observed{Outcome{Exec.Finished{state,events},unapplied},boundaries(final_returned(trace,unapplied))}
103def finish(~Actual:Type,~Error:Data,~Out:Data,~apply:List<&2,U32> -> Actual -> Actual & List<&2,U32>,order:List<&2,U32>,finalApply:Bool,state:Actual,+unapplied:List<&2,U32>,trace:TraceState,events:List<&2,Exec.Observation<Error,Out>>) -> Observed<Actual,Error,Out>:
104  match finalApply:
105    case False{}:Observed{Outcome{Exec.Finished{state,events},unapplied},boundaries(trace)}
106    case True{}:final_applied(~Actual,~Error,~Out,final_entered(trace,unapplied),events,Order.apply(~Actual,~apply,order,unapplied,state))
107def finished(~Actual:Type,~Error:Data,~Out:Data,~apply:List<&2,U32> -> Actual -> Actual & List<&2,U32>,finalApply:Bool,result:Exec.ExecutionResult<Context<Actual>,String,Error,Out>) -> Observed<Actual,Error,Out>:
108  match result:
109    case Exec.Finished{Context{state,unapplied,syncs,trace},events}:finish(~Actual,~Error,~Out,~apply,publication(syncs),finalApply,state,unapplied,trace,events)
110    case Exec.Stopped{Context{state,unapplied,_,trace},error,events}:Observed{Outcome{Exec.Stopped{state,error,events},unapplied},boundaries(trace)}
111    case Exec.Invalid{Context{state,unapplied,_,trace},reason}:Observed{Outcome{Exec.Invalid{state,reason},unapplied},boundaries(trace)}
112def run_ordered(~Actual:Type,~Error:Data,~Out:Data,~condition:Actual -> U32 -> Actual & Exec.Condition<Error>,~dispatch:Actual -> U32 -> Actual & Exec.Invocation<Error,Out>,~handler:Actual -> Error -> Actual & Exec.Handling,~apply:List<&2,U32> -> Actual -> Actual & List<&2,U32>,trace:TraceState,settings:Settings.Settings,syncs:List<&2,U32>,order:List<&2,U32>,plan:Plan.Build<String>,state:Actual,unapplied:List<&2,U32>) -> Observed<Actual,Error,Out>:
113  match settings:
114    case Settings.Settings{_,finalApply,_,_}:finished(~Actual,~Error,~Out,~apply,finalApply,planned(~Actual,~Error,~Out,~condition,~dispatch,~handler,~apply,plan,Context{state,unapplied,Metadata{syncs,order},trace}))
115def run_mode(~Actual:Type,~Error:Data,~Out:Data,~condition:Actual -> U32 -> Actual & Exec.Condition<Error>,~dispatch:Actual -> U32 -> Actual & Exec.Invocation<Error,Out>,~handler:Actual -> Error -> Actual & Exec.Handling,~apply:List<&2,U32> -> Actual -> Actual & List<&2,U32>,trace:TraceState,settings:Settings.Settings,+syncs:List<&2,U32>,+plan:Plan.Build<String>,state:Actual,unapplied:List<&2,U32>) -> Observed<Actual,Error,Out>:
116  run_ordered(~Actual,~Error,~Out,~condition,~dispatch,~handler,~apply,trace,settings,syncs,Order.from_plan(plan,syncs),plan,state,unapplied)
117def run_observed(~Actual:Type,~Error:Data,~Out:Data,~condition:Actual -> U32 -> Actual & Exec.Condition<Error>,~dispatch:Actual -> U32 -> Actual & Exec.Invocation<Error,Out>,~handler:Actual -> Error -> Actual & Exec.Handling,~apply:List<&2,U32> -> Actual -> Actual & List<&2,U32>,settings:Settings.Settings,syncs:List<&2,U32>,plan:Plan.Build<String>,state:Actual,unapplied:List<&2,U32>) -> Observed<Actual,Error,Out>:
118  run_mode(~Actual,~Error,~Out,~condition,~dispatch,~handler,~apply,On{[]},settings,syncs,plan,state,unapplied)
119def unobserved(~Actual:Type,~Error:Data,~Out:Data,value:Observed<Actual,Error,Out>) -> Outcome<Actual,Error,Out>:
120  match value:
121    case Observed{outcome,_}:outcome
122def run(~Actual:Type,~Error:Data,~Out:Data,~condition:Actual -> U32 -> Actual & Exec.Condition<Error>,~dispatch:Actual -> U32 -> Actual & Exec.Invocation<Error,Out>,~handler:Actual -> Error -> Actual & Exec.Handling,~apply:List<&2,U32> -> Actual -> Actual & List<&2,U32>,settings:Settings.Settings,syncs:List<&2,U32>,plan:Plan.Build<String>,state:Actual,unapplied:List<&2,U32>) -> Outcome<Actual,Error,Out>:
123  unobserved(~Actual,~Error,~Out,run_mode(~Actual,~Error,~Out,~condition,~dispatch,~handler,~apply,Off{},settings,syncs,plan,state,unapplied))