// Emit elements into an array private static void EmitElementArrayLoad(ExpressionElement[] elements, Type arrayElementType, FleeILGenerator ilg, IServiceProvider services) { // Load the array length LiteralElement.EmitInt32Load(elements.Length, ilg); // Create the array ilg.Emit(OpCodes.Newarr, arrayElementType); // Store the new array in a unique local and remember the index LocalBuilder local = ilg.DeclareLocal(arrayElementType.MakeArrayType()); int arrayLocalIndex = local.LocalIndex; Utility.EmitStoreLocal(ilg, arrayLocalIndex); for (int i = 0; i <= elements.Length - 1; i++) { // Load the array Utility.EmitLoadLocal(ilg, arrayLocalIndex); // Load the index LiteralElement.EmitInt32Load(i, ilg); // Emit the element (with any required conversions) ExpressionElement element = elements[i]; element.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(element.ResultType, arrayElementType, ilg); // Store it into the array Utility.EmitArrayStore(ilg, arrayElementType); } // Load the array Utility.EmitLoadLocal(ilg, arrayLocalIndex); }
// Emit the arguments to a regular method call private void EmitRegularFunctionInternal(ParameterInfo[] parameters, ExpressionElement[] elements, FleeILGenerator ilg, IServiceProvider services) { Debug.Assert(parameters.Length == elements.Length, "argument count mismatch"); // Emit each element and any required conversions to the actual parameter type for (int i = 0; i <= parameters.Length - 1; i++) { ExpressionElement element = elements[i]; ParameterInfo pi = parameters[i]; element.Emit(ilg, services); bool success = ImplicitConverter.EmitImplicitConvert(element.ResultType, pi.ParameterType, ilg); Debug.Assert(success, "conversion failed"); } }
private static void EmitToAssembly(ExpressionElement rootElement, IServiceContainer services) { AssemblyName assemblyName = new AssemblyName(EmitAssemblyName); string assemblyFileName = string.Format("{0}.dll", EmitAssemblyName); AssemblyBuilder assemblyBuilder = System.AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Save); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyFileName, assemblyFileName); MethodBuilder mb = moduleBuilder.DefineGlobalMethod("Evaluate", MethodAttributes.Public | MethodAttributes.Static, typeof(T), new Type[] { typeof(object), typeof(ExpressionContext), typeof(VariableCollection) }); FleeILGenerator ilg = new FleeILGenerator(mb.GetILGenerator(), 0, false); rootElement.Emit(ilg, services); moduleBuilder.CreateGlobalFunctions(); assemblyBuilder.Save(assemblyFileName); }
// Emit the arguments to a paramArray method call private void EmitParamArrayArguments(ParameterInfo[] parameters, ExpressionElement[] elements, FleeILGenerator ilg, IServiceProvider services) { // Get the fixed parameters ParameterInfo[] fixedParameters = new ParameterInfo[MyTargetMethodInfo.MyFixedArgTypes.Length]; Array.Copy(parameters, fixedParameters, fixedParameters.Length); // Get the corresponding fixed parameters ExpressionElement[] fixedElements = new ExpressionElement[MyTargetMethodInfo.MyFixedArgTypes.Length]; Array.Copy(elements, fixedElements, fixedElements.Length); // Emit the fixed arguments this.EmitRegularFunctionInternal(fixedParameters, fixedElements, ilg, services); // Get the paramArray arguments ExpressionElement[] paramArrayElements = new ExpressionElement[elements.Length - fixedElements.Length]; Array.Copy(elements, fixedElements.Length, paramArrayElements, 0, paramArrayElements.Length); // Emit them into an array EmitElementArrayLoad(paramArrayElements, MyTargetMethodInfo.ParamArrayElementType, ilg, services); }
private void Compile(string expression, ExpressionOptions options) { // Add the services that will be used by elements during the compile IServiceContainer services = new ServiceContainer(); this.AddServices(services); // Parse and get the root element of the parse tree ExpressionElement topElement = MyContext.Parse(expression, services); if (options.ResultType == null) { options.ResultType = topElement.ResultType; } RootExpressionElement rootElement = new RootExpressionElement(topElement, options.ResultType); DynamicMethod dm = this.CreateDynamicMethod(); FleeILGenerator ilg = new FleeILGenerator(dm.GetILGenerator(), 0, false); // Emit the IL rootElement.Emit(ilg, services); ilg.ValidateLength(); // Emit to an assembly if required if (options.EmitToAssembly == true) { EmitToAssembly(rootElement, services); } Type delegateType = typeof(ExpressionEvaluator <>).MakeGenericType(typeof(T)); MyEvaluator = dm.CreateDelegate(delegateType) as ExpressionEvaluator <T>; }
public LocalBasedElement(ExpressionElement target, int index) { MyTarget = target; MyIndex = index; }