private Graph MergeBind(Bind rightBind, BindState rightState) { //HORRORS BELOW var x = this; var leftBinds = rightState.Nodes .Select(n => x.NodeBinds.TryGetValue(n, out var found) ? found : null) .Where(n => n != null) .ToArray(); var leftStates = leftBinds .SelectMany(b => x.BindStates.TryGetValue(b, out var found) ? new[] { found } : new BindState[0]) .ToArray(); var allStates = leftStates.Concat(new[] { rightState }); var allNodes = allStates.SelectMany(s => s.Nodes); var bind = leftBinds.Concat(new[] { rightBind }).First(); var state = allStates.Aggregate(BindState.Empty, (ac, s) => ac.MergeWith(s)); return(new Graph( allNodes .Aggregate(NodeBinds, (ac, n) => ac.SetItem(n, bind)), BindStates .SetItem(bind, state) ) .Propagate(bind, state)); }
private Graph Propagate(Bind b, BindState s, Node n0 = null) { if (s.Nodes.IsEmpty) { return(this); } else { var g = this; var v0 = s.Val; _depth++; Log.WriteLine($"{Prefix}PROP {s}"); _depth++; Log.Write($"{Prefix}{v0}"); var nodes = s.Nodes.ToArray(); int i = 0, j = 0; var v = v0; while (true) { var n = nodes[i]; if (n != n0 || !v.Equals(v0)) { Log.WriteLine($" -> {n}"); var(g2, v2) = n.Impel(g, v); var v3 = Val.Combine(v, v2); Log.Write($"{Prefix}{v3}"); if (!v3.Equals(v)) { j = i; } g = g2; v = v3; } i = (i + 1) % nodes.Length; if (i == j) { break; } } Log.WriteLine(); _depth -= 2; return(new Graph( g.NodeBinds, g.BindStates.SetItem(b, s.WithVal(v)) )); } }
public BindState MergeWith(BindState other) => new BindState( Nodes.Union(other.Nodes), Val.Combine(Val, other.Val));