protected void Initialize(BaseControlFlowGraph source, IEnumerable<ControlFlowBlock> vertices, IEnumerable<ControlFlowEdge> edges, Action<ControlFlowEdge, ViewOfControlFlowGraph> onAlienEdge)
 {
     _hardcodedVertices = vertices != null ? vertices.ToHashSet() :
         (edges != null ? edges.SelectMany(e => new []{e.Source, e.Target}).ToHashSet() : null);
     var vertexFilter = _hardcodedVertices == null ? (cfb => true) : (Func<ControlFlowBlock, bool>)(cfb => _hardcodedVertices.Contains(cfb));
     _hardcodedEdges = edges == null ? null : edges.ToHashSet();
     var edgeFilter = edges == null ? (e => true) : ((Func<ControlFlowEdge, bool>)(e => _hardcodedEdges.Contains(e)));
     InitializeCore(source, vertexFilter, edgeFilter, onAlienEdge);
 }
예제 #2
0
        public ControlFlowGraph(BaseControlFlowGraph proto, bool deep)
            : base(proto, deep)
        {
            _start = proto.Start;
            _finish = proto.Finish;

            _allTimeVertexCounter = __vertices.Count();
            if (_start == null) _allTimeVertexCounter++;
            if (_finish == null) _allTimeVertexCounter++;
            HookUpVertexPostprocessors();
        }
예제 #3
0
        private IfScope(BlockScope parent, ControlFlowBlock head)
        {
            _parent = parent.AssertNotNull();
            _head   = head.AssertNotNull();

            parent.Hir.AddElements(head.BalancedCode);
            _if.Test = head.Residue.AssertSingle();

            var v_true = LocalCfg.TreeVedges(head, null).AssertSingle(e => e.Tag == PredicateType.IsTrue).Target;

            _ifTrue = this.InferBranch(v_true, out _trueOffsprings);
            var v_false = LocalCfg.TreeVedges(head, null).AssertSingle(e => e.Tag == PredicateType.IsFalse).Target;

            _ifFalse = this.InferBranch(v_false, out _falseOffsprings);

            _if.IfTrue  = BlockScope.Decompile(this, _ifTrue).Hir;
            _if.IfFalse = BlockScope.Decompile(this, _ifFalse).Hir;
        }
예제 #4
0
        private ComplexScope(IScope parent, BaseControlFlowGraph cfg)
        {
            _parent   = parent.AssertNotNull();
            _localCfg = cfg;
            var offsprings = new List <Offspring>();

            var adjacentToFinish = cfg.Vedges(null, cfg.Finish).Select(e => e.Source).ToReadOnly();
            var lastInFlow       = cfg.Cflow()[adjacentToFinish.Max(v => cfg.Cflow().IndexOf(v))];

            if (lastInFlow != cfg.Start)
            {
                var flow = lastInFlow.MkArray().Closure(cfg.Vertices,
                                                        (vin, vout) => vout != cfg.Start && cfg.Vedge(vout, vin) != null);
                _localCfg = cfg.CreateView(flow, (e, vcfg) =>
                {
                    if (e.Source == cfg.Start)
                    {
                        vcfg.InheritStart(cfg.Start);
                        vcfg.AddEigenEdge(e.ShallowClone());
                    }
                    else if (e.Target == cfg.Finish)
                    {
                        if (e.Source == lastInFlow)
                        {
                            vcfg.InheritFinish(cfg.Finish);
                        }
                        vcfg.AddEigenEdge(e.ShallowClone());
                    }
                    else
                    {
                        (cfg.Vedges(e.Source, null).Count() == 2).AssertTrue();
                        offsprings.Add(new Offspring(this, e.Source, e.Target));
                    }
                });
            }

            Offsprings = offsprings.ToReadOnly();
            _block     = BlockScope.Decompile(this, _localCfg).Hir;
        }
 public ViewOfControlFlowGraph(BaseControlFlowGraph source, IEnumerable<ControlFlowBlock> vertices, IEnumerable<ControlFlowEdge> edges, Action<ControlFlowEdge, ViewOfControlFlowGraph> onAlienEdge) { Initialize(source, vertices, edges, onAlienEdge); }
 protected void Initialize(BaseControlFlowGraph source, Func<ControlFlowBlock, bool> vertexFilter, Func<ControlFlowEdge, bool> edgeFilter, Action<ControlFlowEdge, ViewOfControlFlowGraph> onAlienEdge)
 {
     vertexFilter = vertexFilter ?? (cfb => true);
     edgeFilter = edgeFilter ?? (e => true);
     InitializeCore(source, vertexFilter, edgeFilter, onAlienEdge);
 }
 protected void Initialize(BaseControlFlowGraph source, Func<ControlFlowBlock, bool> vertexFilter, Func<ControlFlowEdge, bool> edgeFilter)
 {
     Initialize(source, vertexFilter, edgeFilter, (e, _) => { throw AssertionHelper.Fail(); });
 }
 protected void Initialize(BaseControlFlowGraph source, Func<ControlFlowEdge, bool> edgeFilter, Action<ControlFlowEdge, ViewOfControlFlowGraph> onAlienEdge)
 {
     Initialize(source, (IEnumerable<ControlFlowBlock>)null, edgeFilter, onAlienEdge);
 }
        private void InitializeCore(
            BaseControlFlowGraph source,
            Func<ControlFlowBlock, bool> vertexFilter,
            Func<ControlFlowEdge, bool> edgeFilter,
            Action<ControlFlowEdge, ViewOfControlFlowGraph> onAlienEdge)
        {
            Source = source.AssertNotNull();
            HookUpVertexPostprocessors();

            _vertexFilter = vertexFilter.AssertNotNull();
            _edgeFilter = edgeFilter.AssertNotNull();

            _cachedVertices = _hardcodedVertices != null ? null : source.Vertices.Where(_vertexFilter).ToList();
            (_cachedVertices ?? _hardcodedVertices.AsEnumerable()).ForEach(OnVertexAdded);

            ReadOnlyCollection<ControlFlowEdge> alienEdges = null;
            if (_hardcodedEdges != null)
            {
                var edgeVertices = _hardcodedEdges.SelectMany(e => new []{e.Source, e.Target}).ToHashSet();
                edgeVertices.ExceptWith(_cachedVertices ?? _hardcodedVertices.AsEnumerable());
                edgeVertices.AssertEmpty();
            }
            else
            {
                _edgeFilter = e => edgeFilter(e) && _vertexFilter(e.Source) && _vertexFilter(e.Target);

                var relatedEdges = source.Edges(_vertexFilter, null).Concat(source.Edges(null, _vertexFilter)).Distinct();
                var parts = relatedEdges.GroupBy(e => _edgeFilter(e)).ToDictionary(g => g.Key, g => g.AsEnumerable());
                _cachedEdges = (parts.GetOrDefault(true, Seq.Empty<ControlFlowEdge>)).ToList();
                alienEdges = parts.GetOrDefault(false, Seq.Empty<ControlFlowEdge>).ToReadOnly();
            }
            (_cachedEdges ?? _hardcodedEdges.AsEnumerable()).ForEach(OnEdgeAdded);

            Action<ControlFlowBlock> cacheVertex = v => { if (_cachedVertices != null) _cachedVertices.Add(v); else throw AssertionHelper.Fail(); };
            Action<ControlFlowBlock> uncacheVertex = v => { if (_cachedVertices != null) _cachedVertices.Remove(v); else _hardcodedVertices.Remove(v); };
            source.VertexAdded += v => { if (_vertexFilter(v)) { cacheVertex(v); OnVertexAdded(v); } };
            source.VertexRemoved += v => { if (_vertexFilter(v)) { uncacheVertex(v); OnVertexRemoved(v); } };

            Action<ControlFlowEdge> cacheEdge = e => { if (_cachedEdges != null) _cachedEdges.Add(e); else throw AssertionHelper.Fail(); };
            Action<ControlFlowEdge> uncacheEdge = e => { if (_cachedEdges != null) _cachedEdges.Remove(e); else _hardcodedEdges.Remove(e); };
            source.EdgeAdded += e => { if (_edgeFilter(e)) { cacheEdge(e); OnEdgeAdded(e); } };
            source.EdgeRemoved += e => { if (_edgeFilter(e)) { uncacheEdge(e); OnEdgeRemoved(e); } };

            __vertices = new VirtualList<ControlFlowBlock>(
                () => (_hardcodedVertices ?? (IEnumerable<ControlFlowBlock>)_cachedVertices).Concat(_eigenVertices),
                (i, v) =>
                {
                    if (_eigenVertices.Contains(v))
                    {
                        // do nothing - the vertex has just been created by AddEigenVertex
                    }
                    else
                    {
                        _vertexFilter(v).AssertTrue();
                        (_cachedVertices != null && i == _cachedVertices.Count()).AssertTrue();
                        Source.AddVertex(v);
                    }
                },
                (i, v) => { _vertexFilter(v).AssertTrue(); throw AssertionHelper.Fail(); },
                i =>
                {
                    if (i < _cachedEdges.Count())
                    {
                        var v = _cachedVertices[i];
                        Source.RemoveVertex(v);
                    }
                    else
                    {
                        throw AssertionHelper.Fail();
                    }
                });

            __edges = new VirtualList<ControlFlowEdge>(
                () => (_hardcodedEdges ?? (IEnumerable<ControlFlowEdge>)_cachedEdges).Concat(_eigenEdges),
                (i, e) =>
                {
                    if (_eigenEdges.Contains(e))
                    {
                        // do nothing - the edge has just been created by AddEigenEdge
                    }
                    else
                    {
                        _edgeFilter(e).AssertTrue();
                        (_cachedEdges != null && i == _cachedEdges.Count()).AssertTrue();
                        Source.AddEdge(e);
                    }
                },
                (i, e) => { _edgeFilter(e).AssertTrue(); throw AssertionHelper.Fail(); },
                i =>
                {
                    if (i < _cachedEdges.Count())
                    {
                        var e = _cachedEdges[i];
                        Source.RemoveEdge(e);
                    }
                    else
                    {
                        var e = _eigenEdges[i - _cachedEdges.Count()];
                        _eigenEdges.Remove(e);
                    }
                });

            try { _allowAutoCreateStartAndFinish = true; alienEdges.ForEach(e => onAlienEdge(e, this)); }
            finally { _allowAutoCreateStartAndFinish = false; }
        }
 protected void Initialize(BaseControlFlowGraph source, IEnumerable<ControlFlowBlock> vertices, Func<ControlFlowEdge, bool> edgeFilter, Action<ControlFlowEdge, ViewOfControlFlowGraph> onAlienEdge)
 {
     _hardcodedVertices = vertices == null ? null : vertices.ToHashSet();
     var vertexFilter = _hardcodedVertices == null ? (cfb => true) : (Func<ControlFlowBlock, bool>)(cfb => _hardcodedVertices.Contains(cfb));
     InitializeCore(source, vertexFilter, edgeFilter, onAlienEdge);
 }
 protected void Initialize(BaseControlFlowGraph source, IEnumerable<ControlFlowBlock> vertices, Func<ControlFlowEdge, bool> edgeFilter)
 {
     Initialize(source, vertices, edgeFilter, (v, _) => { throw AssertionHelper.Fail(); });
 }
 public ViewOfControlFlowGraph(BaseControlFlowGraph source, IEnumerable<ControlFlowBlock> vertices, Func<ControlFlowEdge, bool> edgeFilter) { Initialize(source, vertices, edgeFilter); }
 protected void Initialize(BaseControlFlowGraph source, Func<ControlFlowBlock, bool> vertexFilter, IEnumerable<ControlFlowEdge> edges, Action<ControlFlowEdge, ViewOfControlFlowGraph> onAlienEdge)
 {
     _hardcodedEdges = edges == null ? null : edges.ToHashSet();
     var edgeFilter = edges == null ? (e => true) : ((Func<ControlFlowEdge, bool>)(e => _hardcodedEdges.Contains(e)));
     InitializeCore(source, vertexFilter, edgeFilter, onAlienEdge);
 }
        // hybrids

        public ViewOfControlFlowGraph(BaseControlFlowGraph source, Func<ControlFlowBlock, bool> vertexFilter, IEnumerable<ControlFlowEdge> edges) { Initialize(source, vertexFilter, edges); }
 protected void Initialize(BaseControlFlowGraph source, Func<ControlFlowBlock, bool> vertexFilter)
 {
     Initialize(source, vertexFilter, (IEnumerable<ControlFlowEdge>)null);
 }
 protected void Initialize(BaseControlFlowGraph source, IEnumerable<ControlFlowBlock> vertices)
 {
     Initialize(source, vertices, (IEnumerable<ControlFlowEdge>)null);
 }
 protected void Initialize(BaseControlFlowGraph source, Func<ControlFlowEdge, bool> edgeFilter)
 {
     Initialize(source, (IEnumerable<ControlFlowBlock>)null, edgeFilter);
 }
 protected void Initialize(BaseControlFlowGraph source, IEnumerable<ControlFlowBlock> vertices, Action<ControlFlowEdge, ViewOfControlFlowGraph> onAlienEdge)
 {
     Initialize(source, vertices, (IEnumerable<ControlFlowEdge>)null, onAlienEdge);
 }
 public ViewOfControlFlowGraph(BaseControlFlowGraph source, Func<ControlFlowBlock, bool> vertexFilter, Func<ControlFlowEdge, bool> edgeFilter) { Initialize(source, vertexFilter, edgeFilter); }
 protected void Initialize(BaseControlFlowGraph source, IEnumerable<ControlFlowEdge> edges)
 {
     Initialize(source, (IEnumerable<ControlFlowBlock>)null, edges);
 }
 public ViewOfControlFlowGraph(BaseControlFlowGraph source, Func<ControlFlowBlock, bool> vertexFilter, Func<ControlFlowEdge, bool> edgeFilter, Action<ControlFlowEdge, ViewOfControlFlowGraph> onAlienEdge) { Initialize(source, vertexFilter, edgeFilter, onAlienEdge); }
 public ViewOfControlFlowGraph(BaseControlFlowGraph source, IEnumerable<ControlFlowBlock> vertices, IEnumerable<ControlFlowEdge> edges) { Initialize(source, vertices, edges); }
예제 #23
0
 public static ComplexScope Decompile(IScope parent, BaseControlFlowGraph cfg)
 {
     return(new ComplexScope(parent, cfg));
 }
 protected void Initialize(BaseControlFlowGraph source, IEnumerable<ControlFlowBlock> vertices, IEnumerable<ControlFlowEdge> edges)
 {
     Initialize(source, vertices, edges, (e, _) => { throw AssertionHelper.Fail(); });
 }
예제 #25
0
        private LoopScope(BlockScope parent, ControlFlowBlock head)
        {
            _parent = parent.AssertNotNull();
            _head   = head.AssertNotNull();

            var cfg         = LocalCfg;
            var jumpsToHead = cfg.BackVedges(null, _head).Select(e => e.Source).ToReadOnly();

            jumpsToHead.AssertNotEmpty();
            _bot = jumpsToHead.OrderBy(v => cfg.Cflow().IndexOf(v)).Last();
            var cflow = cfg.Cflow(_head, _bot);

            // todo. check this
            //
            // all loops can be divided into four categories:
            // 1) while-do (head is test, either bot or head is continue label),
            // 2) while-true (neither head, nor bot are tests; actually, head is hardcoded to "CS$... = 1"
            //    also either bot or head serve as continue label),
            // 3) do-while (bot is test, it is also the only option for continue
            //    (since here we don't need to separate iteration block from other body instructions,
            //     and because of (nota bene - never knew it) the fact that continue in do-while
            //     first tests exit condition and only then proceeds with the next iteration),
            // 4) some loop with offspring embedded into either head or bot
            //
            // in the first two cases before proceeding to detect subscopes and offsprings
            // we need to find out what's the continue label. that's done as follows.
            // todo. we don't process case #4, since that's just too much for me
            //
            // if cflow features multiple jumps to head, then head is a continue label
            // else (if there's only one jump, i.e. from bot), then bot is a continue label
            //
            // now how we distinguish an offspring from loop's body?
            // answer: using regular closure algorithm, i.e.
            // 1) we pick a bot2 vertex (see below for options),
            // 2) we init the closure with cflow(head, bot2) + bot2
            // 3) we expand the closure using universum of parent's local cfg
            // 4) ... and relation of being reachable w/o touching _test and _iter
            //
            // so, bot2 is a logical bottom of the loop's body (while iter exists on its own!)
            // 1) if bot ain't a continue label, then bot2 = bot
            // 2) if bot is a continue label, then check number of jumps to bot
            // 3) if the latter is one, then bot2 = bot
            // 4) else bot2 = the last one that jumps to bot
            //
            // ah, the last point... how do we find convergence?
            // for cases 1 and 3 conv is the node that receives a jump from either head or bot
            // for case 2 conv is the node that receives a jump from the loop's body
            // todo. here we use a hack, assuming that there's exactly 1 jump from the loop's body
            // if there're two or more jumps we will just work incorrectly
            // if there're zero jumps, then it's fail anyways, since we've just entered an infinite loop

            // todo. also verify that test has supported type
            // also don't forget that IL allows using almost everything as a condition of a test
            // cf. brzero === brnull === brfalse, brtrue === brinst

            var hcond = _head.Residue.IsNotEmpty();
            var bcond = _bot.Residue.IsNotEmpty();

            (hcond && bcond).AssertFalse();

            // case #1. while-do
            if (hcond && !bcond)
            {
                _loop.IsWhileDo = true;
                _test           = _head;

                _loop.Test = _test.Residue.AssertSingle();
                parent.Hir.AddElements(_test.BalancedCode);

                var next1 = cfg.Vedges(_test, null).First().Target;
                var next2 = cfg.Vedges(_test, null).Second().Target;
                (cflow.Contains(next1) || cflow.Contains(next2)).AssertTrue();
                _conv     = cflow.Contains(next1) ? next2 : next1;
                _bodyHead = cflow.Contains(next1) ? next1 : next2;

                var botIsContinue = jumpsToHead.Count() == 1;
                if (botIsContinue)
                {
                    var jumpsToBot    = cfg.Vedges(null, _bot).Select(e => e.Source).ToReadOnly();
                    var lastJumpToBot = jumpsToBot.OrderBy(v => cfg.Cflow().IndexOf(v)).Last();

                    _continue = jumpsToBot.Count() > 1 ? _bot : null;
                    _bodyBot  = jumpsToBot.Count() > 1 ? lastJumpToBot : _bot;
                }
                else
                {
                    _continue = _head;
                    _bodyBot  = _bot;
                }
            }
            // case #2. while-true
            else if (!hcond && !bcond)
            {
                _head.Residue.AssertEmpty();
                var es  = _head.BalancedCode.AssertSingle();
                var ass = es.AssertCast <Assign>();
                (ass.Rhs.AssertCast <Const>().Value.AssertCast <int>() == 1).AssertTrue();

                _loop.IsWhileDo = true;
                _loop.Test      = new Const(true);
                _test           = _head;

                // todo. here we use a hack, assuming that there's exactly 1 jump from the loop's body
                var alienEdges = cfg.AlienEdges(cflow);
                var breaks     = alienEdges.Except(cfg.Vedges(null, _head), cfg.Vedges(null, _bot));
                _conv     = breaks.Select(e => e.Target).Distinct().AssertSingle();
                _bodyHead = cfg.Vedges(_head, null).AssertSingle().Target;

                var botIsContinue = jumpsToHead.Count() == 1;
                if (botIsContinue)
                {
                    var jumpsToBot    = cfg.Vedges(null, _bot).Select(e => e.Source).ToReadOnly();
                    var lastJumpToBot = jumpsToBot.OrderBy(v => cfg.Cflow().IndexOf(v)).Last();

                    _continue = (botIsContinue && jumpsToBot.Count() > 1) ? _bot : null;
                    _bodyBot  = (botIsContinue && jumpsToBot.Count() > 1) ? lastJumpToBot : _bot;
                }
                else
                {
                    _continue = _head;
                    _bodyBot  = _bot;
                }
            }
            // case #3: do-while
            else if (!hcond && bcond)
            {
                _loop.IsDoWhile = true;
                _test           = _bot;

                _loop.Test = _test.Residue.AssertSingle();
                parent.Hir.AddElements(_test.BalancedCode);

                var next1 = cfg.Vedges(_test, null).First().Target;
                var next2 = cfg.Vedges(_test, null).Second().Target;
                (cflow.Contains(next1) || cflow.Contains(next2)).AssertTrue();
                _conv     = cflow.Contains(next1) ? next2 : next1;
                _bodyHead = cflow.Contains(next1) ? next1 : next2;

                var jumpsToBot = cfg.Vedges(null, _bot).Select(e => e.Source).ToReadOnly();
                _continue = jumpsToBot.Count() == 1 ? null : _bot;
                _bodyBot  = jumpsToBot.OrderBy(v => cfg.Cflow().IndexOf(v)).Last();
            }
            // case #4: mysterious loop
            else
            {
                // todo. we don't process case #4, since that's just too much for me now
                throw AssertionHelper.Fail();
            }

            // here we need to pass a hint to DoDecompileScopesForLoopLocals
            if (_continue != null)
            {
                if (_continue == _test)
                {
                    _loop.Iter.Add(null);
                }
                else
                {
                    _loop.Iter.SetElements(_continue.AssertThat(cfb => cfb.Residue.IsEmpty()).BalancedCode);
                }
            }

            _body      = this.InferBody(out _offsprings);
            _loop.Body = BlockScope.Decompile(this, _body).Hir;
        }
예제 #26
0
        private BlockScope(IScope parent, BaseControlFlowGraph cfg)
        {
            _parent   = parent.AssertNotNull();
            _localCfg = cfg;

            var offspringsRecursive = new Dictionary <ControlFlowBlock, Offspring>();

            this.Hierarchy().ForEach(s => s.Offsprings.ForEach(off => offspringsRecursive.Add(off.Root, off)));
            var pivotsRecursive = new Dictionary <ControlFlowBlock, IScope>();

            this.Parents().Reverse().ForEach(p => p.Pivots.ForEach(cfb => pivotsRecursive[cfb] = p));

            var cflow    = _localCfg.Cflow().Except(cfg.Start).ToReadOnly();
            var todo     = cflow.ToList();
            var expected = todo.First();

            while (todo.IsNotEmpty())
            {
                var curr = todo.First();
                (expected == curr).AssertTrue();
                todo.Remove(curr);

                var offspring = offspringsRecursive.GetOrDefault(curr);
                if (offspring != null)
                {
                    var parentCfg = offspring.Scope.Parent.LocalCfg;
                    (parentCfg.Vedges(curr, null).Count() == 2).AssertTrue();
                    (parentCfg.BackVedges(null, curr).Count() == 0).AssertTrue();
                    var localEdge = cfg.Vedges(curr, null).AssertSingle();
                    localEdge.IsConditional.AssertTrue();
                    expected = localEdge.Target;

                    _block.AddElements(curr.BalancedCode);
                    var test = curr.Residue.AssertSingle();
                    test = localEdge.Condition == PredicateType.IsTrue ? Operator.Not(test) :
                           localEdge.Condition == PredicateType.IsFalse ? test :
                           ((Func <Expression>)(() => { throw AssertionHelper.Fail(); }))();
                    _block.AddElements(new If(test, ComplexScope.Decompile(this, offspring).Hir));
                }
                else
                {
                    if (_localCfg.BackVedges(null, curr).IsNotEmpty())
                    {
                        var loop = LoopScope.Decompile(this, curr);
                        todo.RemoveElements(loop.Test, loop.Continue);
                        todo.RemoveElements(loop.Body.Vertices);
                        todo.RemoveElements(loop.Offsprings.SelectMany(off => off.Body));

                        _block.AddElements(loop.Hir);
                        expected = loop.Conv;
                    }
                    else if (_localCfg.Vedges(curr, null).Count() >= 2)
                    {
                        (_localCfg.TreeVedges(curr, null).Count() == 2).AssertTrue();
                        (_localCfg.BackVedges(curr, null).Count() == 0).AssertTrue();

                        var @if = IfScope.Decompile(this, curr);
                        todo.RemoveElements(@if.Test);
                        todo.RemoveElements(@if.IfTrue.Vertices);
                        todo.RemoveElements(@if.IfFalse.Vertices);
                        todo.RemoveElements(@if.Offsprings.SelectMany(off => off.Body));

                        _block.AddElements(@if.Hir);
                        expected = @if.Conv;
                    }
                    else
                    {
                        (_localCfg.TreeVedges(curr, null).Count() <= 1).AssertTrue();
                        (_localCfg.BackVedges(curr, null).Count() == 0).AssertTrue();
                        var e_next = _localCfg.TreeVedges(curr, null).SingleOrDefault();
                        (e_next == null).AssertEquiv(todo.IsEmpty());
                        expected = e_next == null ? null : e_next.Target;

                        var isPivot = pivotsRecursive.ContainsKey(curr);
                        isPivot.AssertImplies(e_next == null);
                        if (!isPivot)
                        {
                            _block.AddElements(curr.BalancedCode);
                            if (curr.Residue.IsNotEmpty())
                            {
                                var nextIsRetOf = pivotsRecursive.GetOrDefault(expected) as LambdaScope;
                                (nextIsRetOf != null && nextIsRetOf.Return == expected).AssertTrue();
                                _block.Add(curr.Residue.AssertSingle());
                            }
                        }
                        else
                        {
                            var scope = pivotsRecursive[curr];
                            if (scope is LambdaScope)
                            {
                                var lambda = scope.AssertCast <LambdaScope>();
                                if (curr == lambda.Return)
                                {
                                    var i_curr            = cflow.IndexOf(curr).AssertThat(i => i != -1);
                                    var prev              = cflow.NthOrDefault(i_curr - 1);
                                    var prevWasExpression = _block.LastOrDefault() is Expression;
                                    var prevHasResidue    = prev != null && prev.Residue.IsNotEmpty();

                                    if (prevWasExpression && prevHasResidue)
                                    {
                                        var valueToRet = _block.Last().AssertCast <Expression>();
                                        _block.RemoveLast();
                                        _block.Add(new Return(valueToRet.DeepClone()));
                                    }
                                    else
                                    {
                                        var complex       = parent as ComplexScope;
                                        var global        = complex == null ? null : complex.Parent as LambdaScope;
                                        var canOmitReturn = global != null && global.Return == curr;
                                        if (!canOmitReturn)
                                        {
                                            _block.Add(new Return());
                                        }
                                    }
                                }
                                else
                                {
                                    throw AssertionHelper.Fail();
                                }
                            }
                            else if (scope is LoopScope)
                            {
                                var loop = scope.AssertCast <LoopScope>();
                                (loop == this.Parents().OfType <LoopScope>().First()).AssertTrue();
                                if (curr == loop.Continue)
                                {
                                    _block.Add(new Continue());
                                }
                                else if (curr == loop.Conv)
                                {
                                    _block.Add(new Break());
                                }
                                else
                                {
                                    throw AssertionHelper.Fail();
                                }
                            }
                            else
                            {
                                throw AssertionHelper.Fail();
                            }
                        }
                    }
                }
            }
        }