示例#1
0
        private Expression VisitYield(YieldExpression node)
        {
            var value = Visit(node.Value);

            var block = new List <Expression>();

            if (value == null)
            {
                // Yield break
                block.Add(MakeAssign(_state, AstUtils.Constant(Finished)));
                if (_inTryWithFinally)
                {
                    block.Add(Expression.Assign(_gotoRouter, AstUtils.Constant(GotoRouterYielding)));
                }
                block.Add(Expression.Goto(_returnLabels.Peek()));
                return(Expression.Block(block));
            }

            // Yield return
            block.Add(MakeAssign(_current, value));
            YieldMarker marker = GetYieldMarker(node);

            block.Add(MakeAssign(_state, AstUtils.Constant(marker.State)));
            if (_inTryWithFinally)
            {
                block.Add(Expression.Assign(_gotoRouter, AstUtils.Constant(GotoRouterYielding)));
            }
            block.Add(Expression.Goto(_returnLabels.Peek()));
            block.Add(Expression.Label(marker.Label));
            block.Add(Expression.Assign(_gotoRouter, AstUtils.Constant(GotoRouterNone)));
            block.Add(Utils.Empty());
            return(Expression.Block(block));
        }
示例#2
0
        private YieldMarker GetYieldMarker(YieldExpression node)
        {
            YieldMarker result = new YieldMarker(_yields.Count + 1);

            _yields.Add(result);
            Debug.Assert(node.YieldMarker == -1);
            return(result);
        }
示例#3
0
        private SwitchExpression MakeYieldRouter(Type type, int start, int end, LabelTarget newTarget)
        {
            Debug.Assert(end > start);
            var cases = new SwitchCase[end - start];

            for (int i = start; i < end; i++)
            {
                YieldMarker y = _yields[i];
                cases[i - start] = Expression.SwitchCase(Expression.Goto(y.Label, type), AstUtils.Constant(y.State));
                // Any jumps from outer switch statements should go to the this
                // router, not the original label (which they cannot legally jump to)
                y.Label = newTarget;
            }
            return(Expression.Switch(_gotoRouter, Expression.Default(type), cases));
        }
示例#4
0
        private YieldMarker GetYieldMarker(YieldExpression node)
        {
            YieldMarker result = new YieldMarker(_yields.Count + 1);

            _yields.Add(result);
            if (node.YieldMarker != -1)
            {
                if (_debugCookies == null)
                {
                    _debugCookies = new List <int>(1);
                    _debugCookies.Add(Int32.MaxValue);
                }
                _debugCookies.Insert(result.State, node.YieldMarker);
            }
            else
            {
                _debugCookies?.Insert(result.State, Int32.MaxValue);
            }
            return(result);
        }
示例#5
0
        private Expression VisitYield(YieldExpression node)
        {
            if (node.Target != _generator.Target)
            {
                throw new InvalidOperationException("yield and generator must have the same LabelTarget object");
            }

            var value = Visit(node.Value);

            var block = new ReadOnlyCollectionBuilder <Expression>();

            if (value == null)
            {
                // Yield break
                block.Add(Expression.Assign(_state, AstUtils.Constant(Finished)));
                if (_inTryWithFinally)
                {
                    block.Add(Expression.Assign(_gotoRouter, AstUtils.Constant(GotoRouterYielding)));
                }
                block.Add(Expression.Goto(_returnLabels.Peek()));
                return(Expression.Block(block));
            }

            // Yield return
            block.Add(MakeAssign(_current, value));
            YieldMarker marker = GetYieldMarker(node);

            block.Add(Expression.Assign(_state, AstUtils.Constant(marker.State)));
            if (_inTryWithFinally)
            {
                block.Add(Expression.Assign(_gotoRouter, AstUtils.Constant(GotoRouterYielding)));
            }
            block.Add(Expression.Goto(_returnLabels.Peek()));
            block.Add(Expression.Label(marker.Label));
            block.Add(Expression.Assign(_gotoRouter, AstUtils.Constant(GotoRouterNone)));
            block.Add(Utils.Empty());
            return(Expression.Block(block));
        }