dependency_executor.bend

bendvy-ecs-core@0.1.0.3 · 58 lines · 10 definitions

1import Base
2import bendvy-ecs-core@0.1.0.3/dependency_plan.bend as Plan
3
4type Condition<Error:Data> is Data:
5  Allowed{}
6  Disabled{}
7  ConditionError{error:Error}
8  ConditionRefused{}
9type Invocation<Error:Data,Out:Data> is Data:
10  Completed{output:Out}
11  BodyError{error:Error,output:Out}
12  AdmissionRefused{}
13type Handling is Data:
14  Continue{}
15  Escalate{}
16type Observation<Error:Data,Out:Data> is Data:
17  Ran{id:U32,output:Out}
18  BodyFailed{id:U32,error:Error,output:Out}
19  Skipped{id:U32}
20  ConditionFailed{id:U32,error:Error}
21  ConditionRejected{id:U32}
22  AdmissionRejected{id:U32}
23type ExecutionResult<State:Type,Requirement:Data,Error:Data,Out:Data> is Type:
24  Finished{state:State,events:List<&2,Observation<Error,Out>>}
25  Stopped{state:State,error:Error,events:List<&2,Observation<Error,Out>>}
26  Invalid{state:State,reason:Plan.Invalid<Requirement>}
27
28def handled(~State:Type,~Requirement:Data,~Error:Data,~Out:Data,next:State -> List<&2,Observation<Error,Out>> -> ExecutionResult<State,Requirement,Error,Out>,returned:State & Handling,error:Error,events:List<&2,Observation<Error,Out>>) -> ExecutionResult<State,Requirement,Error,Out>:
29  match returned:
30    case (state,Continue{}):next(state,events)
31    case (state,Escalate{}):Stopped{state,error,events}
32
33def invoked(~State:Type,~Requirement:Data,~Error:Data,~Out:Data,~handler:State -> Error -> State & Handling,next:State -> List<&2,Observation<Error,Out>> -> ExecutionResult<State,Requirement,Error,Out>,returned:State & Invocation<Error,Out>,+id:U32,events:List<&2,Observation<Error,Out>>) -> ExecutionResult<State,Requirement,Error,Out>:
34  match returned:
35    case (state,Completed{output}):next(state,List.append(&2,Observation<Error,Out>,events,[Ran{id,output}]))
36    case (state,BodyError{+error,output}):handled(~State,~Requirement,~Error,~Out,next,handler(state,error),error,List.append(&2,Observation<Error,Out>,events,[BodyFailed{id,error,output}]))
37    case (state,AdmissionRefused{}):next(state,List.append(&2,Observation<Error,Out>,events,[AdmissionRejected{id}]))
38
39def conditioned(~State:Type,~Requirement:Data,~Error:Data,~Out:Data,~dispatch:State -> U32 -> State & Invocation<Error,Out>,~handler:State -> Error -> State & Handling,next:State -> List<&2,Observation<Error,Out>> -> ExecutionResult<State,Requirement,Error,Out>,returned:State & Condition<Error>,+id:U32,events:List<&2,Observation<Error,Out>>) -> ExecutionResult<State,Requirement,Error,Out>:
40  match returned:
41    case (state,Allowed{}):invoked(~State,~Requirement,~Error,~Out,~handler,next,dispatch(state,id),id,events)
42    case (state,Disabled{}):next(state,List.append(&2,Observation<Error,Out>,events,[Skipped{id}]))
43    case (state,ConditionError{+error}):handled(~State,~Requirement,~Error,~Out,next,handler(state,error),error,List.append(&2,Observation<Error,Out>,events,[ConditionFailed{id,error}]))
44    case (state,ConditionRefused{}):next(state,List.append(&2,Observation<Error,Out>,events,[ConditionRejected{id}]))
45
46def execute(~State:Type,~Requirement:Data,~Error:Data,~Out:Data,~condition:State -> U32 -> State & Condition<Error>,~dispatch:State -> U32 -> State & Invocation<Error,Out>,~handler:State -> Error -> State & Handling,order:List<&2,Plan.Node<Requirement>>,state:State,events:List<&2,Observation<Error,Out>>) -> ExecutionResult<State,Requirement,Error,Out>:
47  match order:
48    case []:Finished{state,events}
49    case Plan.Node{+id,_} <> rest:conditioned(~State,~Requirement,~Error,~Out,~dispatch,~handler,state => events => execute(~State,~Requirement,~Error,~Out,~condition,~dispatch,~handler,rest,state,events),condition(state,id),id,events)
50
51# State contains the actual World, registration, argument, condition and handler
52# owners. Closed providers move that state and never duplicate runtime callbacks.
53# The ordered interpreter chooses one valid order; parallel execution may choose
54# any order permitted by dependencies and access conflicts.
55def run(~State:Type,~Requirement:Data,~Error:Data,~Out:Data,~condition:State -> U32 -> State & Condition<Error>,~dispatch:State -> U32 -> State & Invocation<Error,Out>,~handler:State -> Error -> State & Handling,plan:Plan.Build<Requirement>,state:State) -> ExecutionResult<State,Requirement,Error,Out>:
56  match plan:
57    case Plan.Rejected{reason}:Invalid{state,reason}
58    case Plan.Planned{order,_}:execute(~State,~Requirement,~Error,~Out,~condition,~dispatch,~handler,order,state,[])