internal static MSAst.Expression TransformFor(ScopeStatement parent, MSAst.ParameterExpression enumerator, Expression list, Expression left, MSAst.Expression body, Statement else_, SourceSpan span, SourceLocation header, MSAst.LabelTarget breakLabel, MSAst.LabelTarget continueLabel, bool isStatement) { // enumerator, isDisposable = Dynamic(GetEnumeratorBinder, list) MSAst.Expression init = Ast.Assign( enumerator, new PythonDynamicExpression1 <KeyValuePair <IEnumerator, IDisposable> >( Binders.UnaryOperationBinder( parent.GlobalParent.PyContext, PythonOperationKind.GetEnumeratorForIteration ), parent.GlobalParent.CompilationMode, AstUtils.Convert(list, typeof(object)) ) ); // while enumerator.MoveNext(): // left = enumerator.Current // body // else: // else MSAst.Expression ls = AstUtils.Loop( parent.GlobalParent.AddDebugInfo( Ast.Call( Ast.Property( enumerator, typeof(KeyValuePair <IEnumerator, IDisposable>).GetProperty("Key") ), typeof(IEnumerator).GetMethod("MoveNext") ), left.Span ), null, Ast.Block( left.TransformSet( SourceSpan.None, Ast.Call( Ast.Property( enumerator, typeof(KeyValuePair <IEnumerator, IDisposable>).GetProperty("Key") ), typeof(IEnumerator).GetProperty("Current").GetGetMethod() ), PythonOperationKind.None ), body, isStatement ? UpdateLineNumber(parent.GlobalParent.IndexToLocation(list.StartIndex).Line) : AstUtils.Empty(), AstUtils.Empty() ), else_, breakLabel, continueLabel ); return(Ast.Block( init, Ast.TryFinally( ls, Ast.Block( Ast.Call(AstMethods.ForLoopDispose, enumerator), Ast.Assign(enumerator, Ast.New(typeof(KeyValuePair <IEnumerator, IDisposable>))) ) ) )); }
internal protected override Expression ToExpression(OverloadResolver resolver, RestrictedArguments args, bool[] hasBeenUsed) { var actualArgs = resolver.GetActualArguments(); int splatIndex = actualArgs.SplatIndex; int collapsedCount = actualArgs.CollapsedCount; int firstSplatted = actualArgs.FirstSplattedArg; var result = new Expression[2 + _expandedCount + (collapsedCount > 0 ? 2 : 0)]; var arrayVariable = resolver.GetTemporary(_elementType.MakeArrayType(), "a"); int e = 0; result[e++] = Ast.Assign(arrayVariable, Ast.NewArrayBounds(_elementType, Ast.Constant(_expandedCount + collapsedCount))); int itemIndex = 0; int i = _start; while (true) { // inject loop copying collapsed items: if (i == splatIndex) { var indexVariable = resolver.GetTemporary(typeof(int), "t"); // for (int t = 0; t <= {collapsedCount}; t++) { // a[{itemIndex} + t] = CONVERT<ElementType>(list.get_Item({splatIndex - firstSplatted} + t)) // } result[e++] = Ast.Assign(indexVariable, AstUtils.Constant(0)); result[e++] = AstUtils.Loop( Ast.LessThan(indexVariable, Ast.Constant(collapsedCount)), // TODO: not implemented in the old interpreter // Ast.PostIncrementAssign(indexVariable), Ast.Assign(indexVariable, Ast.Add(indexVariable, AstUtils.Constant(1))), Ast.Assign( Ast.ArrayAccess(arrayVariable, Ast.Add(AstUtils.Constant(itemIndex), indexVariable)), resolver.Convert( new DynamicMetaObject( resolver.GetSplattedItemExpression(Ast.Add(AstUtils.Constant(splatIndex - firstSplatted), indexVariable)), BindingRestrictions.Empty ), null, ParameterInfo, _elementType ) ), null ); itemIndex += collapsedCount; } if (i >= _start + _expandedCount) { break; } Debug.Assert(!hasBeenUsed[i]); hasBeenUsed[i] = true; result[e++] = Ast.Assign( Ast.ArrayAccess(arrayVariable, AstUtils.Constant(itemIndex++)), resolver.Convert(args.GetObject(i), args.GetType(i), ParameterInfo, _elementType) ); i++; } result[e++] = arrayVariable; Debug.Assert(e == result.Length); return(Ast.Block(result)); }