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 IStatementVisitor <Expr> .Visit(Statement.Repeat statement) { // Temporarily rewrite the AST so that the test expression can be evaulated in the same scope as the body statement.Body.Statements.Add( new Statement.If( statement.Test, new Block(new List <Statement>(), new LastStatement.Break()), new List <Elseif>(), null)); var breakLabel = scope.BreakLabel(); var expr = Expr.Loop( Visit(statement.Body), breakLabel); statement.Body.Statements.RemoveAt(statement.Body.Statements.Count - 2); return(expr); }