/// <summary> /// Creates a lambda compiler that will compile into the provided Methodbuilder /// </summary> private LambdaCompiler(AnalyzedTree tree, LambdaExpression lambda, IMethodBuilderForLambdaCompiler method) { _hasClosureArgument = tree.Scopes[lambda].NeedsClosure; Type[] paramTypes = GetParameterTypes(lambda); if (_hasClosureArgument) { paramTypes = paramTypes.AddFirst(typeof(Closure)); } method.SetReturnType(lambda.ReturnType); method.SetParameters(paramTypes); var paramNames = lambda.Parameters.Map(p => p.Name); // parameters are index from 1, with closure argument we need to skip the first arg int startIndex = _hasClosureArgument ? 2 : 1; for (int i = 0; i < paramNames.Length; i++) { method.DefineParameter(i + startIndex, ParameterAttributes.None, paramNames[i]); } _tree = tree; _lambda = lambda; _typeBuilder = (TypeBuilder)method.DeclaringType; _method = method.AsMethodBase(); _ilg = method.GetILGenerator(); // These are populated by AnalyzeTree/VariableBinder _scope = tree.Scopes[lambda]; _boundConstants = tree.Constants[lambda]; InitializeMethod(); }
/// <summary> /// Mutates the MethodBuilder parameter, filling in IL, parameters, /// and return type. /// /// (probably shouldn't be modifying parameters/return type...) /// </summary> internal static void Compile(LambdaExpression lambda, IMethodBuilderForLambdaCompiler method, DebugInfoGenerator debugInfoGenerator) { // 1. Bind lambda AnalyzedTree tree = AnalyzeLambda(ref lambda); tree.DebugInfoGenerator = debugInfoGenerator; // 2. Create lambda compiler LambdaCompiler c = new LambdaCompiler(tree, lambda, method); // 3. Emit c.EmitLambdaBody(); }