public void InitializeVectorAndSumWithSliceIterator_Execute_CorrectSumValue()
        {
            DfirRoot       function         = DfirRoot.Create();
            FunctionalNode initializeVector = CreateInitializeVectorWithIntegerConstants(function.BlockDiagram, 4, 4);
            FunctionalNode vectorToSlice    = new FunctionalNode(function.BlockDiagram, Signatures.VectorToSliceType);

            Wire.Create(function.BlockDiagram, initializeVector.OutputTerminals[0], vectorToSlice.InputTerminals[0]);
            FunctionalNode sliceToIterator = new FunctionalNode(function.BlockDiagram, Signatures.SliceToIteratorType);

            Wire.Create(function.BlockDiagram, vectorToSlice.OutputTerminals[0], sliceToIterator.InputTerminals[0]);
            Loop loop = new Loop(function.BlockDiagram);

            CreateLoopConditionTunnel(loop);
            IterateTunnel iterateTunnel = CreateIterateTunnel(loop);
            BorrowTunnel  borrowTunnel  = CreateBorrowTunnel(loop, BorrowMode.Mutable);

            ConnectConstantToInputTerminal(borrowTunnel.InputTerminals[0], NITypes.Int32, 0, true);
            Wire.Create(function.BlockDiagram, sliceToIterator.OutputTerminals[0], iterateTunnel.InputTerminals[0])
            .SetWireBeginsMutableVariable(true);
            FunctionalNode accumulateAdd = new FunctionalNode(loop.Diagrams[0], Signatures.DefineMutatingBinaryFunction("AccumulateAdd", NITypes.Int32));

            Wire.Create(loop.Diagrams[0], borrowTunnel.OutputTerminals[0], accumulateAdd.InputTerminals[0]);
            Wire.Create(loop.Diagrams[0], iterateTunnel.OutputTerminals[0], accumulateAdd.InputTerminals[1]);
            FunctionalNode inspectNode = ConnectInspectToOutputTerminal(borrowTunnel.TerminateLifetimeTunnel.OutputTerminals[0]);

            TestExecutionInstance executionInstance = CompileAndExecuteFunction(function);

            byte[] inspectValue = executionInstance.GetLastValueFromInspectNode(inspectNode);
            AssertByteArrayIsInt32(inspectValue, 16);
        }
        public void SumItemsFromRangeIterator_Execute_CorrectFinalResult()
        {
            DfirRoot            function        = DfirRoot.Create();
            Loop                loop            = new Loop(function.BlockDiagram);
            LoopConditionTunnel conditionTunnel = CreateLoopConditionTunnel(loop);
            IterateTunnel       iterateTunnel   = CreateIterateTunnel(loop);
            FunctionalNode      range           = new FunctionalNode(function.BlockDiagram, Signatures.RangeType);
            Wire                rangeWire       = Wire.Create(function.BlockDiagram, range.OutputTerminals[0], iterateTunnel.InputTerminals[0]);

            rangeWire.SetWireBeginsMutableVariable(true);
            Constant       lowConstant        = ConnectConstantToInputTerminal(range.InputTerminals[0], NITypes.Int32, 0, false);
            Constant       highConstant       = ConnectConstantToInputTerminal(range.InputTerminals[1], NITypes.Int32, 10, false);
            BorrowTunnel   borrow             = CreateBorrowTunnel(loop, BorrowMode.Mutable);
            Constant       accumulateConstant = ConnectConstantToInputTerminal(borrow.InputTerminals[0], NITypes.Int32, 0, true);
            FunctionalNode accumulateAdd      = new FunctionalNode(loop.Diagram, Signatures.DefineMutatingBinaryFunction("AccumulateAdd", NITypes.Int32));

            Wire.Create(loop.Diagram, borrow.OutputTerminals[0], accumulateAdd.InputTerminals[0]);
            Wire.Create(loop.Diagram, iterateTunnel.OutputTerminals[0], accumulateAdd.InputTerminals[1]);
            FunctionalNode inspect = ConnectInspectToOutputTerminal(borrow.TerminateLifetimeTunnel.OutputTerminals[0]);

            TestExecutionInstance executionInstance = CompileAndExecuteFunction(function);

            byte[] inspectValue = executionInstance.GetLastValueFromInspectNode(inspect);
            AssertByteArrayIsInt32(inspectValue, 45);
        }
Beispiel #3
0
        internal LoopConditionTunnel CreateLoopConditionTunnel(Loop loop)
        {
            var loopConditionTunnel   = new LoopConditionTunnel(loop);
            var terminateLifetimeDfir = new TerminateLifetimeTunnel(loop);

            loopConditionTunnel.TerminateLifetimeTunnel = terminateLifetimeDfir;
            terminateLifetimeDfir.BeginLifetimeTunnel   = loopConditionTunnel;
            return(loopConditionTunnel);
        }
Beispiel #4
0
        private static IterateTunnel CreateIterateTunnel(Loop loop)
        {
            var iterateTunnel         = new IterateTunnel(loop);
            var terminateLifetimeDfir = new TerminateLifetimeTunnel(loop);

            iterateTunnel.TerminateLifetimeTunnel     = terminateLifetimeDfir;
            terminateLifetimeDfir.BeginLifetimeTunnel = iterateTunnel;
            return(iterateTunnel);
        }
        private IterateTunnel CreateRangeAndIterateTunnel(Loop loop, int rangeLow, int rangeHigh)
        {
            var range = new FunctionalNode(loop.ParentDiagram, Signatures.RangeType);

            ConnectConstantToInputTerminal(range.InputTerminals[0], NITypes.Int32, 1, false);
            ConnectConstantToInputTerminal(range.InputTerminals[1], NITypes.Int32, 7, false);
            IterateTunnel iterateTunnel = CreateIterateTunnel(loop);

            Wire.Create(loop.ParentDiagram, range.OutputTerminals[0], iterateTunnel.InputTerminals[0])
            .SetWireBeginsMutableVariable(true);
            return(iterateTunnel);
        }
        public void LoopConditionTunnelWithUnwiredInput_SetVariableTypes_InputVariableIsBooleanType()
        {
            DfirRoot            function            = DfirRoot.Create();
            Loop                loop                = new Loop(function.BlockDiagram);
            LoopConditionTunnel loopConditionTunnel = CreateLoopConditionTunnel(loop);

            RunSemanticAnalysisUpToSetVariableTypes(function);

            VariableReference loopConditionInputVariable = loopConditionTunnel.InputTerminals[0].GetTrueVariable();

            Assert.IsTrue(loopConditionInputVariable.Type.IsBoolean());
        }
Beispiel #7
0
        public void IterateTunnelWithImmutableRangeIteratorTypeWired_ValidateVariableUsages_MutableVariableRequiredErrorReported()
        {
            DfirRoot function      = DfirRoot.Create();
            Loop     loop          = new Loop(function.BlockDiagram);
            var      iterateTunnel = CreateIterateTunnel(loop);

            ConnectRangeWithIntegerInputsToInputTerminal(iterateTunnel.InputTerminals[0], false);

            RunSemanticAnalysisUpToValidation(function);

            Assert.IsTrue(iterateTunnel.InputTerminals[0].GetDfirMessages().Any(message => message.Descriptor == Messages.TerminalDoesNotAcceptImmutableType.Descriptor));
        }
Beispiel #8
0
        public void IterateTunnelWithNonIteratorTypeWired_ValidateVariableUsages_TypeConflictErrorReported()
        {
            DfirRoot function      = DfirRoot.Create();
            Loop     loop          = new Loop(function.BlockDiagram);
            var      iterateTunnel = CreateIterateTunnel(loop);

            ConnectConstantToInputTerminal(iterateTunnel.InputTerminals[0], PFTypes.Int32, false);

            RunSemanticAnalysisUpToValidation(function);

            AssertTerminalHasMissingTraitMessage(iterateTunnel.InputTerminals[0]);
        }
        public void LoopConditionTunnelWithNonBooleanInput_ValidateVariableUsage_TypeConflictErrorReported()
        {
            DfirRoot            function            = DfirRoot.Create();
            Loop                loop                = new Loop(function.BlockDiagram);
            LoopConditionTunnel loopConditionTunnel = CreateLoopConditionTunnel(loop);

            ConnectConstantToInputTerminal(loopConditionTunnel.InputTerminals[0], PFTypes.Int32, false);

            RunSemanticAnalysisUpToValidation(function);

            AssertTerminalHasTypeConflictMessage(loopConditionTunnel.InputTerminals[0]);
        }
        public void LoopConditionTunnelWithBooleanReferenceInput_ValidateVariableUsage_TypeConflictErrorReported()
        {
            DfirRoot            function            = DfirRoot.Create();
            Loop                loop                = new Loop(function.BlockDiagram);
            LoopConditionTunnel loopConditionTunnel = CreateLoopConditionTunnel(loop);
            ExplicitBorrowNode  borrow              = ConnectExplicitBorrowToInputTerminals(loopConditionTunnel.InputTerminals[0]);

            ConnectConstantToInputTerminal(borrow.InputTerminals[0], NITypes.Boolean, false);

            RunSemanticAnalysisUpToValidation(function);

            AssertTerminalHasTypeConflictMessage(loopConditionTunnel.InputTerminals[0]);
        }
Beispiel #11
0
        public void PanickingUnwrapOptionInsideLoopDiagram_Execute_LoopTerminatesAndDownstreamOfLoopDoesNotExecute()
        {
            DfirRoot            function  = DfirRoot.Create();
            Loop                loop      = new Loop(function.BlockDiagram);
            LoopConditionTunnel condition = CreateLoopConditionTunnel(loop);
            FunctionalNode      unwrap    = CreatePanickingUnwrapOption(loop.Diagram);

            ConnectOutputToOutputTerminal(condition.TerminateLifetimeTunnel.OutputTerminals[0]);

            TestExecutionInstance executionInstance = CompileAndExecuteFunction(function);

            AssertNoOutput(executionInstance);
        }
Beispiel #12
0
        public void IterateTunnelWithRangeIteratorTypeWired_SetVariableTypes_OutputIsInt32()
        {
            DfirRoot function      = DfirRoot.Create();
            Loop     loop          = new Loop(function.BlockDiagram);
            var      iterateTunnel = CreateIterateTunnel(loop);

            ConnectRangeWithIntegerInputsToInputTerminal(iterateTunnel.InputTerminals[0]);

            RunSemanticAnalysisUpToSetVariableTypes(function);

            VariableReference iterateOutputVariable = iterateTunnel.OutputTerminals[0].GetTrueVariable();

            Assert.IsTrue(iterateOutputVariable.Type.IsInt32());
        }
        public void LoopConditionTunnel_SetVariableTypes_OutputLifetimeIsBoundedAndDoesNotOutlastDiagram()
        {
            DfirRoot            function            = DfirRoot.Create();
            Loop                loop                = new Loop(function.BlockDiagram);
            LoopConditionTunnel loopConditionTunnel = CreateLoopConditionTunnel(loop);

            RunSemanticAnalysisUpToSetVariableTypes(function);

            VariableReference loopConditionOutputVariable = loopConditionTunnel.OutputTerminals[0].GetTrueVariable();

            Assert.IsTrue(loopConditionOutputVariable.Type.IsMutableReferenceType());
            Lifetime lifetime = loopConditionOutputVariable.Lifetime;

            Assert.IsTrue(lifetime.IsBounded);
            Assert.IsFalse(lifetime.DoesOutlastDiagram(loop.Diagrams[0]));
        }
Beispiel #14
0
        private void VisitLoop(SourceModel.Loop loop)
        {
            var firstDiagram = loop.NestedDiagrams.First();
            var loopDfir     = new Nodes.Loop(_currentDiagram);

            _map.AddMapping(loop, loopDfir);
            _map.AddMapping(firstDiagram, loopDfir.Diagrams[0]);

            foreach (BorderNode borderNode in loop.BorderNodes)
            {
                NationalInstruments.Dfir.BorderNode dfirBorderNode = TranslateBorderNode(borderNode, loopDfir);
                MapBorderNode(borderNode, dfirBorderNode);
            }

            firstDiagram.AcceptVisitor(this);
        }
Beispiel #15
0
        public void LoopWithOutputTunnelThatDoesNotExecute_Execute_TunnelOutputsNoneValue()
        {
            DfirRoot            function        = DfirRoot.Create();
            Loop                loop            = new Loop(function.BlockDiagram);
            LoopConditionTunnel conditionTunnel = CreateLoopConditionTunnel(loop);
            Constant            falseConstant   = ConnectConstantToInputTerminal(conditionTunnel.InputTerminals[0], NITypes.Boolean, false, false);
            Tunnel              outputTunnel    = CreateOutputTunnel(loop);

            ConnectConstantToInputTerminal(outputTunnel.InputTerminals[0], NITypes.Int32, false);
            FunctionalNode inspect = ConnectInspectToOutputTerminal(outputTunnel.OutputTerminals[0]);

            TestExecutionInstance executionInstance = CompileAndExecuteFunction(function);

            byte[] inspectValue = executionInstance.GetLastValueFromInspectNode(inspect);
            AssertByteArrayIsNoneInteger(inspectValue);
        }
Beispiel #16
0
        public void FillVectorEnoughToGrowItThenRemoveAllElements_Execute_AllElementsPreservedAndRemoved()
        {
            DfirRoot function     = DfirRoot.Create();
            var      createVector = new FunctionalNode(function.BlockDiagram, Signatures.VectorCreateType);
            Loop     firstLoop    = new Loop(function.BlockDiagram);

            CreateLoopConditionTunnel(firstLoop);
            BorrowTunnel firstLoopBorrowTunnel = CreateBorrowTunnel(firstLoop, BorrowMode.Mutable);

            Wire.Create(function.BlockDiagram, createVector.OutputTerminals[0], firstLoopBorrowTunnel.InputTerminals[0])
            .SetWireBeginsMutableVariable(true);
            IterateTunnel iterateTunnel  = CreateRangeAndIterateTunnel(firstLoop, 1, 7);
            var           appendToVector = new FunctionalNode(firstLoop.Diagram, Signatures.VectorAppendType);

            Wire.Create(firstLoop.Diagram, firstLoopBorrowTunnel.OutputTerminals[0], appendToVector.InputTerminals[0]);
            Wire.Create(firstLoop.Diagram, iterateTunnel.OutputTerminals[0], appendToVector.InputTerminals[1]);
            Loop secondLoop = new Loop(function.BlockDiagram);

            CreateLoopConditionTunnel(secondLoop);
            BorrowTunnel secondLoopBorrowTunnel = CreateBorrowTunnel(secondLoop, BorrowMode.Mutable);

            Wire.Create(function.BlockDiagram, firstLoopBorrowTunnel.TerminateLifetimeTunnel.OutputTerminals[0], secondLoopBorrowTunnel.InputTerminals[0]);
            CreateRangeAndIterateTunnel(secondLoop, 1, 7);
            var removeLastFromVector = new FunctionalNode(secondLoop.Diagram, Signatures.VectorRemoveLastType);

            Wire.Create(secondLoop.Diagram, secondLoopBorrowTunnel.OutputTerminals[0], removeLastFromVector.InputTerminals[0]);
            BorrowTunnel resultBorrowTunnel = CreateBorrowTunnel(secondLoop, BorrowMode.Mutable);

            ConnectConstantToInputTerminal(resultBorrowTunnel.InputTerminals[0], NITypes.Int32, 0, true);
            Frame unwrapFrame = Frame.Create(secondLoop.Diagram);
            UnwrapOptionTunnel unwrapTunnel = CreateUnwrapOptionTunnel(unwrapFrame);

            Wire.Create(secondLoop.Diagram, removeLastFromVector.OutputTerminals[1], unwrapTunnel.InputTerminals[0]);
            Tunnel inputTunnel = CreateInputTunnel(unwrapFrame);

            Wire.Create(secondLoop.Diagram, resultBorrowTunnel.OutputTerminals[0], inputTunnel.InputTerminals[0]);
            var accumulateAdd = new FunctionalNode(unwrapFrame.Diagram, Signatures.DefineMutatingBinaryFunction("AccumulateAdd", NITypes.Int32));

            Wire.Create(unwrapFrame.Diagram, inputTunnel.OutputTerminals[0], accumulateAdd.InputTerminals[0]);
            Wire.Create(unwrapFrame.Diagram, unwrapTunnel.OutputTerminals[0], accumulateAdd.InputTerminals[1]);
            FunctionalNode inspect = ConnectInspectToOutputTerminal(resultBorrowTunnel.TerminateLifetimeTunnel.OutputTerminals[0]);

            TestExecutionInstance executionInstance = CompileAndExecuteFunction(function);

            byte[] inspectValue = executionInstance.GetLastValueFromInspectNode(inspect);
            AssertByteArrayIsInt32(inspectValue, 21);
        }
        public void LoopConditionTunnel_SetVariableTypes_OutputLifetimeHasCorrectInterruptedVariables()
        {
            DfirRoot            function            = DfirRoot.Create();
            Loop                loop                = new Loop(function.BlockDiagram);
            LoopConditionTunnel loopConditionTunnel = CreateLoopConditionTunnel(loop);
            var lifetimeAssociation = new LifetimeVariableAssociation();

            RunSemanticAnalysisUpToSetVariableTypes(function, null, null, lifetimeAssociation);

            VariableReference loopConditionOutputVariable = loopConditionTunnel.OutputTerminals[0].GetTrueVariable(),
                              loopConditionInputVariable  = loopConditionTunnel.InputTerminals[0].GetTrueVariable();
            Lifetime lifetime = loopConditionOutputVariable.Lifetime;
            IEnumerable <VariableReference> interruptedVariables = lifetimeAssociation.GetVariablesInterruptedByLifetime(lifetime);

            Assert.AreEqual(1, interruptedVariables.Count());
            Assert.AreEqual(loopConditionInputVariable, interruptedVariables.First());
        }
Beispiel #18
0
        public void LoopWithOutputTunnelThatExecutes_Execute_TunnelOutputsSomeValue()
        {
            DfirRoot            function        = DfirRoot.Create();
            Loop                loop            = new Loop(function.BlockDiagram);
            LoopConditionTunnel conditionTunnel = CreateLoopConditionTunnel(loop);
            Constant            trueConstant    = ConnectConstantToInputTerminal(conditionTunnel.InputTerminals[0], NITypes.Boolean, true, false);
            FunctionalNode      assign          = new FunctionalNode(loop.Diagram, Signatures.AssignType);

            Wire.Create(loop.Diagram, conditionTunnel.OutputTerminals[0], assign.InputTerminals[0]);
            Constant       falseConstant = ConnectConstantToInputTerminal(assign.InputTerminals[1], NITypes.Boolean, false, false);
            Tunnel         outputTunnel  = CreateOutputTunnel(loop);
            Constant       intConstant   = ConnectConstantToInputTerminal(outputTunnel.InputTerminals[0], NITypes.Int32, 5, false);
            FunctionalNode inspect       = ConnectInspectToOutputTerminal(outputTunnel.OutputTerminals[0]);

            TestExecutionInstance executionInstance = CompileAndExecuteFunction(function);

            byte[] inspectValue = executionInstance.GetLastValueFromInspectNode(inspect);
            AssertByteArrayIsSomeInteger(inspectValue, 5);
        }
Beispiel #19
0
        public void IterateTunnelWithIterableTypeWired_SetVariableTypes_OutputLifetimeHasCorrectInterruptedVariables()
        {
            DfirRoot function     = DfirRoot.Create();
            Loop     loop         = new Loop(function.BlockDiagram);
            var      borrowTunnel = CreateIterateTunnel(loop);

            ConnectConstantToInputTerminal(borrowTunnel.InputTerminals[0], PFTypes.Int32, false);
            var lifetimeAssociation = new LifetimeVariableAssociation();

            RunSemanticAnalysisUpToSetVariableTypes(function, null, null, lifetimeAssociation);

            VariableReference borrowOutputVariable = borrowTunnel.OutputTerminals[0].GetTrueVariable(),
                              borrowInputVariable  = borrowTunnel.InputTerminals[0].GetTrueVariable();
            Lifetime lifetime = borrowOutputVariable.Lifetime;
            IEnumerable <VariableReference> interruptedVariables = lifetimeAssociation.GetVariablesInterruptedByLifetime(lifetime);

            Assert.AreEqual(1, interruptedVariables.Count());
            Assert.AreEqual(borrowInputVariable, interruptedVariables.First());
        }
Beispiel #20
0
        public void PanickingUnwrapOptionIntoLoop_Execute_LoopDoesNotExecute()
        {
            DfirRoot            function  = DfirRoot.Create();
            FunctionalNode      unwrap    = CreatePanickingUnwrapOption(function.BlockDiagram);
            Loop                loop      = new Loop(function.BlockDiagram);
            LoopConditionTunnel condition = CreateLoopConditionTunnel(loop);

            // Wire explicit true to condition so that it is initialized outside the PanicAndContinue's clump
            ConnectConstantToInputTerminal(condition.InputTerminals[0], NITypes.Boolean, true, false);
            Tunnel inputTunnel = CreateInputTunnel(loop);

            Wire.Create(function.BlockDiagram, unwrap.OutputTerminals[0], inputTunnel.InputTerminals[0]);
            ConnectOutputToOutputTerminal(inputTunnel.OutputTerminals[0]);
            AssignFalseToLoopConditionOutputTerminal(condition);

            TestExecutionInstance executionInstance = CompileAndExecuteFunction(function);

            AssertNoOutput(executionInstance);
        }
Beispiel #21
0
        public void StringSplitIteratorIntoOutput_Execute_CorrectResult()
        {
            DfirRoot       function = DfirRoot.Create();
            FunctionalNode stringSliceToStringSplitIterator = new FunctionalNode(function.BlockDiagram, Signatures.StringSliceToStringSplitIteratorType);

            ConnectConstantToInputTerminal(stringSliceToStringSplitIterator.InputTerminals[0], DataTypes.StringSliceType.CreateImmutableReference(), "one two three", false);
            var loop = new Loop(function.BlockDiagram);
            LoopConditionTunnel loopCondition = CreateLoopConditionTunnel(loop);
            IterateTunnel       iterateTunnel = CreateIterateTunnel(loop);

            Wire.Create(function.BlockDiagram, stringSliceToStringSplitIterator.OutputTerminals[0], iterateTunnel.InputTerminals[0])
            .SetWireBeginsMutableVariable(true);
            FunctionalNode output = new FunctionalNode(loop.Diagram, Signatures.OutputType);

            Wire.Create(loop.Diagram, iterateTunnel.OutputTerminals[0], output.InputTerminals[0]);

            TestExecutionInstance executionInstance = CompileAndExecuteFunction(function);

            Assert.AreEqual("three", executionInstance.RuntimeServices.LastOutputValue);
        }
        public void LoopFollowedByLoop_GroupAsyncStates_SubsequentLoopStartsInPredecessorLoopTerminalGroup()
        {
            DfirRoot     function        = DfirRoot.Create();
            Loop         firstLoop       = new Loop(function.BlockDiagram);
            BorrowTunnel firstLoopBorrow = CreateBorrowTunnel(firstLoop, BorrowMode.Immutable);

            ConnectConstantToInputTerminal(firstLoopBorrow.InputTerminals[0], NITypes.Int32, false);
            TerminateLifetimeTunnel firstLoopTerminate = firstLoopBorrow.TerminateLifetimeTunnel;
            Loop   secondLoop = new Loop(function.BlockDiagram);
            Tunnel loopTunnel = CreateInputTunnel(secondLoop);

            Wire.Create(function.BlockDiagram, firstLoopTerminate.OutputTerminals[0], loopTunnel.InputTerminals[0]);

            IEnumerable <AsyncStateGroup> asyncStateGroups = GroupAsyncStates(function);

            string          terminalGroupName      = $"loop{firstLoop.UniqueId}_terminalGroup";
            AsyncStateGroup firstLoopTerminalGroup = asyncStateGroups.First(g => g.Label == terminalGroupName);
            AsyncStateGroup secondLoopInitialGroup = asyncStateGroups.First(g => g.GroupContainsStructureTraversalPoint(secondLoop, secondLoop.Diagram, StructureTraversalPoint.BeforeLeftBorderNodes));

            Assert.AreEqual(firstLoopTerminalGroup, secondLoopInitialGroup);
        }
Beispiel #23
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));
            }
        }
 bool IDfirStructureVisitor <bool> .VisitLoop(Nodes.Loop loop, StructureTraversalPoint traversalPoint)
 {
     return(true);
 }