dependency_composer_program.bend

bendvy-ecs-core@0.1.0.3 · 77 lines · 22 definitions

1import Base
2import bendvy-ecs-core@0.1.0.3/dependency_registration.bend as Reg
3import bendvy-ecs-core@0.1.0.3/dependency_registry_program.bend as Prog
4import bendvy-ecs-core@0.1.0.3/dependency_plan.bend as Plan
5import bendvy-ecs-core@0.1.0.3/dependency_executor.bend as Exec
6
7type Scope is Data:
8  Scope{members:List<&2,U32>,children:List<&2,Scope>}
9type Compiled<-World:Type,-Owners:Type,-Error:Data,-Out:Data,-dispatch:Owners -> World -> U32 -> Owners & (World & Exec.Invocation<Error,Out>)> is Type:
10  Compiled{registry:Reg.Registry<World,Owners,Error,Out,dispatch>,scope:Scope}
11def Scoped(~Error:Data,~Out:Data,~World:Type,~Owners:Type,~dispatch:Prog.Dispatch(~World,~Owners,~Error,~Out)) -> Type:
12  Compiled<World,Owners,Error,Out,dispatch>
13def ids(nodes:List<&2,Plan.Node<String>>) -> List<&2,U32>:
14  match nodes:
15    case []:[]
16    case Plan.Node{id,_} <> rest:id <> ids(rest)
17def lifted(~World:Type,~Owners:Type,~Error:Data,~Out:Data,~dispatch:Prog.Dispatch(~World,~Owners,~Error,~Out),registry:Reg.Registry<World,Owners,Error,Out,dispatch>) -> Compiled<World,Owners,Error,Out,dispatch>:
18  match registry:
19    case Reg.Registry{owners,+nodes}:Compiled{Reg.Registry{owners,nodes},Scope{ids(nodes),[]}}
20def compile_embed(~Error:Data,~Out:Data,~World:Type,~Owners:Type,~dispatch:Prog.Dispatch(~World,~Owners,~Error,~Out),registry:Reg.Registry<World,Owners,Error,Out,dispatch>) -> Compiled<World,Owners,Error,Out,dispatch>:
21  lifted(~World,~Owners,~Error,~Out,~dispatch,registry)
22def joined(~Error:Data,~Out:Data,~World:Type,~L:Type,~R:Type,~left:Prog.Dispatch(~World,~L,~Error,~Out),~right:Prog.Dispatch(~World,~R,~Error,~Out),leftScope:Scope,rightScope:Scope,registry:Reg.Registry<World,Reg.Product<L,R>,Error,Out,Reg.paired_dispatch(~World,~L,~R,~Error,~Out,~left,~right)>) -> Compiled<World,Reg.Product<L,R>,Error,Out,Reg.paired_dispatch(~World,~L,~R,~Error,~Out,~left,~right)>:
23  match registry:
24    case Reg.Registry{owners,+nodes}:Compiled{Reg.Registry{owners,nodes},Scope{ids(nodes),[leftScope,rightScope]}}
25def compile_join(~Error:Data,~Out:Data,~World:Type,~L:Type,~R:Type,~left:Prog.Dispatch(~World,~L,~Error,~Out),~right:Prog.Dispatch(~World,~R,~Error,~Out),l:Compiled<World,L,Error,Out,left>,r:Compiled<World,R,Error,Out,right>) -> Compiled<World,Reg.Product<L,R>,Error,Out,Reg.paired_dispatch(~World,~L,~R,~Error,~Out,~left,~right)>:
26  match l r:
27    case Compiled{lr,+ls} Compiled{rr,+rs}:joined(~Error,~Out,~World,~L,~R,~left,~right,ls,rs,Reg.paired(~World,~L,~R,~Error,~Out,~left,~right,lr,rr))
28def compile_empty(~Error:Data,~Out:Data,~World:Type) -> Compiled<World,Unit,Error,Out,Reg.empty_dispatch(~World,~Error,~Out)>:
29  lifted(~World,~Unit,~Error,~Out,~Reg.empty_dispatch(~World,~Error,~Out),Reg.empty(~World,~Error,~Out))
30def compile(~World:Type,~Owners:Type,~Error:Data,~Out:Data,~dispatch:Prog.Dispatch(~World,~Owners,~Error,~Out),~selection:Prog.Selection(~World,~Owners,~Error,~Out,~dispatch),owners:Owners) -> Compiled<World,Owners,Error,Out,dispatch>:
31  selection(Scoped(~Error,~Out),compile_embed(~Error,~Out),compile_join(~Error,~Out),compile_empty(~Error,~Out),owners)
32
33
34
35type Nested is Data:
36  Nested{path:List<&2,U32>,edges:List<&2,Plan.Edge>}
37type NestError is Data:
38  UnknownScope{path:List<&2,U32>}
39  InvalidEdges{path:List<&2,U32>,reason:Plan.Invalid<String>}
40type Nesting is Data:
41  Nesting{edges:List<&2,Plan.Edge>,invalid:Maybe<&2,NestError>}
42def child_selected(first:Bool,current:Scope,next:Maybe<&2,Scope>) -> Maybe<&2,Scope>:
43  match first:
44    case True{}:Some{current}
45    case False{}:next
46def child(children:List<&2,Scope>,+index:U32) -> Maybe<&2,Scope>:
47  match children:
48    case []:None{}
49    case scope <> rest:child_selected(U32.is_eq(index,0),scope,child(rest,U32.sub(index,1)))
50def scoped(path:List<&2,U32>,scope:Maybe<&2,Scope>) -> Maybe<&2,Scope>:
51  match path scope:
52    case [] scope:scope
53    case _ None{}:None{}
54    case index <> rest Some{Scope{_,children}}:scoped(rest,child(children,index))
55def members(values:List<&2,U32>) -> List<&2,Plan.Node<String>>:
56  match values:
57    case []:[]
58    case id <> rest:Plan.Node{id,[]} <> members(rest)
59def checked_endpoints(path:List<&2,U32>,value:Maybe<&2,Plan.Invalid<String>>) -> Maybe<&2,NestError>:
60  match value:
61    case None{}:None{}
62    case Some{reason}:Some{InvalidEdges{path,reason}}
63def checked_scope(+path:List<&2,U32>,edges:List<&2,Plan.Edge>,scope:Maybe<&2,Scope>) -> Maybe<&2,NestError>:
64  match scope:
65    case None{}:Some{UnknownScope{path}}
66    case Some{Scope{ids,_}}:checked_endpoints(path,Plan.endpoints(~String,edges,members(ids)))
67def first_nesting(first:Maybe<&2,NestError>,next:Maybe<&2,NestError>) -> Maybe<&2,NestError>:
68  match first:
69    case None{}:next
70    case Some{reason}:Some{reason}
71def nested_next(edges:List<&2,Plan.Edge>,invalid:Maybe<&2,NestError>,next:Nesting) -> Nesting:
72  match next:
73    case Nesting{later,error}:Nesting{List.append(&2,Plan.Edge,edges,later),first_nesting(invalid,error)}
74def nested(items:List<&2,Nested>,+scope:Scope) -> Nesting:
75  match items:
76    case []:Nesting{[],None{}}
77    case Nested{+path,+edges} <> rest:nested_next(edges,checked_scope(path,edges,scoped(path,Some{scope})),nested(rest,scope))