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