public static ReadOnlyCollection <ControlFlowEdge> AlienEdges(this BaseControlFlowGraph cfg, IEnumerable <ControlFlowBlock> vertices) { var allEdges = cfg.Edges(vertices, null).Concat(cfg.Edges(null, vertices)); var innerEdges = cfg.Edges(vertices, vertices); return(allEdges.Except(innerEdges).ToReadOnly()); }
protected BaseControlFlowGraph(BaseControlFlowGraph proto, bool deep) : this() { proto.Vertices.ForEach(v => AddVertex(v)); proto.Edges().ForEach(e => AddEdge(deep ? e.ShallowClone() : e)); }
private void InitializeCore( BaseControlFlowGraph source, Func <ControlFlowBlock, bool> vertexFilter, Func <ControlFlowEdge, bool> edgeFilter, Action <ControlFlowEdge, ViewOfControlFlowGraph> onAlienEdge) { Source = source.AssertNotNull(); HookUpVertexPostprocessors(); _vertexFilter = vertexFilter.AssertNotNull(); _edgeFilter = edgeFilter.AssertNotNull(); _cachedVertices = _hardcodedVertices != null ? null : source.Vertices.Where(_vertexFilter).ToList(); (_cachedVertices ?? _hardcodedVertices.AsEnumerable()).ForEach(OnVertexAdded); ReadOnlyCollection <ControlFlowEdge> alienEdges = null; if (_hardcodedEdges != null) { var edgeVertices = _hardcodedEdges.SelectMany(e => new [] { e.Source, e.Target }).ToHashSet(); edgeVertices.ExceptWith(_cachedVertices ?? _hardcodedVertices.AsEnumerable()); edgeVertices.AssertEmpty(); } else { _edgeFilter = e => edgeFilter(e) && _vertexFilter(e.Source) && _vertexFilter(e.Target); var relatedEdges = source.Edges(_vertexFilter, null).Concat(source.Edges(null, _vertexFilter)).Distinct(); var parts = relatedEdges.GroupBy(e => _edgeFilter(e)).ToDictionary(g => g.Key, g => g.AsEnumerable()); _cachedEdges = (parts.GetOrDefault(true, Seq.Empty <ControlFlowEdge>)).ToList(); alienEdges = parts.GetOrDefault(false, Seq.Empty <ControlFlowEdge>).ToReadOnly(); } (_cachedEdges ?? _hardcodedEdges.AsEnumerable()).ForEach(OnEdgeAdded); Action <ControlFlowBlock> cacheVertex = v => { if (_cachedVertices != null) { _cachedVertices.Add(v); } else { throw AssertionHelper.Fail(); } }; Action <ControlFlowBlock> uncacheVertex = v => { if (_cachedVertices != null) { _cachedVertices.Remove(v); } else { _hardcodedVertices.Remove(v); } }; source.VertexAdded += v => { if (_vertexFilter(v)) { cacheVertex(v); OnVertexAdded(v); } }; source.VertexRemoved += v => { if (_vertexFilter(v)) { uncacheVertex(v); OnVertexRemoved(v); } }; Action <ControlFlowEdge> cacheEdge = e => { if (_cachedEdges != null) { _cachedEdges.Add(e); } else { throw AssertionHelper.Fail(); } }; Action <ControlFlowEdge> uncacheEdge = e => { if (_cachedEdges != null) { _cachedEdges.Remove(e); } else { _hardcodedEdges.Remove(e); } }; source.EdgeAdded += e => { if (_edgeFilter(e)) { cacheEdge(e); OnEdgeAdded(e); } }; source.EdgeRemoved += e => { if (_edgeFilter(e)) { uncacheEdge(e); OnEdgeRemoved(e); } }; __vertices = new VirtualList <ControlFlowBlock>( () => (_hardcodedVertices ?? (IEnumerable <ControlFlowBlock>)_cachedVertices).Concat(_eigenVertices), (i, v) => { if (_eigenVertices.Contains(v)) { // do nothing - the vertex has just been created by AddEigenVertex } else { _vertexFilter(v).AssertTrue(); (_cachedVertices != null && i == _cachedVertices.Count()).AssertTrue(); Source.AddVertex(v); } }, (i, v) => { _vertexFilter(v).AssertTrue(); throw AssertionHelper.Fail(); }, i => { if (i < _cachedEdges.Count()) { var v = _cachedVertices[i]; Source.RemoveVertex(v); } else { throw AssertionHelper.Fail(); } }); __edges = new VirtualList <ControlFlowEdge>( () => (_hardcodedEdges ?? (IEnumerable <ControlFlowEdge>)_cachedEdges).Concat(_eigenEdges), (i, e) => { if (_eigenEdges.Contains(e)) { // do nothing - the edge has just been created by AddEigenEdge } else { _edgeFilter(e).AssertTrue(); (_cachedEdges != null && i == _cachedEdges.Count()).AssertTrue(); Source.AddEdge(e); } }, (i, e) => { _edgeFilter(e).AssertTrue(); throw AssertionHelper.Fail(); }, i => { if (i < _cachedEdges.Count()) { var e = _cachedEdges[i]; Source.RemoveEdge(e); } else { var e = _eigenEdges[i - _cachedEdges.Count()]; _eigenEdges.Remove(e); } }); try { _allowAutoCreateStartAndFinish = true; alienEdges.ForEach(e => onAlienEdge(e, this)); } finally { _allowAutoCreateStartAndFinish = false; } }