internal override MSA.Expression /*!*/ Transform(AstGenerator /*!*/ gen)
 {
     return(AstUtils.IfThenElse(
                _condition.TransformCondition(gen, !_negateCondition),
                _body.Transform(gen),
                _elseStatement != null ? _elseStatement.Transform(gen) : AstUtils.Empty()
                ));
 }
예제 #2
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;

            MSA.LabelTarget retryLabel = Ast.Label("retry");

            var result = new AstBlock {
                Ast.Assign(blockArgVariable, Ast.Convert(transformedBlock, blockArgVariable.Type)),

                Ast.Label(retryLabel),

                (isBlockDefinition) ? Methods.InitializeBlock.OpCall(blockArgVariable) : null,

                AstUtils.Try(
                    Ast.Assign(resultVariable, invoke)
                    ).Catch(evalUnwinder = Ast.Parameter(typeof(EvalUnwinder), "#u"),
                            Ast.Assign(
                                resultVariable,
                                Ast.Field(evalUnwinder, EvalUnwinder.ReturnValueField)
                                )
                            ),

                Ast.IfThen(Ast.TypeEqual(resultVariable, typeof(BlockReturnResult)),
                           Ast.IfThenElse(Methods.IsRetrySingleton.OpCall(resultVariable),
                                          // retry:
                                          AstUtils.IfThenElse(Ast.Equal(gen.MakeMethodBlockParameterRead(), blockArgVariable),
                                                              RetryStatement.TransformRetry(gen),
                                                              Ast.Goto(retryLabel)
                                                              ),
                                          // return:
                                          gen.Return(ReturnStatement.Propagate(gen, resultVariable))
                                          )
                           ),

                resultVariable
            };

            return(result);
        }