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); }
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; } }
public string Format(EvaluableExpression expression) { if (expression == null) { return(""); } var builder = new StringBuilder(); Format(expression, 0, builder); return(builder.ToString()); }
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; } }
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)); }
public ObjectMemberExpression(EvaluableExpression @object, EvaluableExpression member, int startIndex, int endIndex, bool isIndexer) : base(isIndexer ? "ObjectIndexer" : "ObjectMember", startIndex, endIndex) { Object = @object; Member = member; IsIndexer = isIndexer; }
public ConditionalExpression(EvaluableExpression condition, EvaluableExpression valueIfTrue, EvaluableExpression valueIfFalse, int startIndex, int endIndex) : base("Conditional", startIndex, endIndex) { Condition = condition; ValueIfTrue = valueIfTrue; ValueIfFalse = valueIfFalse; }
public static string ToPrettyString(this EvaluableExpression expr, IFormatter formatter = null) => (formatter ?? Formatter.Default).Format(expr);
public static IEvaluator <TState> Compile <TState>(this EvaluableExpression expr, ICompiler compiler = null) => (compiler ?? Compiler.Default).Compile <TState>(expr);
public InExpression(EvaluableExpression value, EvaluableExpression[] values, int startIndex, int endIndex) : base("In", startIndex, endIndex) { Value = value; Values = values; }
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; } }