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)); }
private YieldMarker GetYieldMarker(YieldExpression node) { YieldMarker result = new YieldMarker(_yields.Count + 1); _yields.Add(result); Debug.Assert(node.YieldMarker == -1); return(result); }
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)); }
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); }
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)); }