Expr IStatementVisitor <Expr> .Visit(Statement.For statement) { var parentScope = scope; scope = Scope.CreateChild(parentScope); var step = statement.Step == null ? new Expression.Number(1.0).Visit(this) : ExprHelpers.ConvertToNumber(context, statement.Step.Visit(this)); var loopVariable = scope.AddLocal(statement.Identifier); var varVar = Expr.Variable(typeof(double)); var limitVar = Expr.Variable(typeof(double)); var stepVar = Expr.Variable(typeof(double)); var breakConditionExpr = ForLoopBreakCondition(limitVar, stepVar, varVar); var expr = Expr.Block( new[] { loopVariable, varVar, limitVar, stepVar }, Expr.Assign(varVar, ExprHelpers.ConvertToNumber(context, statement.Var.Visit(this))), Expr.Assign(limitVar, ExprHelpers.ConvertToNumber(context, statement.Limit.Visit(this))), Expr.Assign(stepVar, step), ExprHelpers.CheckNumberForNan(varVar, String.Format(ExceptionMessage.FOR_VALUE_NOT_NUMBER, "inital value")), ExprHelpers.CheckNumberForNan(limitVar, String.Format(ExceptionMessage.FOR_VALUE_NOT_NUMBER, "limit")), ExprHelpers.CheckNumberForNan(stepVar, String.Format(ExceptionMessage.FOR_VALUE_NOT_NUMBER, "step")), ForLoop(statement, stepVar, loopVariable, varVar, breakConditionExpr)); scope = parentScope; return(expr); }
Expr IStatementVisitor <Expr> .Visit(Statement.ForIn statement) { var iterFuncVar = Expr.Variable(typeof(object)); var iterStateVar = Expr.Variable(typeof(object)); var iterableVar = Expr.Variable(typeof(object)); var iterVars = new[] { iterFuncVar, iterStateVar, iterableVar }; var valueExprs = statement.Values.Select(v => Expr.Convert(v.Visit(this), typeof(object))); var assignIterVars = VarargsExpandAssignment(iterVars, valueExprs); var parentScope = scope; scope = Scope.CreateChild(scope); var locals = statement.Identifiers.Select(id => scope.AddLocal(id)).ToList(); var invokeIterFunc = Expr.Dynamic(Context.DynamicCache.GetInvokeBinder(new CallInfo(2)), typeof(object), iterFuncVar, iterStateVar, iterableVar); var loop = Expr.Loop( Expr.Block( locals, VarargsExpandAssignment( locals, new[] { invokeIterFunc }), Expr.IfThen(Expr.Equal(locals[0], Expr.Constant(null)), Expr.Break(scope.BreakLabel())), Visit(statement.Body)), scope.BreakLabel()); var expr = Expr.Block(iterVars, assignIterVars, loop); scope = parentScope; return(expr); }
Expr Visit(Block block) { var parentScope = scope; scope = Scope.CreateChild(parentScope); var statementExprs = block.Statements.Select(s => s.Visit(this)).ToList(); if (block.LastStatement != null) { statementExprs.Add(block.LastStatement.Visit(this)); } var locals = scope.AllLocals(); // Don't output blocks if we don't declare any locals and it's a single statement var expr = locals.Length == 0 && statementExprs.Count == 1 ? statementExprs[0] : Expr.Block(locals, statementExprs); scope = parentScope; return(expr); }
Expr IStatementVisitor <Expr> .Visit(Statement.Do statement) { scope = Scope.CreateChild(scope); return(Visit(statement.Body)); }