Exemplo n.º 1
0
        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);
        }