Пример #1
0
        private static void GenerateExecuteMethod(EvaluableExpression expression, TypeBuilder typeBuilder, string methodName, CompileContext compileContext)
        {
            var execute = typeBuilder.DefineMethod(methodName, MethodAttributes.Public | MethodAttributes.HideBySig, CallingConventions.Standard,
                                                   typeof(object), new[] { typeof(object) });
            var executeIl = execute.GetILGenerator();

            GenerateIL(executeIl, expression, compileContext, GenerateNaturalObjectMember);
            executeIl.Emit(OpCodes.Ret);
        }
Пример #2
0
        private static void GenerateNaturalObjectMember(ILGenerator il, EvaluableExpression expr, CompileContext context)
        {
            switch (expr)
            {
            case IdentifierExpression identifierExpression:
                context.Cacheable = false;
                if (string.Equals("this", identifierExpression.Name, StringComparison.Ordinal))
                {
                    il.Emit(OpCodes.Ldarg_1);
                }
                else
                {
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Ldfld, context.ObjectMemberEvaluator);
                    il.Emit(OpCodes.Ldarg_1);
                    il.Emit(OpCodes.Ldstr, identifierExpression.Name);
                    il.Emit(OpCodes.Ldc_I4_0);
                    il.Emit(OpCodes.Call, Delegates.EvaluateObjectMemberExpression);
                }

                break;

            case ObjectMemberExpression objectMemberExpression:
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, context.ObjectMemberEvaluator);
                GenerateIL(il, objectMemberExpression.Object, context, GenerateNaturalObjectMember);
                switch (objectMemberExpression.Member)
                {
                case IdentifierExpression identifierExpr:
                    il.Emit(OpCodes.Ldstr, identifierExpr.Name);
                    break;

                case Expressions.ConstantExpression constant when constant.Value is string stringValue:
                    il.Emit(OpCodes.Ldstr, stringValue);
                    break;

                case LiteralExpression literal when literal.LiteralValue.Value is string stringValue:
                    il.Emit(OpCodes.Ldstr, stringValue);
                    break;

                default:
                    GenerateIL(il, objectMemberExpression.Member, context, GenerateNaturalObjectMember);
                    break;
                }
                il.Emit(objectMemberExpression.IsIndexer ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
                il.Emit(OpCodes.Call, Delegates.EvaluateObjectMemberExpression);
                break;

            case ObjectsFunctionCallExpression objectsFunctionCallExpression:
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, context.FunctionCaller);
                GenerateIL(il, objectsFunctionCallExpression.Callee, context, GenerateNaturalObjectMember);
                GenerateArray(il, objectsFunctionCallExpression.Arguments, context, GenerateNaturalObjectMember);
                il.Emit(OpCodes.Call, Delegates.CallFunction);
                break;
            }
        }
Пример #3
0
        public string Format(EvaluableExpression expression)
        {
            if (expression == null)
            {
                return("");
            }
            var builder = new StringBuilder();

            Format(expression, 0, builder);
            return(builder.ToString());
        }
Пример #4
0
        private static void Format(EvaluableExpression expression, int prefixLength, StringBuilder builder)
        {
            const int count = 4;

            builder.AppendLine(AddPrefix(prefixLength, $"type: {expression.TypeName}"));
            switch (expression)
            {
            case ArrayExpression arrayExpression:
                FormatArrayExpression(prefixLength, builder, arrayExpression, count);
                break;

            case BinaryExpression binaryExpression:
                FormatBinaryExpression(prefixLength, builder, binaryExpression, count);
                break;

            case ConditionalExpression conditionalExpression:
                FormatConditionalExpression(prefixLength, builder, conditionalExpression, count);
                break;

            case ConstantExpression constantExpression:
                FormatConstantExpression(prefixLength, builder, constantExpression);
                break;

            case IdentifierExpression identifierExpression:
                builder.AppendLine(AddPrefix(prefixLength, $"name: {identifierExpression.Name}"));
                break;

            case InExpression inExpression:
                FormatInExpression(prefixLength, builder, inExpression, count);
                break;

            case LiteralExpression literalExpression:
                FormatLiteralExpression(prefixLength, builder, literalExpression);
                break;

            case NakedFunctionCallExpression nakedFunctionCallExpression:
                FormatNakedFunctionCallExpression(prefixLength, builder, nakedFunctionCallExpression, count);
                break;

            case ObjectMemberExpression objectMemberExpression:
                FormatObjectMemberExpression(prefixLength, builder, objectMemberExpression, count);
                break;

            case ObjectsFunctionCallExpression objectsFunctionCallExpression:
                FormatObjectsFunctionCallExpression(prefixLength, builder, objectsFunctionCallExpression, count);
                break;

            case UnaryExpression unaryExpression:
                FormatUnaryExpression(prefixLength, builder, unaryExpression, count);
                break;
            }
        }
Пример #5
0
        public IEvaluator Compile(EvaluableExpression expression)
        {
            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }
            var className      = $"TupacAmaru.Yacep.DynamicAssembly.Executers.Executer{NameCounter.GetCurrentCount()}";
            var typeBuilder    = dynamicModule.DefineType(className, TypeAttributes.Public | TypeAttributes.Sealed);
            var compileContext = new CompileContext(typeBuilder);
            var methodName     = "Execute";

            GenerateExecuteMethod(expression, typeBuilder, methodName, compileContext);
            GenerateConstructor(compileContext);

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

            return(CreateEvaluator(workerType, workerType.GetMethod(methodName), compileContext));
        }
Пример #6
0
 public ObjectMemberExpression(EvaluableExpression @object, EvaluableExpression member, int startIndex, int endIndex, bool isIndexer) : base(isIndexer ? "ObjectIndexer" : "ObjectMember", startIndex, endIndex)
 {
     Object    = @object;
     Member    = member;
     IsIndexer = isIndexer;
 }
Пример #7
0
 public ConditionalExpression(EvaluableExpression condition, EvaluableExpression valueIfTrue, EvaluableExpression valueIfFalse, int startIndex, int endIndex) : base("Conditional", startIndex, endIndex)
 {
     Condition    = condition;
     ValueIfTrue  = valueIfTrue;
     ValueIfFalse = valueIfFalse;
 }
Пример #8
0
 public static string ToPrettyString(this EvaluableExpression expr, IFormatter formatter = null)
 => (formatter ?? Formatter.Default).Format(expr);
Пример #9
0
 public static IEvaluator <TState> Compile <TState>(this EvaluableExpression expr, ICompiler compiler = null)
 => (compiler ?? Compiler.Default).Compile <TState>(expr);
Пример #10
0
 public InExpression(EvaluableExpression value, EvaluableExpression[] values, int startIndex, int endIndex) : base("In", startIndex, endIndex)
 {
     Value  = value;
     Values = values;
 }
Пример #11
0
        private static void GenerateIL(ILGenerator il, EvaluableExpression expression, CompileContext compileContext, Action <ILGenerator, EvaluableExpression, CompileContext> objectExpressionGenerater)
        {
            switch (expression)
            {
            case ArrayExpression arrayExpression:
                GenerateArray(il, arrayExpression.Elements, compileContext, objectExpressionGenerater);
                break;

            case Expressions.BinaryExpression binaryExpression:
                il.Emit(OpCodes.Ldarg_0);
                var binaryOperator      = binaryExpression.BinaryOperator;
                var binaryOperatorField = GetOrAddValue(compileContext.TypeBuilder, compileContext.Binarys, binaryOperator.Operator, typeof(BinaryOperatorHandler), binaryOperator.Handler);
                il.Emit(OpCodes.Ldfld, binaryOperatorField);
                GenerateIL(il, binaryExpression.Left, compileContext, objectExpressionGenerater);
                GenerateIL(il, binaryExpression.Right, compileContext, objectExpressionGenerater);
                il.Emit(OpCodes.Call, Delegates.HandleBinaryOperator);
                break;

            case Expressions.ConstantExpression constantExpression:
                var constantValueName = $"_c{constantExpression.Raw.GetHashCode()}";
                GenerateValue(il, constantExpression.Value, compileContext, constantValueName, true);
                break;

            case Expressions.ConditionalExpression conditionalExpression:
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, compileContext.ConditionEvaluator);
                GenerateIL(il, conditionalExpression.Condition, compileContext, objectExpressionGenerater);
                GenerateIL(il, conditionalExpression.ValueIfTrue, compileContext, objectExpressionGenerater);
                GenerateIL(il, conditionalExpression.ValueIfFalse, compileContext, objectExpressionGenerater);
                il.Emit(OpCodes.Call, Delegates.EvaluateConditionExpression);
                break;

            case InExpression inExpression:
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, compileContext.InEvaluator);
                GenerateIL(il, inExpression.Value, compileContext, objectExpressionGenerater);
                GenerateArray(il, inExpression.Values, compileContext, objectExpressionGenerater);
                il.Emit(OpCodes.Call, Delegates.EvaluateInExpression);
                break;

            case LiteralExpression literalExpression:
                var literalValue     = literalExpression.LiteralValue;
                var literalValueName = $"_l{literalValue.Literal.GetHashCode()}";
                GenerateValue(il, literalValue.Value, compileContext, literalValueName, true);
                break;

            case Expressions.UnaryExpression unaryExpression:
                il.Emit(OpCodes.Ldarg_0);
                var unaryOperator      = unaryExpression.UnaryOperator;
                var unaryOperatorField = GetOrAddValue(compileContext.TypeBuilder, compileContext.Unarys, unaryOperator.Operator, typeof(UnaryOperatorHandler), unaryOperator.Handler);
                il.Emit(OpCodes.Ldfld, unaryOperatorField);
                GenerateIL(il, unaryExpression.Argument, compileContext, objectExpressionGenerater);
                il.Emit(OpCodes.Call, Delegates.HandleUnaryOperator);
                break;

            case NakedFunctionCallExpression nakedFunctionCallExpression:
                if (!nakedFunctionCallExpression.NakedFunction.Cacheable)
                {
                    compileContext.Cacheable = false;
                }
                il.Emit(OpCodes.Ldarg_0);
                var nakedFunction      = nakedFunctionCallExpression.NakedFunction;
                var nakedFunctionField = GetOrAddValue(compileContext.TypeBuilder, compileContext.Functions, nakedFunction.Name, typeof(NakedFunctionHandler), nakedFunction.Handler);
                il.Emit(OpCodes.Ldfld, nakedFunctionField);
                GenerateArray(il, nakedFunctionCallExpression.Arguments, compileContext, objectExpressionGenerater);
                il.Emit(OpCodes.Call, Delegates.HandleNakedFunction);
                break;

            case IdentifierExpression _:
            case ObjectMemberExpression _:
            case ObjectsFunctionCallExpression _:
                objectExpressionGenerater(il, expression, compileContext);
                break;
            }
        }