internal override MSAst.Expression Transform(AstGenerator ag, Type type) { MSAst.Expression left = ag.Transform(_left); MSAst.Expression right = ag.Transform(_right); Type t = left.Type == right.Type ? left.Type : typeof(object); MSAst.ParameterExpression tmp = ag.GetTemporary("__all__", t); return Ast.Condition( Binders.Convert( ag.BinderState, typeof(bool), ConversionResultKind.ExplicitCast, AstUtils.Assign( tmp, AstUtils.Convert( left, t ) ) ), AstUtils.Convert( right, t ), tmp ); }
internal override MSAst.Expression Transform(AstGenerator ag) { MSAst.Expression result; if (_else != null) { result = ag.Transform(_else); } else { result = Ast.Empty(); } // Now build from the inside out int i = _tests.Length; while (i-- > 0) { IfStatementTest ist = _tests[i]; result = ag.AddDebugInfo( Ast.Condition( ag.TransformAndDynamicConvert(ist.Test, typeof(bool)), ag.Transform(ist.Body), result ), new SourceSpan(ist.Start, ist.Header) ); } return result; }
internal override MSAst.Expression TransformSet(AstGenerator ag, SourceSpan span, MSAst.Expression right, Operators op) { if (op == Operators.None) { return ag.AddDebugInfoAndVoid( Binders.Set( ag.BinderState, typeof(object), SymbolTable.IdToString(_name), ag.Transform(_target), right ), span ); } else { MSAst.ParameterExpression temp = ag.GetTemporary("inplace"); return ag.AddDebugInfo( Ast.Block( Ast.Assign(temp, ag.Transform(_target)), SetMemberOperator(ag, right, op, temp), Ast.Empty() ), Span.Start, span.End ); } }
internal override MSAst.Expression Transform(AstGenerator ag, Type type) { return ag.Get( type, SymbolTable.IdToString(_name), ag.Transform(_target) ); }
private static MSAst.Expression GetSliceValue(AstGenerator ag, Expression expr) { if (expr != null) { return ag.Transform(expr); } return Ast.Field(null, typeof(MissingParameter).GetField("Value")); }
internal override MSAst.Expression Transform(AstGenerator ag, Type type) { return ag.Operation( type, PythonOperatorToOperatorString(_op), ag.Transform(_expression) ); }
internal override MSAst.Expression Transform(AstGenerator ag, Type type) { return ag.Get( type, _name, ag.Transform(_target) ); }
internal override MSAst.Expression Transform(AstGenerator ag) { if (_left.Length == 1) { // Do not need temps for simple assignment return AssignOne(ag); } else { return AssignComplex(ag, ag.Transform(_right)); } }
internal override MSAst.Expression Transform(AstGenerator ag) { // Only the body is "in the loop" for the purposes of break/continue // The "else" clause is outside MSAst.LabelTarget breakLabel, continueLabel; ConstantExpression constTest = _test as ConstantExpression; if (constTest != null && constTest.Value is int) { // while 0: / while 1: int val = (int)constTest.Value; if (val == 0) { // completely optimize the loop away if (_else == null) { return MSAst.Expression.Empty(); } else { return ag.Transform(_else); } } MSAst.Expression test = MSAst.Expression.Constant(true); MSAst.Expression res = AstUtils.While( test, ag.TransformLoopBody(_body, SourceLocation.Invalid, out breakLabel, out continueLabel), ag.Transform(_else), breakLabel, continueLabel ); if (_test.Start.Line != _body.Start.Line) { res = ag.AddDebugInfo(res, _test.Span); } return res; } return AstUtils.While( ag.AddDebugInfo( ag.TransformAndDynamicConvert(_test, typeof(bool)), Header ), ag.TransformLoopBody(_body, _test.Start, out breakLabel, out continueLabel), ag.Transform(_else), breakLabel, continueLabel ); }
private MSAst.Expression[] GetActionArgumentsForGetOrDelete(AstGenerator ag) { TupleExpression te = _index as TupleExpression; if (te != null && te.IsExpandable) { return ArrayUtils.Insert(AstUtils.CodeContext(), ag.Transform(_target), ag.Transform(te.Items)); } SliceExpression se = _index as SliceExpression; if (se != null) { if (se.StepProvided) { return new MSAst.Expression[] { AstUtils.CodeContext(), ag.Transform(_target), GetSliceValue(ag, se.SliceStart), GetSliceValue(ag, se.SliceStop), GetSliceValue(ag, se.SliceStep) }; } return new MSAst.Expression[] { AstUtils.CodeContext(), ag.Transform(_target), GetSliceValue(ag, se.SliceStart), GetSliceValue(ag, se.SliceStop) }; } return new MSAst.Expression[] { AstUtils.CodeContext(), ag.Transform(_target), ag.Transform(_index) }; }
internal Argument Transform(AstGenerator ag, out MSAst.Expression expression) { expression = ag.Transform(_expression); if (_name == null) { return Argument.Simple; } else if (_name == "*") { return new Argument(ArgumentType.List); } else if (_name == "**") { return new Argument(ArgumentType.Dictionary); } else { return new Argument(_name); } }
internal override MSAst.Expression Transform(AstGenerator ag) { MSAst.Expression expression = ag.Transform(_expression); if (ag.PrintExpressions) { expression = Ast.Call( AstGenerator.GetHelperMethod("PrintExpressionValue"), ag.LocalContext, AstGenerator.ConvertIfNeeded(expression, typeof(object)) ); } return ag.AddDebugInfoAndVoid(expression, _expression.Span); }
internal Argument Transform(AstGenerator ag, out MSAst.Expression expression) { expression = ag.Transform(_expression); if (_name == SymbolId.Empty) { return Argument.Simple; } else if (_name == Symbols.Star) { return new Argument(ArgumentType.List); } else if (_name == Symbols.StarStar) { return new Argument(ArgumentType.Dictionary); } else { return new Argument(_name); } }
internal override MSAst.Expression TransformSet(AstGenerator ag, SourceSpan span, MSAst.Expression right, PythonOperationKind op) { if (op == PythonOperationKind.None) { return ag.AddDebugInfoAndVoid( ag.Set( typeof(object), _name, ag.Transform(_target), right ), span ); } else { MSAst.ParameterExpression temp = ag.GetTemporary("inplace"); return ag.AddDebugInfo( Ast.Block( Ast.Assign(temp, ag.Transform(_target)), SetMemberOperator(ag, right, op, temp), AstUtils.Empty() ), Span.Start, span.End ); } }
internal override MSAst.Expression Transform(AstGenerator ag, Type type) { MSAst.Expression res; if (Op == PythonOperator.Not) { Debug.Assert(type == typeof(object) || type == typeof(bool)); if (type == typeof(bool)) { res = ag.Operation(typeof(bool), PythonOperationKind.Not, ag.Transform(_expression)); } else { res = ag.Operation(typeof(object), PythonOperationKind.NotRetObject, ag.Transform(_expression)); } } else { res = ag.Operation( typeof(object), PythonOperatorToOperatorString(_op), ag.Transform(_expression) ); if (type != typeof(object)) { res = ag.Convert(type, Microsoft.Scripting.Actions.ConversionResultKind.ExplicitCast, res); } } return res; }
internal override MSAst.Expression Transform(AstGenerator ag) { if (_statements.Length == 0) { return AstGenerator.EmptyBlock; } var stmts = ag.Transform(_statements); foreach (MSAst.Expression stmt in stmts) { if (stmt == null) { // error was encountered and added to sync, // don't return any of the block return null; } } return Ast.Block(stmts); }
internal override MSAst.Expression Transform(AstGenerator ag) { // Only the body is "in the loop" for the purposes of break/continue // The "else" clause is outside MSAst.LabelTarget breakLabel, continueLabel; MSAst.Expression body = ag.TransformLoopBody(_body, out breakLabel, out continueLabel); return AstUtils.While( ag.AddDebugInfo( ag.TransformAndDynamicConvert(_test, typeof(bool)), Header ), body, ag.Transform(_else), breakLabel, continueLabel ); }
internal override MSAst.Expression Transform(AstGenerator ag, Type type) { MSAst.Expression[] values = new MSAst.Expression[_args.Length + 2]; Argument[] kinds = new Argument[_args.Length]; values[0] = ag.LocalContext; values[1] = ag.Transform(_target); for (int i = 0; i < _args.Length; i++) { kinds[i] = _args[i].Transform(ag, out values[i + 2]); } return ag.Invoke( type, new CallSignature(kinds), ArrayUtils.RemoveFirst(values) ); }
internal override MSAst.Expression Transform(AstGenerator ag, Type type) { // (yield z) becomes: // .comma (1) { // .void ( .yield_statement (_expression) ), // $gen.CheckThrowable() // <-- has return result from send // } return Ast.Block( ag.AddDebugInfo( AstUtils.YieldReturn( ag.GeneratorLabel, AstUtils.Convert(ag.Transform(_expression), typeof(object)) ), Span ), CreateCheckThrowExpression(ag, Span) // emits ($gen.CheckThrowable()) ); }
internal override MSAst.Expression Transform(AstGenerator ag) { if (_statements.Length == 0) { return AstGenerator.EmptyBlock; } MSAst.Expression[] stmts = ag.Transform(_statements); if (stmts.Length == 0) { return AstUtils.Empty(); } foreach (MSAst.Expression stmt in stmts) { if (stmt == null) { // error was encountered and added to sync, // don't return any of the block return null; } } return AstUtils.Void(Ast.Block(new ReadOnlyCollection<MSAst.Expression>(stmts))); }
internal override MSAst.Expression Transform(AstGenerator ag) { // allocated all variables here so they won't be shared w/ other // locals allocated during the body or except blocks. MSAst.ParameterExpression noNestedException = null; if (_finally != null) { noNestedException = ag.GetTemporary("$noException", typeof(bool)); } MSAst.ParameterExpression lineUpdated = null; MSAst.ParameterExpression runElse = null; if (_else != null || (_handlers != null && _handlers.Length > 0)) { lineUpdated = ag.GetTemporary("$lineUpdated", typeof(bool)); if (_else != null) { runElse = ag.GetTemporary("run_else", typeof(bool)); } } // don't allocate locals below here... MSAst.Expression body = ag.Transform(_body); MSAst.Expression @else = ag.Transform(_else); if (body == null) { return null; } MSAst.ParameterExpression exception; MSAst.Expression @catch = TransformHandlers(ag, out exception); MSAst.Expression result; // We have else clause, must generate guard around it if (@else != null) { Debug.Assert(@catch != null); // run_else = true; // try { // try_body // } catch ( ... ) { // run_else = false; // catch_body // } // if (run_else) { // else_body // } result = Ast.Block( Ast.Assign(runElse, Ast.Constant(true)), // save existing line updated, we could choose to do this only for nested exception handlers. ag.PushLineUpdated(false, lineUpdated), AstUtils.Try( ag.AddDebugInfo(Ast.Empty(), new SourceSpan(Span.Start, _header)), body ).Catch(exception, Ast.Assign(runElse, Ast.Constant(false)), @catch, // restore existing line updated after exception handler completes ag.PopLineUpdated(lineUpdated), Ast.Default(body.Type) ), AstUtils.IfThen(runElse, @else ), Ast.Empty() ); } else if (@catch != null) { // no "else" clause // try { // <try body> // } catch (Exception e) { // ... catch handling ... // } // result = AstUtils.Try( ag.AddDebugInfo(Ast.Empty(), new SourceSpan(Span.Start, _header)), // save existing line updated ag.PushLineUpdated(false, lineUpdated), body ).Catch(exception, @catch, // restore existing line updated after exception handler completes ag.PopLineUpdated(lineUpdated), Ast.Default(body.Type) ); } else { result = body; } try { return AddFinally(ag, result, noNestedException); } finally { // free all locals here after the children nodes have been generated if (lineUpdated != null) { ag.FreeTemp(lineUpdated); } if (runElse != null) { ag.FreeTemp(@runElse); } } }
internal override MSAst.Expression TransformDelete(AstGenerator ag) { return ag.Delete( typeof(void), _name, ag.Transform(_target) ); }
internal override MSAst.Expression TransformDelete(AstGenerator ag) { return Binders.Delete( ag.BinderState, typeof(object), SymbolTable.IdToString(_name), ag.Transform(_target) ); }
/// <summary> /// Transform multiple python except handlers for a try block into a single catch body. /// </summary> /// <param name="ag"></param> /// <param name="variable">The variable for the exception in the catch block.</param> /// <returns>Null if there are no except handlers. Else the statement to go inside the catch handler</returns> private MSAst.Expression TransformHandlers(AstGenerator ag, out MSAst.ParameterExpression variable) { if (_handlers == null || _handlers.Length == 0) { variable = null; return null; } MSAst.ParameterExpression exception = ag.GetTemporary("exception", typeof(Exception)); MSAst.ParameterExpression extracted = ag.GetTemporary("extracted", typeof(object)); // The variable where the runtime will store the exception. variable = exception; var tests = new List<Microsoft.Scripting.Ast.IfStatementTest>(_handlers.Length); MSAst.ParameterExpression converted = null; MSAst.Expression catchAll = null; for (int index = 0; index < _handlers.Length; index++) { TryStatementHandler tsh = _handlers[index]; if (tsh.Test != null) { Microsoft.Scripting.Ast.IfStatementTest ist; // translating: // except Test ... // // generate following AST for the Test (common part): // CheckException(exception, Test) MSAst.Expression test = Ast.Call( AstGenerator.GetHelperMethod("CheckException"), extracted, ag.TransformAsObject(tsh.Test) ); if (tsh.Target != null) { // translating: // except Test, Target: // <body> // into: // if ((converted = CheckException(exception, Test)) != null) { // Target = converted; // traceback-header // <body> // } if (converted == null) { converted = ag.GetTemporary("converted"); } ist = AstUtils.IfCondition( Ast.NotEqual( Ast.Assign(converted, test), Ast.Constant(null) ), Ast.Block( tsh.Target.TransformSet(ag, SourceSpan.None, converted, Operators.None), GetTracebackHeader( new SourceSpan(tsh.Start, tsh.Header), ag, exception, ag.Transform(tsh.Body) ), Ast.Empty() ) ); } else { // translating: // except Test: // <body> // into: // if (CheckException(exception, Test) != null) { // traceback-header // <body> // } ist = AstUtils.IfCondition( Ast.NotEqual( test, Ast.Constant(null) ), GetTracebackHeader( new SourceSpan(tsh.Start, tsh.Header), ag, exception, ag.Transform(tsh.Body) ) ); } // Add the test to the if statement test cascade tests.Add(ist); } else { Debug.Assert(index == _handlers.Length - 1); Debug.Assert(catchAll == null); // translating: // except: // <body> // into: // { // traceback-header // <body> // } catchAll = GetTracebackHeader(new SourceSpan(tsh.Start, tsh.Header), ag, exception, ag.Transform(tsh.Body)); } } MSAst.Expression body = null; if (tests.Count > 0) { // rethrow the exception if we have no catch-all block if (catchAll == null) { catchAll = Ast.Throw(exception); } body = AstUtils.If( tests.ToArray(), catchAll ); } else { Debug.Assert(catchAll != null); body = catchAll; } if (converted != null) { ag.FreeTemp(converted); } ag.FreeTemp(exception); ag.FreeTemp(extracted); // Codegen becomes: // extracted = PythonOps.SetCurrentException(exception) // < dynamic exception analysis > return Ast.Block( Ast.Assign( extracted, Ast.Call( AstGenerator.GetHelperMethod("SetCurrentException"), AstUtils.CodeContext(), exception ) ), body, Ast.Empty() ); }
private MSAst.Expression AddFinally(AstGenerator/*!*/ ag, MSAst.Expression/*!*/ body, MSAst.ParameterExpression noNestedException) { if (_finally != null) { Debug.Assert(noNestedException != null); MSAst.ParameterExpression nestedFrames = ag.GetTemporary("$nestedFrames", typeof(List<DynamicStackFrame>)); bool inFinally = ag.InFinally; ag.InFinally = true; MSAst.Expression @finally = ag.Transform(_finally); ag.InFinally = inFinally; if (@finally == null) { // error reported during compilation return null; } if (ag.TrackLines) { // lots is going on here. We need to consider: // 1. Exceptions propagating out of try/except/finally. Here we need to save the line # // from the exception block and not save the # from the finally block later. // 2. Exceptions propagating out of the finally block. Here we need to report the line number // from the finally block and leave the existing stack traces cleared. // 3. Returning from the try block: Here we need to run the finally block and not update the // line numbers. body = AstUtils.Try(// we use a filter to know when we have an exception and when control leaves normally (via // either a return or the body completing successfully). AstUtils.Try( ag.AddDebugInfo(Ast.Empty(), new SourceSpan(Span.Start, _header)), Ast.Assign(noNestedException, Ast.Constant(true)), body ).Filter( typeof(Exception), // condition is never true, just note the exception and let it propagate Ast.Equal( Ast.Assign(noNestedException, Ast.Constant(false)), Ast.Constant(true) ), Ast.Default(body.Type) ) ).Finally( // if we had an exception save the line # that was last executing during the try AstUtils.If( Ast.Not(noNestedException), ag.GetLineNumberUpdateExpression(false) ), // clear the frames incase thae finally throws, and allow line number // updates to proceed ag.UpdateLineUpdated(false), Ast.Assign( nestedFrames, Ast.Call(AstGenerator.GetHelperMethod("GetAndClearDynamicStackFrames")) ), // run the finally code @finally, // if the finally exits normally restore any previous exception info Ast.Call( AstGenerator.GetHelperMethod("SetDynamicStackFrames"), nestedFrames ), ag.UpdateLineUpdated(true) ); ag.FreeTemp(nestedFrames); ag.FreeTemp(noNestedException); } else { body = AstUtils.Try(body).Finally( Ast.Assign( nestedFrames, Ast.Call(AstGenerator.GetHelperMethod("GetAndClearDynamicStackFrames")) ), // run the finally code @finally, // if the finally exits normally restore any previous exception info Ast.Call( AstGenerator.GetHelperMethod("SetDynamicStackFrames"), nestedFrames ) ); } } return body; }
private void TransformBody(AstGenerator ag, List<MSAst.Expression> statements) { SuiteStatement suite = _body as SuiteStatement; // Special case suite statement to avoid unnecessary allocation of extra node. if (suite != null) { foreach (Statement one in suite.Statements) { MSAst.Expression transforned = ag.Transform(one); if (transforned != null) { statements.Add(transforned); } } } else { MSAst.Expression transformed = ag.Transform(_body); if (transformed != null) { statements.Add(transformed); } } }
internal override MSAst.Expression Transform(AstGenerator ag) { string className = _name; AstGenerator classGen = new AstGenerator(ag, className, false, "class " + className); classGen.Parameter(_parentContextParam); // we always need to create a nested context for class defs classGen.CreateNestedContext(); List<MSAst.Expression> init = new List<MSAst.Expression>(); classGen.AddHiddenVariable(ArrayGlobalAllocator._globalContext); init.Add(Ast.Assign(ArrayGlobalAllocator._globalContext, Ast.Call(typeof(PythonOps).GetMethod("GetGlobalContext"), _parentContextParam))); init.AddRange(classGen.Globals.PrepareScope(classGen)); CreateVariables(classGen, _parentContextParam, init, true, false); List<MSAst.Expression> statements = new List<MSAst.Expression>(); // Create the body MSAst.Expression bodyStmt = classGen.Transform(_body); // __module__ = __name__ MSAst.Expression modStmt = GlobalAllocator.Assign( classGen.Globals.GetVariable(classGen, _modVariable), classGen.Globals.GetVariable(classGen, _modNameVariable)); string doc = classGen.GetDocumentation(_body); if (doc != null) { statements.Add( GlobalAllocator.Assign( classGen.Globals.GetVariable(classGen, _docVariable), AstUtils.Constant(doc) ) ); } FunctionCode funcCodeObj = new FunctionCode( ag.PyContext, null, null, Name, ag.GetDocumentation(_body), ArrayUtils.EmptyStrings, FunctionAttributes.None, Span, ag.Context.SourceUnit.Path, ag.EmitDebugSymbols, ag.ShouldInterpret, FreeVariables, GlobalVariables, CellVariables, AppendVariables(new List<string>()), Variables == null ? 0 : Variables.Count, classGen.LoopLocationsNoCreate, classGen.HandlerLocationsNoCreate ); MSAst.Expression funcCode = classGen.Globals.GetConstant(funcCodeObj); classGen.FuncCodeExpr = funcCode; if (_body.CanThrow && ag.PyContext.PythonOptions.Frames) { bodyStmt = AstGenerator.AddFrame(classGen.LocalContext, funcCode, bodyStmt); classGen.AddHiddenVariable(AstGenerator._functionStack); } bodyStmt = classGen.WrapScopeStatements( Ast.Block( statements.Count == 0 ? AstGenerator.EmptyBlock : Ast.Block(new ReadOnlyCollection<MSAst.Expression>(statements)), modStmt, bodyStmt, classGen.LocalContext // return value ) ); var lambda = Ast.Lambda<Func<CodeContext, CodeContext>>( classGen.MakeBody(_parentContextParam, init.ToArray(), bodyStmt), classGen.Name + "$" + _classId++, classGen.Parameters ); funcCodeObj.Code = lambda; MSAst.Expression classDef = Ast.Call( AstGenerator.GetHelperMethod("MakeClass"), ag.EmitDebugSymbols ? (MSAst.Expression)lambda : Ast.Convert(funcCode, typeof(object)), ag.LocalContext, AstUtils.Constant(_name), Ast.NewArrayInit( typeof(object), ag.TransformAndConvert(_bases, typeof(object)) ), AstUtils.Constant(FindSelfNames()) ); classDef = ag.AddDecorators(classDef, _decorators); return ag.AddDebugInfoAndVoid(GlobalAllocator.Assign(ag.Globals.GetVariable(ag, _variable), classDef), new SourceSpan(Start, Header)); }
internal override MSAst.Expression Transform(AstGenerator ag) { List<MSAst.Expression> block = new List<MSAst.Expression>(); // Create the variables CreateVariables(ag, null, block, false, false); MSAst.Expression bodyStmt = ag.Transform(_body); string doc = ag.GetDocumentation(_body); if (_isModule) { block.Add(ag.Globals.Assign( ag.Globals.GetVariable(ag, _docVariable), Ast.Constant(doc) )); } if (bodyStmt != null) { block.Add(bodyStmt); // bodyStmt could be null if we have an error - e.g. a top level break } block.Add(AstUtils.Empty()); return Ast.Block(block); }
internal override MSAst.Expression Transform(AstGenerator ag) { string className = SymbolTable.IdToString(_name); AstGenerator builder = new AstGenerator(ag, className, false, "class " + className); // we always need to create a nested context for class defs builder.CreateNestedContext(); List<MSAst.Expression> init = new List<MSAst.Expression>(); CreateVariables(builder, init); // Create the body MSAst.Expression bodyStmt = builder.Transform(_body); MSAst.Expression modStmt = ag.Globals.Assign(ag.Globals.GetVariable(_modVariable), ag.Globals.GetVariable(_modNameVariable)); string doc = ag.GetDocumentation(_body); if (doc != null) { init.Add( ag.Globals.Assign( ag.Globals.GetVariable(_docVariable), AstUtils.Constant(doc) ) ); } bodyStmt = builder.WrapScopeStatements( Ast.Block( init.Count == 0 ? AstGenerator.EmptyBlock : Ast.Block(new ReadOnlyCollection<MSAst.Expression>(init)), modStmt, bodyStmt, builder.LocalContext // return value ) ); MSAst.LambdaExpression lambda = Ast.Lambda( typeof(Func<CodeContext>), builder.MakeBody(bodyStmt, true, false), builder.Name + "$" + _classId++, builder.Parameters ); MSAst.Expression classDef = Ast.Call( AstGenerator.GetHelperMethod("MakeClass"), lambda, ag.LocalContext, AstUtils.Constant(SymbolTable.IdToString(_name)), Ast.NewArrayInit( typeof(object), ag.TransformAndConvert(_bases, typeof(object)) ), AstUtils.Constant(FindSelfNames()) ); classDef = ag.AddDecorators(classDef, _decorators); return ag.AddDebugInfo(ag.Globals.Assign(ag.Globals.GetVariable(_variable), classDef), new SourceSpan(Start, Header)); }
internal static MSAst.Expression TransformForStatement(AstGenerator ag, MSAst.ParameterExpression enumerator, Expression list, Expression left, MSAst.Expression body, Statement else_, SourceSpan span, SourceLocation header, MSAst.LabelTarget breakLabel, MSAst.LabelTarget continueLabel) { // enumerator = PythonOps.GetEnumeratorForIteration(list) MSAst.Expression init = Ast.Assign( enumerator, ag.Operation( typeof(IEnumerator), PythonOperationKind.GetEnumeratorForIteration, ag.TransformAsObject(list) ) ); // while enumerator.MoveNext(): // left = enumerator.Current // body // else: // else MSAst.Expression ls = AstUtils.Loop( ag.AddDebugInfo(Ast.Call( enumerator, typeof(IEnumerator).GetMethod("MoveNext") ), left.Span), null, Ast.Block( left.TransformSet( ag, SourceSpan.None, Ast.Call( enumerator, typeof(IEnumerator).GetProperty("Current").GetGetMethod() ), PythonOperationKind.None ), body, ag.UpdateLineNumber(list.Start.Line), AstUtils.Empty() ), ag.Transform(else_), breakLabel, continueLabel ); return Ast.Block( init, ls, AstUtils.Empty() ); }