/// <summary> /// Gets all sub paths like path[1..n], path[2..n], path[3..n] to path[n-1..n] /// </summary> /// <param name="maxTrim">maximum amount to trim by, inclusive</param> /// <returns>enumerable of sub-paths</returns> public IEnumerable <CodePath> GetSubPaths(int maxTrim = -1) { var current = this.GetNextNode(this.FirstNode); var trimmed = 1; while (current != null) { var newCodePath = new CodePath(); newCodePath.FirstNode = current; newCodePath.LastNode = this.LastNode; newCodePath.treePath = new Dictionary <ulong, int>(this.treePath); newCodePath.Length = this.Length - trimmed; yield return(newCodePath); if (current == this.LastNode) { yield break; } current = this.GetNextNode(current); if (trimmed++ == maxTrim && maxTrim > 0) { yield break; } } }
public CodePath ConcatNew(CodePath other) { if (this.LastNode.NodeId == other.FirstNode.NodeId) { return(this); } var newPath = new CodePath(); newPath.FirstNode = this.FirstNode; var version = this.LastNode.AddNextNode(other.FirstNode); newPath.treePath = new Dictionary <ulong, int>(this.treePath); foreach (var kv in other.treePath) { if (!newPath.treePath.ContainsKey(kv.Key)) { newPath.treePath[kv.Key] = kv.Value; } } newPath.treePath[this.LastNode.NodeId] = version; newPath.LastNode = other.LastNode; newPath.Length = this.Length + other.Length; return(newPath); }
/// <summary> /// Creates a code path with a single method /// </summary> /// <param name="method">method to add</param> /// <returns>initialized code path</returns> public static CodePath FromSingleMethod(Method method) { var node = new MethodNode(method); var path = new CodePath { FirstNode = node, LastNode = node }; path.Length = 1; return(path); }
public CodePath Concat(CodePath other) { if (this.LastNode.NodeId == other.FirstNode.NodeId) { return(this); } var version = this.LastNode.AddNextNode(other.FirstNode); this.treePath[this.LastNode.NodeId] = version; this.LastNode = other.LastNode; this.Length += other.Length; return(this); }
/// <summary> /// Constructs the partial paths which forms the sub-graph of solution nodes /// </summary> /// <param name="start">starting method</param> /// <param name="end">ending method</param> /// <param name="cancellationToken">cancellation token</param> /// <returns>void Task</returns> public async Task ConstructPartialPaths(Method start, Method end, CancellationToken cancellationToken) { this.partialPaths = new List <CodePath>(); this.visited = new HashSet <Method>(); this.pathSolutionMap = new Dictionary <Method, List <CodePath> >(); this.solutionMethods = new HashSet <Method>(); this.completedMethods = new HashSet <Method>(); // left for potential future multi-threading support var proctor = new StackProctor(1); var stack = proctor.GetStack(0); stack.Push(CodePath.FromSingleMethod(start)); await Task.Run(() => RunSearchThread(end, proctor, 0, cancellationToken)); }
/// <summary> /// Compare the sort order for the two classes /// </summary> /// <param name="other">the class to compare to </param> /// <returns>0 for equal, -1 for other greater, 1 for this greater</returns> public int CompareTo(CodePath other) { var stringKeyBuilder1 = new StringBuilder(); var stringKeyBuilder2 = new StringBuilder(); foreach (var method in this) { stringKeyBuilder1.Append(method.FullName); } foreach (var method in other) { stringKeyBuilder2.Append(method.FullName); } var stringKey1 = stringKeyBuilder1.ToString(); var stringKey2 = stringKeyBuilder2.ToString(); return(stringKey1.CompareTo(stringKey2)); }
/// <summary> /// Adds a method to the end of this code path and returns new CodePath. /// Leaves the current instance unmodified /// </summary> /// <param name="node">method to add</param> /// <returns>cloned code path with new method added</returns> public CodePath AddLastNew(Method method) { if (this.FirstNode == null && this.LastNode == null) { return(FromSingleMethod(method)); } var @new = new CodePath(); var newNode = new MethodNode(method); @new.FirstNode = this.FirstNode; var version = this.LastNode.AddNextNode(newNode); @new.treePath = new Dictionary <ulong, int>(this.treePath); @new.treePath[this.LastNode.NodeId] = version; @new.LastNode = newNode; @new.Length = this.Length + 1; return(@new); }
/// <summary> /// The <see cref="path" /> parameter must end in either a goal method, /// or a known intermediate method. For each subsequence ending in the same /// method, add the beginning node to known solution nodes /// </summary> /// <param name="path">the path, and whose subpaths, to cache</param> private void AddPathToSolutionMap(CodePath path) { Method method = null; foreach (var subPath in path.GetSubPaths()) { if (method != null) { if (!pathSolutionMap.ContainsKey(method)) { pathSolutionMap[method] = new List <CodePath>(); } if (!pathSolutionMap[method].Contains(subPath)) { pathSolutionMap[method].Add(subPath); } solutionMethods.Add(method); } method = subPath.FirstMethod; } }