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{[],[]})