internal override MSA.Expression /*!*/ Transform(AstGenerator /*!*/ gen)
 {
     return(AstUtils.IfThenElse(
                _condition.TransformCondition(gen, !_negateCondition),
                _body.Transform(gen),
                _elseStatement != null ? _elseStatement.Transform(gen) : AstUtils.Empty()
                ));
 }
Example #2
0
 internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
 {
     return(AstFactory.Condition(
                _condition.TransformCondition(gen, false),
                gen.TransformStatementsToExpression(_statements),
                gen.TransformStatementsToExpression(_elseClause != null ? _elseClause.Statements : null)
                ));
 }
        internal override MSA.Expression /*!*/ TransformRead(AstGenerator /*!*/ gen)
        {
            MSA.Expression result;

            int i = _elseIfClauses.Count - 1;

            if (i >= 0 && _elseIfClauses[i].Condition == null)
            {
                // ... else body end
                result = gen.TransformStatementsToExpression(_elseIfClauses[i].Statements);
                i--;
            }
            else
            {
                // no else clause => the result of the if-expression is nil:
                result = AstUtils.Constant(null);
            }

            while (i >= 0)
            {
                // emit: else (if (condition) body else result)
                result = AstFactory.Condition(
                    _elseIfClauses[i].Condition.TransformCondition(gen, true),
                    gen.TransformStatementsToExpression(_elseIfClauses[i].Statements),
                    result
                    );
                i--;
            }

            // if (condition) body else result
            return(AstFactory.Condition(
                       _condition.TransformCondition(gen, true),
                       gen.TransformStatementsToExpression(_body),
                       result
                       ));
        }
Example #4
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 unwinder;

            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 = _condition.TransformCondition(gen, true);
            gen.LeaveLoop();

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

            // make the loop first:
            MSA.Expression loop = new AstBlock {
                gen.ClearDebugInfo(),
                           Ast.Assign(redoVariable, AstUtils.Constant(_isPostTest)),

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

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

                                        transformedBody,
                                        AstUtils.Empty()

                                        ).Catch(unwinder = Ast.Parameter(typeof(BlockUnwinder), "#u"),
                                                // redo = u.IsRedo
                                                Ast.Assign(redoVariable, Ast.Field(unwinder, BlockUnwinder.IsRedoField)),
                                                AstUtils.Empty()

                                                ).Filter(unwinder = Ast.Parameter(typeof(EvalUnwinder), "#u"),
                                                         Ast.Equal(Ast.Field(unwinder, EvalUnwinder.ReasonField), AstFactory.BlockReturnReasonBreak),

                                                         // result = unwinder.ReturnValue
                                                         Ast.Assign(resultVariable, Ast.Field(unwinder, EvalUnwinder.ReturnValueField)),
                                                         Ast.Break(breakLabel)
                                                         )
                                    ),
                gen.ClearDebugInfo(),
                AstUtils.Empty(),
            };

            // wrap it to try finally that updates RFC state:
            if (!isInnerLoop)
            {
                loop = AstUtils.Try(
                    Methods.EnterLoop.OpCall(gen.CurrentScopeVariable),
                    loop
                    ).Finally(
                    Methods.LeaveLoop.OpCall(gen.CurrentScopeVariable)
                    );
            }

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