1 import Base 2 import ./restore_graph_data.bend as R 3 import ./entity_key.bend as Key 4 import ./snapshot_data.bend as Basic 5 import ./relation_types.bend as G 6 import ./relation_graph.bend as Graph 7 import ./relation_failure_reader.bend as Ordinary 8 9 def 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)) 13 def descriptor_found(~S:Data,found:Bool,descriptor:G.Descriptor,next:Unit -> Maybe<&2,G.Descriptor>) -> Maybe<&2,G.Descriptor>: 14 match found: 15 case True{}:Some{descriptor} 16 case False{}:next(Unit{}) 17 def descriptor(~S:Data,+name:String,declarations:List<&2,Ordinary.Declaration>) -> Maybe<&2,G.Descriptor>: 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)) 21 def absent(~S:Data,value:Maybe<&2,Key.Key>) -> Bool: 22 match value: 23 case None{}:True{} 24 case Some{_}:False{} 25 def added(~S:Data,graph:G.Graph,descriptor:G.Descriptor,source:Key.Key,target:Key.Key) -> G.Graph: 26 match graph: 27 case G.Graph{edges,inverses}:Graph.updated(~S,False{},edges,inverses,descriptor,source,target) 28 def source_checked(~S:Data,valid:Bool,graph:G.Graph,descriptor:G.Descriptor,source:Key.Key,target:Key.Key,next:G.Graph -> R.GraphResult) -> R.GraphResult: 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)) 32 def sources(~S:Data,values:List<&2,Key.Key>,+target:Key.Key,+descriptor:G.Descriptor,+entities:List<&2,Basic.Entity>,+graph:G.Graph,next:G.Graph -> R.GraphResult) -> R.GraphResult: 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)) 36 def groups(~S:Data,values:List<&2,R.Group>,+descriptor:G.Descriptor,+entities:List<&2,Basic.Entity>,graph:G.Graph,next:G.Graph -> R.GraphResult) -> R.GraphResult: 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)) 40 def cycle_checked(~S:Data,cyclic:Bool,descriptor:G.Descriptor,source:Key.Key,target:Key.Key,next:Unit -> R.GraphResult) -> R.GraphResult: 41 match cyclic: 42 case True{}:R.Rejected{R.InvalidRelation{Graph.name(~S,descriptor),source,target}} 43 case False{}:next(Unit{}) 44 def cycles(~S:Data,edges:List<&2,G.Edge>,+graph:G.Graph,next:Unit -> R.GraphResult) -> R.GraphResult: 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)) 48 def acyclic(~S:Data,+graph:G.Graph,next:G.Graph -> R.GraphResult) -> R.GraphResult: 49 match graph: 50 case G.Graph{+edges,+inverses}:cycles(~S,edges,G.Graph{edges,inverses},_ => next(G.Graph{edges,inverses})) 51 def declared(~S:Data,name:String,values:List<&2,R.Group>,entities:List<&2,Basic.Entity>,graph:G.Graph,next:G.Graph -> R.GraphResult,found:Maybe<&2,G.Descriptor>) -> R.GraphResult: 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)) 55 def relations(~S:Data,values:List<&2,R.Relation>,+entities:List<&2,Basic.Entity>,+declarations:List<&2,Ordinary.Declaration>,graph:G.Graph) -> R.GraphResult: 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)) 59 def validate(~S:Data,values:List<&2,R.Relation>,entities:List<&2,Basic.Entity>,declarations:List<&2,Ordinary.Declaration>) -> R.GraphResult: 60 relations(~S,values,entities,declarations,G.Graph{[],[]})