/// <summary> /// Walks the lambda and produces a higher order function, which can be /// used to bind the lambda to a closure array from the interpreter. /// </summary> /// <param name="lambda">The lambda to bind.</param> /// <param name="closureVariables">Variables which are being accessed defined in the outer scope.</param> /// <returns>A delegate that can be called to produce a delegate bound to the passed in closure array.</returns> internal static Func <StrongBox <object>[], Delegate> BindLambda(LambdaExpression lambda, Dictionary <ParameterExpression, LocalVariable> closureVariables) { // 1. Create rewriter var closure = Expression.Parameter(typeof(StrongBox <object>[]), "closure"); var visitor = new LightLambdaClosureVisitor(closureVariables, closure); // 2. Visit the lambda lambda = (LambdaExpression)visitor.Visit(lambda); // 3. Create a higher-order function which fills in the parameters var result = Expression.Lambda <Func <StrongBox <object>[], Delegate> >(lambda, closure); // 4. Compile it return(result.Compile()); }
/// <summary> /// Create a compiled delegate for the LightLambda, and saves it so /// future calls to Run will execute the compiled code instead of /// interpreting. /// </summary> internal void Compile(object state) { if (_compiled != null) { return; } // Compilation is expensive, we only want to do it once. lock (_compileLock) { if (_compiled != null) { return; } PerfTrack.NoteEvent(PerfTrack.Categories.Compiler, "Interpreted lambda compiled"); // Interpreter needs a standard delegate type. // So change the lambda's delegate type to Func<...> or // Action<...> so it can be called from the LightLambda.Run // methods. LambdaExpression lambda = (_lambda as LambdaExpression) ?? (LambdaExpression)((LightLambdaExpression)_lambda).Reduce(); if (_interpreter != null) { _compiledDelegateType = GetFuncOrAction(lambda); lambda = Expression.Lambda(_compiledDelegateType, lambda.Body, lambda.Name, lambda.Parameters); } if (HasClosure) { _compiled = LightLambdaClosureVisitor.BindLambda(lambda, _interpreter.ClosureVariables); } else { _compiled = lambda.Compile(); } } }