restore_graph_validation.bend
bendvy-ecs-core@0.1.0.0 · 60 lines · 0 definitions
1import Base
2import bendvy-ecs-core@0.1.0.0/restore_graph_data.bend as R
3import bendvy-ecs-core@0.1.0.0/entity_key.bend as Key
4import bendvy-ecs-core@0.1.0.0/snapshot_data.bend as Basic
5import bendvy-ecs-core@0.1.0.0/relation_types.bend as G
6import bendvy-ecs-core@0.1.0.0/relation_graph.bend as Graph
7import bendvy-ecs-core@0.1.0.0/relation_failure_reader.bend as Ordinary
8
9def contains(+key:Key.Key,entities:List<&2,Basic.Entity>) -> Bool:
10 match entities:
11 case []:False{}
12 case Basic.Entity{other,_} <> rest:Bool.or(Key.equal(key,other),contains(key,rest))
13def descriptor_found(~S:Data,found:Bool,descriptor:G.Descriptor<S>,next:Unit -> Maybe<&2,G.Descriptor<S>>) -> Maybe<&2,G.Descriptor<S>>:
14 match found:
15 case True{}:Some{descriptor}
16 case False{}:next(Unit{})
17def descriptor(~S:Data,+name:String,declarations:List<&2,Ordinary.Declaration<S>>) -> Maybe<&2,G.Descriptor<S>>:
18 match declarations:
19 case []:None{}
20 case Ordinary.Declaration{+value} <> rest:descriptor_found(~S,String.eq(name,Graph.name(~S,value)),value,_ => descriptor(~S,name,rest))
21def absent(~S:Data,value:Maybe<&2,Key.Key>) -> Bool:
22 match value:
23 case None{}:True{}
24 case Some{_}:False{}
25def added(~S:Data,graph:G.Graph<S>,descriptor:G.Descriptor<S>,source:Key.Key,target:Key.Key) -> G.Graph<S>:
26 match graph:
27 case G.Graph{edges,inverses}:Graph.updated(~S,False{},edges,inverses,descriptor,source,target)
28def source_checked(~S:Data,valid:Bool,graph:G.Graph<S>,descriptor:G.Descriptor<S>,source:Key.Key,target:Key.Key,next:G.Graph<S> -> R.GraphResult<S>) -> R.GraphResult<S>:
29 match valid:
30 case False{}:R.Rejected{R.InvalidRelation{Graph.name(~S,descriptor),source,target}}
31 case True{}:next(added(~S,graph,descriptor,source,target))
32def sources(~S:Data,values:List<&2,Key.Key>,+target:Key.Key,+descriptor:G.Descriptor<S>,+entities:List<&2,Basic.Entity>,+graph:G.Graph<S>,next:G.Graph<S> -> R.GraphResult<S>) -> R.GraphResult<S>:
33 match values:
34 case []:next(graph)
35 case +source <> rest:source_checked(~S,Bool.and(contains(source,entities),Bool.and(contains(target,entities),Bool.and(Bool.not(Key.equal(source,target)),absent(~S,Graph.target(~S,graph,descriptor,source))))),graph,descriptor,source,target,graph => sources(~S,rest,target,descriptor,entities,graph,next))
36def groups(~S:Data,values:List<&2,R.Group>,+descriptor:G.Descriptor<S>,+entities:List<&2,Basic.Entity>,graph:G.Graph<S>,next:G.Graph<S> -> R.GraphResult<S>) -> R.GraphResult<S>:
37 match values:
38 case []:next(graph)
39 case R.Group{target,members} <> rest:sources(~S,members,target,descriptor,entities,graph,graph => groups(~S,rest,descriptor,entities,graph,next))
40def cycle_checked(~S:Data,cyclic:Bool,descriptor:G.Descriptor<S>,source:Key.Key,target:Key.Key,next:Unit -> R.GraphResult<S>) -> R.GraphResult<S>:
41 match cyclic:
42 case True{}:R.Rejected{R.InvalidRelation{Graph.name(~S,descriptor),source,target}}
43 case False{}:next(Unit{})
44def cycles(~S:Data,edges:List<&2,G.Edge<S>>,+graph:G.Graph<S>,next:Unit -> R.GraphResult<S>) -> R.GraphResult<S>:
45 match edges:
46 case []:next(Unit{})
47 case G.Edge{+descriptor,+source,+target} <> rest:cycle_checked(~S,Graph.cycle(~S,graph,descriptor,source,target),descriptor,source,target,_ => cycles(~S,rest,graph,next))
48def acyclic(~S:Data,+graph:G.Graph<S>,next:G.Graph<S> -> R.GraphResult<S>) -> R.GraphResult<S>:
49 match graph:
50 case G.Graph{+edges,+inverses}:cycles(~S,edges,G.Graph{edges,inverses},_ => next(G.Graph{edges,inverses}))
51def declared(~S:Data,name:String,values:List<&2,R.Group>,entities:List<&2,Basic.Entity>,graph:G.Graph<S>,next:G.Graph<S> -> R.GraphResult<S>,found:Maybe<&2,G.Descriptor<S>>) -> R.GraphResult<S>:
52 match found:
53 case None{}:R.Rejected{R.UnknownRelation{name}}
54 case Some{descriptor}:groups(~S,values,descriptor,entities,graph,graph => acyclic(~S,graph,next))
55def relations(~S:Data,values:List<&2,R.Relation>,+entities:List<&2,Basic.Entity>,+declarations:List<&2,Ordinary.Declaration<S>>,graph:G.Graph<S>) -> R.GraphResult<S>:
56 match values:
57 case []:R.Accepted{graph}
58 case R.Relation{+name,groups} <> rest:declared(~S,name,groups,entities,graph,graph => relations(~S,rest,entities,declarations,graph),descriptor(~S,name,declarations))
59def validate(~S:Data,values:List<&2,R.Relation>,entities:List<&2,Basic.Entity>,declarations:List<&2,Ordinary.Declaration<S>>) -> R.GraphResult<S>:
60 relations(~S,values,entities,declarations,G.Graph{[],[]})