Example #1
0
        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;
            }
        }
Example #2
0
        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;
 }