private ReturnTracerResult TraceFrom(int startAt, LinqList <Label> path, LinqHashSet <Label> pathLookup) { ReturnTracerResult cached; if (Cache.TryGetValue(startAt, out cached)) { return(cached); } var nextBranches = Branches.Where(b => b.Item3 >= startAt).GroupBy(g => g.Item3).OrderBy(x => x.Key).FirstOrDefault(); var orReturn = Returns.Where(ix => ix >= startAt && (nextBranches != null ? ix < nextBranches.Key : true)).Count(); var orThrow = Throws.Where(ix => ix >= startAt && (nextBranches != null ? ix < nextBranches.Key : true)).Count(); if (orReturn != 0) { Cache[startAt] = cached = ReturnTracerResult.Success(); return(cached); } if (orThrow != 0) { Cache[startAt] = cached = ReturnTracerResult.Success(); return(cached); } if (nextBranches == null) { Cache[startAt] = cached = ReturnTracerResult.Failure(path); return(cached); } var ret = new LinqList <ReturnTracerResult>(); foreach (var nextBranch in nextBranches) { if (pathLookup.Contains(nextBranch.Item2)) { Cache[startAt] = cached = ReturnTracerResult.Success(); ret.Add(cached); continue; } var branchOp = nextBranch.Item1; var branchTo = Marks[nextBranch.Item2]; var removeFromPathAt = path.Count; path.Add(nextBranch.Item2); pathLookup.Add(nextBranch.Item2); var fromFollowingBranch = TraceFrom(branchTo, path, pathLookup); path.RemoveAt(removeFromPathAt); pathLookup.Remove(nextBranch.Item2); if (IsUnconditionalBranch(branchOp)) { Cache[startAt] = cached = fromFollowingBranch; //return cached; ret.Add(cached); continue; } var fromFallingThrough = TraceFrom(startAt + 1, path, pathLookup); Cache[startAt] = cached = ReturnTracerResult.Combo(fromFallingThrough, fromFollowingBranch); ret.Add(cached); } Cache[startAt] = cached = ReturnTracerResult.Combo(ret.ToArray()); return(cached); }