예제 #1
0
        // 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);
        }
예제 #2
0
        // 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");
            }
        }
예제 #3
0
        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);
        }
예제 #4
0
        // 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);
        }
예제 #5
0
        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>;
        }
예제 #6
0
 public LocalBasedElement(ExpressionElement target, int index)
 {
     MyTarget = target;
     MyIndex  = index;
 }