+ public List<ParameterExpression> GetHoistedLocals (LambdaExpression lambda)
+ {
+ if (hoisted_map == null)
+ return null;
+
+ List<ParameterExpression> hoisted;
+ hoisted_map.TryGetValue (lambda, out hoisted);
+ return hoisted;
+ }
+
+ public object [] CreateHoistedLocals (int unit)
+ {
+ var hoisted = GetHoistedLocals (units [unit].Lambda);
+ return new object [hoisted == null ? 0 : hoisted.Count];
+ }
+
+ public Expression IsolateExpression (ExecutionScope scope, object [] locals, Expression expression)
+ {
+ return new ParameterReplacer (this, scope, locals).Transform (expression);
+ }
+
+ public Delegate CreateDelegate ()
+ {
+ return CreateDelegate (0, new ExecutionScope (this));
+ }
+
+ public Delegate CreateDelegate (int unit, ExecutionScope scope)
+ {
+ return units [unit].CreateDelegate (scope);
+ }
+ }
+
+ class EmitContext {
+
+ CompilationContext context;
+ EmitContext parent;
+ LambdaExpression lambda;
+ DynamicMethod method;
+ LocalBuilder hoisted_store;
+ List<ParameterExpression> hoisted;
+
+ public readonly ILGenerator ig;
+
+ public bool HasHoistedLocals {
+ get { return hoisted != null && hoisted.Count > 0; }
+ }
+
+ public LambdaExpression Lambda {
+ get { return lambda; }
+ }
+
+ public EmitContext (CompilationContext context, EmitContext parent, LambdaExpression lambda)
+ {
+ this.context = context;
+ this.parent = parent;
+ this.lambda = lambda;
+ this.hoisted = context.GetHoistedLocals (lambda);
+
+ method = new DynamicMethod (
+ "lambda_method",
+ lambda.GetReturnType (),
+ CreateParameterTypes (lambda.Parameters),
+ typeof (ExecutionScope),
+ true);
+
+ ig = method.GetILGenerator ();
+ }
+
+ public void Emit ()
+ {
+ if (HasHoistedLocals)
+ EmitStoreHoistedLocals ();
+
+ lambda.EmitBody (this);
+ }
+
+ static Type [] CreateParameterTypes (IList<ParameterExpression> parameters)