private void SetSkippableGroups() { AsyncStateGroup rootInitialGroup = _diagramInitialGroups[_dfirRoot.BlockDiagram]; var groupTraversalStates = new Dictionary <AsyncStateGroup, GroupTraversalState>(); _groups.ForEach(g => groupTraversalStates[g] = GroupTraversalState.NotVisited); Queue <AsyncStateGroup> groupQueue = new Queue <AsyncStateGroup>(); groupQueue.Enqueue(rootInitialGroup); while (groupQueue.Any()) { AsyncStateGroup group = groupQueue.Dequeue(); if (groupTraversalStates[group] == GroupTraversalState.Skippable) { continue; } bool startsWithPanicOrContinue = group.StartsWithPanicOrContinue; bool hasSkippablePredecessor = group.Predecessors.Any(g => g.IsSkippable); bool isDiagramInitialGroup = group.BeginsAsDiagramInitialGroup; bool isSkippable = !isDiagramInitialGroup && (startsWithPanicOrContinue || hasSkippablePredecessor); group.IsSkippable = isSkippable; bool traverseSuccessors = isSkippable || groupTraversalStates[group] == GroupTraversalState.NotVisited; if (traverseSuccessors) { group.Continuation.Successors.ForEach(groupQueue.Enqueue); } groupTraversalStates[group] = isSkippable ? GroupTraversalState.Skippable : GroupTraversalState.VisitedAndNotSkippable; } }
private AsyncStateGroup CreateNewGroupFromNode(Node node, IEnumerable <AsyncStateGroup> nodePredecessors) { AsyncStateGroup group = CreateNewGroupWithPredecessors($"node{node.UniqueId}", node.ParentDiagram, nodePredecessors); AddNode(group, node); return(group); }
protected override void VisitNode(Node node) { HashSet <AsyncStateGroup> nodePredecessors = GetNodePredecessorGroups(node).ToHashSet(); if (node is AwaitNode) { CreateNewGroupFromNode(node, nodePredecessors); return; } if (node is PanicOrContinueNode) { AsyncStateGroup group = CreateNewGroupFromNode(node, nodePredecessors); group.StartsWithPanicOrContinue = true; #if FALSE AsyncStateGroup singlePredecessor; if (nodePredecessors.TryGetSingleElement(out singlePredecessor)) { group.FunctionId = singlePredecessor.FunctionId; } #endif return; } AsyncStateGroup nodeGroup = GetGroupJoinOfPredecessorGroups( $"node{node.UniqueId}", node.ParentDiagram, nodePredecessors); AddNode(nodeGroup, node); }
private void AddConditionalSuccessorGroups(AsyncStateGroup predecessor, HashSet <AsyncStateGroup> successors) { ((ConditionallyScheduleGroupsContinuation)predecessor.Continuation).SuccessorConditionGroups.Add(successors); foreach (AsyncStateGroup successor in successors) { ((HashSet <AsyncStateGroup>)successor.Predecessors).Add(predecessor); successor.SignaledConditionally = true; } }
public static bool GroupContainsNode(this AsyncStateGroup group, Node node) { return(group.Visitations.Any( v => { var nodeVisitation = v as NodeVisitation; return nodeVisitation != null && nodeVisitation.Node == node; })); }
private IEnumerable <AsyncStateGroup> GetNodePredecessorGroups(Node node, Diagram onDiagram) { foreach (Terminal inputTerminal in node.InputTerminals.Where(terminal => terminal.ParentDiagram == onDiagram)) { AsyncStateGroup inputTerminalPredecessorGroup = GetTerminalPredecessorGroup(node, inputTerminal); if (inputTerminalPredecessorGroup != null) { yield return(inputTerminalPredecessorGroup); } } }
protected override void VisitWire(Wire wire) { AsyncStateGroup sourceGroup = GetTerminalPredecessorGroup(wire, wire.SourceTerminal); if (sourceGroup == null) { throw new InvalidStateException("Wire source terminal should have a group"); } AddVisitationToGroup(sourceGroup, new NodeVisitation(wire)); _nodeGroups[wire] = sourceGroup; }
private AsyncStateGroup CreateGroupThatConditionallySchedulesSuccessors(string label, Diagram diagram) { var group = new AsyncStateGroup( label, new List <Visitation>(), new HashSet <AsyncStateGroup>(), new ConditionallyScheduleGroupsContinuation()); _groups.Add(group); _groupDiagrams[group] = diagram; return(group); }
public static bool GroupContainsStructureTraversalPoint(this AsyncStateGroup group, Structure structure, Diagram diagram, StructureTraversalPoint traversalPoint) { return(group.Visitations.Any( v => { var structureVisitation = v as StructureVisitation; return structureVisitation != null && structureVisitation.Structure == structure && structureVisitation.Diagram == diagram && structureVisitation.TraversalPoint == traversalPoint; })); }
protected override void VisitBorderNode(DfirBorderNode borderNode) { // TODO: Iterate Nodes may need to await if (borderNode.Direction == Direction.Input) { AsyncStateGroup initialGroup = _structureInputBorderNodeGroups[borderNode.ParentStructure]; AddNode(initialGroup, borderNode); } else { AsyncStateGroup outputBorderNodeGroup = _structureOutputBorderNodeGroups[borderNode.ParentStructure]; AddNode(outputBorderNodeGroup, borderNode); } }
private void AddFinalGroupIfNecessary() { var groupsWithoutSuccessors = _groups.Where(group => !group.Continuation.Successors.Any()).ToList(); if (groupsWithoutSuccessors.HasMoreThan(1)) { AsyncStateGroup finalGroup = CreateGroupThatUnconditionallySchedulesSuccessors( "terminalGroup", _dfirRoot.BlockDiagram); foreach (AsyncStateGroup predecessor in groupsWithoutSuccessors) { AddUnconditionalSuccessorGroup(predecessor, finalGroup); } } }
private static string PrettyPrintAsyncStateGroup(AsyncStateGroup asyncStateGroup) { var stringBuilder = new StringBuilder(); stringBuilder.Append($"Group {asyncStateGroup.Label}\n"); stringBuilder.Append("Predecessors:"); foreach (AsyncStateGroup predecessor in asyncStateGroup.Predecessors) { stringBuilder.Append(" " + predecessor.Label); } stringBuilder.Append("\n"); foreach (Visitation visitation in asyncStateGroup.Visitations) { stringBuilder.Append(PrettyPrintVisitation(visitation)); stringBuilder.Append("\n"); } stringBuilder.Append(PrettyPrintContinuation(asyncStateGroup.Continuation)); stringBuilder.Append("\n"); return(stringBuilder.ToString()); }
private void VisitVariantMatchStructure(VariantMatchStructure variantMatchStructure, Diagram diagram, StructureTraversalPoint traversalPoint) { var predecessors = new HashSet <AsyncStateGroup>(); switch (traversalPoint) { case StructureTraversalPoint.BeforeLeftBorderNodes: { predecessors.AddRange(GetStructureBorderNodePredecessorGroups( variantMatchStructure, variantMatchStructure.ParentDiagram, Direction.Input)); AsyncStateGroup structureInitialGroup = GetGroupJoinOfPredecessorGroups( $"variantMatchStructure{variantMatchStructure.UniqueId}_initialGroup", variantMatchStructure.ParentDiagram, predecessors); _structureInitialGroups[variantMatchStructure] = structureInitialGroup; AsyncStateGroup structureInputBorderNodeGroup = CreateGroupThatConditionallySchedulesSuccessors( $"variantMatchStructure{variantMatchStructure.UniqueId}_inputBNGroup", variantMatchStructure.ParentDiagram); AddUnconditionalSuccessorGroup(structureInitialGroup, structureInputBorderNodeGroup); _structureInputBorderNodeGroups[variantMatchStructure] = structureInputBorderNodeGroup; AddVisitationToGroup( structureInputBorderNodeGroup, new StructureVisitation(variantMatchStructure, null, StructureTraversalPoint.BeforeLeftBorderNodes)); AsyncStateGroup structureTerminalGroup = CreateGroupThatUnconditionallySchedulesSuccessors( $"variantMatchStructure{variantMatchStructure.UniqueId}_terminalGroup", variantMatchStructure.ParentDiagram); structureTerminalGroup.SignaledConditionally = true; _nodeGroups[variantMatchStructure] = structureTerminalGroup; _structureOutputBorderNodeGroups[variantMatchStructure] = structureTerminalGroup; break; } case StructureTraversalPoint.AfterLeftBorderNodesAndBeforeDiagram: { AsyncStateGroup structureInputBorderNodeGroup = _structureInputBorderNodeGroups[variantMatchStructure]; AsyncStateGroup diagramInitialGroup = CreateGroupThatUnconditionallySchedulesSuccessors( $"diagram{diagram.UniqueId}_initialGroup", diagram); diagramInitialGroup.BeginsAsDiagramInitialGroup = true; _diagramInitialGroups[diagram] = diagramInitialGroup; AddConditionalSuccessorGroups(structureInputBorderNodeGroup, new HashSet <AsyncStateGroup>() { diagramInitialGroup }); AddVisitationToGroup( diagramInitialGroup, new StructureVisitation(variantMatchStructure, diagram, StructureTraversalPoint.AfterLeftBorderNodesAndBeforeDiagram)); break; } case StructureTraversalPoint.AfterDiagram: { predecessors.AddRange(GetStructureBorderNodePredecessorGroups( variantMatchStructure, diagram, Direction.Output)); foreach (Node node in diagram.Nodes) { if (!node.GetDownstreamNodesSameDiagram(false).Any()) { predecessors.Add(_nodeGroups[node]); } } AsyncStateGroup diagramTerminalGroup = GetGroupJoinOfPredecessorGroups( $"diagram{diagram.UniqueId}_terminalGroup", diagram, predecessors); AsyncStateGroup structureTerminalGroup = _nodeGroups[variantMatchStructure]; AddUnconditionalSuccessorGroup(diagramTerminalGroup, structureTerminalGroup); AddVisitationToGroup( diagramTerminalGroup, new StructureVisitation(variantMatchStructure, diagram, StructureTraversalPoint.AfterDiagram)); break; } } }
private void VisitFrame(Frame frame, StructureTraversalPoint traversalPoint) { var predecessors = new HashSet <AsyncStateGroup>(); AsyncStateGroup currentGroup = null; switch (traversalPoint) { case StructureTraversalPoint.BeforeLeftBorderNodes: { predecessors.AddRange(GetStructureBorderNodePredecessorGroups(frame, frame.ParentDiagram, Direction.Input)); if (!frame.DoesStructureExecuteConditionally()) { currentGroup = GetGroupJoinOfPredecessorGroups( $"frame{frame.UniqueId}_initialGroup", frame.ParentDiagram, predecessors); _structureInputBorderNodeGroups[frame] = currentGroup; _diagramInitialGroups[frame.Diagram] = currentGroup; } else { AsyncStateGroup frameInitialGroup = CreateGroupThatConditionallySchedulesSuccessors( $"frame{frame.UniqueId}_initialGroup", frame.ParentDiagram); foreach (var predecessor in predecessors) { AddUnconditionalSuccessorGroup(predecessor, frameInitialGroup); } currentGroup = frameInitialGroup; _structureInitialGroups[frame] = frameInitialGroup; _structureInputBorderNodeGroups[frame] = frameInitialGroup; AsyncStateGroup diagramInitialGroup = CreateGroupThatUnconditionallySchedulesSuccessors( $"frame{frame.UniqueId}_diagramInitialGroup", frame.Diagram); diagramInitialGroup.BeginsAsDiagramInitialGroup = true; _diagramInitialGroups[frame.Diagram] = diagramInitialGroup; AsyncStateGroup frameSkippedGroup = CreateGroupThatUnconditionallySchedulesSuccessors( $"frame{frame.UniqueId}_frameSkippedGroup", null); AddVisitationToGroup(frameSkippedGroup, new FrameSkippedBlockVisitation(frame)); _frameSkippedBlockGroups[frame] = frameSkippedGroup; AsyncStateGroup frameTerminalGroup = CreateGroupThatUnconditionallySchedulesSuccessors( $"frame{frame.UniqueId}_terminalGroup", frame.ParentDiagram); frameTerminalGroup.SignaledConditionally = true; AddConditionalSuccessorGroups(frameInitialGroup, new HashSet <AsyncStateGroup> { frameSkippedGroup }); // false/0 AddUnconditionalSuccessorGroup(frameSkippedGroup, frameTerminalGroup); AddConditionalSuccessorGroups(frameInitialGroup, new HashSet <AsyncStateGroup> { diagramInitialGroup }); // true/1 _nodeGroups[frame] = frameTerminalGroup; } break; } case StructureTraversalPoint.AfterLeftBorderNodesAndBeforeDiagram: { currentGroup = _structureInputBorderNodeGroups[frame]; break; } case StructureTraversalPoint.AfterAllDiagramsAndBeforeRightBorderNodes: { // look at all output border nodes' predecessors and the groups of all nodes with no successors predecessors.AddRange(GetStructureBorderNodePredecessorGroups(frame, frame.Diagram, Direction.Output)); foreach (Node node in frame.Diagram.Nodes) { if (!node.GetDownstreamNodesSameDiagram(false).Any()) { predecessors.Add(_nodeGroups[node]); } } currentGroup = GetGroupJoinOfPredecessorGroups( $"frame{frame.UniqueId}_diagramTerminalGroup", frame.Diagram, predecessors); if (!frame.DoesStructureExecuteConditionally()) { _nodeGroups[frame] = currentGroup; } else { AsyncStateGroup frameTerminalGroup = _nodeGroups[frame]; AddUnconditionalSuccessorGroup(currentGroup, frameTerminalGroup); } _structureOutputBorderNodeGroups[frame] = currentGroup; break; } case StructureTraversalPoint.AfterRightBorderNodes: { AsyncStateGroup frameTerminalGroup = _nodeGroups[frame]; currentGroup = frameTerminalGroup; // attempt to consolidate groups if (frame.DoesStructureExecuteConditionally()) { AsyncStateGroup diagramInitialGroup = _diagramInitialGroups[frame.Diagram], diagramTerminalGroup = _structureOutputBorderNodeGroups[frame]; if (diagramInitialGroup == diagramTerminalGroup) { AsyncStateGroup frameInitialGroup = _structureInitialGroups[frame]; diagramTerminalGroup.FunctionId = frameInitialGroup.FunctionId; frameTerminalGroup.FunctionId = frameInitialGroup.FunctionId; AsyncStateGroup frameSkippedGroup = _frameSkippedBlockGroups[frame]; frameSkippedGroup.FunctionId = frameInitialGroup.FunctionId; } } break; } } if (currentGroup != null) { AddVisitationToGroup(currentGroup, new StructureVisitation(frame, frame.Diagram, traversalPoint)); } }
private void VisitLoop(Loop loop, StructureTraversalPoint traversalPoint) { AsyncStateGroup currentGroup = null; var predecessors = new HashSet <AsyncStateGroup>(); switch (traversalPoint) { case StructureTraversalPoint.BeforeLeftBorderNodes: { predecessors.AddRange(GetStructureBorderNodePredecessorGroups(loop, loop.ParentDiagram, Direction.Input)); AsyncStateGroup loopInitialGroup = GetGroupJoinOfPredecessorGroups( $"loop{loop.UniqueId}_initialGroup", loop.ParentDiagram, predecessors); _structureInitialGroups[loop] = loopInitialGroup; currentGroup = loopInitialGroup; AsyncStateGroup loopInputBorderNodeGroup = CreateGroupThatConditionallySchedulesSuccessors( $"loop{loop.UniqueId}_inputBNGroup", loop.ParentDiagram); loopInputBorderNodeGroup.SignaledConditionally = true; _structureInputBorderNodeGroups[loop] = loopInputBorderNodeGroup; AddUnconditionalSuccessorGroup(loopInitialGroup, loopInputBorderNodeGroup); break; } case StructureTraversalPoint.AfterLeftBorderNodesAndBeforeDiagram: { AsyncStateGroup diagramInitialGroup = CreateGroupThatUnconditionallySchedulesSuccessors( $"loop{loop.UniqueId}_diagramInitialGroup", loop.Diagram), loopTerminalGroup = CreateGroupThatUnconditionallySchedulesSuccessors( $"loop{loop.UniqueId}_terminalGroup", loop.ParentDiagram), loopInputBorderNodeGroup = _structureInputBorderNodeGroups[loop]; diagramInitialGroup.BeginsAsDiagramInitialGroup = true; currentGroup = loopInputBorderNodeGroup; _diagramInitialGroups[loop.Diagram] = diagramInitialGroup; _nodeGroups[loop] = loopTerminalGroup; AddConditionalSuccessorGroups(loopInputBorderNodeGroup, new HashSet <AsyncStateGroup>() { loopTerminalGroup }); AddConditionalSuccessorGroups(loopInputBorderNodeGroup, new HashSet <AsyncStateGroup>() { diagramInitialGroup }); break; } case StructureTraversalPoint.AfterAllDiagramsAndBeforeRightBorderNodes: { predecessors.AddRange(GetStructureBorderNodePredecessorGroups(loop, loop.Diagram, Direction.Output)); foreach (Node node in loop.Diagram.Nodes) { if (!node.GetDownstreamNodesSameDiagram(false).Any()) { predecessors.Add(_nodeGroups[node]); } } AsyncStateGroup diagramTerminalGroup = GetGroupJoinOfPredecessorGroups( $"loop{loop.UniqueId}_diagramTerminalGroup", loop.Diagram, predecessors); _structureOutputBorderNodeGroups[loop] = diagramTerminalGroup; AddUnconditionalSuccessorGroup(diagramTerminalGroup, _structureInputBorderNodeGroups[loop]); break; } case StructureTraversalPoint.AfterRightBorderNodes: { AsyncStateGroup diagramTerminalGroup = _structureOutputBorderNodeGroups[loop]; currentGroup = diagramTerminalGroup; break; } } if (currentGroup != null) { AddVisitationToGroup(currentGroup, new StructureVisitation(loop, loop.Diagram, traversalPoint)); } }
private void AddVisitationToGroup(AsyncStateGroup group, Visitation visitation) { ((List <Visitation>)group.Visitations).Add(visitation); }
private void AddUnconditionalSuccessorGroup(AsyncStateGroup predecessor, AsyncStateGroup successor) { ((UnconditionallySchduleGroupsContinuation)predecessor.Continuation).UnconditionalSuccessors.Add(successor); ((HashSet <AsyncStateGroup>)successor.Predecessors).Add(predecessor); }
private void AddNode(AsyncStateGroup group, Node node) { AddVisitationToGroup(group, new NodeVisitation(node)); _nodeGroups[node] = group; }