/// <summary> /// Handles a nested block. A nested block is explained with an if statement as example. /// The given lists/matrices are correctly updated. /// <para/> /// Consider the following block. Only the first block is shown. The texts in [] describe the role of the important steps for that statement. /// <para/> /// IF George can fly THEN [block start] /// <para/> /// Go fly George. [nested block step] /// <para/> /// And don't come back. [nested block step] /// <para/> /// ELSE [block end] /// <para/> /// You're trapped to this world. :( /// <para/> /// ENDIF [exit target step] /// </summary> /// <param name="steps">The steps containing the block.</param> /// <param name="edgeMatrix">The edge matrix.</param> /// <param name="externalEdges">The external edges list.</param> /// <param name="possibleInvalidIfEdges">The possible invalid if edge list.</param> /// <param name="conditionMatrix">The condition matrix.</param> /// <param name="blockStartIndex">The index of the block start. (The step before the nested block begins)</param> /// <param name="blockEndIndex">The index of the block end. (The step after the nested block ends)</param> /// <param name="exitStepsTargetStep">The step to where create the edges if the nested block has exit steps.</param> /// <param name="blockEntryCondition">The condition to be fulfilled to enter the nested block.</param> public static void SetEdgesInNestedBlock( IReadOnlyList <Node> steps, ref Matrix <bool> edgeMatrix, ref List <ExternalEdge> externalEdges, ref List <InternalEdge> possibleInvalidIfEdges, ref Matrix <Condition?> conditionMatrix, int blockStartIndex, int blockEndIndex, int exitStepsTargetStep, Condition?blockEntryCondition) { int blockSize = blockEndIndex - blockStartIndex - 1; // Set edge into the nested block edgeMatrix[blockStartIndex, blockStartIndex + 1] = true; conditionMatrix[blockStartIndex, blockStartIndex + 1] = blockEntryCondition; List <Node> nestedSteps = steps.Skip(blockStartIndex + 1).Take(blockSize).ToList(); Matrix <bool> nestedEdgeMatrix; List <ExternalEdge> nestedExternalEdges; List <InternalEdge> nestedPossibleInvalidIfEdges; List <Tuple <int, Condition?> > nestedExitSteps; Matrix <Condition?> nestedConditionMatrix; GraphBuilder.SetEdgesInStepBlock(nestedSteps, out nestedEdgeMatrix, out nestedExternalEdges, out nestedPossibleInvalidIfEdges, out nestedExitSteps, out nestedConditionMatrix); // Unite matrices GraphBuilder.InsertMatrix(ref edgeMatrix, blockStartIndex + 1, blockStartIndex + 1, nestedEdgeMatrix); GraphBuilder.InsertMatrix(ref conditionMatrix, blockStartIndex + 1, blockStartIndex + 1, nestedConditionMatrix); // Unite externalEdges externalEdges.AddRange(nestedExternalEdges.ConvertAll((edge) => edge.NewWithIncreasedSourceStepNumber(blockStartIndex + 1))); // Unite possible invalid if edges possibleInvalidIfEdges.AddRange(nestedPossibleInvalidIfEdges.ConvertAll((edge) => edge.NewWithIncreasedSourceTargetStep(blockStartIndex + 1))); // Wire exit steps to end if step foreach (Tuple <int, Condition?> exitStep in nestedExitSteps) { edgeMatrix[exitStep.Item1 + blockStartIndex + 1, exitStepsTargetStep] = true; conditionMatrix[exitStep.Item1 + blockStartIndex + 1, exitStepsTargetStep] = exitStep.Item2; } }
/// <summary> /// Wires a flow individually meaning all steps inside. Basically the method <see cref="SetEdgesInStepBlock(IReadOnlyList{Node}, out Matrix{bool}, out List{ExternalEdge}, out List{InternalEdge}, out List{int})"/> /// is called for the flow. /// </summary> /// <param name="flow">The flow to wire.</param> /// <param name="flowOffset">The offset of the flows nodes. Later used to identify its edges in the edge matrix.</param> /// <returns>A tuple containing the offset as item 1, the flow as item 2 and then all the out parameters of <see cref="SetEdgesInStepBlock(IReadOnlyList{Node}, out Matrix{bool}, out List{ExternalEdge}, out List{InternalEdge}, out List{int})"/>.</returns> public static Tuple <int, Flow, Matrix <bool>, List <ExternalEdge>, List <InternalEdge>, List <Tuple <int, Condition?> >, Matrix <Condition?> > WireFlowIndividually(Flow flow, int flowOffset) { IReadOnlyList <Node> steps = flow.Nodes; Matrix <bool> edgeMatrix; List <ExternalEdge> externalEdges; List <InternalEdge> possibleInvalidIfEdges; List <Tuple <int, Condition?> > exitSteps; Matrix <Condition?> conditionMatrix; GraphBuilder.SetEdgesInStepBlock(steps, out edgeMatrix, out externalEdges, out possibleInvalidIfEdges, out exitSteps, out conditionMatrix); return(new Tuple <int, Flow, Matrix <bool>, List <ExternalEdge>, List <InternalEdge>, List <Tuple <int, Condition?> >, Matrix <Condition?> >( flowOffset, flow, edgeMatrix, externalEdges, possibleInvalidIfEdges, exitSteps, conditionMatrix)); }