public static Loop ( Expression test, Expression increment, Expression body, Expression @else ) : LoopExpression | ||
test | Expression | |
increment | Expression | |
body | Expression | |
@else | Expression | |
Результат | LoopExpression |
internal static MSAst.Expression TransformForStatement(ScopeStatement parent, MSAst.ParameterExpression enumerator, Expression list, Expression left, MSAst.Expression body, Statement else_, SourceSpan span, SourceLocation header, MSAst.LabelTarget breakLabel, MSAst.LabelTarget continueLabel) { // enumerator, isDisposable = Dynamic(GetEnumeratorBinder, list) MSAst.Expression init = Ast.Assign( enumerator, parent.GlobalParent.Operation( typeof(KeyValuePair <IEnumerator, IDisposable>), PythonOperationKind.GetEnumeratorForIteration, 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, UpdateLineNumber(list.Start.Line), AstUtils.Empty() ), else_, breakLabel, continueLabel ); return(Ast.Block( init, Ast.TryFinally( ls, Ast.Call(AstMethods.ForLoopDispose, enumerator) ) )); }
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)); }