public static UnaryOperatorSymbol ClassifyOperation(UnaryOperatorKind kind, TypeSymbol expr) { int exprIdx = ConversionEasyOut.TypeToIndex(expr); if (exprIdx < 0) { return(null); } return(s_unOp[(int)kind][exprIdx]); }
public static BinaryOperatorSymbol ClassifyOperation(BinaryOperatorKind kind, TypeSymbol left, TypeSymbol right) { int leftIdx = ConversionEasyOut.TypeToIndex(left); if (leftIdx < 0) { return(null); } int rightIdx = ConversionEasyOut.TypeToIndex(right); if (rightIdx < 0) { return(null); } return(s_binOp[(int)kind][leftIdx, rightIdx]); }
internal static ConversionSymbol Conversion(Expr expr, TypeSymbol type, BindOptions options) { var noConversion = ConversionKind.NoConversion; var conversion = ConversionEasyOut.ClassifyConversion(expr.Datatype, type); if (expr.Symbol.IsConstant() || expr.IsConstant) { options |= BindOptions.Explicit; } if (conversion != ConversionKind.NoConversion) { var conv = ConversionSymbol.Create(conversion); if (!conv.IsCast && options.HasFlag(BindOptions.Explicit) || conv.IsImplicit) { return(conv); } if (conv.IsCast && options.HasFlag(BindOptions.Cast)) { return(conv); } if (conv.IsExplicit && conv.Kind == ConversionKind.ExplicitNumeric && options.HasFlag(BindOptions.AllowImplicitNarrowingConversions)) { return(conv); // TODO nvk: this should raise a warning! } if (conv.Exists) { noConversion = ConversionKind.NoImplicitConversion; } } if (TypesMatch(expr.Datatype, type)) { return(ConversionSymbol.Create(ConversionKind.Identity)); } if (type.Type.IsGenericType || expr.Datatype.Type.IsGenericType) { return(ConversionSymbol.Create(noConversion)); } MethodSymbol converter = null; ResolveUserDefinedConversion(expr, type, expr.Datatype.Lookup(OperatorNames.Implicit), type.Lookup(OperatorNames.Implicit), ref converter, options | BindOptions.Special); if (converter != null) { return(ConversionSymbol.Create(ConversionKind.ImplicitUserDefined, converter)); } if (options.HasFlag(BindOptions.Explicit)) { ResolveUserDefinedConversion(expr, type, expr.Datatype.Lookup(OperatorNames.Explicit), type.Lookup(OperatorNames.Explicit), ref converter, options | BindOptions.Special); if (converter != null) { return(ConversionSymbol.Create(ConversionKind.ExplicitUserDefined, converter)); } } { var conv = ResolveUsualConversion(expr, type, options); if (conv != null) { return(conv); } } if (type.IsByRef != expr.Datatype.IsByRef) { var conv = ResolveByRefConversion(expr, type, options); if (conv != null) { return(conv); } } if (type.NativeType == NativeType.Object) { if (expr.Datatype.Type.IsValueType) { return(ConversionSymbol.Create(ConversionKind.Boxing)); } else { return(ConversionSymbol.Create(ConversionKind.ImplicitReference)); } } else if (expr.Datatype.NativeType == NativeType.Object) { if (!options.HasFlag(BindOptions.AllowDynamic)) { if (options.HasFlag(BindOptions.Explicit)) { return(type.IsValueType ? ConversionSymbol.Create(ConversionKind.Unboxing) : ConversionSymbol.Create(ConversionKind.ExplicitReference)); } else { noConversion = ConversionKind.NoImplicitConversion; } } } else if (type.IsReferenceType && expr.Datatype.IsReferenceType) { if (expr.Datatype.IsSubclassOf(type)) { return(ConversionSymbol.Create(ConversionKind.ImplicitReference)); } if (type.IsSubclassOf(expr.Datatype)) { if (options.HasFlag(BindOptions.Explicit)) { return(ConversionSymbol.Create(ConversionKind.ExplicitReference)); } else { noConversion = ConversionKind.NoImplicitConversion; } } } { var conv = ResolveEnumConversion(expr, type, options); if (conv != null) { return(conv); } } if (options.HasFlag(BindOptions.AllowDynamic)) { var conv = ResolveDynamicConversion(expr, type, options); if (conv != null) { return(conv); } } if (!options.HasFlag(BindOptions.Explicit) && noConversion == ConversionKind.NoConversion) { ResolveUserDefinedConversion(expr, type, expr.Datatype.Lookup(OperatorNames.Explicit), type.Lookup(OperatorNames.Explicit), ref converter, options | BindOptions.Special); if (converter != null) { noConversion = ConversionKind.NoImplicitConversion; } } return(ConversionSymbol.Create(noConversion)); }