protected static bool IsOwnerMemberAccessible(MemberInfo member, ExpressionOptions options) { bool accessAllowed = false; // Get the allowed access defined in the options if (IsMemberPublic(member) == true) { accessAllowed = (options.OwnerMemberAccess & BindingFlags.Public) != 0; } else { accessAllowed = (options.OwnerMemberAccess & BindingFlags.NonPublic) != 0; } // See if the member has our access attribute defined ExpressionOwnerMemberAccessAttribute attr = Attribute.GetCustomAttribute(member, typeof(ExpressionOwnerMemberAccessAttribute)) as ExpressionOwnerMemberAccessAttribute; if (attr == null) { // No, so return the access level return(accessAllowed); } else { // Member has our access attribute defined; use its access value instead return(attr.AllowAccess); } }
internal ExpressionOptions Clone() { ExpressionOptions clonedOptions = this.MemberwiseClone() as ExpressionOptions; clonedOptions.MyProperties = MyProperties.Clone(); return(clonedOptions); }
public void Resolve(IServiceProvider services) { MyServices = services; MyOptions = services.GetService(typeof(ExpressionOptions)) as ExpressionOptions; MyContext = services.GetService(typeof(ExpressionContext)) as ExpressionContext; this.ResolveInternal(); this.Validate(); }
private void SetupOptions(ExpressionOptions options, bool isGeneric) { // Make sure we clone the options MyOptions = options; MyOptions.IsGeneric = isGeneric; if (isGeneric) { MyOptions.ResultType = typeof(T); } MyOptions.SetOwnerType(MyOwner.GetType()); }
public override void Emit(FleeILGenerator ilg, IServiceProvider services) { MyChild.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(MyChild.ResultType, MyResultType, ilg); ExpressionOptions options = services.GetService(typeof(ExpressionOptions)) as ExpressionOptions; if (options.IsGeneric == false) { ImplicitConverter.EmitImplicitConvert(MyResultType, typeof(object), ilg); } ilg.Emit(OpCodes.Ret); }
private static void EmitStringEquality(FleeILGenerator ilg, LogicalCompareOperation op, IServiceProvider services) { // Get the StringComparison from the options ExpressionOptions options = services.GetService(typeof(ExpressionOptions)) as ExpressionOptions; Int32LiteralElement ic = new Int32LiteralElement((int)options.StringComparison); ic.Emit(ilg, services); // and emit the method call MethodInfo mi = typeof(string).GetMethod("Equals", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string), typeof(string), typeof(StringComparison) }, null); ilg.Emit(OpCodes.Call, mi); if (op == LogicalCompareOperation.NotEqual) { ilg.Emit(OpCodes.Ldc_I4_0); ilg.Emit(OpCodes.Ceq); } }
/// <summary> /// Create a variable /// </summary> /// <param name="variableValueType">The variable's type</param> /// <param name="variableValue">The actual value; may be null</param> /// <returns>A new variable for the value</returns> /// <remarks></remarks> private IVariable CreateVariable(Type variableValueType, object variableValue) { Type variableType = default(Type); // Is the variable value an expression? IExpression expression = variableValue as IExpression; ExpressionOptions options = null; if (expression != null) { options = expression.Context.Options; // Get its result type variableValueType = options.ResultType; } if (expression != null) { // Create a variable that wraps the expression if (options.IsGeneric == false) { variableType = typeof(DynamicExpressionVariable <>); } else { variableType = typeof(GenericExpressionVariable <>); } } else { // Create a variable for a regular value MyContext.AssertTypeIsAccessible(variableValueType); variableType = typeof(GenericVariable <>); } // Create the generic variable instance variableType = variableType.MakeGenericType(variableValueType); IVariable v = Activator.CreateInstance(variableType) as IVariable; return(v); }
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>; }
private static void EmitExplicitNumericCast(FleeILGenerator ilg, Type sourceType, Type destType, IServiceProvider services) { TypeCode desttc = Type.GetTypeCode(destType); TypeCode sourcetc = Type.GetTypeCode(sourceType); bool unsigned = IsUnsignedType(sourceType); ExpressionOptions options = services.GetService(typeof(ExpressionOptions)) as ExpressionOptions; bool @checked = options.Checked; OpCode op = OpCodes.Nop; switch (desttc) { case TypeCode.SByte: if (unsigned == true & @checked == true) { op = OpCodes.Conv_Ovf_I1_Un; } else if (@checked == true) { op = OpCodes.Conv_Ovf_I1; } else { op = OpCodes.Conv_I1; } break; case TypeCode.Byte: if (unsigned == true & @checked == true) { op = OpCodes.Conv_Ovf_U1_Un; } else if (@checked == true) { op = OpCodes.Conv_Ovf_U1; } else { op = OpCodes.Conv_U1; } break; case TypeCode.Int16: if (unsigned == true & @checked == true) { op = OpCodes.Conv_Ovf_I2_Un; } else if (@checked == true) { op = OpCodes.Conv_Ovf_I2; } else { op = OpCodes.Conv_I2; } break; case TypeCode.UInt16: if (unsigned == true & @checked == true) { op = OpCodes.Conv_Ovf_U2_Un; } else if (@checked == true) { op = OpCodes.Conv_Ovf_U2; } else { op = OpCodes.Conv_U2; } break; case TypeCode.Int32: if (unsigned == true & @checked == true) { op = OpCodes.Conv_Ovf_I4_Un; } else if (@checked == true) { op = OpCodes.Conv_Ovf_I4; } else if (sourcetc != TypeCode.UInt32) { // Don't need to emit a convert for this case since, to the CLR, it is the same data type op = OpCodes.Conv_I4; } break; case TypeCode.UInt32: if (unsigned == true & @checked == true) { op = OpCodes.Conv_Ovf_U4_Un; } else if (@checked == true) { op = OpCodes.Conv_Ovf_U4; } else if (sourcetc != TypeCode.Int32) { op = OpCodes.Conv_U4; } break; case TypeCode.Int64: if (unsigned == true & @checked == true) { op = OpCodes.Conv_Ovf_I8_Un; } else if (@checked == true) { op = OpCodes.Conv_Ovf_I8; } else if (sourcetc != TypeCode.UInt64) { op = OpCodes.Conv_I8; } break; case TypeCode.UInt64: if (unsigned == true & @checked == true) { op = OpCodes.Conv_Ovf_U8_Un; } else if (@checked == true) { op = OpCodes.Conv_Ovf_U8; } else if (sourcetc != TypeCode.Int64) { op = OpCodes.Conv_U8; } break; case TypeCode.Single: op = OpCodes.Conv_R4; break; default: Debug.Assert(false, "Unknown cast dest type"); break; } if (op.Equals(OpCodes.Nop) == false) { ilg.Emit(op); } }
// Emit an arithmetic operation with handling for unsigned and checked contexts private void EmitArithmeticOperation(BinaryArithmeticOperation op, FleeILGenerator ilg, IServiceProvider services) { ExpressionOptions options = services.GetService(typeof(ExpressionOptions)) as ExpressionOptions; bool unsigned = IsUnsignedForArithmetic(MyLeftChild.ResultType) & IsUnsignedForArithmetic(MyRightChild.ResultType); bool integral = Utility.IsIntegralType(MyLeftChild.ResultType) & Utility.IsIntegralType(MyRightChild.ResultType); bool emitOverflow = integral & options.Checked; switch (op) { case BinaryArithmeticOperation.Add: if (emitOverflow == true) { if (unsigned == true) { ilg.Emit(OpCodes.Add_Ovf_Un); } else { ilg.Emit(OpCodes.Add_Ovf); } } else { ilg.Emit(OpCodes.Add); } break; case BinaryArithmeticOperation.Subtract: if (emitOverflow == true) { if (unsigned == true) { ilg.Emit(OpCodes.Sub_Ovf_Un); } else { ilg.Emit(OpCodes.Sub_Ovf); } } else { ilg.Emit(OpCodes.Sub); } break; case BinaryArithmeticOperation.Multiply: if (emitOverflow == true) { if (unsigned == true) { ilg.Emit(OpCodes.Mul_Ovf_Un); } else { ilg.Emit(OpCodes.Mul_Ovf); } } else { ilg.Emit(OpCodes.Mul); } break; case BinaryArithmeticOperation.Divide: if (unsigned == true) { ilg.Emit(OpCodes.Div_Un); } else { ilg.Emit(OpCodes.Div); } break; case BinaryArithmeticOperation.Mod: if (unsigned == true) { ilg.Emit(OpCodes.Rem_Un); } else { ilg.Emit(OpCodes.Rem); } break; case BinaryArithmeticOperation.Power: ilg.Emit(OpCodes.Call, OurPowerMethodInfo); break; default: Debug.Fail("Unknown op type"); break; } }
// Attempt to find the first type of integer that a number can fit into public static LiteralElement Create(string image, bool isHex, bool negated, IServiceProvider services) { StringComparison comparison = StringComparison.OrdinalIgnoreCase; ExpressionOptions options = services.GetService(typeof(ExpressionOptions)) as ExpressionOptions; // Convert to a double if option is set if (options.IntegersAsDoubles == true) { return(DoubleLiteralElement.Parse(image, services)); } bool hasUSuffix = image.EndsWith("u", comparison) & !image.EndsWith("lu", comparison); bool hasLSuffix = image.EndsWith("l", comparison) & !image.EndsWith("ul", comparison); bool hasULSuffix = image.EndsWith("ul", comparison) | image.EndsWith("lu", comparison); bool hasSuffix = hasUSuffix | hasLSuffix | hasULSuffix; LiteralElement constant = default(LiteralElement); NumberStyles numStyles = NumberStyles.Integer; if (isHex == true) { numStyles = NumberStyles.AllowHexSpecifier; image = image.Remove(0, 2); } if (hasSuffix == false) { // If the literal has no suffix, it has the first of these types in which its value can be represented: int, uint, long, ulong. constant = Int32LiteralElement.TryCreate(image, isHex, negated); if ((constant != null)) { return(constant); } constant = UInt32LiteralElement.TryCreate(image, numStyles); if ((constant != null)) { return(constant); } constant = Int64LiteralElement.TryCreate(image, isHex, negated); if ((constant != null)) { return(constant); } return(new UInt64LiteralElement(image, numStyles)); } else if (hasUSuffix == true) { image = image.Remove(image.Length - 1); // If the literal is suffixed by U or u, it has the first of these types in which its value can be represented: uint, ulong. constant = UInt32LiteralElement.TryCreate(image, numStyles); if ((constant != null)) { return(constant); } else { return(new UInt64LiteralElement(image, numStyles)); } } else if (hasLSuffix == true) { // If the literal is suffixed by L or l, it has the first of these types in which its value can be represented: long, ulong. image = image.Remove(image.Length - 1); constant = Int64LiteralElement.TryCreate(image, isHex, negated); if ((constant != null)) { return(constant); } else { return(new UInt64LiteralElement(image, numStyles)); } } else { // If the literal is suffixed by UL, Ul, uL, ul, LU, Lu, lU, or lu, it is of type ulong. Debug.Assert(hasULSuffix == true, "expecting ul suffix"); image = image.Remove(image.Length - 2); return(new UInt64LiteralElement(image, numStyles)); } }