Beispiel #1
0
        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;
            }
        }
Beispiel #2
0
        private AsyncStateGroup CreateNewGroupFromNode(Node node, IEnumerable <AsyncStateGroup> nodePredecessors)
        {
            AsyncStateGroup group = CreateNewGroupWithPredecessors($"node{node.UniqueId}", node.ParentDiagram, nodePredecessors);

            AddNode(group, node);
            return(group);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
 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;
     }
 }
Beispiel #5
0
 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;
     }));
 }
Beispiel #6
0
 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);
         }
     }
 }
Beispiel #7
0
        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;
        }
Beispiel #8
0
        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);
        }
Beispiel #9
0
 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;
     }));
 }
Beispiel #10
0
 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);
     }
 }
Beispiel #11
0
        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);
                }
            }
        }
Beispiel #12
0
        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());
        }
Beispiel #13
0
        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;
            }
            }
        }
Beispiel #14
0
        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));
            }
        }
Beispiel #15
0
        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));
            }
        }
Beispiel #16
0
 private void AddVisitationToGroup(AsyncStateGroup group, Visitation visitation)
 {
     ((List <Visitation>)group.Visitations).Add(visitation);
 }
Beispiel #17
0
 private void AddUnconditionalSuccessorGroup(AsyncStateGroup predecessor, AsyncStateGroup successor)
 {
     ((UnconditionallySchduleGroupsContinuation)predecessor.Continuation).UnconditionalSuccessors.Add(successor);
     ((HashSet <AsyncStateGroup>)successor.Predecessors).Add(predecessor);
 }
Beispiel #18
0
 private void AddNode(AsyncStateGroup group, Node node)
 {
     AddVisitationToGroup(group, new NodeVisitation(node));
     _nodeGroups[node] = group;
 }