ExpressionEmitter
using Stashbox.Expressions.Compile.Emitters;
using Stashbox.Expressions.Compile.Extensions;
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection.Emit;
namespace Stashbox.Expressions.Compile
{
internal static class ExpressionEmitter
{
public static bool TryEmit(this LambdaExpression expression, out Delegate resultDelegate)
{
return expression.Body.TryEmit(out resultDelegate, expression.Type, expression.ReturnType, expression.Parameters.ToArray());
}
public static bool TryEmit(this Expression expression, out Delegate resultDelegate, Type delegateType, Type returnType, params ParameterExpression[] parameters)
{
resultDelegate = null;
TreeAnalyzer treeAnalyzer = new TreeAnalyzer();
if (!treeAnalyzer.Analyze(expression, parameters))
return false;
if (!treeAnalyzer.NestedLambdas.IsEmpty)
treeAnalyzer.StoredObjects.AddRange(new object[treeAnalyzer.NestedLambdas.Length]);
CompilerContext compilerContext = new CompilerContext(treeAnalyzer.StoredObjects.IsEmpty ? null : new Closure(treeAnalyzer.StoredObjects.AsArray()), treeAnalyzer.DefinedVariables, treeAnalyzer.CapturedParameters, treeAnalyzer.NestedLambdas);
DynamicMethod dynamicMethod = Emitter.CreateDynamicMethod(compilerContext, returnType, parameters);
ILGenerator iLGenerator = dynamicMethod.GetILGenerator();
if (compilerContext.HasCapturedVariablesArgument) {
compilerContext.CapturedArgumentsHolderVariable = iLGenerator.PrepareCapturedArgumentsHolderVariable(treeAnalyzer.CapturedParameters.Length);
iLGenerator.CopyParametersToCapturedArgumentsIfAny(compilerContext, parameters);
}
if (treeAnalyzer.DefinedVariables.Length > 0)
compilerContext.LocalBuilders = treeAnalyzer.DefinedVariables.BuildLocals(iLGenerator);
if (!expression.TryEmit(iLGenerator, compilerContext, parameters))
return false;
iLGenerator.Emit(OpCodes.Ret);
resultDelegate = (compilerContext.HasClosure ? dynamicMethod.CreateDelegate(delegateType, compilerContext.Target) : dynamicMethod.CreateDelegate(delegateType));
return true;
}
}
}