public void ResetCounters() { currentDepth = maxDepth; int[] keys = controllingPairs.Keys.ToArray(); for (int i = 0; i < keys.Length; i++) { LoopPair pair = controllingPairs[keys[i]]; pair.Iteration = 0; controllingPairs[keys[i]] = pair; } }
public void AddLoopPair(ref LoopPair pair) { if (controllingPairs.ContainsKey(pair.Depth)) { return; } controllingPairs.Add(pair.Depth, pair); if (pair.Depth > maxDepth) { maxDepth = pair.Depth; } }
private bool ContainsLoop(LoopPair instance, out int foundId) { List <int> ignore = new List <int>(); ignore.AddRange(new[] { instance.Start.NodeId }); if (CheckDependenciesFor(dependencyGraph[instance.End.NodeId], out foundId, ignore, LoopEnd.TypeName)) { if (foundId != instance.Start.NodeId) { //must have an internal loop return(true); } return(false); } return(false); }
private void FindLoopPairs(DependentNode loopEnd, ref List <int> foundEnds, int depth = 0) { LoopPair instance = new LoopPair(); instance.Id = loopIdCount++; if (loopEnd.Type == LoopEnd.TypeName) { instance.End = new LoopEnd(loopEnd, instance); instance.Depth = depth; int startNode = ExecutionHelper.FindFirstNodeSlotInDependencies(loopEnd, dependencyGraph, 0).NodeId; if (startNode == -1) { throw new MissingLinkException("No link for loop start specified"); } DependentNode loopStart = dependencyGraph[startNode]; //try to keep one instance per unique loop start node Id if (loopStarts.ContainsKey(startNode)) { instance.Start = loopStarts[startNode]; } else { instance.Start = new LoopStart(loopStart); loopStarts.Add(startNode, instance.Start); } //ensure that only the start and end nodes are linked if (loopStart.Dependents.Where((testSlot, b) => { bool incorrectType = dependencyGraph[testSlot.NodeId].Type != LoopEnd.TypeName; foreach (NodeSlot slot in dependencyGraph[testSlot.NodeId].Dependencies) { if (slot.NodeId == loopStart.Id && slot.SlotPos == 0) { if (incorrectType) { return(true); } } } return(false); }).Any()) { throw new InvalidNodeException("Loop Start Link (slot 0) cannot link to anything but a Loop End"); } //find out how many loops the "LoopStart" node is directly responsible for int loopCount; { List <int> matched = new List <int>(); loopCount = loopStart.Dependents.Where((testSlot, b) => { if (matched.Contains(testSlot.NodeId)) { return(false); } foreach (NodeSlot slot in dependencyGraph[testSlot.NodeId].Dependencies) { if (slot.NodeId == loopStart.Id && slot.SlotPos == 0) { matched.Add(testSlot.NodeId); return(true); } } return(false); }).Count(); } if (loopCount > 1) { throw new SlotLimitExceeded("Loop Start may only have one loop end, use multiple loop starts for nesting or branching"); #region //multiple nodes linked so there must be nested loops sharing this start position /*int[] ids = new int[loopCount]; * for (int i = 0, c = 0; i < loopStart.Dependents.Length; i++) * if (loopStart.Dependents[i].SlotPos == 0) * ids[c++] = loopStart.Dependents[i].NodeId; * * //check if co dependent nodes exist * List<int> dependencies = new List<int>(); * for (int a = 0; a < ids.Length; a++) * { * for (int b = 0; b < ids.Length; b++) * { * if (a == b) continue; * * bool aTob = NodeDependentOn(ids[a], ids[b]), * bToa = NodeDependentOn(ids[b], ids[a]); * * if (aTob && bToa) throw new CoDependentLoopException * ("Node " + ids[a] + " and " + ids[b] + "Are dependent on each other and can't loop!"); * * if (aTob && !dependencies.Contains(a)) dependencies.Add(ids[a]); * } * } * * //check non dependent nodes for internal loops * foreach (int id in ids) * { * if (dependencies.Contains(id)) continue; * * LoopPair subPair = new LoopPair(); * subPair.Id = loopIdCount++; * subPair.Depth = depth; * subPair.End = new LoopEnd(dependencyGraph[id], subPair); * if (loopStarts.ContainsKey(loopEnd.Dependencies[0].NodeId)) * subPair.Start = loopStarts[loopEnd.Dependencies[0].NodeId]; * else * { * instance.Start = new LoopStart(dependencyGraph[loopEnd.Dependencies[0].NodeId]); * loopStarts.Add(loopEnd.Dependencies[0].NodeId, subPair.Start); * } * * int foundEnd; * if (ContainsLoop(instance, out foundEnd)) * //contains internal loop * FindLoopPairs(dependencyGraph[foundEnd], ref foundEnds, subPair.Depth + 1); * * foundEnds.Add(subPair.End.NodeId); * subPair.Start.AddLoopPair(ref subPair); * loopPairs.Add(subPair); * } * * //go back and handle the nodes which are dependent on each other * if (dependencies.Count > 1) * { * throw new NotImplementedException(); * //todo * }*/ #endregion } else { NodeSlot startLink = ExecutionHelper.FindFirstNodeSlotInDependents(loopStart, dependencyGraph, 0); if (startLink.NodeId == -1) { throw new MissingLinkException("No link for loop start specified"); } if (startLink.NodeId != loopEnd.Id) { throw new MissingLinkException(StartEndIdMismatch); } int foundEnd; //contains internal loop? if (ContainsLoop(instance, out foundEnd)) { FindLoopPairs(dependencyGraph[foundEnd], ref foundEnds, instance.Depth + 1); } instance.ContainedNodes = FindContainingNodeIds(instance.Start.NodeId, instance.End.NodeId); int start = 0, end = 0; foreach (NodeSlot nodes in instance.ContainedNodes) { if (dependencyGraph[nodes.NodeId].Type == LoopStart.TypeName) { start += 1; } else if (dependencyGraph[nodes.NodeId].Type == LoopEnd.TypeName) { end += 1; } } if (start != end) { throw new CoDependentLoopException(); } foundEnds.Add(instance.End.NodeId); instance.Start.AddLoopPair(ref instance); loopPairs.Add(instance); } } else if (loopEnd.Type == LoopStart.TypeName) { //abort as you are in the middle of a loop rather than at the end if (instance.End == null) { return; } } }
public LoopEnd(DependentNode node, LoopPair pair) { NodeId = node.Id; this.node = node; this.pair = pair; }