예제 #1
0
        private MSA.Expression /*!*/ MakeParametersInitialization(AstGenerator /*!*/ gen, MSA.Expression[] /*!*/ parameters)
        {
            Assert.NotNull(gen);
            Assert.NotNullItems(parameters);

            var result = AstFactory.CreateExpressionArray(
                _parameters.LeftValues.Count +
                (_parameters.UnsplattedValue != null ? 1 : 0) +
                1
                );

            int resultIndex = 0;

            bool paramsInArray = HasFormalParametersInArray;

            for (int i = 0; i < _parameters.LeftValues.Count; i++)
            {
                var parameter = paramsInArray ?
                                Ast.ArrayAccess(parameters[HiddenParameterCount], Ast.Constant(i)) :
                                parameters[HiddenParameterCount + i];

                result[resultIndex++] = _parameters.LeftValues[i].TransformWrite(gen, parameter);
            }

            if (_parameters.UnsplattedValue != null)
            {
                // the last parameter is unsplat:
                var parameter = parameters[parameters.Length - 1];
                result[resultIndex++] = _parameters.UnsplattedValue.TransformWrite(gen, parameter);
            }

            result[resultIndex++] = Ast.Empty();
            Debug.Assert(resultIndex == result.Length);
            return(AstFactory.Block(result));
        }
예제 #2
0
        // when [<expr>, ...] *<array>
        //
        // generates this code:
        //
        // IEnumerator<object>/*!*/ enumVar = RubyOps.Unsplat(<array>).GetEnumerator();
        // bool result = false;
        // while (enumVar.MoveNext()) {
        //     if (<MakeTest>(enumVar.Current)) {
        //         result = true;
        //         break;
        //     }
        // }
        private static MSA.Expression /*!*/ MakeArrayTest(AstGenerator /*!*/ gen, MSA.Expression /*!*/ array, MSA.Expression value)
        {
            MSA.Expression enumVariable   = gen.CurrentScope.DefineHiddenVariable("#case-enumerator", typeof(IEnumerator <object>));
            MSA.Expression resultVariable = gen.CurrentScope.DefineHiddenVariable("#case-compare-result", typeof(bool));

            MSA.LabelTarget label = Ast.Label();
            return(AstFactory.Block(
                       Ast.Assign(enumVariable, Ast.Call(
                                      Methods.Unsplat.OpCall(AstFactory.Box(array)),
                                      Methods.IEnumerable_Of_Object_GetEnumerator
                                      )),

                       Ast.Assign(resultVariable, Ast.Constant(false)),

                       AstUtils.While(
                           Ast.Call(enumVariable, Methods.IEnumerator_MoveNext),
                           AstUtils.If(
                               MakeTest(gen, Ast.Call(enumVariable, Methods.IEnumerator_get_Current), value),
                               Ast.Block(
                                   Ast.Assign(resultVariable, Ast.Constant(true)),
                                   Ast.Break(label),
                                   Ast.Empty()
                                   )
                               ),
                           null,
                           label,
                           null
                           ),
                       resultVariable
                       ));
        }
예제 #3
0
        internal sealed override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            string debugString = (IsSingletonDeclaration) ? "SINGLETON" : ((this is ClassDeclaration) ? "CLASS" : "MODULE") + " " + QualifiedName.Name;

            ScopeBuilder outerLocals = gen.CurrentScope;

            // definition needs to take place outside the defined lexical scope:
            MSA.Expression definition   = MakeDefinitionExpression(gen);
            MSA.Expression selfVariable = outerLocals.DefineHiddenVariable("#module", typeof(RubyModule));
            MSA.Expression rfcVariable  = gen.CurrentRfcVariable;
            MSA.Expression parentScope  = gen.CurrentScopeVariable;

            // inner locals:
            ScopeBuilder scope = new ScopeBuilder();

            MSA.Expression scopeVariable = scope.DefineHiddenVariable("#scope", typeof(RubyScope));

            gen.EnterModuleDefinition(
                scope,
                selfVariable,
                scopeVariable,
                IsSingletonDeclaration
                );

            // first, transform locals defined within the module body:
            DefinedScope.TransformLocals(scope);

            // second, transform body:
            MSA.Expression transformedBody = Body.TransformRead(gen);

            // outer local:
            MSA.Expression resultVariable = outerLocals.DefineHiddenVariable("#result", transformedBody.Type);

            // begin with new scope
            //   self = DefineModule/Class(... parent scope here ...)
            //   <body>
            // end
            MSA.Expression result = AstFactory.Block(
                gen.DebugMarker(debugString),
                Ast.Assign(selfVariable, definition),
                scope.CreateScope(
                    Ast.Block(
                        Ast.Assign(scopeVariable,
                                   Methods.CreateModuleScope.OpCall(scope.VisibleVariables(), parentScope, rfcVariable, selfVariable)),
                        Ast.Assign(resultVariable, transformedBody),
                        Ast.Empty()
                        )
                    ),
                gen.DebugMarker("END OF " + debugString),
                resultVariable
                );

            gen.LeaveModuleDefinition();

            return(result);
        }
예제 #4
0
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            MSA.Expression transformedCondition = AstFactory.Box(_condition.TransformRead(gen));
            MSA.Expression tmpVariable          = gen.CurrentScope.DefineHiddenVariable("#tmp_cond", transformedCondition.Type);

            return(AstFactory.Block(
                       Ast.Assign(tmpVariable, transformedCondition),
                       AstUtils.IfThen(
                           (_negateCondition ? AstFactory.IsFalse(tmpVariable) : AstFactory.IsTrue(tmpVariable)),
                           _jumpStatement.Transform(gen)
                           ),
                       (_value != null) ? _value.TransformRead(gen) : tmpVariable
                       ));
        }
예제 #5
0
파일: Body.cs 프로젝트: gaybro8777/ironruby
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            Assert.NotNull(gen);

            if (HasExceptionHandling)
            {
                MSA.Expression resultVariable = gen.CurrentScope.DefineHiddenVariable("#block-result", typeof(object));

                return(AstFactory.Block(
                           TransformExceptionHandling(gen, ResultOperation.Store(resultVariable)),
                           resultVariable
                           ));
            }
            else
            {
                return(gen.TransformStatementsToExpression(_statements));
            }
        }
예제 #6
0
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            MSA.Expression result;
            if (_elseStatements != null)
            {
                // ... else body end
                result = gen.TransformStatementsToExpression(_elseStatements);
            }
            else
            {
                // no else clause => the result of the if-expression is nil:
                result = Ast.Constant(null);
            }

            MSA.Expression value;
            if (_value != null)
            {
                value = gen.CurrentScope.DefineHiddenVariable("#case-compare-value", typeof(object));
            }
            else
            {
                value = null;
            }

            for (int i = _whenClauses.Count - 1; i >= 0; i--)
            {
                // emit: else (if (condition) body else result)
                result = AstFactory.Condition(
                    TransformWhenCondition(gen, _whenClauses[i].Comparisons, _whenClauses[i].ComparisonArray, value),
                    gen.TransformStatementsToExpression(_whenClauses[i].Statements),
                    result
                    );
            }

            if (_value != null)
            {
                result = AstFactory.Block(
                    Ast.Assign(value, Ast.Convert(_value.TransformRead(gen), typeof(object))),
                    result
                    );
            }

            return(result);
        }
예제 #7
0
        // see Ruby Language.doc/Runtime/Control Flow Implementation/Yield
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            MSA.Expression bfcVariable    = gen.CurrentScope.DefineHiddenVariable("#yielded-bfc", typeof(BlockParam));
            MSA.Expression resultVariable = gen.CurrentScope.DefineHiddenVariable("#result", typeof(object));
            MSA.Expression evalUnwinder   = gen.CurrentScope.DefineHiddenVariable("#unwinder", typeof(EvalUnwinder));

            MSA.Expression postYield;

            if (gen.CompilerOptions.IsEval)
            {
                // eval:
                postYield = Methods.EvalYield.OpCall(gen.CurrentRfcVariable, bfcVariable, resultVariable);
            }
            else if (gen.CurrentBlock != null)
            {
                // block:
                postYield = Methods.BlockYield.OpCall(gen.CurrentRfcVariable, gen.CurrentBlock.BfcVariable, bfcVariable, resultVariable);
            }
            else
            {
                // method:
                postYield = Methods.MethodYield.OpCall(gen.CurrentRfcVariable, bfcVariable, resultVariable);
            }

            return(AstFactory.Block(
                       gen.DebugMarker("#RB: yield begin"),

                       Ast.Assign(bfcVariable, Methods.CreateBfcForYield.OpCall(gen.MakeMethodBlockParameterRead())),

                       Ast.Assign(resultVariable, (Arguments ?? Arguments.Empty).TransformToYield(gen, bfcVariable,
                                                                                                  Ast.Property(AstUtils.Convert(gen.MakeMethodBlockParameterRead(), typeof(Proc)), Proc.SelfProperty)
                                                                                                  )),

                       AstUtils.IfThen(postYield, gen.Return(resultVariable)),

                       gen.DebugMarker("#RB: yield end"),

                       resultVariable
                       ));
        }
예제 #8
0
        internal static MSA.Expression /*!*/ MakeCallWithBlockRetryable(AstGenerator /*!*/ gen, MSA.Expression /*!*/ invoke,
                                                                        MSA.Expression blockArgVariable, MSA.Expression transformedBlock, bool isBlockDefinition)
        {
            Assert.NotNull(invoke);
            Debug.Assert((blockArgVariable == null) == (transformedBlock == null));

            // see Ruby Language.doc/Control Flow Implementation/Method Call With a Block
            MSA.Expression          resultVariable = gen.CurrentScope.DefineHiddenVariable("#method-result", typeof(object));
            MSA.ParameterExpression evalUnwinder   = gen.CurrentScope.DefineHiddenVariable("#unwinder", typeof(EvalUnwinder));

            MSA.LabelTarget label = Ast.Label();

            return(AstFactory.Block(
                       Ast.Assign(blockArgVariable, Ast.Convert(transformedBlock, blockArgVariable.Type)),
                       AstFactory.Infinite(label, null,
                                           (!isBlockDefinition) ?
                                           (MSA.Expression)Ast.Empty() :
                                           (MSA.Expression)Methods.InitializeBlock.OpCall(blockArgVariable),

                                           AstUtils.Try(
                                               Ast.Assign(resultVariable, invoke)
                                               ).Catch(evalUnwinder,
                                                       Ast.Assign(
                                                           resultVariable,
                                                           Ast.Field(evalUnwinder, EvalUnwinder.ReturnValueField)
                                                           )
                                                       ),

                                           // if result != RetrySingleton then break end
                                           AstUtils.Unless(Methods.IsRetrySingleton.OpCall(AstFactory.Box(resultVariable)), Ast.Break(label)),

                                           // if blockParam == #block then retry end
                                           (gen.CurrentMethod.IsTopLevelCode) ? Ast.Empty() :
                                           AstUtils.IfThen(Ast.Equal(gen.MakeMethodBlockParameterRead(), blockArgVariable), RetryStatement.TransformRetry(gen))

                                           ),
                       resultVariable
                       ));
        }
예제 #9
0
 internal MSA.Expression /*!*/ DebugMark(MSA.Expression /*!*/ expression, string /*!*/ marker)
 {
     return(_debugCompiler ? AstFactory.Block(Methods.X.OpCall(Ast.Constant(marker)), expression) : expression);
 }
예제 #10
0
        // arguments: complex arguments (expressions, maplets, splat, block)
        // singleArgument: siple argument (complex are not used)
        // assignmentRhsArgument: rhs of the assignment: target.method=(rhs)
        internal static MSA.Expression /*!*/ TransformRead(Expression /*!*/ node, AstGenerator /*!*/ gen, bool hasImplicitSelf,
                                                           string /*!*/ methodName, MSA.Expression /*!*/ transformedTarget,
                                                           Arguments arguments, Block block, MSA.Expression singleArgument, MSA.Expression assignmentRhsArgument)
        {
            Debug.Assert(assignmentRhsArgument == null || block == null, "Block not allowed in assignment");
            Debug.Assert(singleArgument == null || arguments == null && assignmentRhsArgument == null);
            Assert.NotNull(gen, transformedTarget);
            Assert.NotEmpty(methodName);

            // Pass args in this order:
            // 1. instance
            // 2. block (if present)
            // 3. passed args: normal args, maplets, array
            // 4. RHS of assignment (if present)

            CallBuilder callBuilder = new CallBuilder(gen);

            callBuilder.Instance = transformedTarget;

            MSA.Expression blockArgVariable = null;
            MSA.Expression transformedBlock = null;

            if (block != null)
            {
                blockArgVariable  = gen.CurrentScope.DefineHiddenVariable("#block-def", typeof(Proc));
                transformedBlock  = block.Transform(gen);
                callBuilder.Block = blockArgVariable;
            }

            if (arguments != null)
            {
                arguments.TransformToCall(gen, callBuilder);
            }
            else if (singleArgument != null)
            {
                callBuilder.Add(singleArgument);
            }

            MSA.Expression rhsVariable = null;
            if (assignmentRhsArgument != null)
            {
                rhsVariable             = gen.CurrentScope.DefineHiddenVariable("#rhs", assignmentRhsArgument.Type);
                callBuilder.RhsArgument = Ast.Assign(rhsVariable, assignmentRhsArgument);
            }

            var dynamicSite = callBuilder.MakeCallAction(methodName, hasImplicitSelf);

            gen.TraceCallSite(node, dynamicSite);

            MSA.Expression result = gen.DebugMark(dynamicSite, methodName);

            if (block != null)
            {
                result = gen.DebugMark(MakeCallWithBlockRetryable(gen, result, blockArgVariable, transformedBlock, block.IsDefinition),
                                       "#RB: method call with a block ('" + methodName + "')");
            }

            if (assignmentRhsArgument != null)
            {
                result = AstFactory.Block(result, rhsVariable);
            }

            return(result);
        }
예제 #11
0
        //
        // rescue stmts                     ... if (StandardError === $!) { stmts; }
        // rescue <types> stmts             ... temp1 = type1; ...; if (<temp1> === $! || ...) { stmts; }
        // rescue <types> => <lvalue> stmts ... temp1 = type1; ...; if (<temp1> === $! || ...) { <lvalue> = $!; stmts; }
        //
        internal IfStatementTest /*!*/ Transform(AstGenerator /*!*/ gen, ResultOperation resultOperation)
        {
            Assert.NotNull(gen);

            MSA.Expression condition;
            if (_types.Count != 0 || _splatType != null)
            {
                if (_types.Count == 0)
                {
                    // splat only:
                    condition = MakeCompareSplattedExceptions(gen, TransformSplatType(gen));
                }
                else if (_types.Count == 1 && _splatType == null)
                {
                    condition = MakeCompareException(gen, _types[0].TransformRead(gen));
                }
                else
                {
                    // forall{i}: <temps[i]> = evaluate type[i]
                    var temps = new MSA.Expression[_types.Count + (_splatType != null ? 1 : 0)];
                    var exprs = new MSA.Expression[temps.Length + 1];

                    int i = 0;
                    while (i < _types.Count)
                    {
                        var tmp = gen.CurrentScope.DefineHiddenVariable("#type_" + i, typeof(object));
                        temps[i] = tmp;
                        exprs[i] = Ast.Assign(tmp, _types[i].TransformRead(gen));
                        i++;
                    }

                    if (_splatType != null)
                    {
                        var tmp = gen.CurrentScope.DefineHiddenVariable("#type_" + i, typeof(object));
                        temps[i] = tmp;
                        exprs[i] = Ast.Assign(tmp, TransformSplatType(gen));

                        i++;
                    }

                    Debug.Assert(i == temps.Length);

                    // CompareException(<temps[0]>) || ... CompareException(<temps[n]>) || CompareSplattedExceptions(<splatTypes>)
                    i         = 0;
                    condition = MakeCompareException(gen, temps[i++]);
                    while (i < _types.Count)
                    {
                        condition = Ast.OrElse(condition, MakeCompareException(gen, temps[i++]));
                    }

                    if (_splatType != null)
                    {
                        condition = Ast.OrElse(condition, MakeCompareSplattedExceptions(gen, temps[i++]));
                    }

                    Debug.Assert(i == temps.Length);

                    // (temps[0] = type[0], ..., temps[n] == type[n], condition)
                    exprs[exprs.Length - 1] = condition;
                    condition = AstFactory.Block(exprs);
                }
            }
            else
            {
                condition = Methods.CompareDefaultException.OpCall(gen.CurrentScopeVariable, gen.CurrentSelfVariable);
            }

            return(AstUtils.IfCondition(condition,
                                        gen.TransformStatements(
                                            // <lvalue> = e;
                                            (_target != null) ? _target.TransformWrite(gen, Methods.GetCurrentException.OpCall(gen.CurrentScopeVariable)) : null,

                                            // body:
                                            _statements,

                                            resultOperation
                                            )
                                        ));
        }
예제 #12
0
        private MSA.Expression /*!*/ TransformWrite(AstGenerator /*!*/ gen, List <MSA.Expression> /*!*/ rightValues, MSA.Expression splattedValue)
        {
            // We need to distinguish various special cases here.
            // Each of the bool variables defined below is true iff the corresponding special form of LHS/RHS occurs.
            // These flags drive the DLR AST being produced by this method.
            // For parallel assignment specification, see "Ruby Language.docx/Runtime/Parallel Assignment".

            // L(0,-) not applicable
            Debug.Assert(!(_leftValues.Count == 0 && _unsplattedValue == null));

            // L(1,-)?
            bool leftOneNone = _leftValues.Count == 1 && _unsplattedValue == null;

            // L(0,*)?
            bool leftNoneSplat = _leftValues.Count == 0 && _unsplattedValue != null;

            // R(0,*)?
            bool rightNoneSplat = rightValues.Count == 0 && splattedValue != null;

            // R(1,-)?
            bool rightOneNone = rightValues.Count == 1 && splattedValue == null;

            // R(1,*)?
            bool rightOneSplat = rightValues.Count == 1 && splattedValue != null;

            // R(0,-) not applicable
            Debug.Assert(!(rightValues.Count == 0 && splattedValue == null));

            MSA.Expression resultExpression;

            if (leftOneNone)
            {
                // L(1,-):

                // recurse right away (X) = RHS is equivalent to X = RHS:
                CompoundLeftValue compound = _leftValues[0] as CompoundLeftValue;
                if (compound != null)
                {
                    return(compound.TransformWrite(gen, rightValues, splattedValue));
                }

                if (rightOneSplat)
                {
                    // R(1,*)
                    resultExpression = Methods.SplatPair.OpCall(AstFactory.Box(rightValues[0]), AstFactory.Box(splattedValue));
                }
                else
                {
                    // case 1: R(1,-)
                    // case 2: R(0,*)
                    // case 3: otherwise
                    resultExpression = Arguments.TransformRead(gen, rightValues, splattedValue, true /* Splat */);
                }

                return(_leftValues[0].TransformWrite(gen, resultExpression));
            }

            bool optimizeReads = true;

            if (rightOneNone && !leftNoneSplat)
            {
                // R(1,-) && !L(0,*)
                resultExpression = Methods.Unsplat.OpCall(AstFactory.Box(rightValues[0]));
                optimizeReads    = false;
            }
            else
            {
                // case 1: R(0,*) = L
                // case 2: otherwise
                resultExpression = Arguments.TransformRead(gen, rightValues, splattedValue, false /* Unsplat */);
                optimizeReads    = !rightNoneSplat;
            }

            int writesCount = _leftValues.Count + (_unsplattedValue != null ? 1 : 0);

            if (writesCount == 0)
            {
                return(resultExpression);
            }

            var writes = new MSA.Expression[
                1 +                // store result to a temp
                writesCount +
                1                  // load from the temp
                         ];

            int writeIndex = 0;

            MSA.Expression result = gen.CurrentScope.DefineHiddenVariable("#rhs", typeof(List <object>));
            writes[writeIndex++] = Ast.Assign(result, resultExpression);

            MethodInfo itemGetter = typeof(List <object>).GetMethod("get_Item");

            for (int i = 0; i < _leftValues.Count; i++)
            {
                MSA.Expression rvalue;

                if (optimizeReads)
                {
                    if (i < rightValues.Count)
                    {
                        // unchecked get item:
                        rvalue = Ast.Call(result, itemGetter, Ast.Constant(i));
                    }
                    else if (splattedValue != null)
                    {
                        // checked get item:
                        rvalue = Methods.GetArrayItem.OpCall(result, Ast.Constant(i));
                    }
                    else
                    {
                        // missing item:
                        rvalue = Ast.Constant(null);
                    }
                }
                else
                {
                    rvalue = Methods.GetArrayItem.OpCall(result, Ast.Constant(i));
                }

                writes[writeIndex++] = _leftValues[i].TransformWrite(gen, rvalue);
            }

            // unsplatting the rest of rhs values into an array:
            if (_unsplattedValue != null)
            {
                // copies the rest of resulting array to the *LHS;
                // the resulting array contains splatted *RHS - no need for additional appending:
                MSA.Expression array = Methods.GetArraySuffix.OpCall(result, Ast.Constant(_leftValues.Count));

                // assign the array (possibly empty) to *LHS:
                writes[writeIndex++] = _unsplattedValue.TransformWrite(gen, array);
            }

            writes[writeIndex++] = result;

            Debug.Assert(writes.Length == writeIndex);
            return(AstFactory.Block(writes));
        }
예제 #13
0
 internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
 {
     return(AstFactory.Block(Transform(gen), Ast.Constant(null)));
 }
예제 #14
0
        // see Ruby Language.doc/Runtime/Control Flow Implementation/While-Until
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            MSA.Expression          resultVariable = gen.CurrentScope.DefineHiddenVariable("#loop-result", typeof(object));
            MSA.Expression          redoVariable   = gen.CurrentScope.DefineHiddenVariable("#skip-condition", typeof(bool));
            MSA.ParameterExpression blockUnwinder  = gen.CurrentScope.DefineHiddenVariable("#unwinder", typeof(BlockUnwinder));
            MSA.ParameterExpression evalUnwinder   = gen.CurrentScope.DefineHiddenVariable("#unwinder", typeof(EvalUnwinder));

            bool isInnerLoop = gen.CurrentLoop != null;

            MSA.LabelTarget breakLabel    = Ast.Label();
            MSA.LabelTarget continueLabel = Ast.Label();

            gen.EnterLoop(redoVariable, resultVariable, breakLabel, continueLabel);
            MSA.Expression transformedBody      = gen.TransformStatements(_statements, ResultOperation.Ignore);
            MSA.Expression transformedCondition = AstFactory.IsTrue(_condition.TransformRead(gen));
            gen.LeaveLoop();

            MSA.Expression conditionPositiveStmt, conditionNegativeStmt;
            if (_isWhileLoop)
            {
                conditionPositiveStmt = Ast.Empty();
                conditionNegativeStmt = Ast.Break(breakLabel);
            }
            else
            {
                conditionPositiveStmt = Ast.Break(breakLabel);
                conditionNegativeStmt = Ast.Empty();
            }

            // make the loop first:
            MSA.Expression loop = Ast.Block(
                Ast.Assign(redoVariable, Ast.Constant(_isPostTest)),

                AstFactory.Infinite(breakLabel, continueLabel,
                                    AstUtils.Try(

                                        AstUtils.If(redoVariable,
                                                    Ast.Assign(redoVariable, Ast.Constant(false))
                                                    ).ElseIf(transformedCondition,
                                                             conditionPositiveStmt
                                                             ).Else(
                                            conditionNegativeStmt
                                            ),

                                        transformedBody

                                        ).Catch(blockUnwinder,
                                                // redo = u.IsRedo
                                                Ast.Assign(redoVariable, Ast.Field(blockUnwinder, BlockUnwinder.IsRedoField))

                                                ).Filter(evalUnwinder, Ast.Equal(Ast.Field(evalUnwinder, EvalUnwinder.ReasonField), AstFactory.BlockReturnReasonBreak),
                                                         // result = unwinder.ReturnValue
                                                         Ast.Assign(resultVariable, Ast.Field(evalUnwinder, EvalUnwinder.ReturnValueField)),
                                                         Ast.Break(breakLabel)
                                                         )
                                    ),
                Ast.Empty()
                );

            // wrap it to try finally that updates RFC state:
            if (!isInnerLoop)
            {
                loop = AstUtils.Try(
                    Ast.Assign(Ast.Field(gen.CurrentRfcVariable, RuntimeFlowControl.InLoopField), Ast.Constant(true)),
                    loop
                    ).Finally(
                    Ast.Assign(Ast.Field(gen.CurrentRfcVariable, RuntimeFlowControl.InLoopField), Ast.Constant(false))
                    );
            }

            return(AstFactory.Block(loop, resultVariable));
        }