Example #1
0
        private static Action <ILGenerator> GenerateNestedFunc2(Type stateType, MethodInfo methodInfo)
        {
            var className   = $"TupacAmaru.Yacep.DynamicAssembly.Functions.Function{NameCounter.GetCurrentCount()}";
            var typeBuilder = dynamicModule.DefineType(className, TypeAttributes.Public | TypeAttributes.Sealed);
            var target      = typeBuilder.DefineField("_target", stateType, FieldAttributes.Private | FieldAttributes.InitOnly);
            var ctor        = typeBuilder.DefineConstructor(
                MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName |
                MethodAttributes.RTSpecialName, CallingConventions.HasThis, new[] { stateType });
            var ctorIl = ctor.GetILGenerator();

            ctorIl.Emit(OpCodes.Ldarg_0);
            ctorIl.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
            ctorIl.Emit(OpCodes.Ldarg_0);
            ctorIl.Emit(OpCodes.Ldarg_1);
            ctorIl.Emit(OpCodes.Stfld, target);
            ctorIl.Emit(OpCodes.Ret);

            var methodName    = $"FuncProxy{NameCounter.GetCurrentCount()}";
            var proxyMethod   = typeBuilder.DefineMethod(methodName, MethodAttributes.Public | MethodAttributes.HideBySig, CallingConventions.Standard, typeof(object), new[] { typeof(object[]) });
            var proxyMethodIl = proxyMethod.GetILGenerator();
            var parameters    = methodInfo.GetParameters();
            var num           = parameters.Length;

            proxyMethodIl.Emit(OpCodes.Ldarg_0);
            proxyMethodIl.Emit(OpCodes.Ldfld, target);
            for (var i = 0; i < num; i++)
            {
                var parameterInfo = parameters[i];
                var parameterType = parameterInfo.ParameterType;
                proxyMethodIl.Emit(OpCodes.Ldarg_1);
                proxyMethodIl.Emit(OpCodes.Ldc_I4_S, i);
                proxyMethodIl.Emit(OpCodes.Ldelem_Ref);
                proxyMethodIl.Emit(parameterType.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, parameterType);
            }
            proxyMethodIl.Emit(OpCodes.Callvirt, methodInfo);
            if (methodInfo.ReturnType == typeof(void))
            {
                proxyMethodIl.Emit(OpCodes.Ldnull);
            }
            else if (methodInfo.ReturnType.IsValueType)
            {
                proxyMethodIl.Emit(OpCodes.Box, methodInfo.ReturnType);
            }
            proxyMethodIl.Emit(OpCodes.Ret);
            var type            = typeBuilder.CreateTypeInfo().AsType();
            var ctorInfo        = type.GetConstructor(new[] { stateType });
            var proxyMethodInfo = type.GetMethod(methodName);

            return(il =>
            {
                il.Emit(OpCodes.Newobj, ctorInfo);
                il.Emit(OpCodes.Ldftn, proxyMethodInfo);
                il.Emit(OpCodes.Newobj, Delegates.NewObjectArrayArgumentFunc);
            });
        }
Example #2
0
        private static FieldBuilder GetOrAddValue <V>(TypeBuilder typeBuilder, Conjunction <V> conjunction, string symbol, Type fieldType, V value)
        {
            if (conjunction.TryGetValue(symbol, out var definedValue))
            {
                return(definedValue);
            }
            var field = typeBuilder.DefineField($"_f{NameCounter.GetCurrentCount()}", fieldType, FieldAttributes.Private | FieldAttributes.InitOnly);

            conjunction.Add(symbol, field, value);
            return(field);
        }
Example #3
0
        public IEvaluator <TState> Compile <TState>(EvaluableExpression expression)
        {
            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }
            var className      = $"TupacAmaru.Yacep.DynamicAssembly.Workers.Worker{NameCounter.GetCurrentCount()}";
            var typeBuilder    = dynamicModule.DefineType(className, TypeAttributes.Public | TypeAttributes.Sealed);
            var compileContext = new CompileContext(typeBuilder);

            var methodName = "Execute";

            GenerateExecuteMethod <TState>(expression, typeBuilder, methodName, compileContext);
            GenerateConstructor(compileContext);

            var workerType = typeBuilder.CreateTypeInfo().AsType();

            return(CreateEvaluator <TState>(workerType, workerType.GetMethod(methodName), compileContext));
        }
Example #4
0
        private static EvaluableExpression TryGenerateObjectMemberIL(Type stateType, ObjectMemberExpression objectMemberExpression, ILGenerator iLGenerator, CompileContext compileContext)
        {
            var unresolvedExpression = objectMemberExpression;
            var stack = new Stack <(string memberName, object indexerValue)>();

            while (true)
            {
                var target = unresolvedExpression.Object;
                if (target is IdentifierExpression maybeIdentifier)
                {
                    if (unresolvedExpression.IsIndexer)
                    {
                        if (unresolvedExpression.Member is ConstantExpression constantExpression)
                        {
                            stack.Push(("", constantExpression.Value));
                            stack.Push((maybeIdentifier.Name, null));
                            break;
                        }
                        if (unresolvedExpression.Member is LiteralExpression literalExpression &&
                            literalExpression.LiteralValue.Value != null)
                        {
                            stack.Push(("", literalExpression.LiteralValue.Value));
                            stack.Push((maybeIdentifier.Name, null));
                            break;
                        }
                    }
                    else
                    {
                        var identifierExpression = (IdentifierExpression)unresolvedExpression.Member;
                        stack.Push((identifierExpression.Name, null));
                        stack.Push((maybeIdentifier.Name, null));
                        break;
                    }
                    stack.Clear();
                    return(objectMemberExpression);
                }
                var member = unresolvedExpression.Member;
                if (unresolvedExpression.IsIndexer)
                {
                    switch (member)
                    {
                    case ConstantExpression constantExpression:
                        stack.Push(("", constantExpression.Value));
                        break;

                    case LiteralExpression literalExpression when literalExpression.LiteralValue.Value != null:
                        stack.Push(("", literalExpression.LiteralValue.Value));
                        break;

                    default:
                        stack.Clear();
                        return(objectMemberExpression);
                    }
                }
                else
                {
                    var identifierExpression = (IdentifierExpression)unresolvedExpression.Member;
                    stack.Push((identifierExpression.Name, null));
                }
                if (target is ObjectMemberExpression objectMember)
                {
                    unresolvedExpression = objectMember;
                }
                else
                {
                    stack.Clear();
                    return(objectMemberExpression);
                }
            }
            var currentType = stateType;
            var first       = stack.Peek();

            if (string.Equals("this", first.memberName, StringComparison.Ordinal))
            {
                stack.Pop();
            }
            var readers = new List <Action <CompileContext, ILGenerator> > {
                (c, il) => il.Emit(OpCodes.Ldarg_1)
            };

            while (stack.Count > 0)
            {
                var(memberName, indexerValue) = stack.Pop();
                if (indexerValue != null)
                {
                    var indexerType = indexerValue.GetType();
                    var method      = currentType.GetMethod("Get", new[] { indexerType }) ?? currentType.GetMethod("get_Item", new[] { indexerType });
                    if (method != null)
                    {
                        currentType = method.ReturnType;
                        readers.Add((context, il) =>
                        {
                            var valueName = $"_v{NameCounter.GetCurrentCount()}";
                            GenerateValue(il, indexerValue, context, valueName, false);
                            il.Emit(OpCodes.Callvirt, method);
                        });
                        continue;
                    }
                    if (indexerValue is string stringValue)
                    {
                        memberName = stringValue;
                    }
                    else
                    {
                        return(objectMemberExpression);
                    }
                }
                if (!string.IsNullOrWhiteSpace(memberName))
                {
                    var propertyInfo = currentType.GetProperty(memberName);
                    if (propertyInfo != null && propertyInfo.CanRead)
                    {
                        var getter = propertyInfo.GetGetMethod();
                        if (getter != null)
                        {
                            currentType = propertyInfo.PropertyType;
                            readers.Add((context, il) => il.Emit(OpCodes.Callvirt, getter));
                            continue;
                        }
                    }
                    var fieldInfo = currentType.GetField(memberName);
                    if (fieldInfo != null)
                    {
                        currentType = fieldInfo.FieldType;
                        readers.Add((context, il) => il.Emit(OpCodes.Ldfld, fieldInfo));
                        continue;
                    }
                    var method = currentType.GetMethod("get_Item", new[] { typeof(string) }) ?? currentType.GetMethod("Get", new[] { typeof(string) })
                                 ?? currentType.GetInterfaces().FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IDictionary <,>) &&
                                                                               x.GetGenericArguments()[0] == typeof(string))?.GetMethod("get_Item");
                    if (method != null)
                    {
                        currentType = method.ReturnType;
                        readers.Add((context, il) =>
                        {
                            il.Emit(OpCodes.Ldstr, memberName);
                            il.Emit(OpCodes.Callvirt, method);
                        });
                        continue;
                    }

                    var methodInfo = currentType.GetMethod(memberName);
                    if (methodInfo != null)
                    {
                        var type = currentType;
                        readers.Add((context, il) => GenerateNestedFunc2(type, methodInfo)(il));
                        currentType = typeof(Func <object[], object>);
                        continue;
                    }
                }
                return(objectMemberExpression);
            }
            foreach (var reader in readers)
            {
                reader(compileContext, iLGenerator);
            }
            if (currentType.IsValueType)
            {
                iLGenerator.Emit(OpCodes.Box, currentType);
            }
            return(null);
        }