private void EmitInlinedInvoke(InvocationExpression invoke, CompilationFlags flags) { var lambda = invoke.LambdaOperand; // This is tricky: we need to emit the arguments outside of the // scope, but set them inside the scope. Fortunately, using the IL // stack it is entirely doable. // 1. Emit invoke arguments var wb = EmitArguments(lambda.Type.GetMethod("Invoke"), invoke); // 2. Create the nested LambdaCompiler var inner = new LambdaCompiler(this, lambda); // 3. Emit the body // if the inlined lambda is the last expression of the whole lambda, // tail call can be applied. if (wb.Count != 0) { flags = UpdateEmitAsTailCallFlag(flags, CompilationFlags.EmitAsNoTail); } inner.EmitLambdaBody(_scope, true, flags); // 4. Emit writebacks if needed EmitWriteBack(wb); }
/// <summary> /// Compiler entry point /// </summary> /// <param name="lambda">LambdaExpression to compile.</param> /// <returns>The compiled delegate.</returns> internal static Delegate Compile(LambdaExpression lambda) { // 1. Bind lambda var tree = AnalyzeLambda(ref lambda); // 2. Create lambda compiler var c = new LambdaCompiler(tree, lambda); // 3. Emit c.EmitLambdaBody(); // 4. Return the delegate. return(c.CreateDelegate()); }