public void Assign(Operand target, Operand value, bool allowExplicitConversion) { if ((object)target == null) throw new ArgumentNullException("target"); BeforeStatement(); target.Assign(value, allowExplicitConversion).Emit(this); }
public void AssignDivide(Operand target, Operand value) { if ((object)target == null) throw new ArgumentNullException("target"); BeforeStatement(); target.AssignDivide(value).Emit(this); }
internal static void SetLeakedState(Operand[] operands, bool state) { if (operands != null) { for (int i = 0; i < operands.Length; i++) { OperandExtensions.SetLeakedState(operands[i], state); } } }
public void EmitArgs(CodeGen g, Operand[] args) { if (args.Length != appliedSignature.Length) throw new InvalidOperationException(); if (IsExpanded) { int fixedCount = methodSignature.Length - 1; Type expType = methodSignature[fixedCount].GetElementType(); for (int i = 0; i < fixedCount; i++) EmitArg(g, i, args[i]); int arrayLen = args.Length - methodSignature.Length - 1; g.EmitI4Helper(arrayLen); g.IL.Emit(OpCodes.Newarr, expType); OpCode stelemCode = CodeGen.GetStelemOpCode(expType); for (int i = 0; i < arrayLen; i++) { g.IL.Emit(OpCodes.Dup); g.EmitI4Helper(i); if (stelemCode == OpCodes.Stobj) g.IL.Emit(OpCodes.Ldelema, expType); EmitArg(g, fixedCount + i, args[fixedCount + i]); if (stelemCode == OpCodes.Stobj) g.IL.Emit(OpCodes.Stobj, expType); else g.IL.Emit(stelemCode); } } else { for (int i = 0; i < args.Length; i++) EmitArg(g, i, args[i]); } }
public static Conversion GetExplicit(Operand op, Type to, bool onlyStandard, ITypeMapper typeMapper) { // try implicit Conversion conv = GetImplicit(op, to, onlyStandard, typeMapper); if (conv.IsValid) return conv; Type from = Operand.GetType(op, typeMapper); Type fromUnderlying = Helpers.GetNullableUnderlyingType(@from); if (fromUnderlying == to) return new UnwrapNullable(typeMapper); Type toUnderlying = Helpers.GetNullableUnderlyingType(to); if (toUnderlying != null && fromUnderlying != null) { var c = GetExplicit(new FakeTypedOperand(fromUnderlying), toUnderlying, onlyStandard, typeMapper); if (c.IsValid) return new ConvertNullable(typeMapper, c); } // section 6.3.2 - Standard explicit conversions if (onlyStandard) { if (from == null || !GetImplicit(to, @from, true, typeMapper).IsValid) return new Invalid(typeMapper); } TypeCode tcFrom = Type.GetTypeCode(from); TypeCode tcTo = Type.GetTypeCode(to); byte ct = _convTable[(int)tcFrom][(int)tcTo]; // section 6.2.1 - Explicit numeric conversions, 6.2.2 - Explicit enumeration conversions if ((from.IsPrimitive || from.IsEnum || Helpers.AreTypesEqual(from, typeof(decimal), typeMapper)) && (to.IsPrimitive || to.IsEnum || Helpers.AreTypesEqual(to, typeof(decimal), typeMapper))) { if (ct == D) return new Direct(typeMapper); // this can happen for conversions involving enum-s if (ct <= E) { if (Helpers.AreTypesEqual(from, typeof(decimal), typeMapper) || Helpers.AreTypesEqual(to, typeof(decimal), typeMapper)) // decimal is handled as user-defined conversion, but as it is a standard one, always enable UDC processing onlyStandard = false; else return new Primitive(typeMapper); } } // section 6.2.5 - User-defined explicit conversions (details in section 6.4.4) if (!(onlyStandard || Helpers.AreTypesEqual(from, typeof(object), typeMapper) || Helpers.AreTypesEqual(to, typeof(object), typeMapper) || from.IsInterface || to.IsInterface || to.IsSubclassOf(from) || from.IsSubclassOf(to))) { List<UserDefined> candidates = null; FindCandidates(ref candidates, FindExplicitMethods(from, to, typeMapper), op, to, GetExplicit, typeMapper); if (candidates != null) { if (candidates.Count == 1) return candidates[0]; return UserDefined.FindExplicit(candidates, @from, to, typeMapper); } } // section 6.2.3 - Explicit reference conversions, 6.2.4 - Unboxing conversions // TODO: not really according to spec, but mostly works if (!from.IsValueType && from.IsAssignableFrom(to)) { if (to.IsValueType) return new Unboxing(typeMapper); else return new Cast(typeMapper); } return new Invalid(typeMapper); }
void DoInvoke(Operand invocation) { Eval(invocation); }
// the sections mentioned in comments of this method are from C# specification v1.2 public static Conversion GetImplicit(Operand op, Type to, bool onlyStandard) { Type from = Operand.GetType(op); if (to.Equals(from)) return Direct.Instance; // required for arrays created from TypeBuilder-s if (from != null && to.IsArray && from.IsArray) { if (to.GetArrayRank() == from.GetArrayRank()) { if (to.GetElementType().Equals(from.GetElementType())) return Direct.Instance; } } TypeCode tcFrom = Type.GetTypeCode(from); TypeCode tcTo = Type.GetTypeCode(to); byte ct = convTable[(int)tcFrom][(int)tcTo]; // section 6.1.2 - Implicit numeric conversions if ((from != null && (from.IsPrimitive || from == typeof(decimal))) && (to.IsPrimitive || to == typeof(decimal))) { if (ct <= I) { if (from == typeof(decimal) || to == typeof(decimal)) // decimal is handled as user-defined conversion, but as it is a standard one, always enable UDC processing onlyStandard = false; else return Primitive.Instance; } } IntLiteral intLit = op as IntLiteral; // section 6.1.3 - Implicit enumeration conversions if (!onlyStandard && to.IsEnum && (object)intLit != null && intLit.Value == 0) return Primitive.Instance; // section 6.1.4 - Implicit reference conversions if ((from == null || !from.IsValueType) && !to.IsValueType) { if (from == null) // from the null type to any reference type return Direct.Instance; if (to.IsAssignableFrom(from)) // the rest return Direct.Instance; } if (from == null) // no other conversion from null type is possible return Invalid.Instance; // section 6.1.5 - Boxing conversions if (from.IsValueType) { if (to.IsAssignableFrom(from)) return Boxing.Instance; } // section 6.1.6 - Implicit constant expression conversions if ((object)intLit != null && from == typeof(int) && to.IsPrimitive) { int val = intLit.Value; switch (tcTo) { case TypeCode.SByte: if (val >= sbyte.MinValue && val <= sbyte.MaxValue) return Direct.Instance; break; case TypeCode.Byte: if (val >= byte.MinValue && val <= byte.MaxValue) return Direct.Instance; break; case TypeCode.Int16: if (val >= short.MinValue && val <= short.MaxValue) return Direct.Instance; break; case TypeCode.UInt16: if (val >= ushort.MinValue && val <= ushort.MaxValue) return Direct.Instance; break; case TypeCode.UInt32: if (val >= 0) return Direct.Instance; break; case TypeCode.UInt64: if (val >= 0) return Primitive.Instance; break; } } if (from == typeof(long)) { LongLiteral longLit = op as LongLiteral; if ((object)longLit != null && longLit.Value > 0) return Direct.Instance; } // section 6.1.7 - User-defined implicit conversions (details in section 6.4.3) if (onlyStandard || from == typeof(object) || to == typeof(object) || from.IsInterface || to.IsInterface || to.IsSubclassOf(from) || from.IsSubclassOf(to)) return Invalid.Instance; // skip not-permitted conversion attempts (section 6.4.1) List<UserDefined> candidates = null; FindCandidates(ref candidates, FindImplicitMethods(from, to), op, to, GetImplicit); if (candidates == null) return Invalid.Instance; if (candidates.Count == 1) return candidates[0]; return UserDefined.FindImplicit(candidates, from, to); }
// the sections mentioned in comments of this method are from C# specification v1.2 public static Conversion GetImplicit(Operand op, Type to, bool onlyStandard, ITypeMapper typeMapper) { Type from = Operand.GetType(op, typeMapper); Type toUnderlying = Helpers.GetNullableUnderlyingType(to); if (to.Equals(from)) return new Direct(typeMapper); Type fromUnderlying = Helpers.GetNullableUnderlyingType(@from); if (toUnderlying != null) { if (fromUnderlying != null) { Conversion c = GetImplicit(new FakeTypedOperand(fromUnderlying), toUnderlying, onlyStandard, typeMapper); if (c.IsValid) return new ConvertNullable(typeMapper, c); } else { Conversion c = GetImplicit(op, toUnderlying, onlyStandard, typeMapper); if (c.IsValid) return new WrapNullable(typeMapper, c); } } // required for arrays created from TypeBuilder-s if (from != null && to.IsArray && from.IsArray) { if (to.GetArrayRank() == from.GetArrayRank()) { if (to.GetElementType().Equals(from.GetElementType())) return new Direct(typeMapper); } } TypeCode tcFrom = Type.GetTypeCode(from); TypeCode tcTo = Type.GetTypeCode(to); byte ct = _convTable[(int)tcFrom][(int)tcTo]; // section 6.1.2 - Implicit numeric conversions if (from != null && (from.IsPrimitive || Helpers.AreTypesEqual(from, typeof(decimal), typeMapper)) && (to.IsPrimitive || Helpers.AreTypesEqual(to, typeof(decimal), typeMapper))) { if (ct <= I) { if (Helpers.AreTypesEqual(from, typeof(decimal), typeMapper) || Helpers.AreTypesEqual(to, typeof(decimal), typeMapper)) // decimal is handled as user-defined conversion, but as it is a standard one, always enable UDC processing onlyStandard = false; else return new Primitive(typeMapper); } } IntLiteral intLit = op as IntLiteral; // section 6.1.3 - Implicit enumeration conversions if (!onlyStandard && to.IsEnum && (object)intLit != null && intLit.Value == 0) return new Primitive(typeMapper); // section 6.1.4 - Implicit reference conversions if ((from == null || !from.IsValueType) && !to.IsValueType) { if (from == null) // from the null type to any reference type return new Direct(typeMapper); if (to.IsAssignableFrom(from)) // the rest return new Direct(typeMapper); } if (from == null) // no other conversion from null type is possible return new Invalid(typeMapper); // section 6.1.5 - Boxing conversions if (from.IsValueType) { if (to.IsAssignableFrom(from)) return new Boxing(typeMapper); } // section 6.1.6 - Implicit constant expression conversions if ((object)intLit != null && Helpers.AreTypesEqual(from, typeof(int), typeMapper) && to.IsPrimitive) { int val = intLit.Value; switch (tcTo) { case TypeCode.SByte: if (val >= sbyte.MinValue && val <= sbyte.MaxValue) return new Direct(typeMapper); break; case TypeCode.Byte: if (val >= byte.MinValue && val <= byte.MaxValue) return new Direct(typeMapper); break; case TypeCode.Int16: if (val >= short.MinValue && val <= short.MaxValue) return new Direct(typeMapper); break; case TypeCode.UInt16: if (val >= ushort.MinValue && val <= ushort.MaxValue) return new Direct(typeMapper); break; case TypeCode.UInt32: if (val >= 0) return new Direct(typeMapper); break; case TypeCode.UInt64: if (val >= 0) return new Direct(typeMapper); break; } } // section 6.1.7 - User-defined implicit conversions (details in section 6.4.3) if (onlyStandard || Helpers.AreTypesEqual(from, typeof(object), typeMapper) || Helpers.AreTypesEqual(to, typeof(object), typeMapper) || from.IsInterface || to.IsInterface || to.IsSubclassOf(from) || from.IsSubclassOf(to)) return new Invalid(typeMapper); // skip not-permitted conversion attempts (section 6.4.1) List<UserDefined> candidates = null; FindCandidates(ref candidates, FindImplicitMethods(from, to, typeMapper), op, to, GetImplicit, typeMapper); if (candidates == null) return new Invalid(typeMapper); if (candidates.Count == 1) return candidates[0]; return UserDefined.FindImplicit(candidates, @from, to, typeMapper); }
protected internal static Type GetType(Operand op, ITypeMapper typeMapper) { if ((object)op == null) return null; return op.GetReturnType(typeMapper); }
protected internal virtual void EmitSet(CodeGen g, Operand value, bool allowExplicitConversion) { throw new InvalidOperationException(string.Format(null, Properties.Messages.ErrOperandNotWritable, GetType())); }
public Operand LogicalAnd(Operand other) { return OperandExtensions.SetLeakedState(Conditional(other, false), true); }
protected void EmitGetHelper(CodeGen g, Operand op, Type desiredType, bool allowExplicitConversion) { g.EmitGetHelper(op, desiredType,allowExplicitConversion); }
public Operand Multiply(Operand value) { return OperandExtensions.SetLeakedState(new OverloadableOperation(Operator.Multiply, this, value), true); }
public Operand Xor(Operand value) { return OperandExtensions.SetLeakedState(new OverloadableOperation(Operator.Xor, this, value), true); }
public void Invoke(Operand target, MethodInfo method, params Operand[] args) { DoInvoke(target.Invoke(method, TypeMapper, args)); }
public void Invoke(Operand target, string method) { Invoke(target, method, Operand.EmptyArray); }
public void DebugAssert(Operand condition, Operand message) { Invoke(TypeMapper.MapType(typeof(System.Diagnostics.Debug)), "Assert", condition, message); }
public void DebugWriteLine(Operand message) { Invoke(TypeMapper.MapType(typeof(System.Diagnostics.Debug)), "WriteLine", message); }
public void InvokeDelegate(Operand targetDelegate) { InvokeDelegate(targetDelegate, Operand.EmptyArray); }
public Operand BitwiseAnd(Operand value) { return OperandExtensions.SetLeakedState(new OverloadableOperation(Operator.And, this, value), true); }
public IStatement AssignXor(Operand value) { return Assign(Xor(value)); }
public Operand RightShift(Operand value) { return OperandExtensions.SetLeakedState(new OverloadableOperation(Operator.RightShift, this, value), true); }
public IStatement AssignLeftShift(Operand value) { return Assign(LeftShift(value)); }
public Operand LogicalOr(Operand other) { return OperandExtensions.SetLeakedState(Conditional(true, other), true); }
public IStatement AssignRightShift(Operand value) { return Assign(RightShift(value)); }
public Operand Conditional(Operand ifTrue, Operand ifFalse) { return OperandExtensions.SetLeakedState(new Conditional(this, ifTrue, ifFalse), true); }
public ContextualOperand InvokeEquals(Operand right, ITypeMapper typeMapper) { Operand left = this; var args = new Operand[] { left, right }; return OperandExtensions.SetLeakedState(new ContextualOperand(new Invocation(typeMapper.TypeInfo.FindMethod(typeMapper.MapType(typeof(object)), "Equals", args, true), null, args), typeMapper), true); }
protected internal static Type[] GetTypes(Operand[] ops, ITypeMapper typeMapper) { if (ops == null) return null; Type[] types = new Type[ops.Length]; for (int i = 0; i < ops.Length; i++) types[i] = (object)ops[i] == null ? null : ops[i].GetReturnType(typeMapper); return types; }
public Operand Ne(Operand value) { return new OverloadableOperation(Operator.Inequality, this, value); }
public Reference(Operand op) { _op = op; }
public Operand Ge(Operand value) { return new OverloadableOperation(Operator.GreaterThanOrEqual, this, value); }
public static Conversion GetExplicit(Operand op, Type to, bool onlyStandard) { // try implicit Conversion conv = GetImplicit(op, to, onlyStandard); if (conv.IsValid) return conv; Type from = Operand.GetType(op); // section 6.3.2 - Standard explicit conversions if (onlyStandard) { if (from == null || !GetImplicit(to, from, true).IsValid) return Invalid.Instance; } TypeCode tcFrom = Type.GetTypeCode(from); TypeCode tcTo = Type.GetTypeCode(to); byte ct = convTable[(int)tcFrom][(int)tcTo]; // section 6.2.1 - Explicit numeric conversions, 6.2.2 - Explicit enumeration conversions if ((from.IsPrimitive || from.IsEnum || from == typeof(decimal)) && (to.IsPrimitive || to.IsEnum || to == typeof(decimal))) { if (ct == D) return Direct.Instance; // this can happen for conversions involving enum-s if (ct <= E) { if (from == typeof(decimal) || to == typeof(decimal)) // decimal is handled as user-defined conversion, but as it is a standard one, always enable UDC processing onlyStandard = false; else return Primitive.Instance; } } // section 6.2.5 - User-defined explicit conversions (details in section 6.4.4) if (!(onlyStandard || from == typeof(object) || to == typeof(object) || from.IsInterface || to.IsInterface || to.IsSubclassOf(from) || from.IsSubclassOf(to))) { List<UserDefined> candidates = null; FindCandidates(ref candidates, FindExplicitMethods(from, to), op, to, GetExplicit); if (candidates != null) { if (candidates.Count == 1) return candidates[0]; return UserDefined.FindExplicit(candidates, from, to); } } // section 6.2.3 - Explicit reference conversions, 6.2.4 - Unboxing conversions // TODO: not really according to spec, but mostly works if (!from.IsValueType && from.IsAssignableFrom(to)) { if (to.IsValueType) return Unboxing.Instance; else return Cast.Instance; } return Invalid.Instance; }
public Operand Le(Operand value) { return new OverloadableOperation(Operator.LessThanOrEqual, this, value); }
static void FindCandidates(ref List<UserDefined> candidates, IEnumerable<IMemberInfo> methods, Operand from, Type to, ConversionProvider extraConv, ITypeMapper typeMapper) { foreach (IMemberInfo mi in methods) { Conversion before = extraConv(from, mi.ParameterTypes[0], true, typeMapper); if (!before.IsValid) continue; Conversion after = extraConv(new FakeTypedOperand(mi.ReturnType), to, true, typeMapper); if (!after.IsValid) continue; if (candidates == null) candidates = new List<UserDefined>(); candidates.Add(new UserDefined(before, mi, after, typeMapper)); } }
public Operand Subtract(Operand value) { return OperandExtensions.SetLeakedState(new OverloadableOperation(Operator.Subtract, this, value), true); }
internal AttributeGen(AttributeTargets target, AttributeType attributeType, object[] args) { if (args != null) { foreach (object arg in args) { CheckValue(arg); } } // TODO: target validation this.attributeType = attributeType; Operand[] argOperands; if (args == null || args.Length == 0) { this.args = EmptyArray<object>.Instance; argOperands = Operand.EmptyArray; } else { this.args = args; argOperands = new Operand[args.Length]; for (int i = 0; i < args.Length; i++) { argOperands[i] = GetOperand(args[i]); } } this.ctor = TypeInfo.FindConstructor(attributeType, argOperands); }
public ForeachBlock(Type elementType, Operand collection, ITypeMapper typeMapper) { _elementType = elementType; _collection = collection; _typeMapper = typeMapper; }