ExpressionBinder
                    struct ExpressionBinder
                
                using Microsoft.CSharp.RuntimeBinder.Errors;
using Microsoft.CSharp.RuntimeBinder.Syntax;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
{
    internal readonly struct ExpressionBinder
    {
        private sealed class BinOpArgInfo
        {
            public Expr arg1;
            public Expr arg2;
            public PredefinedType pt1;
            public PredefinedType pt2;
            public PredefinedType ptRaw1;
            public PredefinedType ptRaw2;
            public CType type1;
            public CType type2;
            public CType typeRaw1;
            public CType typeRaw2;
            public BinOpKind binopKind;
            public BinOpMask mask;
            public BinOpArgInfo(Expr op1, Expr op2)
            {
                arg1 = op1;
                arg2 = op2;
                type1 = arg1.Type;
                type2 = arg2.Type;
                typeRaw1 = type1.StripNubs();
                typeRaw2 = type2.StripNubs();
                pt1 = (type1.IsPredefined ? type1.PredefinedType : PredefinedType.PT_COUNT);
                pt2 = (type2.IsPredefined ? type2.PredefinedType : PredefinedType.PT_COUNT);
                ptRaw1 = (typeRaw1.IsPredefined ? typeRaw1.PredefinedType : PredefinedType.PT_COUNT);
                ptRaw2 = (typeRaw2.IsPredefined ? typeRaw2.PredefinedType : PredefinedType.PT_COUNT);
            }
            public bool ValidForDelegate()
            {
                return (mask & BinOpMask.Delegate) != BinOpMask.None;
            }
            public bool ValidForEnumAndUnderlyingType()
            {
                return (mask & BinOpMask.EnumUnder) != BinOpMask.None;
            }
            public bool ValidForUnderlyingTypeAndEnum()
            {
                return (mask & BinOpMask.Add) != BinOpMask.None;
            }
            public bool ValidForEnum()
            {
                return (mask & BinOpMask.Enum) != BinOpMask.None;
            }
        }
        private class BinOpSig
        {
            public PredefinedType pt1;
            public PredefinedType pt2;
            public BinOpMask mask;
            public int cbosSkip;
            public PfnBindBinOp pfn;
            public OpSigFlags grfos;
            public BinOpFuncKind fnkind;
            protected BinOpSig()
            {
            }
            public BinOpSig(PredefinedType pt1, PredefinedType pt2, BinOpMask mask, int cbosSkip, PfnBindBinOp pfn, OpSigFlags grfos, BinOpFuncKind fnkind)
            {
                this.pt1 = pt1;
                this.pt2 = pt2;
                this.mask = mask;
                this.cbosSkip = cbosSkip;
                this.pfn = pfn;
                this.grfos = grfos;
                this.fnkind = fnkind;
            }
            public bool ConvertOperandsBeforeBinding()
            {
                return (grfos & OpSigFlags.Convert) != OpSigFlags.None;
            }
            public bool CanLift()
            {
                return (grfos & OpSigFlags.CanLift) != OpSigFlags.None;
            }
            public bool AutoLift()
            {
                return (grfos & OpSigFlags.AutoLift) != OpSigFlags.None;
            }
        }
        private sealed class BinOpFullSig : BinOpSig
        {
            private readonly LiftFlags _grflt;
            private readonly CType _type1;
            private readonly CType _type2;
            public BinOpFullSig(CType type1, CType type2, PfnBindBinOp pfn, OpSigFlags grfos, LiftFlags grflt, BinOpFuncKind fnkind)
            {
                pt1 = PredefinedType.PT_UNDEFINEDINDEX;
                pt2 = PredefinedType.PT_UNDEFINEDINDEX;
                mask = BinOpMask.None;
                cbosSkip = 0;
                base.pfn = pfn;
                base.grfos = grfos;
                _type1 = type1;
                _type2 = type2;
                _grflt = grflt;
                base.fnkind = fnkind;
            }
            public BinOpFullSig(ExpressionBinder fnc, BinOpSig bos)
            {
                pt1 = bos.pt1;
                pt2 = bos.pt2;
                mask = bos.mask;
                cbosSkip = bos.cbosSkip;
                pfn = bos.pfn;
                grfos = bos.grfos;
                fnkind = bos.fnkind;
                _type1 = ((pt1 != PredefinedType.PT_UNDEFINEDINDEX) ? GetPredefindType(pt1) : null);
                _type2 = ((pt2 != PredefinedType.PT_UNDEFINEDINDEX) ? GetPredefindType(pt2) : null);
                _grflt = LiftFlags.None;
            }
            public bool FPreDef()
            {
                return pt1 != PredefinedType.PT_UNDEFINEDINDEX;
            }
            public bool isLifted()
            {
                if (_grflt == LiftFlags.None)
                    return false;
                return true;
            }
            public bool ConvertFirst()
            {
                return (_grflt & LiftFlags.Convert1) != LiftFlags.None;
            }
            public bool ConvertSecond()
            {
                return (_grflt & LiftFlags.Convert2) != LiftFlags.None;
            }
            public CType Type1()
            {
                return _type1;
            }
            public CType Type2()
            {
                return _type2;
            }
        }
        private delegate bool ConversionFunc (Expr pSourceExpr, CType pSourceType, CType pDestinationType, bool needsExprDest, out Expr ppDestinationExpr, CONVERTTYPE flags);
        private sealed class ExplicitConversion
        {
            private readonly ExpressionBinder _binder;
            private Expr _exprSrc;
            private readonly CType _typeSrc;
            private readonly CType _typeDest;
            private Expr _exprDest;
            private readonly bool _needsExprDest;
            private readonly CONVERTTYPE _flags;
            public Expr ExprDest => _exprDest;
            public ExplicitConversion(ExpressionBinder binder, Expr exprSrc, CType typeSrc, CType typeDest, bool needsExprDest, CONVERTTYPE flags)
            {
                _binder = binder;
                _exprSrc = exprSrc;
                _typeSrc = typeSrc;
                _typeDest = typeDest;
                _needsExprDest = needsExprDest;
                _flags = flags;
                _exprDest = null;
            }
            public bool Bind()
            {
                if (_binder.BindImplicitConversion(_exprSrc, _typeSrc, _typeDest, _needsExprDest, out _exprDest, _flags | CONVERTTYPE.ISEXPLICIT))
                    return true;
                if (_typeSrc == null || _typeDest == null || _typeDest is MethodGroupType)
                    return false;
                if (_typeDest is NullableType)
                    return false;
                if (_typeSrc is NullableType)
                    return bindExplicitConversionFromNub();
                if (bindExplicitConversionFromArrayToIList())
                    return true;
                switch (_typeDest.TypeKind) {
                default:
                    return false;
                case TypeKind.TK_VoidType:
                    return false;
                case TypeKind.TK_NullType:
                    return false;
                case TypeKind.TK_ArrayType:
                    if (bindExplicitConversionToArray((ArrayType)_typeDest))
                        return true;
                    break;
                case TypeKind.TK_PointerType:
                    if (bindExplicitConversionToPointer())
                        return true;
                    break;
                case TypeKind.TK_AggregateType:
                    switch (bindExplicitConversionToAggregate(_typeDest as AggregateType)) {
                    case AggCastResult.Success:
                        return true;
                    case AggCastResult.Abort:
                        return false;
                    }
                    break;
                }
                if ((_flags & CONVERTTYPE.NOUDC) == (CONVERTTYPE)0)
                    return _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, _typeDest, _needsExprDest, out _exprDest, false);
                return false;
            }
            private bool bindExplicitConversionFromNub()
            {
                if (_typeDest.IsValueType && _binder.BindExplicitConversion(null, _typeSrc.StripNubs(), _typeDest, _flags | CONVERTTYPE.NOUDC)) {
                    if (_needsExprDest) {
                        Expr expr = _exprSrc;
                        if (expr.Type is NullableType)
                            expr = BindNubValue(expr);
                        if (!_binder.BindExplicitConversion(expr, expr.Type, _typeDest, _needsExprDest, out _exprDest, _flags | CONVERTTYPE.NOUDC))
                            return false;
                        ExprUserDefinedConversion exprUserDefinedConversion = _exprDest as ExprUserDefinedConversion;
                        if (exprUserDefinedConversion != null)
                            exprUserDefinedConversion.Argument = _exprSrc;
                    }
                    return true;
                }
                if ((_flags & CONVERTTYPE.NOUDC) == (CONVERTTYPE)0)
                    return _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, _typeDest, _needsExprDest, out _exprDest, false);
                return false;
            }
            private bool bindExplicitConversionFromArrayToIList()
            {
                ArrayType arrayType = _typeSrc as ArrayType;
                if (arrayType != null && arrayType.IsSZArray) {
                    AggregateType aggregateType = _typeDest as AggregateType;
                    if (aggregateType != null && aggregateType.IsInterfaceType && aggregateType.TypeArgsAll.Count == 1) {
                        AggregateSymbol predefAgg = SymbolLoader.GetPredefAgg(PredefinedType.PT_G_ILIST);
                        AggregateSymbol predefAgg2 = SymbolLoader.GetPredefAgg(PredefinedType.PT_G_IREADONLYLIST);
                        if ((predefAgg == null || !SymbolLoader.IsBaseAggregate(predefAgg, aggregateType.OwningAggregate)) && (predefAgg2 == null || !SymbolLoader.IsBaseAggregate(predefAgg2, aggregateType.OwningAggregate)))
                            return false;
                        CType elementType = arrayType.ElementType;
                        CType typeDst = aggregateType.TypeArgsAll[0];
                        if (!CConversions.FExpRefConv(elementType, typeDst))
                            return false;
                        if (_needsExprDest)
                            _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest, EXPRFLAG.EXF_OPERATOR);
                        return true;
                    }
                }
                return false;
            }
            private bool bindExplicitConversionFromIListToArray(ArrayType arrayDest)
            {
                if (arrayDest.IsSZArray) {
                    AggregateType aggregateType = _typeSrc as AggregateType;
                    if (aggregateType != null && aggregateType.IsInterfaceType && aggregateType.TypeArgsAll.Count == 1) {
                        AggregateSymbol predefAgg = SymbolLoader.GetPredefAgg(PredefinedType.PT_G_ILIST);
                        AggregateSymbol predefAgg2 = SymbolLoader.GetPredefAgg(PredefinedType.PT_G_IREADONLYLIST);
                        if ((predefAgg == null || !SymbolLoader.IsBaseAggregate(predefAgg, aggregateType.OwningAggregate)) && (predefAgg2 == null || !SymbolLoader.IsBaseAggregate(predefAgg2, aggregateType.OwningAggregate)))
                            return false;
                        CType elementType = arrayDest.ElementType;
                        CType cType = aggregateType.TypeArgsAll[0];
                        if (elementType != cType && !CConversions.FExpRefConv(elementType, cType))
                            return false;
                        if (_needsExprDest)
                            _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest, EXPRFLAG.EXF_OPERATOR);
                        return true;
                    }
                }
                return false;
            }
            private bool bindExplicitConversionFromArrayToArray(ArrayType arraySrc, ArrayType arrayDest)
            {
                if (arraySrc.Rank != arrayDest.Rank || arraySrc.IsSZArray != arrayDest.IsSZArray)
                    return false;
                if (CConversions.FExpRefConv(arraySrc.ElementType, arrayDest.ElementType)) {
                    if (_needsExprDest)
                        _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest, EXPRFLAG.EXF_OPERATOR);
                    return true;
                }
                return false;
            }
            private bool bindExplicitConversionToArray(ArrayType arrayDest)
            {
                ArrayType arrayType = _typeSrc as ArrayType;
                if (arrayType != null)
                    return bindExplicitConversionFromArrayToArray(arrayType, arrayDest);
                if (bindExplicitConversionFromIListToArray(arrayDest))
                    return true;
                if (_binder.canConvert(GetPredefindType(PredefinedType.PT_ARRAY), _typeSrc, CONVERTTYPE.NOUDC)) {
                    if (_needsExprDest)
                        _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest, EXPRFLAG.EXF_OPERATOR);
                    return true;
                }
                return false;
            }
            private bool bindExplicitConversionToPointer()
            {
                if (_typeSrc is PointerType || (_typeSrc.FundamentalType <= FUNDTYPE.FT_U8 && _typeSrc.IsNumericType)) {
                    if (_needsExprDest)
                        _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest);
                    return true;
                }
                return false;
            }
            private AggCastResult bindExplicitConversionFromEnumToAggregate(AggregateType aggTypeDest)
            {
                if (!_typeSrc.IsEnumType)
                    return AggCastResult.Failure;
                AggregateSymbol owningAggregate = aggTypeDest.OwningAggregate;
                if (owningAggregate.isPredefAgg(PredefinedType.PT_DECIMAL))
                    return bindExplicitConversionFromEnumToDecimal(aggTypeDest);
                if (!owningAggregate.getThisType().IsNumericType && !owningAggregate.IsEnum() && (!owningAggregate.IsPredefined() || owningAggregate.GetPredefType() != PredefinedType.PT_CHAR))
                    return AggCastResult.Failure;
                if (_exprSrc.GetConst() != null) {
                    switch (_binder.bindConstantCast(_exprSrc, _typeDest, _needsExprDest, out _exprDest, true)) {
                    case ConstCastResult.Success:
                        return AggCastResult.Success;
                    case ConstCastResult.CheckFailure:
                        return AggCastResult.Abort;
                    }
                }
                if (_needsExprDest)
                    _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest);
                return AggCastResult.Success;
            }
            private AggCastResult bindExplicitConversionFromDecimalToEnum(AggregateType aggTypeDest)
            {
                if (_exprSrc.GetConst() != null) {
                    switch (_binder.bindConstantCast(_exprSrc, _typeDest, _needsExprDest, out _exprDest, true)) {
                    case ConstCastResult.Success:
                        return AggCastResult.Success;
                    case ConstCastResult.CheckFailure:
                        if ((_flags & CONVERTTYPE.CHECKOVERFLOW) == (CONVERTTYPE)0)
                            return AggCastResult.Abort;
                        break;
                    }
                }
                bool flag = true;
                if (_needsExprDest) {
                    CType underlyingEnumType = aggTypeDest.UnderlyingEnumType;
                    flag = _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, underlyingEnumType, _needsExprDest, out _exprDest, false);
                    if (flag)
                        _binder.bindSimpleCast(_exprDest, _typeDest, out _exprDest);
                }
                if (!flag)
                    return AggCastResult.Failure;
                return AggCastResult.Success;
            }
            private AggCastResult bindExplicitConversionFromEnumToDecimal(AggregateType aggTypeDest)
            {
                AggregateType underlyingEnumType = _typeSrc.UnderlyingEnumType;
                Expr pexprDest;
                if (_exprSrc == null)
                    pexprDest = null;
                else
                    _binder.bindSimpleCast(_exprSrc, underlyingEnumType, out pexprDest);
                if (pexprDest.GetConst() != null) {
                    switch (_binder.bindConstantCast(pexprDest, _typeDest, _needsExprDest, out _exprDest, true)) {
                    case ConstCastResult.Success:
                        return AggCastResult.Success;
                    case ConstCastResult.CheckFailure:
                        if ((_flags & CONVERTTYPE.CHECKOVERFLOW) == (CONVERTTYPE)0)
                            return AggCastResult.Abort;
                        break;
                    }
                }
                if (_needsExprDest) {
                    bool flag = _binder.bindUserDefinedConversion(pexprDest, underlyingEnumType, aggTypeDest, _needsExprDest, out _exprDest, false);
                }
                return AggCastResult.Success;
            }
            private AggCastResult bindExplicitConversionToEnum(AggregateType aggTypeDest)
            {
                AggregateSymbol owningAggregate = aggTypeDest.OwningAggregate;
                if (!owningAggregate.IsEnum())
                    return AggCastResult.Failure;
                if (_typeSrc.IsPredefType(PredefinedType.PT_DECIMAL))
                    return bindExplicitConversionFromDecimalToEnum(aggTypeDest);
                if (_typeSrc.IsNumericType || (_typeSrc.IsPredefined && _typeSrc.PredefinedType == PredefinedType.PT_CHAR)) {
                    if (_exprSrc.GetConst() != null) {
                        switch (_binder.bindConstantCast(_exprSrc, _typeDest, _needsExprDest, out _exprDest, true)) {
                        case ConstCastResult.Success:
                            return AggCastResult.Success;
                        case ConstCastResult.CheckFailure:
                            return AggCastResult.Abort;
                        }
                    }
                    if (_needsExprDest)
                        _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest);
                    return AggCastResult.Success;
                }
                if (_typeSrc.IsPredefined && (_typeSrc.IsPredefType(PredefinedType.PT_OBJECT) || _typeSrc.IsPredefType(PredefinedType.PT_VALUE) || _typeSrc.IsPredefType(PredefinedType.PT_ENUM))) {
                    if (_needsExprDest)
                        _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest, EXPRFLAG.EXF_INDEXER);
                    return AggCastResult.Success;
                }
                return AggCastResult.Failure;
            }
            private AggCastResult bindExplicitConversionBetweenSimpleTypes(AggregateType aggTypeDest)
            {
                if (!_typeSrc.IsSimpleType || !aggTypeDest.IsSimpleType)
                    return AggCastResult.Failure;
                AggregateSymbol owningAggregate = aggTypeDest.OwningAggregate;
                PredefinedType predefinedType = _typeSrc.PredefinedType;
                PredefinedType predefType = owningAggregate.GetPredefType();
                ConvKind convKind = GetConvKind(predefinedType, predefType);
                if (convKind != ConvKind.Explicit)
                    return AggCastResult.Failure;
                if (_exprSrc.GetConst() != null) {
                    switch (_binder.bindConstantCast(_exprSrc, _typeDest, _needsExprDest, out _exprDest, true)) {
                    case ConstCastResult.Success:
                        return AggCastResult.Success;
                    case ConstCastResult.CheckFailure:
                        if ((_flags & CONVERTTYPE.CHECKOVERFLOW) == (CONVERTTYPE)0)
                            return AggCastResult.Abort;
                        break;
                    }
                }
                bool flag = true;
                if (_needsExprDest) {
                    if (isUserDefinedConversion(predefinedType, predefType))
                        flag = _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, aggTypeDest, _needsExprDest, out _exprDest, false);
                    else
                        _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest, ((_flags & CONVERTTYPE.CHECKOVERFLOW) != 0) ? EXPRFLAG.EXF_CHECKOVERFLOW : ((EXPRFLAG)0));
                }
                if (!flag)
                    return AggCastResult.Failure;
                return AggCastResult.Success;
            }
            private AggCastResult bindExplicitConversionBetweenAggregates(AggregateType aggTypeDest)
            {
                AggregateType aggregateType = _typeSrc as AggregateType;
                if (aggregateType == null)
                    return AggCastResult.Failure;
                AggregateSymbol owningAggregate = aggregateType.OwningAggregate;
                AggregateSymbol owningAggregate2 = aggTypeDest.OwningAggregate;
                if (SymbolLoader.HasBaseConversion(aggTypeDest, aggregateType)) {
                    if (_needsExprDest) {
                        ref ExpressionBinder binder = ref _binder;
                        Expr exprSrc = _exprSrc;
                        CType typeDest = _typeDest;
                        ref Expr exprDest = ref _exprDest;
                        int exprFlags;
                        if (!owningAggregate2.IsValueType() || owningAggregate.getThisType().FundamentalType != FUNDTYPE.FT_REF) {
                            Expr exprSrc2 = _exprSrc;
                            exprFlags = (int)(EXPRFLAG.EXF_OPERATOR | ((exprSrc2 != null) ? (exprSrc2.Flags & EXPRFLAG.EXF_CANTBENULL) : ((EXPRFLAG)0)));
                        } else
                            exprFlags = 4;
                        binder.bindSimpleCast(exprSrc, typeDest, out exprDest, (EXPRFLAG)exprFlags);
                    }
                    return AggCastResult.Success;
                }
                if ((owningAggregate.IsClass() && !owningAggregate.IsSealed() && owningAggregate2.IsInterface()) || (owningAggregate.IsInterface() && owningAggregate2.IsClass() && !owningAggregate2.IsSealed()) || (owningAggregate.IsInterface() && owningAggregate2.IsInterface()) || CConversions.HasGenericDelegateExplicitReferenceConversion(_typeSrc, aggTypeDest)) {
                    if (_needsExprDest) {
                        ref ExpressionBinder binder2 = ref _binder;
                        Expr exprSrc3 = _exprSrc;
                        CType typeDest2 = _typeDest;
                        ref Expr exprDest2 = ref _exprDest;
                        Expr exprSrc4 = _exprSrc;
                        binder2.bindSimpleCast(exprSrc3, typeDest2, out exprDest2, EXPRFLAG.EXF_OPERATOR | ((exprSrc4 != null) ? (exprSrc4.Flags & EXPRFLAG.EXF_CANTBENULL) : ((EXPRFLAG)0)));
                    }
                    return AggCastResult.Success;
                }
                return AggCastResult.Failure;
            }
            private AggCastResult bindExplicitConversionFromPointerToInt(AggregateType aggTypeDest)
            {
                if (!(_typeSrc is PointerType) || aggTypeDest.FundamentalType > FUNDTYPE.FT_U8 || !aggTypeDest.IsNumericType)
                    return AggCastResult.Failure;
                if (_needsExprDest)
                    _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest);
                return AggCastResult.Success;
            }
            private AggCastResult bindExplicitConversionToAggregate(AggregateType aggTypeDest)
            {
                AggCastResult aggCastResult = bindExplicitConversionFromEnumToAggregate(aggTypeDest);
                if (aggCastResult != AggCastResult.Failure)
                    return aggCastResult;
                aggCastResult = bindExplicitConversionToEnum(aggTypeDest);
                if (aggCastResult != AggCastResult.Failure)
                    return aggCastResult;
                aggCastResult = bindExplicitConversionBetweenSimpleTypes(aggTypeDest);
                if (aggCastResult != AggCastResult.Failure)
                    return aggCastResult;
                aggCastResult = bindExplicitConversionBetweenAggregates(aggTypeDest);
                if (aggCastResult != AggCastResult.Failure)
                    return aggCastResult;
                aggCastResult = bindExplicitConversionFromPointerToInt(aggTypeDest);
                if (aggCastResult != AggCastResult.Failure)
                    return aggCastResult;
                if (_typeSrc is VoidType)
                    return AggCastResult.Abort;
                return AggCastResult.Failure;
            }
        }
        private delegate Expr PfnBindBinOp (ExpressionBinder binder, ExpressionKind ek, EXPRFLAG flags, Expr op1, Expr op2);
        private delegate Expr PfnBindUnaOp (ExpressionBinder binder, ExpressionKind ek, EXPRFLAG flags, Expr op);
        public enum NamedArgumentsKind
        {
            None,
            Positioning,
            NonTrailing
        }
        internal sealed class GroupToArgsBinder
        {
            private enum Result
            {
                Success,
                Failure_SearchForExpanded,
                Failure_NoSearchForExpanded
            }
            private readonly ExpressionBinder _pExprBinder;
            private bool _fCandidatesUnsupported;
            private readonly BindingFlag _fBindFlags;
            private readonly ExprMemberGroup _pGroup;
            private readonly ArgInfos _pArguments;
            private readonly ArgInfos _pOriginalArguments;
            private readonly NamedArgumentsKind _namedArgumentsKind;
            private AggregateType _pCurrentType;
            private MethodOrPropertySymbol _pCurrentSym;
            private TypeArray _pCurrentTypeArgs;
            private TypeArray _pCurrentParameters;
            private int _nArgBest;
            private readonly GroupToArgsBinderResult _results;
            private readonly List<CandidateFunctionMember> _methList;
            private readonly MethPropWithInst _mpwiParamTypeConstraints;
            private readonly MethPropWithInst _mpwiBogus;
            private readonly MethPropWithInst _misnamed;
            private readonly MethPropWithInst _mpwiCantInferInstArg;
            private readonly MethWithType _mwtBadArity;
            private Name _pInvalidSpecifiedName;
            private Name _pNameUsedInPositionalArgument;
            private Name _pDuplicateSpecifiedName;
            private readonly List<CType> _HiddenTypes;
            private bool _bArgumentsChangedForNamedOrOptionalArguments;
            public GroupToArgsBinder(ExpressionBinder exprBinder, BindingFlag bindFlags, ExprMemberGroup grp, ArgInfos args, ArgInfos originalArgs, NamedArgumentsKind namedArgumentsKind)
            {
                _pExprBinder = exprBinder;
                _fCandidatesUnsupported = false;
                _fBindFlags = bindFlags;
                _pGroup = grp;
                _pArguments = args;
                _pOriginalArguments = originalArgs;
                _namedArgumentsKind = namedArgumentsKind;
                _pCurrentType = null;
                _pCurrentSym = null;
                _pCurrentTypeArgs = null;
                _pCurrentParameters = null;
                _nArgBest = -1;
                _results = new GroupToArgsBinderResult();
                _methList = new List<CandidateFunctionMember>();
                _mpwiParamTypeConstraints = new MethPropWithInst();
                _mpwiBogus = new MethPropWithInst();
                _misnamed = new MethPropWithInst();
                _mpwiCantInferInstArg = new MethPropWithInst();
                _mwtBadArity = new MethWithType();
                _HiddenTypes = new List<CType>();
            }
            public void Bind()
            {
                LookForCandidates();
                if (!GetResultOfBind())
                    throw ReportErrorsOnFailure();
            }
            public GroupToArgsBinderResult GetResultsOfBind()
            {
                return _results;
            }
            private static CType GetTypeQualifier(ExprMemberGroup pGroup)
            {
                if ((pGroup.Flags & EXPRFLAG.EXF_CTOR) == (EXPRFLAG)0)
                    return pGroup.OptionalObject?.Type;
                return pGroup.ParentType;
            }
            private void LookForCandidates()
            {
                bool flag = false;
                bool flag2 = true;
                bool flag3 = true;
                bool flag4 = false;
                symbmask_t mask = (symbmask_t)(1 << (int)_pGroup.SymKind);
                CMemberLookupResults.CMethodIterator methodIterator = _pGroup.MemberLookupResults.GetMethodIterator(GetTypeQualifier(_pGroup), _pExprBinder.ContextForMemberLookup, _pGroup.TypeArgs.Count, _pGroup.Flags, mask, (_namedArgumentsKind == NamedArgumentsKind.NonTrailing) ? _pOriginalArguments : null);
                while (true) {
                    bool flag5 = false;
                    if (flag2 && !flag)
                        flag5 = (flag = ConstructExpandedParameters());
                    if (!flag5) {
                        flag = false;
                        if (!GetNextSym(methodIterator))
                            break;
                        _pCurrentParameters = _pCurrentSym.Params;
                        flag2 = true;
                    }
                    if (_bArgumentsChangedForNamedOrOptionalArguments) {
                        _bArgumentsChangedForNamedOrOptionalArguments = false;
                        CopyArgInfos(_pOriginalArguments, _pArguments);
                    }
                    if (_namedArgumentsKind == NamedArgumentsKind.Positioning) {
                        if (!ReOrderArgsForNamedArguments())
                            continue;
                    } else if (HasOptionalParameters() && !AddArgumentsForOptionalParameters()) {
                        continue;
                    }
                    if (!flag5) {
                        flag4 = true;
                        flag3 &= CSemanticChecker.CheckBogus(_pCurrentSym);
                        if (_pCurrentParameters.Count != _pArguments.carg) {
                            flag2 = true;
                            continue;
                        }
                    }
                    if (methodIterator.CanUseCurrentSymbol) {
                        Result result = DetermineCurrentTypeArgs();
                        if (result != 0)
                            flag2 = (result == Result.Failure_SearchForExpanded);
                        else {
                            bool flag6 = !methodIterator.IsCurrentSymbolInaccessible;
                            if (!flag6 && (!_methList.IsEmpty() || (bool)_results.InaccessibleResult))
                                flag2 = false;
                            else {
                                bool flag7 = flag6 && methodIterator.IsCurrentSymbolMisnamed;
                                if (flag7 && (!_methList.IsEmpty() || (bool)_results.InaccessibleResult || (bool)_misnamed))
                                    flag2 = false;
                                else {
                                    bool flag8 = flag6 && !flag7 && methodIterator.IsCurrentSymbolBogus;
                                    if (flag8 && (!_methList.IsEmpty() || (bool)_results.InaccessibleResult || (bool)_mpwiBogus || (bool)_misnamed))
                                        flag2 = false;
                                    else if (!ArgumentsAreConvertible()) {
                                        flag2 = true;
                                    } else {
                                        if (!flag6)
                                            _results.InaccessibleResult.Set(_pCurrentSym, _pCurrentType, _pCurrentTypeArgs);
                                        else if (flag7) {
                                            _misnamed.Set(_pCurrentSym, _pCurrentType, _pCurrentTypeArgs);
                                        } else if (flag8) {
                                            _mpwiBogus.Set(_pCurrentSym, _pCurrentType, _pCurrentTypeArgs);
                                        } else {
                                            _methList.Add(new CandidateFunctionMember(new MethPropWithInst(_pCurrentSym, _pCurrentType, _pCurrentTypeArgs), _pCurrentParameters, 0, flag));
                                            if (_pCurrentType.IsInterfaceType) {
                                                CType[] items = _pCurrentType.IfacesAll.Items;
                                                for (int i = 0; i < items.Length; i++) {
                                                    AggregateType item = (AggregateType)items[i];
                                                    _HiddenTypes.Add(item);
                                                }
                                                AggregateType predefindType = SymbolLoader.GetPredefindType(PredefinedType.PT_OBJECT);
                                                _HiddenTypes.Add(predefindType);
                                            }
                                        }
                                        flag2 = false;
                                    }
                                }
                            }
                        }
                    }
                }
                _fCandidatesUnsupported = (flag3 & flag4);
                if (_bArgumentsChangedForNamedOrOptionalArguments)
                    CopyArgInfos(_pOriginalArguments, _pArguments);
            }
            private static void CopyArgInfos(ArgInfos src, ArgInfos dst)
            {
                dst.carg = src.carg;
                dst.types = src.types;
                dst.prgexpr.Clear();
                for (int i = 0; i < src.prgexpr.Count; i++) {
                    dst.prgexpr.Add(src.prgexpr[i]);
                }
            }
            private bool GetResultOfBind()
            {
                if (!_methList.IsEmpty()) {
                    CandidateFunctionMember candidateFunctionMember;
                    if (_methList.Count == 1)
                        candidateFunctionMember = _methList.Head();
                    else {
                        CType pTypeThrough = _pGroup.OptionalObject?.Type;
                        candidateFunctionMember = _pExprBinder.FindBestMethod(_methList, pTypeThrough, _pArguments, out CandidateFunctionMember methAmbig, out CandidateFunctionMember methAmbig2);
                        if (candidateFunctionMember == null) {
                            if (methAmbig.params != methAmbig2.params || methAmbig.mpwi.MethProp().Params.Count != methAmbig2.mpwi.MethProp().Params.Count || methAmbig.mpwi.TypeArgs != methAmbig2.mpwi.TypeArgs || methAmbig.mpwi.GetType() != methAmbig2.mpwi.GetType() || methAmbig.mpwi.MethProp().Params == methAmbig2.mpwi.MethProp().Params)
                                throw ErrorHandling.Error(ErrorCode.ERR_AmbigCall, methAmbig.mpwi, methAmbig2.mpwi);
                            throw ErrorHandling.Error(ErrorCode.ERR_AmbigCall, methAmbig.mpwi.MethProp(), methAmbig2.mpwi.MethProp());
                        }
                    }
                    _results.BestResult = candidateFunctionMember.mpwi;
                    ReportErrorsOnSuccess();
                    return true;
                }
                return false;
            }
            private bool ReOrderArgsForNamedArguments()
            {
                MethodOrPropertySymbol methodOrPropertySymbol = FindMostDerivedMethod(_pCurrentSym, _pGroup.OptionalObject);
                if (methodOrPropertySymbol == null)
                    return false;
                int count = _pCurrentParameters.Count;
                if (count == 0 || count < _pArguments.carg)
                    return false;
                if (!NamedArgumentNamesAppearInParameterList(methodOrPropertySymbol))
                    return false;
                _bArgumentsChangedForNamedOrOptionalArguments = ReOrderArgsForNamedArguments(methodOrPropertySymbol, _pCurrentParameters, _pCurrentType, _pGroup, _pArguments);
                return _bArgumentsChangedForNamedOrOptionalArguments;
            }
            internal static bool ReOrderArgsForNamedArguments(MethodOrPropertySymbol methprop, TypeArray pCurrentParameters, AggregateType pCurrentType, ExprMemberGroup pGroup, ArgInfos pArguments)
            {
                int count = pCurrentParameters.Count;
                Expr[] array = new Expr[count];
                int num = 0;
                Expr expr = null;
                TypeArray typeArray = TypeManager.SubstTypeArray(pCurrentParameters, pCurrentType, pGroup.TypeArgs);
                foreach (Name parameterName in methprop.ParameterNames) {
                    if (num >= pCurrentParameters.Count)
                        break;
                    if (methprop.isParamArray && num < pArguments.carg) {
                        ExprArrayInit exprArrayInit = pArguments.prgexpr[num] as ExprArrayInit;
                        if (exprArrayInit != null && exprArrayInit.GeneratedForParamArray)
                            expr = pArguments.prgexpr[num];
                    }
                    if (num < pArguments.carg && !(pArguments.prgexpr[num] is ExprNamedArgumentSpecification)) {
                        ExprArrayInit exprArrayInit2 = pArguments.prgexpr[num] as ExprArrayInit;
                        if (exprArrayInit2 == null || !exprArrayInit2.GeneratedForParamArray) {
                            array[num] = pArguments.prgexpr[num++];
                            continue;
                        }
                    }
                    Expr expr2 = FindArgumentWithName(pArguments, parameterName);
                    if (expr2 == null) {
                        if (methprop.IsParameterOptional(num))
                            expr2 = GenerateOptionalArgument(methprop, typeArray[num], num);
                        else {
                            if (expr == null || num != methprop.Params.Count - 1)
                                return false;
                            expr2 = expr;
                        }
                    }
                    array[num++] = expr2;
                }
                CType[] array2 = new CType[pCurrentParameters.Count];
                for (int i = 0; i < count; i++) {
                    if (i < pArguments.prgexpr.Count)
                        pArguments.prgexpr[i] = array[i];
                    else
                        pArguments.prgexpr.Add(array[i]);
                    array2[i] = pArguments.prgexpr[i].Type;
                }
                pArguments.carg = pCurrentParameters.Count;
                pArguments.types = TypeArray.Allocate(array2);
                return true;
            }
            private static Expr GenerateOptionalArgument(MethodOrPropertySymbol methprop, CType type, int index)
            {
                CType cType = type.StripNubs();
                Expr expr;
                if (methprop.HasDefaultParameterValue(index)) {
                    CType defaultParameterValueConstValType = methprop.GetDefaultParameterValueConstValType(index);
                    ConstVal defaultParameterValue = methprop.GetDefaultParameterValue(index);
                    if (!defaultParameterValueConstValType.IsPredefType(PredefinedType.PT_DATETIME) || (!cType.IsPredefType(PredefinedType.PT_DATETIME) && !cType.IsPredefType(PredefinedType.PT_OBJECT) && !cType.IsPredefType(PredefinedType.PT_VALUE)))
                        expr = (defaultParameterValueConstValType.IsSimpleOrEnumOrString ? ExprFactory.CreateConstant((cType.IsEnumType && defaultParameterValueConstValType == cType.UnderlyingEnumType) ? cType : defaultParameterValueConstValType, defaultParameterValue) : (((!type.IsReferenceType && !(type is NullableType)) || !defaultParameterValue.IsNullRef) ? ExprFactory.CreateZeroInit(type) : ExprFactory.CreateNull()));
                    else {
                        AggregateType predefindType = SymbolLoader.GetPredefindType(PredefinedType.PT_DATETIME);
                        expr = ExprFactory.CreateConstant(predefindType, ConstVal.Get(DateTime.FromBinary(defaultParameterValue.Int64Val)));
                    }
                } else if (type.IsPredefType(PredefinedType.PT_OBJECT)) {
                    if (methprop.MarshalAsObject(index))
                        expr = ExprFactory.CreateNull();
                    else {
                        AggregateSymbol predefAgg = SymbolLoader.GetPredefAgg(PredefinedType.PT_MISSING);
                        Name predefinedName = NameManager.GetPredefinedName(PredefinedName.PN_CAP_VALUE);
                        FieldSymbol field = SymbolLoader.LookupAggMember(predefinedName, predefAgg, symbmask_t.MASK_FieldSymbol) as FieldSymbol;
                        FieldWithType field2 = new FieldWithType(field, predefAgg.getThisType());
                        ExprField argument = ExprFactory.CreateField(predefAgg.getThisType(), null, field2);
                        expr = ExprFactory.CreateCast(type, argument);
                    }
                } else {
                    expr = ExprFactory.CreateZeroInit(type);
                }
                expr.IsOptionalArgument = true;
                return expr;
            }
            private static MethodOrPropertySymbol FindMostDerivedMethod(MethodOrPropertySymbol pMethProp, Expr pObject)
            {
                return FindMostDerivedMethod(pMethProp, pObject?.Type);
            }
            public static MethodOrPropertySymbol FindMostDerivedMethod(MethodOrPropertySymbol pMethProp, CType pType)
            {
                bool flag = false;
                MethodSymbol methodSymbol = pMethProp as MethodSymbol;
                if (methodSymbol == null) {
                    PropertySymbol propertySymbol = (PropertySymbol)pMethProp;
                    methodSymbol = (propertySymbol.GetterMethod ?? propertySymbol.SetterMethod);
                    if (methodSymbol == null)
                        return null;
                    flag = (propertySymbol is IndexerSymbol);
                }
                if (!methodSymbol.isVirtual || pType == null)
                    return methodSymbol;
                MethodSymbol methodSymbol2 = methodSymbol.swtSlot?.Meth();
                if (methodSymbol2 != null)
                    methodSymbol = methodSymbol2;
                AggregateType aggregateType = pType as AggregateType;
                if (aggregateType == null)
                    return methodSymbol;
                AggregateSymbol aggregateSymbol = aggregateType.OwningAggregate;
                while (aggregateSymbol?.GetBaseAgg() != null) {
                    for (MethodOrPropertySymbol methodOrPropertySymbol = SymbolLoader.LookupAggMember(methodSymbol.name, aggregateSymbol, symbmask_t.MASK_MethodSymbol | symbmask_t.MASK_PropertySymbol) as MethodOrPropertySymbol; methodOrPropertySymbol != null; methodOrPropertySymbol = (methodOrPropertySymbol.LookupNext(symbmask_t.MASK_MethodSymbol | symbmask_t.MASK_PropertySymbol) as MethodOrPropertySymbol)) {
                        if (methodOrPropertySymbol.isOverride && methodOrPropertySymbol.swtSlot.Sym != null && methodOrPropertySymbol.swtSlot.Sym == methodSymbol) {
                            if (flag)
                                return ((MethodSymbol)methodOrPropertySymbol).getProperty();
                            return methodOrPropertySymbol;
                        }
                    }
                    aggregateSymbol = aggregateSymbol.GetBaseAgg();
                }
                return methodSymbol;
            }
            private bool HasOptionalParameters()
            {
                return FindMostDerivedMethod(_pCurrentSym, _pGroup.OptionalObject)?.HasOptionalParameters() ?? false;
            }
            private bool AddArgumentsForOptionalParameters()
            {
                if (_pCurrentParameters.Count <= _pArguments.carg)
                    return true;
                MethodOrPropertySymbol methodOrPropertySymbol = FindMostDerivedMethod(_pCurrentSym, _pGroup.OptionalObject);
                if (methodOrPropertySymbol == null)
                    return false;
                int num = _pArguments.carg;
                int num2 = 0;
                TypeArray typeArray = TypeManager.SubstTypeArray(_pCurrentParameters, _pCurrentType, _pGroup.TypeArgs);
                Expr[] array = new Expr[_pCurrentParameters.Count - num];
                while (num < typeArray.Count) {
                    if (!methodOrPropertySymbol.IsParameterOptional(num))
                        return false;
                    array[num2] = GenerateOptionalArgument(methodOrPropertySymbol, typeArray[num], num);
                    num++;
                    num2++;
                }
                for (int i = 0; i < num2; i++) {
                    _pArguments.prgexpr.Add(array[i]);
                }
                CType[] array2 = new CType[typeArray.Count];
                for (int j = 0; j < typeArray.Count; j++) {
                    array2[j] = _pArguments.prgexpr[j].Type;
                }
                _pArguments.types = TypeArray.Allocate(array2);
                _pArguments.carg = typeArray.Count;
                _bArgumentsChangedForNamedOrOptionalArguments = true;
                return true;
            }
            private static Expr FindArgumentWithName(ArgInfos pArguments, Name pName)
            {
                List<Expr> prgexpr = pArguments.prgexpr;
                for (int i = 0; i < pArguments.carg; i++) {
                    Expr expr = prgexpr[i];
                    ExprNamedArgumentSpecification exprNamedArgumentSpecification = expr as ExprNamedArgumentSpecification;
                    if (exprNamedArgumentSpecification != null && exprNamedArgumentSpecification.Name == pName)
                        return expr;
                }
                return null;
            }
            private bool NamedArgumentNamesAppearInParameterList(MethodOrPropertySymbol methprop)
            {
                List<Name> list = methprop.ParameterNames;
                HashSet<Name> hashSet = new HashSet<Name>();
                for (int i = 0; i < _pArguments.carg; i++) {
                    ExprNamedArgumentSpecification exprNamedArgumentSpecification = _pArguments.prgexpr[i] as ExprNamedArgumentSpecification;
                    if (exprNamedArgumentSpecification == null) {
                        if (!list.IsEmpty())
                            list = list.Tail();
                    } else {
                        Name name = exprNamedArgumentSpecification.Name;
                        if (!methprop.ParameterNames.Contains(name)) {
                            if (_pInvalidSpecifiedName == null)
                                _pInvalidSpecifiedName = name;
                            return false;
                        }
                        if (!list.Contains(name)) {
                            if (_pNameUsedInPositionalArgument == null)
                                _pNameUsedInPositionalArgument = name;
                            return false;
                        }
                        if (!hashSet.Add(name)) {
                            if (_pDuplicateSpecifiedName == null)
                                _pDuplicateSpecifiedName = name;
                            return false;
                        }
                    }
                }
                return true;
            }
            private bool GetNextSym(CMemberLookupResults.CMethodIterator iterator)
            {
                if (!iterator.MoveNext())
                    return false;
                _pCurrentSym = iterator.CurrentSymbol;
                AggregateType currentType = iterator.CurrentType;
                if (_pCurrentType != currentType && _pCurrentType != null && !_methList.IsEmpty() && !_methList.Head().mpwi.GetType().IsInterfaceType)
                    return false;
                _pCurrentType = currentType;
                while (_HiddenTypes.Contains(_pCurrentType)) {
                    while (iterator.CurrentType == _pCurrentType) {
                        iterator.MoveNext();
                    }
                    _pCurrentSym = iterator.CurrentSymbol;
                    _pCurrentType = iterator.CurrentType;
                    if (iterator.AtEnd)
                        return false;
                }
                return true;
            }
            private bool ConstructExpandedParameters()
            {
                if (_pCurrentSym == null || _pArguments == null || _pCurrentParameters == null)
                    return false;
                if ((_fBindFlags & BindingFlag.BIND_NOPARAMS) != 0)
                    return false;
                if (!_pCurrentSym.isParamArray)
                    return false;
                int num = 0;
                for (int i = _pArguments.carg; i < _pCurrentSym.Params.Count; i++) {
                    if (_pCurrentSym.IsParameterOptional(i))
                        num++;
                }
                if (_pArguments.carg + num < _pCurrentParameters.Count - 1)
                    return false;
                return TryGetExpandedParams(_pCurrentSym.Params, _pArguments.carg, out _pCurrentParameters);
            }
            private Result DetermineCurrentTypeArgs()
            {
                TypeArray typeArgs = _pGroup.TypeArgs;
                MethodSymbol methodSymbol = _pCurrentSym as MethodSymbol;
                if (methodSymbol != null && methodSymbol.typeVars.Count != typeArgs.Count) {
                    if (typeArgs.Count > 0) {
                        if (!(bool)_mwtBadArity)
                            _mwtBadArity.Set(methodSymbol, _pCurrentType);
                        return Result.Failure_NoSearchForExpanded;
                    }
                    if (!MethodTypeInferrer.Infer(_pExprBinder, methodSymbol, _pCurrentParameters, _pArguments, out _pCurrentTypeArgs)) {
                        if (_results.IsBetterUninferableResult(_pCurrentTypeArgs)) {
                            TypeArray typeVars = methodSymbol.typeVars;
                            if (typeVars != null && _pCurrentTypeArgs != null && typeVars.Count == _pCurrentTypeArgs.Count)
                                _mpwiCantInferInstArg.Set(methodSymbol, _pCurrentType, _pCurrentTypeArgs);
                            else
                                _mpwiCantInferInstArg.Set(methodSymbol, _pCurrentType, typeVars);
                        }
                        return Result.Failure_SearchForExpanded;
                    }
                } else
                    _pCurrentTypeArgs = typeArgs;
                return Result.Success;
            }
            private bool ArgumentsAreConvertible()
            {
                bool flag = false;
                if (_pArguments.carg != 0) {
                    UpdateArguments();
                    for (int i = 0; i < _pArguments.carg; i++) {
                        CType cType = _pCurrentParameters[i];
                        if (!TypeBind.CheckConstraints(cType, CheckConstraintsFlags.NoErrors) && !DoesTypeArgumentsContainErrorSym(cType)) {
                            _mpwiParamTypeConstraints.Set(_pCurrentSym, _pCurrentType, _pCurrentTypeArgs);
                            return false;
                        }
                    }
                    for (int j = 0; j < _pArguments.carg; j++) {
                        CType cType2 = _pCurrentParameters[j];
                        flag |= DoesTypeArgumentsContainErrorSym(cType2);
                        Expr expr = _pArguments.prgexpr[j];
                        ExprNamedArgumentSpecification exprNamedArgumentSpecification = expr as ExprNamedArgumentSpecification;
                        if (exprNamedArgumentSpecification != null)
                            expr = exprNamedArgumentSpecification.Value;
                        if (!_pExprBinder.canConvert(expr, cType2) && !flag) {
                            if (j > _nArgBest) {
                                _nArgBest = j;
                                if (!(bool)_results.BestResult)
                                    _results.BestResult.Set(_pCurrentSym, _pCurrentType, _pCurrentTypeArgs);
                            } else if (j == _nArgBest && _pArguments.types[j] != cType2) {
                                ParameterModifierType parameterModifierType = _pArguments.types[j] as ParameterModifierType;
                                CType cType3 = (parameterModifierType != null) ? parameterModifierType.ParameterType : _pArguments.types[j];
                                ParameterModifierType parameterModifierType2 = cType2 as ParameterModifierType;
                                CType cType4 = (parameterModifierType2 != null) ? parameterModifierType2.ParameterType : cType2;
                                if (cType3 == cType4 && !(bool)_results.BestResult)
                                    _results.BestResult.Set(_pCurrentSym, _pCurrentType, _pCurrentTypeArgs);
                            }
                            return false;
                        }
                    }
                }
                if (flag) {
                    if (_results.IsBetterUninferableResult(_pCurrentTypeArgs)) {
                        MethodSymbol methodSymbol = _pCurrentSym as MethodSymbol;
                        if (methodSymbol != null)
                            _results.UninferableResult.Set(methodSymbol, _pCurrentType, _pCurrentTypeArgs);
                    }
                    return false;
                }
                return true;
            }
            private void UpdateArguments()
            {
                _pCurrentParameters = TypeManager.SubstTypeArray(_pCurrentParameters, _pCurrentType, _pCurrentTypeArgs);
                if (_pArguments.prgexpr != null && _pArguments.prgexpr.Count != 0) {
                    MethodOrPropertySymbol methodOrPropertySymbol = null;
                    for (int i = 0; i < _pCurrentParameters.Count; i++) {
                        Expr expr = _pArguments.prgexpr[i];
                        if (expr.IsOptionalArgument) {
                            CType cType = _pCurrentParameters[i];
                            if (cType != expr.Type) {
                                if (methodOrPropertySymbol == null)
                                    methodOrPropertySymbol = FindMostDerivedMethod(_pCurrentSym, _pGroup.OptionalObject);
                                Expr value = GenerateOptionalArgument(methodOrPropertySymbol, _pCurrentParameters[i], i);
                                _pArguments.prgexpr[i] = value;
                            }
                        }
                    }
                }
            }
            private static bool DoesTypeArgumentsContainErrorSym(CType var)
            {
                AggregateType aggregateType = var as AggregateType;
                if (aggregateType == null)
                    return false;
                TypeArray typeArgsAll = aggregateType.TypeArgsAll;
                for (int i = 0; i < typeArgsAll.Count; i++) {
                    CType cType = typeArgsAll[i];
                    if (cType == null)
                        return true;
                    if (cType is AggregateType && DoesTypeArgumentsContainErrorSym(cType))
                        return true;
                }
                return false;
            }
            private void ReportErrorsOnSuccess()
            {
                if (_pGroup.SymKind == SYMKIND.SK_MethodSymbol && _results.BestResult.TypeArgs.Count > 0)
                    TypeBind.CheckMethConstraints(new MethWithInst(_results.BestResult));
            }
            private RuntimeBinderException ReportErrorsOnFailure()
            {
                if (_pDuplicateSpecifiedName != null)
                    return ErrorHandling.Error(ErrorCode.ERR_DuplicateNamedArgument, _pDuplicateSpecifiedName);
                if ((bool)_results.InaccessibleResult)
                    return CSemanticChecker.ReportAccessError(_results.InaccessibleResult, _pExprBinder.ContextForMemberLookup, GetTypeQualifier(_pGroup));
                if ((bool)_misnamed) {
                    List<Name> parameterNames = FindMostDerivedMethod(_misnamed.MethProp(), _pGroup.OptionalObject).ParameterNames;
                    for (int i = 0; i != _pOriginalArguments.carg; i++) {
                        ExprNamedArgumentSpecification exprNamedArgumentSpecification = _pOriginalArguments.prgexpr[i] as ExprNamedArgumentSpecification;
                        if (exprNamedArgumentSpecification != null) {
                            Name name = exprNamedArgumentSpecification.Name;
                            if (parameterNames[i] != name) {
                                if (!parameterNames.Contains(name)) {
                                    _pInvalidSpecifiedName = name;
                                    break;
                                }
                                return ErrorHandling.Error(ErrorCode.ERR_BadNonTrailingNamedArgument, name);
                            }
                        }
                    }
                } else if ((bool)_mpwiBogus) {
                    return ErrorHandling.Error(ErrorCode.ERR_BindToBogus, _mpwiBogus);
                }
                bool flag = false;
                Name name2 = _pGroup.Name;
                if (_pGroup.OptionalObject?.Type != null && _pGroup.OptionalObject.Type.IsDelegateType && _pGroup.Name == NameManager.GetPredefinedName(PredefinedName.PN_INVOKE)) {
                    flag = true;
                    name2 = ((AggregateType)_pGroup.OptionalObject.Type).OwningAggregate.name;
                }
                if ((bool)_results.BestResult)
                    return ReportErrorsForBestMatching(flag);
                if ((bool)_results.UninferableResult || (bool)_mpwiCantInferInstArg) {
                    if (!(bool)_results.UninferableResult)
                        _results.UninferableResult.Set(_mpwiCantInferInstArg.Sym as MethodSymbol, _mpwiCantInferInstArg.GetType(), _mpwiCantInferInstArg.TypeArgs);
                    MethWithType swt = new MethWithType(_results.UninferableResult.Meth(), _results.UninferableResult.GetType());
                    return ErrorHandling.Error(ErrorCode.ERR_CantInferMethTypeArgs, swt);
                }
                if ((bool)_mwtBadArity) {
                    int count = _mwtBadArity.Meth().typeVars.Count;
                    return ErrorHandling.Error((count > 0) ? ErrorCode.ERR_BadArity : ErrorCode.ERR_HasNoTypeVars, _mwtBadArity, new ErrArgSymKind(_mwtBadArity.Meth()), _pArguments.carg);
                }
                if ((bool)_mpwiParamTypeConstraints) {
                    TypeBind.CheckMethConstraints(new MethWithInst(_mpwiParamTypeConstraints));
                    return null;
                }
                if (_pInvalidSpecifiedName != null) {
                    AggregateType aggregateType = _pGroup.OptionalObject?.Type as AggregateType;
                    if (aggregateType == null || !aggregateType.OwningAggregate.IsDelegate())
                        return ErrorHandling.Error(ErrorCode.ERR_BadNamedArgument, _pGroup.Name, _pInvalidSpecifiedName);
                    return ErrorHandling.Error(ErrorCode.ERR_BadNamedArgumentForDelegateInvoke, aggregateType.OwningAggregate.name, _pInvalidSpecifiedName);
                }
                if (_pNameUsedInPositionalArgument != null)
                    return ErrorHandling.Error(ErrorCode.ERR_NamedArgumentUsedInPositional, _pNameUsedInPositionalArgument);
                if (_fCandidatesUnsupported)
                    return ErrorHandling.Error(ErrorCode.ERR_BindToBogus, name2);
                if (flag)
                    return ErrorHandling.Error(ErrorCode.ERR_BadDelArgCount, name2, _pArguments.carg);
                if ((_pGroup.Flags & EXPRFLAG.EXF_CTOR) != 0)
                    return ErrorHandling.Error(ErrorCode.ERR_BadCtorArgCount, _pGroup.ParentType, _pArguments.carg);
                return ErrorHandling.Error(ErrorCode.ERR_BadArgCount, name2, _pArguments.carg);
            }
            private RuntimeBinderException ReportErrorsForBestMatching(bool bUseDelegateErrors)
            {
                if (bUseDelegateErrors)
                    return ErrorHandling.Error(ErrorCode.ERR_BadDelArgTypes, _results.BestResult.GetType());
                return ErrorHandling.Error(ErrorCode.ERR_BadArgTypes, _results.BestResult);
            }
        }
        internal sealed class GroupToArgsBinderResult
        {
            public MethPropWithInst BestResult { get; set; }
            public MethPropWithInst InaccessibleResult { get; }
            public MethPropWithInst UninferableResult { get; }
            public GroupToArgsBinderResult()
            {
                BestResult = new MethPropWithInst();
                InaccessibleResult = new MethPropWithInst();
                UninferableResult = new MethPropWithInst();
            }
            private static int NumberOfErrorTypes(TypeArray pTypeArgs)
            {
                int num = 0;
                for (int i = 0; i < pTypeArgs.Count; i++) {
                    if (pTypeArgs[i] == null)
                        num++;
                }
                return num;
            }
            private static bool IsBetterThanCurrent(TypeArray pTypeArgs1, TypeArray pTypeArgs2)
            {
                int num = NumberOfErrorTypes(pTypeArgs1);
                int num2 = NumberOfErrorTypes(pTypeArgs2);
                if (num == num2) {
                    int num3 = (pTypeArgs1.Count > pTypeArgs2.Count) ? pTypeArgs2.Count : pTypeArgs1.Count;
                    for (int i = 0; i < num3; i++) {
                        AggregateType aggregateType = pTypeArgs1[i] as AggregateType;
                        if (aggregateType != null)
                            num += NumberOfErrorTypes(aggregateType.TypeArgsAll);
                        AggregateType aggregateType2 = pTypeArgs2[i] as AggregateType;
                        if (aggregateType2 != null)
                            num2 += NumberOfErrorTypes(aggregateType2.TypeArgsAll);
                    }
                }
                return num2 < num;
            }
            public bool IsBetterUninferableResult(TypeArray pTypeArguments)
            {
                if (UninferableResult.Sym == null)
                    return true;
                if (pTypeArguments == null)
                    return false;
                return IsBetterThanCurrent(UninferableResult.TypeArgs, pTypeArguments);
            }
        }
        private sealed class ImplicitConversion
        {
            private Expr _exprDest;
            private readonly ExpressionBinder _binder;
            private readonly Expr _exprSrc;
            private readonly CType _typeSrc;
            private readonly CType _typeDest;
            private readonly bool _needsExprDest;
            private CONVERTTYPE _flags;
            public Expr ExprDest => _exprDest;
            public ImplicitConversion(ExpressionBinder binder, Expr exprSrc, CType typeSrc, CType typeDest, bool needsExprDest, CONVERTTYPE flags)
            {
                _binder = binder;
                _exprSrc = exprSrc;
                _typeSrc = typeSrc;
                _typeDest = typeDest;
                _needsExprDest = needsExprDest;
                _flags = flags;
                _exprDest = null;
            }
            public bool Bind()
            {
                if (_typeSrc != null && _typeDest != null && !(_typeDest is MethodGroupType)) {
                    switch (_typeDest.TypeKind) {
                    case TypeKind.TK_NullType:
                        if (!(_typeSrc is NullType))
                            return false;
                        if (_needsExprDest)
                            _exprDest = _exprSrc;
                        return true;
                    case TypeKind.TK_ArgumentListType:
                        return _typeSrc == _typeDest;
                    case TypeKind.TK_VoidType:
                        return false;
                    default: {
                        if (_typeSrc == _typeDest && ((_flags & CONVERTTYPE.ISEXPLICIT) == (CONVERTTYPE)0 || (!_typeSrc.IsPredefType(PredefinedType.PT_FLOAT) && !_typeSrc.IsPredefType(PredefinedType.PT_DOUBLE)))) {
                            if (_needsExprDest)
                                _exprDest = _exprSrc;
                            return true;
                        }
                        NullableType nullableType = _typeDest as NullableType;
                        if (nullableType != null)
                            return BindNubConversion(nullableType);
                        NullableType nullableType2 = _typeSrc as NullableType;
                        if (nullableType2 != null)
                            return bindImplicitConversionFromNullable(nullableType2);
                        if ((_flags & CONVERTTYPE.ISEXPLICIT) != 0)
                            _flags |= CONVERTTYPE.NOUDC;
                        FUNDTYPE fundamentalType = _typeDest.FundamentalType;
                        switch (_typeSrc.TypeKind) {
                        case TypeKind.TK_VoidType:
                        case TypeKind.TK_ArgumentListType:
                        case TypeKind.TK_ParameterModifierType:
                            return false;
                        case TypeKind.TK_NullType:
                            if (bindImplicitConversionFromNull())
                                return true;
                            break;
                        case TypeKind.TK_ArrayType:
                            if (bindImplicitConversionFromArray())
                                return true;
                            break;
                        case TypeKind.TK_PointerType:
                            if (bindImplicitConversionFromPointer())
                                return true;
                            break;
                        case TypeKind.TK_AggregateType:
                            if (bindImplicitConversionFromAgg(_typeSrc as AggregateType))
                                return true;
                            break;
                        }
                        object obj = _exprSrc?.RuntimeObject;
                        if (obj != null && _typeDest.AssociatedSystemType.IsInstanceOfType(obj) && CSemanticChecker.CheckTypeAccess(_typeDest, _binder.Context.ContextForMemberLookup)) {
                            if (_needsExprDest)
                                _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest, _exprSrc.Flags & EXPRFLAG.EXF_CANTBENULL);
                            return true;
                        }
                        if ((_flags & CONVERTTYPE.NOUDC) == (CONVERTTYPE)0)
                            return _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, _typeDest, _needsExprDest, out _exprDest, true);
                        return false;
                    }
                    }
                }
                return false;
            }
            private bool BindNubConversion(NullableType nubDst)
            {
                AggregateType ats = nubDst.GetAts();
                if (SymbolLoader.HasBaseConversion(nubDst.UnderlyingType, _typeSrc) && !CConversions.FWrappingConv(_typeSrc, nubDst)) {
                    if ((_flags & CONVERTTYPE.ISEXPLICIT) == (CONVERTTYPE)0)
                        return false;
                    if (_needsExprDest)
                        _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest, EXPRFLAG.EXF_INDEXER);
                    return true;
                }
                bool wasNullable;
                CType cType = nubDst.StripNubs(out wasNullable);
                bool wasNullable2;
                CType cType2 = _typeSrc.StripNubs(out wasNullable2);
                ConversionFunc conversionFunc = ((_flags & CONVERTTYPE.ISEXPLICIT) != 0) ? new ConversionFunc(_binder.BindExplicitConversion) : new ConversionFunc(_binder.BindImplicitConversion);
                if (!wasNullable2) {
                    if (_typeSrc is NullType) {
                        if (_needsExprDest)
                            _exprDest = ((_exprSrc is ExprConstant) ? ExprFactory.CreateZeroInit(nubDst) : ExprFactory.CreateCast(_typeDest, _exprSrc));
                        return true;
                    }
                    Expr ppDestinationExpr = _exprSrc;
                    if (_typeSrc == cType || conversionFunc(_exprSrc, _typeSrc, cType, _needsExprDest, out ppDestinationExpr, _flags | CONVERTTYPE.NOUDC)) {
                        if (_needsExprDest) {
                            ExprUserDefinedConversion exprUserDefinedConversion = ppDestinationExpr as ExprUserDefinedConversion;
                            if (exprUserDefinedConversion != null)
                                ppDestinationExpr = exprUserDefinedConversion.UserDefinedCall;
                            if (wasNullable) {
                                ExprCall exprCall = BindNubNew(ppDestinationExpr);
                                ppDestinationExpr = exprCall;
                                exprCall.NullableCallLiftKind = NullableCallLiftKind.NullableConversionConstructor;
                            }
                            if (exprUserDefinedConversion != null) {
                                exprUserDefinedConversion.UserDefinedCall = ppDestinationExpr;
                                ppDestinationExpr = exprUserDefinedConversion;
                            }
                            _exprDest = ppDestinationExpr;
                        }
                        return true;
                    }
                    if ((_flags & CONVERTTYPE.NOUDC) == (CONVERTTYPE)0)
                        return _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, nubDst, _needsExprDest, out _exprDest, (_flags & CONVERTTYPE.ISEXPLICIT) == (CONVERTTYPE)0);
                    return false;
                }
                if (cType2 != cType && !conversionFunc(null, cType2, cType, false, out _exprDest, _flags | CONVERTTYPE.NOUDC)) {
                    if ((_flags & CONVERTTYPE.NOUDC) == (CONVERTTYPE)0)
                        return _binder.bindUserDefinedConversion(_exprSrc, _typeSrc, nubDst, _needsExprDest, out _exprDest, (_flags & CONVERTTYPE.ISEXPLICIT) == (CONVERTTYPE)0);
                    return false;
                }
                if (_needsExprDest) {
                    MethWithInst method = new MethWithInst(null, null);
                    ExprMemberGroup memberGroup = ExprFactory.CreateMemGroup(null, method);
                    ExprCall exprCall2 = ExprFactory.CreateCall((EXPRFLAG)0, nubDst, _exprSrc, memberGroup, null);
                    Expr ppDestinationExpr2 = _binder.mustCast(_exprSrc, cType2);
                    if (!(((_flags & CONVERTTYPE.ISEXPLICIT) != 0) ? _binder.BindExplicitConversion(ppDestinationExpr2, ppDestinationExpr2.Type, cType, out ppDestinationExpr2, _flags | CONVERTTYPE.NOUDC) : _binder.BindImplicitConversion(ppDestinationExpr2, ppDestinationExpr2.Type, cType, out ppDestinationExpr2, _flags | CONVERTTYPE.NOUDC)))
                        return false;
                    exprCall2.CastOfNonLiftedResultToLiftedType = _binder.mustCast(ppDestinationExpr2, nubDst, (CONVERTTYPE)0);
                    exprCall2.NullableCallLiftKind = NullableCallLiftKind.NullableConversion;
                    exprCall2.PConversions = exprCall2.CastOfNonLiftedResultToLiftedType;
                    _exprDest = exprCall2;
                }
                return true;
            }
            private bool bindImplicitConversionFromNull()
            {
                FUNDTYPE fundamentalType = _typeDest.FundamentalType;
                if (fundamentalType != FUNDTYPE.FT_REF && fundamentalType != FUNDTYPE.FT_PTR && !_typeDest.IsPredefType(PredefinedType.PT_G_OPTIONAL))
                    return false;
                if (_needsExprDest)
                    _exprDest = ((_exprSrc is ExprConstant) ? ExprFactory.CreateZeroInit(_typeDest) : ExprFactory.CreateCast(_typeDest, _exprSrc));
                return true;
            }
            private bool bindImplicitConversionFromNullable(NullableType nubSrc)
            {
                AggregateType ats = nubSrc.GetAts();
                if (ats == _typeDest) {
                    if (_needsExprDest)
                        _exprDest = _exprSrc;
                    return true;
                }
                if (SymbolLoader.HasBaseConversion(nubSrc.UnderlyingType, _typeDest) && !CConversions.FUnwrappingConv(nubSrc, _typeDest)) {
                    if (_needsExprDest) {
                        _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest, EXPRFLAG.EXF_CTOR);
                        if (!_typeDest.IsPredefType(PredefinedType.PT_OBJECT))
                            _binder.bindSimpleCast(_exprDest, _typeDest, out _exprDest, EXPRFLAG.EXF_ASFINALLYLEAVE);
                    }
                    return true;
                }
                if ((_flags & CONVERTTYPE.NOUDC) == (CONVERTTYPE)0)
                    return _binder.bindUserDefinedConversion(_exprSrc, nubSrc, _typeDest, _needsExprDest, out _exprDest, true);
                return false;
            }
            private bool bindImplicitConversionFromArray()
            {
                if (!SymbolLoader.HasBaseConversion(_typeSrc, _typeDest))
                    return false;
                EXPRFLAG exprFlags = (EXPRFLAG)0;
                if (!(_typeDest is ArrayType)) {
                    AggregateType aggregateType = _typeDest as AggregateType;
                    if (aggregateType == null || !aggregateType.IsInterfaceType || aggregateType.TypeArgsAll.Count != 1 || (aggregateType.TypeArgsAll[0] == ((ArrayType)_typeSrc).ElementType && (_flags & CONVERTTYPE.FORCECAST) == (CONVERTTYPE)0))
                        goto IL_009b;
                }
                if ((_flags & CONVERTTYPE.FORCECAST) != 0 || TypeManager.TypeContainsTyVars(_typeSrc, null) || TypeManager.TypeContainsTyVars(_typeDest, null))
                    exprFlags = EXPRFLAG.EXF_OPERATOR;
                goto IL_009b;
                IL_009b:
                if (_needsExprDest)
                    _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest, exprFlags);
                return true;
            }
            private bool bindImplicitConversionFromPointer()
            {
                PointerType pointerType = _typeDest as PointerType;
                if (pointerType != null && pointerType.ReferentType == VoidType.Instance) {
                    if (_needsExprDest)
                        _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest);
                    return true;
                }
                return false;
            }
            private bool bindImplicitConversionFromAgg(AggregateType aggTypeSrc)
            {
                AggregateSymbol owningAggregate = aggTypeSrc.OwningAggregate;
                if (owningAggregate.IsEnum())
                    return bindImplicitConversionFromEnum(aggTypeSrc);
                if (_typeDest.IsEnumType) {
                    if (bindImplicitConversionToEnum(aggTypeSrc))
                        return true;
                } else if (owningAggregate.getThisType().IsSimpleType && _typeDest.IsSimpleType && bindImplicitConversionBetweenSimpleTypes(aggTypeSrc)) {
                    return true;
                }
                return bindImplicitConversionToBase(aggTypeSrc);
            }
            private bool bindImplicitConversionToBase(AggregateType pSource)
            {
                if (!(_typeDest is AggregateType) || !SymbolLoader.HasBaseConversion(pSource, _typeDest))
                    return false;
                EXPRFLAG exprFlags = (EXPRFLAG)0;
                if (pSource.OwningAggregate.IsStruct() && _typeDest.FundamentalType == FUNDTYPE.FT_REF)
                    exprFlags = (EXPRFLAG.EXF_CTOR | EXPRFLAG.EXF_CANTBENULL);
                else if (_exprSrc != null) {
                    exprFlags = (_exprSrc.Flags & EXPRFLAG.EXF_CANTBENULL);
                }
                if (_needsExprDest)
                    _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest, exprFlags);
                return true;
            }
            private bool bindImplicitConversionFromEnum(AggregateType aggTypeSrc)
            {
                AggregateType aggregateType = _typeDest as AggregateType;
                if (aggregateType != null && SymbolLoader.HasBaseConversion(aggTypeSrc, aggregateType)) {
                    if (_needsExprDest)
                        _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest, EXPRFLAG.EXF_CTOR | EXPRFLAG.EXF_CANTBENULL);
                    return true;
                }
                return false;
            }
            private bool bindImplicitConversionToEnum(AggregateType aggTypeSrc)
            {
                if (aggTypeSrc.OwningAggregate.GetPredefType() != PredefinedType.PT_BOOL && _exprSrc != null && _exprSrc.IsZero() && _exprSrc.Type.IsNumericType && (_flags & CONVERTTYPE.STANDARD) == (CONVERTTYPE)0) {
                    if (_needsExprDest)
                        _exprDest = ExprFactory.CreateConstant(_typeDest, ConstVal.GetDefaultValue(_typeDest.ConstValKind));
                    return true;
                }
                return false;
            }
            private bool bindImplicitConversionBetweenSimpleTypes(AggregateType aggTypeSrc)
            {
                AggregateSymbol owningAggregate = aggTypeSrc.OwningAggregate;
                PredefinedType predefType = owningAggregate.GetPredefType();
                PredefinedType predefinedType = _typeDest.PredefinedType;
                ExprConstant exprConstant = _exprSrc as ExprConstant;
                ConvKind convKind = (exprConstant != null && ((predefType == PredefinedType.PT_INT && predefinedType != PredefinedType.PT_BOOL && predefinedType != PredefinedType.PT_CHAR) || (predefType == PredefinedType.PT_LONG && predefinedType == PredefinedType.PT_ULONG)) && isConstantInRange(exprConstant, _typeDest)) ? ConvKind.Implicit : ((predefType != predefinedType) ? GetConvKind(predefType, predefinedType) : ConvKind.Implicit);
                if (convKind != ConvKind.Implicit)
                    return false;
                if (_exprSrc.GetConst() != null && _binder.bindConstantCast(_exprSrc, _typeDest, _needsExprDest, out _exprDest, false) == ConstCastResult.Success)
                    return true;
                if (isUserDefinedConversion(predefType, predefinedType)) {
                    if (!_needsExprDest)
                        return true;
                    return _binder.bindUserDefinedConversion(_exprSrc, aggTypeSrc, _typeDest, _needsExprDest, out _exprDest, true);
                }
                if (_needsExprDest)
                    _binder.bindSimpleCast(_exprSrc, _typeDest, out _exprDest);
                return true;
            }
        }
        private class UnaOpSig
        {
            public PredefinedType pt;
            public UnaOpMask grfuom;
            public int cuosSkip;
            public PfnBindUnaOp pfn;
            public UnaOpFuncKind fnkind;
            protected UnaOpSig()
            {
            }
            public UnaOpSig(PredefinedType pt, UnaOpMask grfuom, int cuosSkip, PfnBindUnaOp pfn, UnaOpFuncKind fnkind)
            {
                this.pt = pt;
                this.grfuom = grfuom;
                this.cuosSkip = cuosSkip;
                this.pfn = pfn;
                this.fnkind = fnkind;
            }
        }
        private sealed class UnaOpFullSig : UnaOpSig
        {
            private readonly LiftFlags _grflt;
            private readonly CType _type;
            public UnaOpFullSig(CType type, PfnBindUnaOp pfn, LiftFlags grflt, UnaOpFuncKind fnkind)
            {
                pt = PredefinedType.PT_UNDEFINEDINDEX;
                grfuom = UnaOpMask.None;
                cuosSkip = 0;
                base.pfn = pfn;
                _type = type;
                _grflt = grflt;
                base.fnkind = fnkind;
            }
            public UnaOpFullSig(ExpressionBinder fnc, UnaOpSig uos)
            {
                pt = uos.pt;
                grfuom = uos.grfuom;
                cuosSkip = uos.cuosSkip;
                pfn = uos.pfn;
                fnkind = uos.fnkind;
                _type = ((pt != PredefinedType.PT_UNDEFINEDINDEX) ? GetPredefindType(pt) : null);
                _grflt = LiftFlags.None;
            }
            public bool FPreDef()
            {
                return pt != PredefinedType.PT_UNDEFINEDINDEX;
            }
            public bool isLifted()
            {
                if (_grflt == LiftFlags.None)
                    return false;
                return true;
            }
            public bool Convert()
            {
                return (_grflt & LiftFlags.Convert1) != LiftFlags.None;
            }
            public new CType GetType()
            {
                return _type;
            }
        }
        private static readonly byte[][] s_betterConversionTable = new byte[16][] {
            new byte[16] {
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                2,
                3,
                3,
                3,
                3,
                3,
                3
            },
            new byte[16] {
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                1,
                1,
                1,
                3,
                3,
                3
            },
            new byte[16] {
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                1,
                1,
                3,
                3,
                3
            },
            new byte[16] {
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                1,
                3,
                3,
                3
            },
            new byte[16] {
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3
            },
            new byte[16] {
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3
            },
            new byte[16] {
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3
            },
            new byte[16] {
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3
            },
            new byte[16] {
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3
            },
            new byte[16] {
                1,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                1,
                1,
                1,
                3,
                3,
                3
            },
            new byte[16] {
                3,
                2,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                2,
                3,
                3,
                3,
                3,
                3,
                3
            },
            new byte[16] {
                3,
                2,
                2,
                3,
                3,
                3,
                3,
                3,
                3,
                2,
                3,
                3,
                3,
                3,
                3,
                3
            },
            new byte[16] {
                3,
                2,
                2,
                2,
                3,
                3,
                3,
                3,
                3,
                2,
                3,
                3,
                3,
                3,
                3,
                3
            },
            new byte[16] {
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3
            },
            new byte[16] {
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3
            },
            new byte[16] {
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3
            }
        };
        private static readonly byte[][] s_simpleTypeConversions = new byte[13][] {
            new byte[13] {
                1,
                2,
                2,
                2,
                2,
                2,
                66,
                3,
                5,
                3,
                2,
                2,
                2
            },
            new byte[13] {
                3,
                1,
                2,
                2,
                2,
                2,
                66,
                3,
                5,
                3,
                3,
                3,
                3
            },
            new byte[13] {
                3,
                3,
                1,
                2,
                2,
                2,
                66,
                3,
                5,
                3,
                3,
                3,
                3
            },
            new byte[13] {
                3,
                3,
                3,
                1,
                2,
                2,
                66,
                3,
                5,
                3,
                3,
                3,
                3
            },
            new byte[13] {
                3,
                3,
                3,
                3,
                1,
                2,
                67,
                3,
                5,
                3,
                3,
                3,
                3
            },
            new byte[13] {
                3,
                3,
                3,
                3,
                3,
                1,
                67,
                3,
                5,
                3,
                3,
                3,
                3
            },
            new byte[13] {
                67,
                67,
                67,
                67,
                67,
                67,
                1,
                67,
                5,
                67,
                67,
                67,
                67
            },
            new byte[13] {
                3,
                3,
                2,
                2,
                2,
                2,
                66,
                1,
                5,
                3,
                2,
                2,
                2
            },
            new byte[13] {
                5,
                5,
                5,
                5,
                5,
                5,
                5,
                5,
                1,
                5,
                5,
                5,
                5
            },
            new byte[13] {
                3,
                2,
                2,
                2,
                2,
                2,
                66,
                3,
                5,
                1,
                3,
                3,
                3
            },
            new byte[13] {
                3,
                3,
                2,
                2,
                2,
                2,
                66,
                3,
                5,
                3,
                1,
                2,
                2
            },
            new byte[13] {
                3,
                3,
                3,
                2,
                2,
                2,
                66,
                3,
                5,
                3,
                3,
                1,
                2
            },
            new byte[13] {
                3,
                3,
                3,
                3,
                2,
                2,
                66,
                3,
                5,
                3,
                3,
                3,
                1
            }
        };
        private static readonly byte[][] s_simpleTypeBetter = new byte[16][] {
            new byte[16] {
                0,
                1,
                1,
                1,
                1,
                1,
                1,
                3,
                3,
                2,
                1,
                1,
                1,
                3,
                3,
                1
            },
            new byte[16] {
                2,
                0,
                1,
                1,
                1,
                1,
                1,
                3,
                3,
                2,
                1,
                1,
                1,
                3,
                3,
                1
            },
            new byte[16] {
                2,
                2,
                0,
                1,
                1,
                1,
                1,
                2,
                3,
                2,
                2,
                1,
                1,
                3,
                3,
                1
            },
            new byte[16] {
                2,
                2,
                2,
                0,
                1,
                1,
                1,
                2,
                3,
                2,
                2,
                2,
                1,
                3,
                3,
                1
            },
            new byte[16] {
                2,
                2,
                2,
                2,
                0,
                1,
                3,
                2,
                3,
                2,
                2,
                2,
                2,
                3,
                3,
                1
            },
            new byte[16] {
                2,
                2,
                2,
                2,
                2,
                0,
                3,
                2,
                3,
                2,
                2,
                2,
                2,
                3,
                3,
                1
            },
            new byte[16] {
                2,
                2,
                2,
                2,
                3,
                3,
                0,
                2,
                3,
                2,
                2,
                2,
                2,
                3,
                3,
                1
            },
            new byte[16] {
                3,
                3,
                1,
                1,
                1,
                1,
                1,
                0,
                3,
                3,
                1,
                1,
                1,
                3,
                3,
                1
            },
            new byte[16] {
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                0,
                3,
                3,
                3,
                3,
                3,
                3,
                1
            },
            new byte[16] {
                1,
                1,
                1,
                1,
                1,
                1,
                1,
                3,
                3,
                0,
                1,
                1,
                1,
                3,
                3,
                1
            },
            new byte[16] {
                2,
                2,
                1,
                1,
                1,
                1,
                1,
                2,
                3,
                2,
                0,
                1,
                1,
                3,
                3,
                1
            },
            new byte[16] {
                2,
                2,
                2,
                1,
                1,
                1,
                1,
                2,
                3,
                2,
                2,
                0,
                1,
                3,
                3,
                1
            },
            new byte[16] {
                2,
                2,
                2,
                2,
                1,
                1,
                1,
                2,
                3,
                2,
                2,
                2,
                0,
                3,
                3,
                1
            },
            new byte[16] {
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                0,
                3,
                1
            },
            new byte[16] {
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                3,
                0,
                1
            },
            new byte[16] {
                2,
                2,
                2,
                2,
                2,
                2,
                2,
                2,
                2,
                2,
                2,
                2,
                2,
                2,
                2,
                0
            }
        };
        private static readonly PredefinedType[] s_rgptIntOp = new PredefinedType[4] {
            PredefinedType.PT_INT,
            PredefinedType.PT_UINT,
            PredefinedType.PT_LONG,
            PredefinedType.PT_ULONG
        };
        private static readonly PredefinedName[] s_EK2NAME = new PredefinedName[26] {
            PredefinedName.PN_OPEQUALS,
            PredefinedName.PN_OPCOMPARE,
            PredefinedName.PN_OPTRUE,
            PredefinedName.PN_OPFALSE,
            PredefinedName.PN_OPINCREMENT,
            PredefinedName.PN_OPDECREMENT,
            PredefinedName.PN_OPNEGATION,
            PredefinedName.PN_OPEQUALITY,
            PredefinedName.PN_OPINEQUALITY,
            PredefinedName.PN_OPLESSTHAN,
            PredefinedName.PN_OPLESSTHANOREQUAL,
            PredefinedName.PN_OPGREATERTHAN,
            PredefinedName.PN_OPGREATERTHANOREQUAL,
            PredefinedName.PN_OPPLUS,
            PredefinedName.PN_OPMINUS,
            PredefinedName.PN_OPMULTIPLY,
            PredefinedName.PN_OPDIVISION,
            PredefinedName.PN_OPMODULUS,
            PredefinedName.PN_OPUNARYMINUS,
            PredefinedName.PN_OPUNARYPLUS,
            PredefinedName.PN_OPBITWISEAND,
            PredefinedName.PN_OPBITWISEOR,
            PredefinedName.PN_OPXOR,
            PredefinedName.PN_OPCOMPLEMENT,
            PredefinedName.PN_OPLEFTSHIFT,
            PredefinedName.PN_OPRIGHTSHIFT
        };
        private static readonly BinOpSig[] s_binopSignatures = new BinOpSig[20] {
            new BinOpSig(PredefinedType.PT_INT, PredefinedType.PT_INT, BinOpMask.Integer, 8, BindIntBinOp, OpSigFlags.Value, BinOpFuncKind.IntBinOp),
            new BinOpSig(PredefinedType.PT_UINT, PredefinedType.PT_UINT, BinOpMask.Integer, 7, BindIntBinOp, OpSigFlags.Value, BinOpFuncKind.IntBinOp),
            new BinOpSig(PredefinedType.PT_LONG, PredefinedType.PT_LONG, BinOpMask.Integer, 6, BindIntBinOp, OpSigFlags.Value, BinOpFuncKind.IntBinOp),
            new BinOpSig(PredefinedType.PT_ULONG, PredefinedType.PT_ULONG, BinOpMask.Integer, 5, BindIntBinOp, OpSigFlags.Value, BinOpFuncKind.IntBinOp),
            new BinOpSig(PredefinedType.PT_ULONG, PredefinedType.PT_LONG, BinOpMask.Integer, 4, null, OpSigFlags.Value, BinOpFuncKind.None),
            new BinOpSig(PredefinedType.PT_LONG, PredefinedType.PT_ULONG, BinOpMask.Integer, 3, null, OpSigFlags.Value, BinOpFuncKind.None),
            new BinOpSig(PredefinedType.PT_FLOAT, PredefinedType.PT_FLOAT, BinOpMask.Real, 1, BindRealBinOp, OpSigFlags.Value, BinOpFuncKind.RealBinOp),
            new BinOpSig(PredefinedType.PT_DOUBLE, PredefinedType.PT_DOUBLE, BinOpMask.Real, 0, BindRealBinOp, OpSigFlags.Value, BinOpFuncKind.RealBinOp),
            new BinOpSig(PredefinedType.PT_DECIMAL, PredefinedType.PT_DECIMAL, BinOpMask.Real, 0, BindDecBinOp, OpSigFlags.Value, BinOpFuncKind.DecBinOp),
            new BinOpSig(PredefinedType.PT_STRING, PredefinedType.PT_STRING, BinOpMask.Equal, 0, BindStrCmpOp, OpSigFlags.Convert, BinOpFuncKind.StrCmpOp),
            new BinOpSig(PredefinedType.PT_STRING, PredefinedType.PT_STRING, BinOpMask.Add, 2, BindStrBinOp, OpSigFlags.Convert, BinOpFuncKind.StrBinOp),
            new BinOpSig(PredefinedType.PT_STRING, PredefinedType.PT_OBJECT, BinOpMask.Add, 1, BindStrBinOp, OpSigFlags.Convert, BinOpFuncKind.StrBinOp),
            new BinOpSig(PredefinedType.PT_OBJECT, PredefinedType.PT_STRING, BinOpMask.Add, 0, BindStrBinOp, OpSigFlags.Convert, BinOpFuncKind.StrBinOp),
            new BinOpSig(PredefinedType.PT_INT, PredefinedType.PT_INT, BinOpMask.Shift, 3, BindShiftOp, OpSigFlags.Value, BinOpFuncKind.ShiftOp),
            new BinOpSig(PredefinedType.PT_UINT, PredefinedType.PT_INT, BinOpMask.Shift, 2, BindShiftOp, OpSigFlags.Value, BinOpFuncKind.ShiftOp),
            new BinOpSig(PredefinedType.PT_LONG, PredefinedType.PT_INT, BinOpMask.Shift, 1, BindShiftOp, OpSigFlags.Value, BinOpFuncKind.ShiftOp),
            new BinOpSig(PredefinedType.PT_ULONG, PredefinedType.PT_INT, BinOpMask.Shift, 0, BindShiftOp, OpSigFlags.Value, BinOpFuncKind.ShiftOp),
            new BinOpSig(PredefinedType.PT_BOOL, PredefinedType.PT_BOOL, BinOpMask.BoolNorm, 0, BindBoolBinOp, OpSigFlags.Value, BinOpFuncKind.BoolBinOp),
            new BinOpSig(PredefinedType.PT_BOOL, PredefinedType.PT_BOOL, BinOpMask.Logical, 0, BindBoolBinOp, OpSigFlags.BoolBit, BinOpFuncKind.BoolBinOp),
            new BinOpSig(PredefinedType.PT_BOOL, PredefinedType.PT_BOOL, BinOpMask.Bitwise, 0, BindLiftedBoolBitwiseOp, OpSigFlags.BoolBit, BinOpFuncKind.BoolBitwiseOp)
        };
        private static readonly UnaOpSig[] s_rguos = new UnaOpSig[16] {
            new UnaOpSig(PredefinedType.PT_INT, UnaOpMask.Signed, 7, BindIntUnaOp, UnaOpFuncKind.IntUnaOp),
            new UnaOpSig(PredefinedType.PT_UINT, UnaOpMask.Unsigned, 6, BindIntUnaOp, UnaOpFuncKind.IntUnaOp),
            new UnaOpSig(PredefinedType.PT_LONG, UnaOpMask.Signed, 5, BindIntUnaOp, UnaOpFuncKind.IntUnaOp),
            new UnaOpSig(PredefinedType.PT_ULONG, UnaOpMask.Unsigned, 4, BindIntUnaOp, UnaOpFuncKind.IntUnaOp),
            new UnaOpSig(PredefinedType.PT_ULONG, UnaOpMask.Minus, 3, null, UnaOpFuncKind.None),
            new UnaOpSig(PredefinedType.PT_FLOAT, UnaOpMask.Real, 1, BindRealUnaOp, UnaOpFuncKind.RealUnaOp),
            new UnaOpSig(PredefinedType.PT_DOUBLE, UnaOpMask.Real, 0, BindRealUnaOp, UnaOpFuncKind.RealUnaOp),
            new UnaOpSig(PredefinedType.PT_DECIMAL, UnaOpMask.Real, 0, BindDecUnaOp, UnaOpFuncKind.DecUnaOp),
            new UnaOpSig(PredefinedType.PT_BOOL, UnaOpMask.Bang, 0, BindBoolUnaOp, UnaOpFuncKind.BoolUnaOp),
            new UnaOpSig(PredefinedType.PT_INT, UnaOpMask.IncDec, 6, null, UnaOpFuncKind.None),
            new UnaOpSig(PredefinedType.PT_UINT, UnaOpMask.IncDec, 5, null, UnaOpFuncKind.None),
            new UnaOpSig(PredefinedType.PT_LONG, UnaOpMask.IncDec, 4, null, UnaOpFuncKind.None),
            new UnaOpSig(PredefinedType.PT_ULONG, UnaOpMask.IncDec, 3, null, UnaOpFuncKind.None),
            new UnaOpSig(PredefinedType.PT_FLOAT, UnaOpMask.IncDec, 1, null, UnaOpFuncKind.None),
            new UnaOpSig(PredefinedType.PT_DOUBLE, UnaOpMask.IncDec, 0, null, UnaOpFuncKind.None),
            new UnaOpSig(PredefinedType.PT_DECIMAL, UnaOpMask.IncDec, 0, null, UnaOpFuncKind.None)
        };
        public BindingContext Context { get; }
        private AggregateSymbol ContextForMemberLookup => Context.ContextForMemberLookup;
        private static BetterType WhichMethodIsBetterTieBreaker(CandidateFunctionMember node1, CandidateFunctionMember node2, CType pTypeThrough, ArgInfos args)
        {
            MethPropWithInst mpwi = node1.mpwi;
            MethPropWithInst mpwi2 = node2.mpwi;
            if (node1.ctypeLift != node2.ctypeLift) {
                if (node1.ctypeLift >= node2.ctypeLift)
                    return BetterType.Right;
                return BetterType.Left;
            }
            if (mpwi.TypeArgs.Count != 0) {
                if (mpwi2.TypeArgs.Count == 0)
                    return BetterType.Right;
            } else if (mpwi2.TypeArgs.Count != 0) {
                return BetterType.Left;
            }
            if (node1.fExpanded) {
                if (!node2.fExpanded)
                    return BetterType.Right;
            } else if (node2.fExpanded) {
                return BetterType.Left;
            }
            BetterType betterType = CompareTypes(RearrangeNamedArguments(mpwi.MethProp().Params, mpwi, pTypeThrough, args), RearrangeNamedArguments(mpwi2.MethProp().Params, mpwi2, pTypeThrough, args));
            if (betterType == BetterType.Left || betterType == BetterType.Right)
                return betterType;
            if (mpwi.MethProp().modOptCount != mpwi2.MethProp().modOptCount) {
                if (mpwi.MethProp().modOptCount >= mpwi2.MethProp().modOptCount)
                    return BetterType.Right;
                return BetterType.Left;
            }
            return BetterType.Neither;
        }
        private static BetterType CompareTypes(TypeArray ta1, TypeArray ta2)
        {
            if (ta1 == ta2)
                return BetterType.Same;
            if (ta1.Count != ta2.Count) {
                if (ta1.Count <= ta2.Count)
                    return BetterType.Right;
                return BetterType.Left;
            }
            BetterType betterType = BetterType.Neither;
            for (int i = 0; i < ta1.Count; i++) {
                CType cType = ta1[i];
                CType cType2 = ta2[i];
                BetterType betterType2 = BetterType.Neither;
                while (true) {
                    if (cType.TypeKind != cType2.TypeKind) {
                        if (cType is TypeParameterType)
                            betterType2 = BetterType.Right;
                        else if (cType2 is TypeParameterType) {
                            betterType2 = BetterType.Left;
                        }
                        break;
                    }
                    switch (cType.TypeKind) {
                    case TypeKind.TK_ArrayType:
                    case TypeKind.TK_PointerType:
                    case TypeKind.TK_ParameterModifierType:
                    case TypeKind.TK_NullableType:
                        break;
                    case TypeKind.TK_AggregateType:
                        betterType2 = CompareTypes(((AggregateType)cType).TypeArgsAll, ((AggregateType)cType2).TypeArgsAll);
                        goto end_IL_0042;
                    default:
                        goto end_IL_0042;
                    }
                    cType = cType.BaseOrParameterOrElementType;
                    cType2 = cType2.BaseOrParameterOrElementType;
                    continue;
                    continue;
                    end_IL_0042:
                    break;
                }
                if (betterType2 == BetterType.Right || betterType2 == BetterType.Left) {
                    if (betterType == BetterType.Same || betterType == BetterType.Neither)
                        betterType = betterType2;
                    else if (betterType2 != betterType) {
                        return BetterType.Neither;
                    }
                }
            }
            return betterType;
        }
        private static int FindName(List<Name> names, Name name)
        {
            return names.IndexOf(name);
        }
        private static TypeArray RearrangeNamedArguments(TypeArray pta, MethPropWithInst mpwi, CType pTypeThrough, ArgInfos args)
        {
            if (args.carg == 0 || !(args.prgexpr[args.carg - 1] is ExprNamedArgumentSpecification))
                return pta;
            CType pType = (pTypeThrough != null) ? pTypeThrough : mpwi.GetType();
            CType[] array = new CType[pta.Count];
            MethodOrPropertySymbol methodOrPropertySymbol = GroupToArgsBinder.FindMostDerivedMethod(mpwi.MethProp(), pType);
            for (int i = 0; i < pta.Count; i++) {
                array[i] = pta[i];
            }
            List<Expr> prgexpr = args.prgexpr;
            for (int j = 0; j < args.carg; j++) {
                ExprNamedArgumentSpecification exprNamedArgumentSpecification = prgexpr[j] as ExprNamedArgumentSpecification;
                if (exprNamedArgumentSpecification != null) {
                    int num = FindName(methodOrPropertySymbol.ParameterNames, exprNamedArgumentSpecification.Name);
                    CType cType = pta[num];
                    for (int k = j; k < num; k++) {
                        array[k + 1] = array[k];
                    }
                    array[j] = cType;
                }
            }
            return TypeArray.Allocate(array);
        }
        private BetterType WhichMethodIsBetter(CandidateFunctionMember node1, CandidateFunctionMember node2, CType pTypeThrough, ArgInfos args)
        {
            MethPropWithInst mpwi = node1.mpwi;
            MethPropWithInst mpwi2 = node2.mpwi;
            TypeArray typeArray = RearrangeNamedArguments(node1.params, mpwi, pTypeThrough, args);
            TypeArray typeArray2 = RearrangeNamedArguments(node2.params, mpwi2, pTypeThrough, args);
            if (typeArray == typeArray2)
                return WhichMethodIsBetterTieBreaker(node1, node2, pTypeThrough, args);
            BetterType betterType = BetterType.Neither;
            int carg = args.carg;
            for (int i = 0; i < carg; i++) {
                Expr expr = args.prgexpr[i];
                CType p = typeArray[i];
                CType p2 = typeArray2[i];
                CType argType = expr?.RuntimeObjectActualType ?? args.types[i];
                BetterType betterType2 = WhichConversionIsBetter(argType, p, p2);
                switch (betterType) {
                case BetterType.Right:
                    break;
                case BetterType.Left:
                    goto IL_00b9;
                default:
                    goto IL_00c3;
                }
                if (betterType2 == BetterType.Left) {
                    betterType = BetterType.Neither;
                    break;
                }
                continue;
                IL_00b9:
                if (betterType2 == BetterType.Right) {
                    betterType = BetterType.Neither;
                    break;
                }
                continue;
                IL_00c3:
                if (betterType2 == BetterType.Right || betterType2 == BetterType.Left)
                    betterType = betterType2;
            }
            if (typeArray.Count != typeArray2.Count && betterType == BetterType.Neither) {
                if (node1.fExpanded) {
                    if (!node2.fExpanded)
                        return BetterType.Right;
                } else if (node2.fExpanded) {
                    return BetterType.Left;
                }
                if (typeArray.Count == carg)
                    return BetterType.Left;
                if (typeArray2.Count == carg)
                    return BetterType.Right;
                return BetterType.Neither;
            }
            return betterType;
        }
        private BetterType WhichConversionIsBetter(CType argType, CType p1, CType p2)
        {
            if (p1 == p2)
                return BetterType.Same;
            if (argType == p1)
                return BetterType.Left;
            if (argType == p2)
                return BetterType.Right;
            bool flag = canConvert(p1, p2);
            bool flag2 = canConvert(p2, p1);
            if (flag != flag2) {
                if (!flag)
                    return BetterType.Right;
                return BetterType.Left;
            }
            if (p1.IsPredefined && p2.IsPredefined) {
                PredefinedType predefinedType = p1.PredefinedType;
                if (predefinedType <= PredefinedType.PT_OBJECT) {
                    PredefinedType predefinedType2 = p2.PredefinedType;
                    if (predefinedType2 <= PredefinedType.PT_OBJECT)
                        return (BetterType)s_betterConversionTable[(uint)predefinedType][(uint)predefinedType2];
                }
            }
            return BetterType.Neither;
        }
        private CandidateFunctionMember FindBestMethod(List<CandidateFunctionMember> list, CType pTypeThrough, ArgInfos args, out CandidateFunctionMember methAmbig1, out CandidateFunctionMember methAmbig2)
        {
            CandidateFunctionMember candidateFunctionMember = null;
            CandidateFunctionMember candidateFunctionMember2 = null;
            bool flag = false;
            CandidateFunctionMember candidateFunctionMember3 = list[0];
            for (int i = 1; i < list.Count; i++) {
                CandidateFunctionMember candidateFunctionMember4 = list[i];
                switch (WhichMethodIsBetter(candidateFunctionMember3, candidateFunctionMember4, pTypeThrough, args)) {
                case BetterType.Left:
                    flag = false;
                    break;
                case BetterType.Right:
                    flag = false;
                    candidateFunctionMember3 = candidateFunctionMember4;
                    break;
                default:
                    candidateFunctionMember = candidateFunctionMember3;
                    candidateFunctionMember2 = candidateFunctionMember4;
                    i++;
                    if (i < list.Count) {
                        candidateFunctionMember4 = list[i];
                        candidateFunctionMember3 = candidateFunctionMember4;
                    } else
                        flag = true;
                    break;
                }
            }
            if (!flag) {
                foreach (CandidateFunctionMember item in list) {
                    if (item != candidateFunctionMember3) {
                        switch (WhichMethodIsBetter(item, candidateFunctionMember3, pTypeThrough, args)) {
                        case BetterType.Left:
                            break;
                        case BetterType.Same:
                        case BetterType.Neither:
                            candidateFunctionMember = candidateFunctionMember3;
                            candidateFunctionMember2 = item;
                            break;
                        case BetterType.Right:
                            continue;
                        }
                        break;
                    }
                    methAmbig1 = null;
                    methAmbig2 = null;
                    return candidateFunctionMember3;
                }
            }
            if ((candidateFunctionMember != null) & (candidateFunctionMember2 != null)) {
                methAmbig1 = candidateFunctionMember;
                methAmbig2 = candidateFunctionMember2;
            } else {
                methAmbig1 = list.First();
                methAmbig2 = list.Skip(1).First();
            }
            return null;
        }
        private static void RoundToFloat(double d, out float f)
        {
            f = (float)d;
        }
        private static long I64(long x)
        {
            return x;
        }
        private static long I64(ulong x)
        {
            return (long)x;
        }
        private static ConvKind GetConvKind(PredefinedType ptSrc, PredefinedType ptDst)
        {
            if ((int)ptSrc < 13 && (int)ptDst < 13)
                return (ConvKind)(s_simpleTypeConversions[(uint)ptSrc][(uint)ptDst] & 15);
            if (ptSrc == ptDst || (ptDst == PredefinedType.PT_OBJECT && ptSrc < PredefinedType.PT_COUNT))
                return ConvKind.Implicit;
            if (ptSrc == PredefinedType.PT_OBJECT && ptDst < PredefinedType.PT_COUNT)
                return ConvKind.Explicit;
            return ConvKind.Unknown;
        }
        private static bool isUserDefinedConversion(PredefinedType ptSrc, PredefinedType ptDst)
        {
            if ((int)ptSrc < 13 && (int)ptDst < 13)
                return (s_simpleTypeConversions[(uint)ptSrc][(uint)ptDst] & 64) != 0;
            return false;
        }
        private BetterType WhichSimpleConversionIsBetter(PredefinedType pt1, PredefinedType pt2)
        {
            return (BetterType)s_simpleTypeBetter[(uint)pt1][(uint)pt2];
        }
        private BetterType WhichTypeIsBetter(PredefinedType pt1, PredefinedType pt2, CType typeGiven)
        {
            if (pt1 == pt2)
                return BetterType.Same;
            if (typeGiven.IsPredefType(pt1))
                return BetterType.Left;
            if (typeGiven.IsPredefType(pt2))
                return BetterType.Right;
            if ((int)pt1 < 16 && (int)pt2 < 16)
                return WhichSimpleConversionIsBetter(pt1, pt2);
            if (pt2 == PredefinedType.PT_OBJECT && pt1 < PredefinedType.PT_COUNT)
                return BetterType.Left;
            if (pt1 == PredefinedType.PT_OBJECT && pt2 < PredefinedType.PT_COUNT)
                return BetterType.Right;
            return WhichTypeIsBetter(GetPredefindType(pt1), GetPredefindType(pt2), typeGiven);
        }
        private BetterType WhichTypeIsBetter(CType type1, CType type2, CType typeGiven)
        {
            if (type1 == type2)
                return BetterType.Same;
            if (typeGiven == type1)
                return BetterType.Left;
            if (typeGiven == type2)
                return BetterType.Right;
            bool flag = canConvert(type1, type2);
            bool flag2 = canConvert(type2, type1);
            if (flag != flag2) {
                if (!flag)
                    return BetterType.Right;
                return BetterType.Left;
            }
            NullableType nullableType = type1 as NullableType;
            if (nullableType != null) {
                NullableType nullableType2 = type2 as NullableType;
                if (nullableType2 != null && nullableType.UnderlyingType.IsPredefined && nullableType2.UnderlyingType.IsPredefined) {
                    PredefinedType predefinedType = (type1 as NullableType).UnderlyingType.PredefinedType;
                    PredefinedType predefinedType2 = (type2 as NullableType).UnderlyingType.PredefinedType;
                    if ((int)predefinedType < 16 && (int)predefinedType2 < 16)
                        return WhichSimpleConversionIsBetter(predefinedType, predefinedType2);
                    return BetterType.Neither;
                }
            }
            return BetterType.Neither;
        }
        private bool canConvert(CType src, CType dest, CONVERTTYPE flags)
        {
            return BindImplicitConversion(null, src, dest, flags);
        }
        public bool canConvert(CType src, CType dest)
        {
            return canConvert(src, dest, (CONVERTTYPE)0);
        }
        private bool canConvert(Expr expr, CType dest)
        {
            return canConvert(expr, dest, (CONVERTTYPE)0);
        }
        private bool canConvert(Expr expr, CType dest, CONVERTTYPE flags)
        {
            return BindImplicitConversion(expr, expr.Type, dest, flags);
        }
        private Expr mustConvertCore(Expr expr, CType destExpr)
        {
            return mustConvertCore(expr, destExpr, (CONVERTTYPE)0);
        }
        private Expr mustConvertCore(Expr expr, CType dest, CONVERTTYPE flags)
        {
            if (BindImplicitConversion(expr, expr.Type, dest, out Expr ppDestinationExpr, flags)) {
                CheckUnsafe(expr.Type);
                CheckUnsafe(dest);
                return ppDestinationExpr;
            }
            FUNDTYPE fundamentalType = expr.Type.FundamentalType;
            FUNDTYPE fundamentalType2 = dest.FundamentalType;
            ExprConstant exprConstant = expr as ExprConstant;
            if (exprConstant != null && expr.Type.IsSimpleType && dest.IsSimpleType && ((fundamentalType == FUNDTYPE.FT_I4 && (fundamentalType2 <= FUNDTYPE.FT_U4 || fundamentalType2 == FUNDTYPE.FT_U8)) || (fundamentalType == FUNDTYPE.FT_I8 && fundamentalType2 == FUNDTYPE.FT_U8))) {
                string psz = exprConstant.Int64Value.ToString(CultureInfo.InvariantCulture);
                throw ErrorHandling.Error(ErrorCode.ERR_ConstOutOfRange, psz, dest);
            }
            if (expr.Type is NullType && dest.FundamentalType != FUNDTYPE.FT_REF)
                throw ErrorHandling.Error(ErrorCode.ERR_ValueCantBeNull, dest);
            throw ErrorHandling.Error(canCast(expr.Type, dest, flags) ? ErrorCode.ERR_NoImplicitConvCast : ErrorCode.ERR_NoImplicitConv, new ErrArg(expr.Type, ErrArgFlags.Unique), new ErrArg(dest, ErrArgFlags.Unique));
        }
        public Expr tryConvert(Expr expr, CType dest)
        {
            return tryConvert(expr, dest, (CONVERTTYPE)0);
        }
        private Expr tryConvert(Expr expr, CType dest, CONVERTTYPE flags)
        {
            if (BindImplicitConversion(expr, expr.Type, dest, out Expr ppDestinationExpr, flags)) {
                CheckUnsafe(expr.Type);
                CheckUnsafe(dest);
                return ppDestinationExpr;
            }
            return null;
        }
        public Expr mustConvert(Expr expr, CType dest)
        {
            return mustConvert(expr, dest, (CONVERTTYPE)0);
        }
        private Expr mustConvert(Expr expr, CType dest, CONVERTTYPE flags)
        {
            return mustConvertCore(expr, dest, flags);
        }
        private Expr mustCastCore(Expr expr, CType dest, CONVERTTYPE flags)
        {
            CSemanticChecker.CheckForStaticClass(dest);
            if (BindExplicitConversion(expr, expr.Type, dest, out Expr ppDestinationExpr, flags)) {
                CheckUnsafe(expr.Type);
                CheckUnsafe(dest);
                return ppDestinationExpr;
            }
            Expr const = expr.GetConst();
            if (const != null && expr.Type.IsSimpleOrEnum && dest.IsSimpleOrEnum) {
                FUNDTYPE fundamentalType = expr.Type.FundamentalType;
                ConstVal val;
                if (fundamentalType == FUNDTYPE.FT_STRUCT) {
                    ErrArg[] obj = new ErrArg[2];
                    val = ((ExprConstant)const).Val;
                    obj[0] = val.DecimalVal.ToString(CultureInfo.InvariantCulture);
                    obj[1] = dest;
                    throw ErrorHandling.Error(ErrorCode.ERR_ConstOutOfRange, obj);
                }
                if (Context.Checked) {
                    if (!CanExplicitConversionBeBoundInUncheckedContext(expr, expr.Type, dest, flags | CONVERTTYPE.NOUDC))
                        throw CantConvert(expr, dest);
                    string psz;
                    switch (fundamentalType) {
                    case FUNDTYPE.FT_U1:
                    case FUNDTYPE.FT_U2:
                    case FUNDTYPE.FT_U4:
                    case FUNDTYPE.FT_U8:
                        psz = ((ulong)((ExprConstant)const).Int64Value).ToString((IFormatProvider)CultureInfo.InvariantCulture);
                        break;
                    case FUNDTYPE.FT_I1:
                    case FUNDTYPE.FT_I2:
                    case FUNDTYPE.FT_I4:
                    case FUNDTYPE.FT_I8:
                        psz = ((ExprConstant)const).Int64Value.ToString(CultureInfo.InvariantCulture);
                        break;
                    default:
                        val = ((ExprConstant)const).Val;
                        psz = val.DoubleVal.ToString(CultureInfo.InvariantCulture);
                        break;
                    }
                    throw ErrorHandling.Error(ErrorCode.ERR_ConstOutOfRangeChecked, psz, dest);
                }
            }
            if (expr.Type is NullType && dest.FundamentalType != FUNDTYPE.FT_REF)
                throw ErrorHandling.Error(ErrorCode.ERR_ValueCantBeNull, dest);
            throw CantConvert(expr, dest);
        }
        private static RuntimeBinderException CantConvert(Expr expr, CType dest)
        {
            return ErrorHandling.Error(ErrorCode.ERR_NoExplicitConv, new ErrArg(expr.Type, ErrArgFlags.Unique), new ErrArg(dest, ErrArgFlags.Unique));
        }
        public Expr mustCast(Expr expr, CType dest)
        {
            return mustCast(expr, dest, (CONVERTTYPE)0);
        }
        public Expr mustCast(Expr expr, CType dest, CONVERTTYPE flags)
        {
            return mustCastCore(expr, dest, flags);
        }
        private Expr MustCastInUncheckedContext(Expr expr, CType dest, CONVERTTYPE flags)
        {
            return new ExpressionBinder(new BindingContext(Context)).mustCast(expr, dest, flags);
        }
        private bool canCast(CType src, CType dest, CONVERTTYPE flags)
        {
            return BindExplicitConversion(null, src, dest, flags);
        }
        private bool BindImplicitConversion(Expr pSourceExpr, CType pSourceType, CType destinationType, CONVERTTYPE flags)
        {
            ImplicitConversion implicitConversion = new ImplicitConversion(this, pSourceExpr, pSourceType, destinationType, false, flags);
            return implicitConversion.Bind();
        }
        private bool BindImplicitConversion(Expr pSourceExpr, CType pSourceType, CType destinationType, out Expr ppDestinationExpr, CONVERTTYPE flags)
        {
            ImplicitConversion implicitConversion = new ImplicitConversion(this, pSourceExpr, pSourceType, destinationType, true, flags);
            bool result = implicitConversion.Bind();
            ppDestinationExpr = implicitConversion.ExprDest;
            return result;
        }
        private bool BindImplicitConversion(Expr pSourceExpr, CType pSourceType, CType destinationType, bool needsExprDest, out Expr ppDestinationExpr, CONVERTTYPE flags)
        {
            ImplicitConversion implicitConversion = new ImplicitConversion(this, pSourceExpr, pSourceType, destinationType, needsExprDest, flags);
            bool result = implicitConversion.Bind();
            ppDestinationExpr = (needsExprDest ? implicitConversion.ExprDest : null);
            return result;
        }
        private bool BindExplicitConversion(Expr pSourceExpr, CType pSourceType, CType destinationType, bool needsExprDest, out Expr ppDestinationExpr, CONVERTTYPE flags)
        {
            ExplicitConversion explicitConversion = new ExplicitConversion(this, pSourceExpr, pSourceType, destinationType, needsExprDest, flags);
            bool result = explicitConversion.Bind();
            ppDestinationExpr = (needsExprDest ? explicitConversion.ExprDest : null);
            return result;
        }
        private bool BindExplicitConversion(Expr pSourceExpr, CType pSourceType, CType destinationType, out Expr ppDestinationExpr, CONVERTTYPE flags)
        {
            ExplicitConversion explicitConversion = new ExplicitConversion(this, pSourceExpr, pSourceType, destinationType, true, flags);
            bool result = explicitConversion.Bind();
            ppDestinationExpr = explicitConversion.ExprDest;
            return result;
        }
        private bool BindExplicitConversion(Expr pSourceExpr, CType pSourceType, CType destinationType, CONVERTTYPE flags)
        {
            ExplicitConversion explicitConversion = new ExplicitConversion(this, pSourceExpr, pSourceType, destinationType, false, flags);
            return explicitConversion.Bind();
        }
        private bool bindUserDefinedConversion(Expr exprSrc, CType typeSrc, CType typeDst, bool needExprDest, out Expr pexprDst, bool fImplicitOnly)
        {
            pexprDst = null;
            if (typeSrc == null || typeDst == null || typeSrc.IsInterfaceType || typeDst.IsInterfaceType)
                return false;
            CType cType = typeSrc.StripNubs();
            CType cType2 = typeDst.StripNubs();
            bool flag = cType != typeSrc;
            bool flag2 = cType2 != typeDst;
            bool flag3 = flag2 || typeDst.IsReferenceType || typeDst is PointerType;
            AggregateType[] array = new AggregateType[2];
            int num = 0;
            bool flag4 = fImplicitOnly;
            bool flag5 = false;
            AggregateType aggregateType = cType as AggregateType;
            if (aggregateType != null && aggregateType.OwningAggregate.HasConversion()) {
                array[num++] = aggregateType;
                flag5 = (aggregateType.IsPredefType(PredefinedType.FirstNonSimpleType) || aggregateType.IsPredefType(PredefinedType.PT_UINTPTR));
            }
            AggregateType aggregateType2 = cType2 as AggregateType;
            if (aggregateType2 != null) {
                if (aggregateType2.OwningAggregate.HasConversion())
                    array[num++] = aggregateType2;
                if (flag5 && !cType2.IsPredefType(PredefinedType.PT_LONG) && !cType2.IsPredefType(PredefinedType.PT_ULONG))
                    flag5 = false;
            } else
                flag5 = false;
            if (num == 0)
                return false;
            List<UdConvInfo> list = new List<UdConvInfo>();
            CType cType3 = null;
            CType cType4 = null;
            bool flag6 = false;
            bool flag7 = false;
            int num4 = -1;
            int num5 = -1;
            CType cType5;
            CType cType6;
            for (int i = 0; i < num; i++) {
                AggregateType aggregateType3 = array[i];
                while (aggregateType3 != null && aggregateType3.OwningAggregate.HasConversion()) {
                    AggregateSymbol owningAggregate = aggregateType3.OwningAggregate;
                    PredefinedType predefType = owningAggregate.GetPredefType();
                    bool flag8 = owningAggregate.IsPredefined() && (predefType == PredefinedType.FirstNonSimpleType || predefType == PredefinedType.PT_UINTPTR || predefType == PredefinedType.PT_DECIMAL);
                    for (MethodSymbol methodSymbol = owningAggregate.GetFirstUDConversion(); methodSymbol != null; methodSymbol = methodSymbol.ConvNext()) {
                        if (methodSymbol.Params.Count == 1 && (!fImplicitOnly || methodSymbol.isImplicit())) {
                            cType5 = TypeManager.SubstType(methodSymbol.Params[0], aggregateType3);
                            cType6 = TypeManager.SubstType(methodSymbol.RetType, aggregateType3);
                            bool flag9 = fImplicitOnly;
                            if (flag4 && !flag9 && cType5.StripNubs() != cType) {
                                if (!methodSymbol.isImplicit())
                                    continue;
                                flag9 = true;
                            }
                            FUNDTYPE fundamentalType2;
                            FUNDTYPE fundamentalType;
                            if (((fundamentalType = cType6.FundamentalType) > FUNDTYPE.FT_R8 || fundamentalType <= FUNDTYPE.FT_NONE || (fundamentalType2 = cType5.FundamentalType) > FUNDTYPE.FT_R8 || fundamentalType2 <= FUNDTYPE.FT_NONE) && (!flag5 || (!cType6.IsPredefType(PredefinedType.PT_INT) && !cType6.IsPredefType(PredefinedType.PT_UINT)))) {
                                if (flag && (flag3 || !flag9) && cType5.IsNonNullableValueType)
                                    cType5 = TypeManager.GetNullable(cType5);
                                if (flag2 && cType6.IsNonNullableValueType)
                                    cType6 = TypeManager.GetNullable(cType6);
                                bool flag10 = (exprSrc != null) ? canConvert(exprSrc, cType5, CONVERTTYPE.STANDARDANDNOUDC) : canConvert(typeSrc, cType5, CONVERTTYPE.STANDARDANDNOUDC);
                                if (flag10 || (!flag9 && (canConvert(cType5, typeSrc, CONVERTTYPE.STANDARDANDNOUDC) || (flag8 && !(typeSrc is PointerType) && !(cType5 is PointerType) && canCast(typeSrc, cType5, CONVERTTYPE.NOUDC))))) {
                                    bool flag11 = canConvert(cType6, typeDst, CONVERTTYPE.STANDARDANDNOUDC);
                                    if ((flag11 || (!flag9 && (canConvert(typeDst, cType6, CONVERTTYPE.STANDARDANDNOUDC) || (flag8 && !(typeDst is PointerType) && !(cType6 is PointerType) && canCast(cType6, typeDst, CONVERTTYPE.NOUDC))))) && !IsConvInTable(list, methodSymbol, aggregateType3, flag10, flag11)) {
                                        list.Add(new UdConvInfo(new MethWithType(methodSymbol, aggregateType3), flag10, flag11));
                                        if (!flag6) {
                                            if (cType5 == typeSrc) {
                                                cType3 = cType5;
                                                num4 = list.Count - 1;
                                                flag6 = true;
                                            } else if (cType3 == null) {
                                                cType3 = cType5;
                                                num4 = list.Count - 1;
                                            } else if (cType3 != cType5) {
                                                int num6 = CompareSrcTypesBased(cType3, list[num4].SrcImplicit, cType5, flag10);
                                                if (num6 > 0) {
                                                    cType3 = cType5;
                                                    num4 = list.Count - 1;
                                                }
                                            }
                                        }
                                        if (!flag7) {
                                            if (cType6 == typeDst) {
                                                cType4 = cType6;
                                                num5 = list.Count - 1;
                                                flag7 = true;
                                            } else if (cType4 == null) {
                                                cType4 = cType6;
                                                num5 = list.Count - 1;
                                            } else if (cType4 != cType6) {
                                                int num7 = CompareDstTypesBased(cType4, list[num5].DstImplicit, cType6, flag11);
                                                if (num7 > 0) {
                                                    cType4 = cType6;
                                                    num5 = list.Count - 1;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    aggregateType3 = aggregateType3.BaseClass;
                }
            }
            if (cType3 == null)
                return false;
            int num8 = 3;
            int num9 = -1;
            int num10 = -1;
            for (int j = 0; j < list.Count; j++) {
                UdConvInfo udConvInfo = list[j];
                cType5 = TypeManager.SubstType(udConvInfo.Meth.Meth().Params[0], udConvInfo.Meth.GetType());
                cType6 = TypeManager.SubstType(udConvInfo.Meth.Meth().RetType, udConvInfo.Meth.GetType());
                int num11 = 0;
                if (flag && cType5.IsNonNullableValueType) {
                    cType5 = TypeManager.GetNullable(cType5);
                    num11++;
                }
                if (flag2 && cType6.IsNonNullableValueType) {
                    cType6 = TypeManager.GetNullable(cType6);
                    num11++;
                }
                if (cType5 == cType3 && cType6 == cType4) {
                    if (num8 > num11) {
                        num9 = j;
                        num10 = -1;
                        num8 = num11;
                    } else if (num8 >= num11 && num10 < 0) {
                        num10 = j;
                        if (num11 == 0)
                            break;
                    }
                } else {
                    if (!flag6 && cType5 != cType3) {
                        int num12 = CompareSrcTypesBased(cType3, list[num4].SrcImplicit, cType5, udConvInfo.SrcImplicit);
                        if (num12 >= 0) {
                            if (needExprDest)
                                throw HandleAmbiguity(typeSrc, typeDst, list, num4, j);
                            return true;
                        }
                    }
                    if (!flag7 && cType6 != cType4) {
                        int num13 = CompareDstTypesBased(cType4, list[num5].DstImplicit, cType6, udConvInfo.DstImplicit);
                        if (num13 >= 0) {
                            if (needExprDest)
                                throw HandleAmbiguity(typeSrc, typeDst, list, num4, j);
                            return true;
                        }
                    }
                }
            }
            if (!needExprDest)
                return true;
            if (num9 < 0)
                throw HandleAmbiguity(typeSrc, typeDst, list, num4, num5);
            if (num10 >= 0)
                throw HandleAmbiguity(typeSrc, typeDst, list, num9, num10);
            MethWithInst methWithInst = new MethWithInst(list[num9].Meth.Meth(), list[num9].Meth.GetType(), null);
            cType5 = TypeManager.SubstType(methWithInst.Meth().Params[0], methWithInst.GetType());
            cType6 = TypeManager.SubstType(methWithInst.Meth().RetType, methWithInst.GetType());
            Expr ppTransformedArgument = exprSrc;
            Expr call;
            if ((num8 > 0 && !(cType5 is NullableType)) & flag3) {
                ExprMemberGroup memberGroup = ExprFactory.CreateMemGroup(null, methWithInst);
                ExprCall exprCall = ExprFactory.CreateCall((EXPRFLAG)0, typeDst, exprSrc, memberGroup, methWithInst);
                call = exprCall;
                Expr expr = mustCast(exprSrc, cType5);
                MarkAsIntermediateConversion(expr);
                Expr expr2 = BindUDConversionCore(expr, cType5, cType6, typeDst, methWithInst);
                exprCall.CastOfNonLiftedResultToLiftedType = mustCast(expr2, typeDst);
                exprCall.NullableCallLiftKind = NullableCallLiftKind.UserDefinedConversion;
                if (flag) {
                    Expr expr3;
                    if (cType5 == cType)
                        expr3 = ((!(cType6 is NullableType)) ? exprSrc : mustCast(exprSrc, cType5));
                    else {
                        NullableType nullable = TypeManager.GetNullable(cType5);
                        expr3 = mustCast(exprSrc, nullable);
                        MarkAsIntermediateConversion(expr3);
                    }
                    ExprCall exprCall2 = ExprFactory.CreateCall((EXPRFLAG)0, typeDst, expr3, memberGroup, methWithInst);
                    exprCall2.NullableCallLiftKind = NullableCallLiftKind.NotLiftedIntermediateConversion;
                    exprCall.PConversions = exprCall2;
                } else {
                    Expr expr4 = BindUDConversionCore(expr, cType5, cType6, typeDst, methWithInst);
                    MarkAsIntermediateConversion(expr4);
                    exprCall.PConversions = expr4;
                }
            } else
                call = BindUDConversionCore(exprSrc, cType5, cType6, typeDst, methWithInst, out ppTransformedArgument);
            pexprDst = ExprFactory.CreateUserDefinedConversion(ppTransformedArgument, call, methWithInst);
            return true;
        }
        private static RuntimeBinderException HandleAmbiguity(CType typeSrc, CType typeDst, List<UdConvInfo> prguci, int iuciBestSrc, int iuciBestDst)
        {
            return ErrorHandling.Error(ErrorCode.ERR_AmbigUDConv, prguci[iuciBestSrc].Meth, prguci[iuciBestDst].Meth, typeSrc, typeDst);
        }
        private static void MarkAsIntermediateConversion(Expr pExpr)
        {
            while (true) {
                ExprCall exprCall = pExpr as ExprCall;
                if (exprCall != null) {
                    switch (exprCall.NullableCallLiftKind) {
                    default:
                        return;
                    case NullableCallLiftKind.NotLifted:
                        exprCall.NullableCallLiftKind = NullableCallLiftKind.NotLiftedIntermediateConversion;
                        return;
                    case NullableCallLiftKind.NullableConversion:
                        exprCall.NullableCallLiftKind = NullableCallLiftKind.NullableIntermediateConversion;
                        return;
                    case NullableCallLiftKind.NullableConversionConstructor:
                        break;
                    }
                    pExpr = exprCall.OptionalArguments;
                } else {
                    ExprUserDefinedConversion exprUserDefinedConversion = pExpr as ExprUserDefinedConversion;
                    if (exprUserDefinedConversion == null)
                        break;
                    pExpr = exprUserDefinedConversion.UserDefinedCall;
                }
            }
        }
        private Expr BindUDConversionCore(Expr pFrom, CType pTypeFrom, CType pTypeTo, CType pTypeDestination, MethWithInst mwiBest)
        {
            Expr ppTransformedArgument;
            return BindUDConversionCore(pFrom, pTypeFrom, pTypeTo, pTypeDestination, mwiBest, out ppTransformedArgument);
        }
        private Expr BindUDConversionCore(Expr pFrom, CType pTypeFrom, CType pTypeTo, CType pTypeDestination, MethWithInst mwiBest, out Expr ppTransformedArgument)
        {
            Expr expr = mustCastCore(pFrom, pTypeFrom, CONVERTTYPE.NOUDC);
            ExprMemberGroup memberGroup = ExprFactory.CreateMemGroup(null, mwiBest);
            ExprCall expr2 = ExprFactory.CreateCall((EXPRFLAG)0, pTypeTo, expr, memberGroup, mwiBest);
            Expr result = mustCastCore(expr2, pTypeDestination, CONVERTTYPE.NOUDC);
            ppTransformedArgument = expr;
            return result;
        }
        private ConstCastResult bindConstantCast(Expr exprSrc, CType typeDest, bool needExprDest, out Expr pexprDest, bool explicitConversion)
        {
            pexprDest = null;
            long num = 0;
            double num2 = 0;
            FUNDTYPE fundamentalType = exprSrc.Type.FundamentalType;
            FUNDTYPE fundamentalType2 = typeDest.FundamentalType;
            bool flag = fundamentalType <= FUNDTYPE.FT_U8;
            bool flag2 = fundamentalType <= FUNDTYPE.FT_R8;
            ExprConstant exprConstant = (ExprConstant)exprSrc.GetConst();
            if (fundamentalType == FUNDTYPE.FT_STRUCT || fundamentalType2 == FUNDTYPE.FT_STRUCT) {
                Expr expr = BindDecimalConstCast(typeDest, exprSrc.Type, exprConstant);
                if (expr == null) {
                    if (explicitConversion)
                        return ConstCastResult.CheckFailure;
                    return ConstCastResult.Failure;
                }
                if (needExprDest)
                    pexprDest = expr;
                return ConstCastResult.Success;
            }
            if (explicitConversion && Context.Checked && !isConstantInRange(exprConstant, typeDest, true))
                return ConstCastResult.CheckFailure;
            if (!needExprDest)
                return ConstCastResult.Success;
            if (flag) {
                if (exprConstant.Type.FundamentalType == FUNDTYPE.FT_U8) {
                    if (fundamentalType2 == FUNDTYPE.FT_U8) {
                        ConstVal constVal = ConstVal.Get(exprConstant.UInt64Value);
                        pexprDest = ExprFactory.CreateConstant(typeDest, constVal);
                        return ConstCastResult.Success;
                    }
                    num = ((long)exprConstant.UInt64Value & -1);
                } else
                    num = exprConstant.Int64Value;
            } else {
                if (!flag2)
                    return ConstCastResult.Failure;
                num2 = exprConstant.Val.DoubleVal;
            }
            switch (fundamentalType2) {
            case FUNDTYPE.FT_I1:
                if (!flag)
                    num = (long)num2;
                num = (sbyte)(num & 255);
                break;
            case FUNDTYPE.FT_I2:
                if (!flag)
                    num = (long)num2;
                num = (short)(num & 65535);
                break;
            case FUNDTYPE.FT_I4:
                if (!flag)
                    num = (long)num2;
                num = (int)(num & uint.MaxValue);
                break;
            case FUNDTYPE.FT_I8:
                if (!flag)
                    num = (long)num2;
                break;
            case FUNDTYPE.FT_U1:
                if (!flag)
                    num = (long)num2;
                num = (byte)(num & 255);
                break;
            case FUNDTYPE.FT_U2:
                if (!flag)
                    num = (long)num2;
                num = (ushort)(num & 65535);
                break;
            case FUNDTYPE.FT_U4:
                if (!flag)
                    num = (long)num2;
                num = (uint)(num & uint.MaxValue);
                break;
            case FUNDTYPE.FT_U8:
                if (!flag) {
                    num = (long)(ulong)num2;
                    num = ((!(num2 < 9.223372036854776E+18)) ? ((long)(num2 - 9.223372036854776E+18) + I64(9223372036854775808)) : ((long)num2));
                }
                break;
            case FUNDTYPE.FT_R4:
            case FUNDTYPE.FT_R8:
                if (flag)
                    num2 = ((fundamentalType != FUNDTYPE.FT_U8) ? ((double)num) : ((double)(ulong)num));
                if (fundamentalType2 == FUNDTYPE.FT_R4) {
                    RoundToFloat(num2, out float f);
                    num2 = (double)f;
                }
                break;
            }
            ConstVal constVal2 = (fundamentalType2 == FUNDTYPE.FT_U4) ? ConstVal.Get((uint)num) : ((fundamentalType2 <= FUNDTYPE.FT_U4) ? ConstVal.Get((int)num) : ((fundamentalType2 > FUNDTYPE.FT_U8) ? ConstVal.Get(num2) : ConstVal.Get(num)));
            ExprConstant exprConstant2 = (ExprConstant)(pexprDest = ExprFactory.CreateConstant(typeDest, constVal2));
            return ConstCastResult.Success;
        }
        private int CompareSrcTypesBased(CType type1, bool fImplicit1, CType type2, bool fImplicit2)
        {
            if (fImplicit1 != fImplicit2) {
                if (!fImplicit1)
                    return 1;
                return -1;
            }
            bool flag = canConvert(type1, type2, CONVERTTYPE.NOUDC);
            bool flag2 = canConvert(type2, type1, CONVERTTYPE.NOUDC);
            if (flag == flag2)
                return 0;
            if (fImplicit1 != flag)
                return 1;
            return -1;
        }
        private int CompareDstTypesBased(CType type1, bool fImplicit1, CType type2, bool fImplicit2)
        {
            if (fImplicit1 != fImplicit2) {
                if (!fImplicit1)
                    return 1;
                return -1;
            }
            bool flag = canConvert(type1, type2, CONVERTTYPE.NOUDC);
            bool flag2 = canConvert(type2, type1, CONVERTTYPE.NOUDC);
            if (flag == flag2)
                return 0;
            if (fImplicit1 != flag)
                return -1;
            return 1;
        }
        private static Expr BindDecimalConstCast(CType destType, CType srcType, ExprConstant src)
        {
            CType predefindType = SymbolLoader.GetPredefindType(PredefinedType.PT_DECIMAL);
            if (predefindType == null)
                return null;
            ConstVal val;
            if (destType == predefindType) {
                decimal value;
                switch (srcType.FundamentalType) {
                case FUNDTYPE.FT_I1:
                case FUNDTYPE.FT_I2:
                case FUNDTYPE.FT_I4:
                    val = src.Val;
                    value = Convert.ToDecimal(val.Int32Val);
                    break;
                case FUNDTYPE.FT_U1:
                case FUNDTYPE.FT_U2:
                case FUNDTYPE.FT_U4:
                    val = src.Val;
                    value = Convert.ToDecimal(val.UInt32Val);
                    break;
                case FUNDTYPE.FT_R4:
                    val = src.Val;
                    value = Convert.ToDecimal((float)val.DoubleVal);
                    break;
                case FUNDTYPE.FT_R8:
                    val = src.Val;
                    value = Convert.ToDecimal(val.DoubleVal);
                    break;
                case FUNDTYPE.FT_U8:
                    val = src.Val;
                    value = Convert.ToDecimal((ulong)val.Int64Val);
                    break;
                case FUNDTYPE.FT_I8:
                    val = src.Val;
                    value = Convert.ToDecimal(val.Int64Val);
                    break;
                default:
                    return null;
                }
                ConstVal constVal = ConstVal.Get(value);
                return ExprFactory.CreateConstant(predefindType, constVal);
            }
            if (srcType == predefindType) {
                decimal value2 = default(decimal);
                FUNDTYPE fundamentalType = destType.FundamentalType;
                ConstVal constVal;
                try {
                    if (fundamentalType != FUNDTYPE.FT_R4 && fundamentalType != FUNDTYPE.FT_R8) {
                        val = src.Val;
                        value2 = decimal.Truncate(val.DecimalVal);
                    }
                    switch (fundamentalType) {
                    case FUNDTYPE.FT_I1:
                        constVal = ConstVal.Get(Convert.ToSByte(value2));
                        break;
                    case FUNDTYPE.FT_U1:
                        constVal = ConstVal.Get((uint)Convert.ToByte(value2));
                        break;
                    case FUNDTYPE.FT_I2:
                        constVal = ConstVal.Get(Convert.ToInt16(value2));
                        break;
                    case FUNDTYPE.FT_U2:
                        constVal = ConstVal.Get((uint)Convert.ToUInt16(value2));
                        break;
                    case FUNDTYPE.FT_I4:
                        constVal = ConstVal.Get(Convert.ToInt32(value2));
                        break;
                    case FUNDTYPE.FT_U4:
                        constVal = ConstVal.Get(Convert.ToUInt32(value2));
                        break;
                    case FUNDTYPE.FT_I8:
                        constVal = ConstVal.Get(Convert.ToInt64(value2));
                        break;
                    case FUNDTYPE.FT_U8:
                        constVal = ConstVal.Get(Convert.ToUInt64(value2));
                        break;
                    case FUNDTYPE.FT_R4:
                        val = src.Val;
                        constVal = ConstVal.Get(Convert.ToSingle(val.DecimalVal));
                        break;
                    case FUNDTYPE.FT_R8:
                        val = src.Val;
                        constVal = ConstVal.Get(Convert.ToDouble(val.DecimalVal));
                        break;
                    default:
                        return null;
                    }
                } catch (OverflowException) {
                    return null;
                }
                return ExprFactory.CreateConstant(destType, constVal);
            }
            return null;
        }
        private bool CanExplicitConversionBeBoundInUncheckedContext(Expr exprSrc, CType typeSrc, CType typeDest, CONVERTTYPE flags)
        {
            return new ExpressionBinder(new BindingContext(Context)).BindExplicitConversion(exprSrc, typeSrc, typeDest, flags);
        }
        public ExpressionBinder(BindingContext context)
        {
            Context = context;
        }
        private static AggregateType GetPredefindType(PredefinedType pt)
        {
            return SymbolLoader.GetPredefindType(pt);
        }
        private Expr GenerateAssignmentConversion(Expr op1, Expr op2, bool allowExplicit)
        {
            if (!allowExplicit)
                return mustConvertCore(op2, op1.Type);
            return mustCastCore(op2, op1.Type, (CONVERTTYPE)0);
        }
        public Expr BindAssignment(Expr op1, Expr op2, bool allowExplicit)
        {
            CheckLvalue(op1, CheckLvalueKind.Assignment);
            op2 = GenerateAssignmentConversion(op1, op2, allowExplicit);
            return GenerateOptimizedAssignment(op1, op2);
        }
        internal Expr BindArrayIndexCore(Expr pOp1, Expr pOp2)
        {
            CType pIntType = GetPredefindType(PredefinedType.PT_INT);
            ArrayType arrayType = pOp1.Type as ArrayType;
            CType elementType = arrayType.ElementType;
            CheckUnsafe(elementType);
            CType pDestType = ChooseArrayIndexType(pOp2);
            ExpressionBinder binder = this;
            Expr index = pOp2.Map(delegate(Expr x) {
                Expr expr = binder.mustConvert(x, pDestType);
                if (pDestType != pIntType)
                    return ExprFactory.CreateCast(EXPRFLAG.EXF_LITERALCONST, pDestType, expr);
                return expr;
            });
            return ExprFactory.CreateArrayIndex(elementType, pOp1, index);
        }
        private void bindSimpleCast(Expr exprSrc, CType typeDest, out Expr pexprDest)
        {
            bindSimpleCast(exprSrc, typeDest, out pexprDest, (EXPRFLAG)0);
        }
        private void bindSimpleCast(Expr exprSrc, CType typeDest, out Expr pexprDest, EXPRFLAG exprFlags)
        {
            Expr const = exprSrc.GetConst();
            ExprCast exprCast = ExprFactory.CreateCast(exprFlags, typeDest, exprSrc);
            if (Context.Checked)
                exprCast.Flags |= EXPRFLAG.EXF_CHECKOVERFLOW;
            ExprConstant exprConstant = const as ExprConstant;
            if (exprConstant != null && exprFlags == (EXPRFLAG)0 && exprSrc.Type.FundamentalType == typeDest.FundamentalType && (!exprSrc.Type.IsPredefType(PredefinedType.PT_STRING) || exprConstant.Val.IsNullRef)) {
                ExprConstant exprConstant2 = (ExprConstant)(pexprDest = ExprFactory.CreateConstant(typeDest, exprConstant.Val));
            } else
                pexprDest = exprCast;
        }
        private ExprCall BindToMethod(MethWithInst mwi, Expr pArguments, ExprMemberGroup pMemGroup, MemLookFlags flags)
        {
            Expr optionalObject = pMemGroup.OptionalObject;
            CType callingObjectType = optionalObject?.Type;
            PostBindMethod(mwi);
            optionalObject = (pMemGroup.OptionalObject = AdjustMemberObject(mwi, optionalObject));
            CType type = ((flags & (MemLookFlags.Ctor | MemLookFlags.NewObj)) != (MemLookFlags.Ctor | MemLookFlags.NewObj)) ? TypeManager.SubstType(mwi.Meth().RetType, mwi.GetType(), mwi.TypeArgs) : mwi.Ats;
            ExprCall exprCall = ExprFactory.CreateCall((EXPRFLAG)0, type, pArguments, pMemGroup, mwi);
            if ((flags & MemLookFlags.Ctor) != 0 && (flags & MemLookFlags.NewObj) != 0)
                exprCall.Flags |= (EXPRFLAG.EXF_LITERALCONST | EXPRFLAG.EXF_CANTBENULL);
            verifyMethodArgs(exprCall, callingObjectType);
            return exprCall;
        }
        internal Expr BindToField(Expr pOptionalObject, FieldWithType fwt, BindingFlag bindFlags)
        {
            CType cType = TypeManager.SubstType(fwt.Field().GetType(), fwt.GetType());
            pOptionalObject = AdjustMemberObject(fwt, pOptionalObject);
            CheckUnsafe(cType);
            AggregateType aggregateType = null;
            if (fwt.Field().isEvent && fwt.Field().getEvent() != null && fwt.Field().getEvent().IsWindowsRuntimeEvent) {
                aggregateType = (fwt.Field().GetType() as AggregateType);
                if (aggregateType != null)
                    cType = TypeManager.GetParameterModifier(cType, false);
            }
            ExprField exprField = ExprFactory.CreateField(cType, pOptionalObject, fwt);
            exprField.Flags |= (EXPRFLAG)(bindFlags & BindingFlag.BIND_MEMBERSET);
            if (aggregateType != null) {
                Name predefinedName = NameManager.GetPredefinedName(PredefinedName.PN_GETORCREATEEVENTREGISTRATIONTOKENTABLE);
                SymbolTable.PopulateSymbolTableWithName(predefinedName.Text, null, aggregateType.AssociatedSystemType);
                MethodSymbol mps = SymbolLoader.LookupAggMember(predefinedName, aggregateType.OwningAggregate, symbmask_t.MASK_MethodSymbol) as MethodSymbol;
                MethPropWithInst methPropWithInst = new MethPropWithInst(mps, aggregateType);
                ExprMemberGroup pMemGroup = ExprFactory.CreateMemGroup(null, methPropWithInst);
                Expr expr = BindToMethod(new MethWithInst(methPropWithInst), exprField, pMemGroup, MemLookFlags.None);
                AggregateSymbol owningAggregate = aggregateType.OwningAggregate;
                Name predefinedName2 = NameManager.GetPredefinedName(PredefinedName.PN_INVOCATIONLIST);
                SymbolTable.PopulateSymbolTableWithName(predefinedName2.Text, null, aggregateType.AssociatedSystemType);
                PropertySymbol propertySymbol = SymbolLoader.LookupAggMember(predefinedName2, owningAggregate, symbmask_t.MASK_PropertySymbol) as PropertySymbol;
                MethPropWithInst method = new MethPropWithInst(propertySymbol, aggregateType);
                ExprMemberGroup pMemGroup2 = ExprFactory.CreateMemGroup(expr, method);
                PropWithType pwt = new PropWithType(propertySymbol, aggregateType);
                return BindToProperty(expr, pwt, bindFlags, null, pMemGroup2);
            }
            return exprField;
        }
        internal ExprProperty BindToProperty(Expr pObject, PropWithType pwt, BindingFlag bindFlags, Expr args, ExprMemberGroup pMemGroup)
        {
            Expr expr = pObject;
            PostBindProperty(pwt, out MethWithType pmwtGet, out MethWithType pmwtSet);
            pObject = (((bool)pmwtGet && (!(bool)pmwtSet || pmwtSet.GetType() == pmwtGet.GetType() || SymbolLoader.HasBaseConversion(pmwtGet.GetType(), pmwtSet.GetType()))) ? AdjustMemberObject(pmwtGet, pObject) : ((!(bool)pmwtSet) ? AdjustMemberObject(pwt, pObject) : AdjustMemberObject(pmwtSet, pObject)));
            pMemGroup.OptionalObject = pObject;
            CType type = TypeManager.SubstType(pwt.Prop().RetType, pwt.GetType());
            if ((bindFlags & BindingFlag.BIND_RVALUEREQUIRED) != 0) {
                if (!(bool)pmwtGet)
                    throw ErrorHandling.Error(ErrorCode.ERR_PropertyLacksGet, pwt);
                CType cType = null;
                if (expr != null)
                    cType = expr.Type;
                switch (CSemanticChecker.CheckAccess2(pmwtGet.Meth(), pmwtGet.GetType(), ContextForMemberLookup, cType)) {
                case ACCESSERROR.ACCESSERROR_NOACCESSTHRU:
                    throw ErrorHandling.Error(ErrorCode.ERR_BadProtectedAccess, pwt, cType, ContextForMemberLookup);
                default:
                    throw ErrorHandling.Error(ErrorCode.ERR_InaccessibleGetter, pwt);
                case ACCESSERROR.ACCESSERROR_NOERROR:
                    break;
                }
            }
            ExprProperty exprProperty = ExprFactory.CreateProperty(type, expr, args, pMemGroup, pwt, pmwtSet);
            if (exprProperty.OptionalArguments != null)
                verifyMethodArgs(exprProperty, expr?.Type);
            return exprProperty;
        }
        internal Expr bindUDUnop(ExpressionKind ek, Expr arg)
        {
            Name name = ExpressionKindName(ek);
            CType cType = arg.Type;
            while (true) {
                switch (cType.TypeKind) {
                case TypeKind.TK_NullableType:
                    break;
                case TypeKind.TK_AggregateType: {
                    if ((!cType.IsClassType && !cType.IsStructType) || ((AggregateType)cType).OwningAggregate.IsSkipUDOps())
                        return null;
                    ArgInfos argInfos = new ArgInfos();
                    argInfos.carg = 1;
                    FillInArgInfoFromArgList(argInfos, arg);
                    List<CandidateFunctionMember> list = new List<CandidateFunctionMember>();
                    MethodSymbol methodSymbol = null;
                    AggregateType aggregateType = (AggregateType)cType;
                    while (true) {
                        methodSymbol = (((methodSymbol == null) ? SymbolLoader.LookupAggMember(name, aggregateType.OwningAggregate, symbmask_t.MASK_MethodSymbol) : methodSymbol.LookupNext(symbmask_t.MASK_MethodSymbol)) as MethodSymbol);
                        if (methodSymbol == null) {
                            if (!list.IsEmpty())
                                break;
                            aggregateType = aggregateType.BaseClass;
                            if (aggregateType == null)
                                break;
                        } else if (methodSymbol.isOperator && methodSymbol.Params.Count == 1) {
                            TypeArray typeArray = TypeManager.SubstTypeArray(methodSymbol.Params, aggregateType);
                            CType cType2 = typeArray[0];
                            NullableType nullable;
                            if (canConvert(arg, cType2))
                                list.Add(new CandidateFunctionMember(new MethPropWithInst(methodSymbol, aggregateType, TypeArray.Empty), typeArray, 0, false));
                            else if (cType2.IsNonNullableValueType && TypeManager.SubstType(methodSymbol.RetType, aggregateType).IsNonNullableValueType && canConvert(arg, nullable = TypeManager.GetNullable(cType2))) {
                                list.Add(new CandidateFunctionMember(new MethPropWithInst(methodSymbol, aggregateType, TypeArray.Empty), TypeArray.Allocate(nullable), 1, false));
                            }
                        }
                    }
                    if (list.IsEmpty())
                        return null;
                    CandidateFunctionMember methAmbig;
                    CandidateFunctionMember methAmbig2;
                    CandidateFunctionMember candidateFunctionMember = FindBestMethod(list, null, argInfos, out methAmbig, out methAmbig2);
                    if (candidateFunctionMember == null)
                        throw ErrorHandling.Error(ErrorCode.ERR_AmbigCall, methAmbig.mpwi, methAmbig2.mpwi);
                    ExprCall exprCall = (candidateFunctionMember.ctypeLift == 0) ? BindUDUnopCall(arg, candidateFunctionMember.params[0], candidateFunctionMember.mpwi) : BindLiftedUDUnop(arg, candidateFunctionMember.params[0], candidateFunctionMember.mpwi);
                    return ExprFactory.CreateUserDefinedUnaryOperator(ek, exprCall.Type, arg, exprCall, candidateFunctionMember.mpwi);
                }
                default:
                    return null;
                }
                cType = cType.StripNubs();
            }
        }
        private ExprCall BindLiftedUDUnop(Expr arg, CType typeArg, MethPropWithInst mpwi)
        {
            CType cType = typeArg.StripNubs();
            if (!(arg.Type is NullableType) || !canConvert(arg.Type.StripNubs(), cType, CONVERTTYPE.NOUDC))
                arg = mustConvert(arg, typeArg);
            CType cType2 = TypeManager.SubstType(mpwi.Meth().RetType, mpwi.GetType());
            if (!(cType2 is NullableType))
                cType2 = TypeManager.GetNullable(cType2);
            Expr arg2 = mustCast(arg, cType);
            ExprCall expr = BindUDUnopCall(arg2, cType, mpwi);
            ExprMemberGroup memberGroup = ExprFactory.CreateMemGroup(null, mpwi);
            ExprCall exprCall = ExprFactory.CreateCall((EXPRFLAG)0, cType2, arg, memberGroup, null);
            exprCall.MethWithInst = new MethWithInst(mpwi);
            exprCall.CastOfNonLiftedResultToLiftedType = mustCast(expr, cType2, (CONVERTTYPE)0);
            exprCall.NullableCallLiftKind = NullableCallLiftKind.Operator;
            return exprCall;
        }
        private ExprCall BindUDUnopCall(Expr arg, CType typeArg, MethPropWithInst mpwi)
        {
            CType type = TypeManager.SubstType(mpwi.Meth().RetType, mpwi.GetType());
            CheckUnsafe(type);
            ExprMemberGroup memberGroup = ExprFactory.CreateMemGroup(null, mpwi);
            ExprCall exprCall = ExprFactory.CreateCall((EXPRFLAG)0, type, mustConvert(arg, typeArg), memberGroup, null);
            exprCall.MethWithInst = new MethWithInst(mpwi);
            verifyMethodArgs(exprCall, mpwi.GetType());
            return exprCall;
        }
        private GroupToArgsBinderResult BindMethodGroupToArgumentsCore(BindingFlag bindFlags, ExprMemberGroup grp, Expr args, int carg, NamedArgumentsKind namedArgumentsKind)
        {
            ArgInfos argInfos = new ArgInfos {
                carg = carg
            };
            FillInArgInfoFromArgList(argInfos, args);
            ArgInfos argInfos2 = new ArgInfos {
                carg = carg
            };
            FillInArgInfoFromArgList(argInfos2, args);
            GroupToArgsBinder groupToArgsBinder = new GroupToArgsBinder(this, bindFlags, grp, argInfos, argInfos2, namedArgumentsKind);
            groupToArgsBinder.Bind();
            return groupToArgsBinder.GetResultsOfBind();
        }
        internal ExprWithArgs BindMethodGroupToArguments(BindingFlag bindFlags, ExprMemberGroup grp, Expr args)
        {
            int carg = CountArguments(args);
            NamedArgumentsKind namedArgumentsKind = FindNamedArgumentsType(args);
            MethPropWithInst bestResult = BindMethodGroupToArgumentsCore(bindFlags, grp, args, carg, namedArgumentsKind).BestResult;
            if (grp.SymKind == SYMKIND.SK_PropertySymbol)
                return BindToProperty(grp.OptionalObject, new PropWithType(bestResult), bindFlags, args, grp);
            return BindToMethod(new MethWithInst(bestResult), args, grp, (MemLookFlags)grp.Flags);
        }
        private static NamedArgumentsKind FindNamedArgumentsType(Expr args)
        {
            Expr expr = args;
            while (expr != null) {
                ExprList exprList = expr as ExprList;
                Expr expr2;
                if (exprList != null) {
                    expr2 = exprList.OptionalElement;
                    expr = exprList.OptionalNextListNode;
                } else {
                    expr2 = expr;
                    expr = null;
                }
                if (expr2 is ExprNamedArgumentSpecification) {
                    while (expr != null) {
                        ExprList exprList2 = expr as ExprList;
                        if (exprList2 != null) {
                            expr2 = exprList2.OptionalElement;
                            expr = exprList2.OptionalNextListNode;
                        } else {
                            expr2 = expr;
                            expr = null;
                        }
                        if (!(expr2 is ExprNamedArgumentSpecification))
                            return NamedArgumentsKind.NonTrailing;
                    }
                    return NamedArgumentsKind.Positioning;
                }
            }
            return NamedArgumentsKind.None;
        }
        private static RuntimeBinderException BadOperatorTypesError(Expr pOperand1, Expr pOperand2)
        {
            string errorString = pOperand1.ErrorString;
            if (pOperand2 != null)
                return ErrorHandling.Error(ErrorCode.ERR_BadBinaryOps, errorString, pOperand1.Type, pOperand2.Type);
            return ErrorHandling.Error(ErrorCode.ERR_BadUnaryOp, errorString, pOperand1.Type);
        }
        private static ErrorCode GetStandardLvalueError(CheckLvalueKind kind)
        {
            if (kind != CheckLvalueKind.Increment)
                return ErrorCode.ERR_AssgLvalueExpected;
            return ErrorCode.ERR_IncrementLvalueExpected;
        }
        private void CheckLvalueProp(ExprProperty prop)
        {
            CType type = null;
            if (prop.OptionalObjectThrough != null)
                type = prop.OptionalObjectThrough.Type;
            CheckPropertyAccess(prop.MethWithTypeSet, prop.PropWithTypeSlot, type);
        }
        private void CheckPropertyAccess(MethWithType mwt, PropWithType pwtSlot, CType type)
        {
            switch (CSemanticChecker.CheckAccess2(mwt.Meth(), mwt.GetType(), ContextForMemberLookup, type)) {
            case ACCESSERROR.ACCESSERROR_NOACCESSTHRU:
                throw ErrorHandling.Error(ErrorCode.ERR_BadProtectedAccess, pwtSlot, type, ContextForMemberLookup);
            case ACCESSERROR.ACCESSERROR_NOACCESS:
                throw ErrorHandling.Error(mwt.Meth().isSetAccessor() ? ErrorCode.ERR_InaccessibleSetter : ErrorCode.ERR_InaccessibleGetter, pwtSlot);
            }
        }
        private void CheckLvalue(Expr expr, CheckLvalueKind kind)
        {
            if (!expr.isLvalue()) {
                switch (expr.Kind) {
                case ExpressionKind.Property: {
                    ExprProperty exprProperty = (ExprProperty)expr;
                    throw ErrorHandling.Error(ErrorCode.ERR_AssgReadonlyProp, exprProperty.PropWithTypeSlot);
                }
                case ExpressionKind.Field: {
                    ExprField exprField = (ExprField)expr;
                    throw ErrorHandling.Error(exprField.FieldWithType.Field().isStatic ? ErrorCode.ERR_AssgReadonlyStatic : ErrorCode.ERR_AssgReadonly, Array.Empty<ErrArg>());
                }
                default:
                    throw ErrorHandling.Error(GetStandardLvalueError(kind), Array.Empty<ErrArg>());
                }
            }
            ExprProperty exprProperty2 = expr as ExprProperty;
            if (exprProperty2 != null)
                CheckLvalueProp(exprProperty2);
        }
        private static void PostBindMethod(MethWithInst pMWI)
        {
            MethodSymbol methodSymbol = pMWI.Meth();
            if (methodSymbol.RetType != null) {
                CheckUnsafe(methodSymbol.RetType);
                CType[] items = methodSymbol.Params.Items;
                foreach (CType type in items) {
                    CheckUnsafe(type);
                }
            }
        }
        private static void PostBindProperty(PropWithType pwt, out MethWithType pmwtGet, out MethWithType pmwtSet)
        {
            PropertySymbol propertySymbol = pwt.Prop();
            pmwtGet = ((propertySymbol.GetterMethod != null) ? new MethWithType(propertySymbol.GetterMethod, pwt.GetType()) : new MethWithType());
            pmwtSet = ((propertySymbol.SetterMethod != null) ? new MethWithType(propertySymbol.SetterMethod, pwt.GetType()) : new MethWithType());
            if (propertySymbol.RetType != null)
                CheckUnsafe(propertySymbol.RetType);
        }
        private Expr AdjustMemberObject(SymWithType swt, Expr pObject)
        {
            bool flag = IsMatchingStatic(swt, pObject);
            bool isStatic = swt.Sym.isStatic;
            if (!flag) {
                if (isStatic) {
                    if ((pObject.Flags & EXPRFLAG.EXF_UNREALIZEDGOTO) != 0)
                        return null;
                    throw ErrorHandling.Error(ErrorCode.ERR_ObjectProhibited, swt);
                }
                throw ErrorHandling.Error(ErrorCode.ERR_ObjectRequired, swt);
            }
            if (isStatic)
                return null;
            if (swt.Sym is MethodSymbol && swt.Meth().IsConstructor())
                return pObject;
            if (pObject == null)
                return null;
            CType cType = pObject.Type;
            NullableType nullableType = cType as NullableType;
            CType ats;
            if (nullableType != null && (ats = nullableType.GetAts()) != swt.GetType())
                cType = ats;
            if (cType is TypeParameterType || cType is AggregateType) {
                AggregateSymbol aggregateSymbol = swt.Sym.parent as AggregateSymbol;
                pObject = tryConvert(pObject, swt.GetType(), CONVERTTYPE.NOUDC);
            }
            return pObject;
        }
        private static bool IsMatchingStatic(SymWithType swt, Expr pObject)
        {
            Symbol sym = swt.Sym;
            MethodSymbol methodSymbol = sym as MethodSymbol;
            if (methodSymbol != null && methodSymbol.IsConstructor())
                return !methodSymbol.isStatic;
            if (swt.Sym.isStatic) {
                if (pObject == null)
                    return true;
                if ((pObject.Flags & EXPRFLAG.EXF_SAMENAMETYPE) == (EXPRFLAG)0)
                    return false;
            } else if (pObject == null) {
                return false;
            }
            return true;
        }
        private void verifyMethodArgs(ExprWithArgs call, CType callingObjectType)
        {
            Expr optionalArguments = call.OptionalArguments;
            SymWithType symWithType = call.GetSymWithType();
            MethodOrPropertySymbol mp = symWithType.Sym as MethodOrPropertySymbol;
            TypeArray pTypeArgs = (call as ExprCall)?.MethWithInst.TypeArgs;
            AdjustCallArgumentsForParams(callingObjectType, symWithType.GetType(), mp, pTypeArgs, optionalArguments, out Expr newArgs);
            call.OptionalArguments = newArgs;
        }
        private void AdjustCallArgumentsForParams(CType callingObjectType, CType type, MethodOrPropertySymbol mp, TypeArray pTypeArgs, Expr argsPtr, out Expr newArgs)
        {
            newArgs = null;
            Expr last = null;
            MethodOrPropertySymbol methodOrPropertySymbol = GroupToArgsBinder.FindMostDerivedMethod(mp, callingObjectType);
            int num = mp.Params.Count;
            TypeArray params = mp.Params;
            int num2 = 0;
            MethodSymbol methodSymbol = mp as MethodSymbol;
            int num3 = ExpressionIterator.Count(argsPtr);
            bool flag = false;
            ExpressionIterator expressionIterator = new ExpressionIterator(argsPtr);
            if (argsPtr != null) {
                while (true) {
                    if (expressionIterator.AtEnd())
                        return;
                    Expr expr = expressionIterator.Current();
                    if (!(expr.Type is ParameterModifierType)) {
                        switch (num) {
                        case 1:
                            break;
                        default:
                            goto IL_00a6;
                        case 0:
                            goto IL_0206;
                        }
                        if (mp.isParamArray && num3 > mp.Params.Count)
                            break;
                        goto IL_00a6;
                    }
                    if (num != 0)
                        num--;
                    ExprFactory.AppendItemToList(expr, ref newArgs, ref last);
                    goto IL_0206;
                    IL_0206:
                    num2++;
                    if (num != 0 && mp.isParamArray && num2 == num3) {
                        expr = null;
                        expressionIterator.MoveNext();
                        break;
                    }
                    expressionIterator.MoveNext();
                    continue;
                    IL_00a6:
                    Expr expr2 = expr;
                    ExprNamedArgumentSpecification exprNamedArgumentSpecification = expr2 as ExprNamedArgumentSpecification;
                    Expr expr3;
                    if (exprNamedArgumentSpecification != null) {
                        int num4 = 0;
                        foreach (Name parameterName in methodOrPropertySymbol.ParameterNames) {
                            if (parameterName == exprNamedArgumentSpecification.Name)
                                break;
                            num4++;
                        }
                        CType dest = TypeManager.SubstType(params[num4], type, pTypeArgs);
                        if (!canConvert(exprNamedArgumentSpecification.Value, dest) && mp.isParamArray && num4 == mp.Params.Count - 1) {
                            CType type2 = (ArrayType)TypeManager.SubstType(mp.Params[mp.Params.Count - 1], type, pTypeArgs);
                            ExprArrayInit exprArrayInit = ExprFactory.CreateArrayInit(type2, null, null, new int[1]);
                            exprArrayInit.GeneratedForParamArray = true;
                            exprArrayInit.OptionalArguments = exprNamedArgumentSpecification.Value;
                            exprNamedArgumentSpecification.Value = exprArrayInit;
                            flag = true;
                        } else
                            exprNamedArgumentSpecification.Value = tryConvert(exprNamedArgumentSpecification.Value, dest);
                        expr3 = expr2;
                    } else {
                        CType dest2 = TypeManager.SubstType(params[num2], type, pTypeArgs);
                        expr3 = tryConvert(expr, dest2);
                    }
                    if (expr3 == null) {
                        if (mp.isParamArray && num == 1 && num3 >= mp.Params.Count)
                            break;
                        return;
                    }
                    expr = expr3;
                    ExprFactory.AppendItemToList(expr3, ref newArgs, ref last);
                    num--;
                    goto IL_0206;
                }
            } else if (!mp.isParamArray) {
                return;
            }
            if (!flag) {
                CType cType = TypeManager.SubstType(mp.Params[mp.Params.Count - 1], type, pTypeArgs);
                ArrayType arrayType = cType as ArrayType;
                if (arrayType != null && arrayType.IsSZArray) {
                    CType elementType = arrayType.ElementType;
                    ExprArrayInit exprArrayInit2 = ExprFactory.CreateArrayInit(cType, null, null, new int[1]);
                    exprArrayInit2.GeneratedForParamArray = true;
                    if (expressionIterator.AtEnd()) {
                        exprArrayInit2.DimensionSizes[0] = 0;
                        exprArrayInit2.OptionalArguments = null;
                        argsPtr = ((argsPtr != null) ? ((Expr)ExprFactory.CreateList(argsPtr, exprArrayInit2)) : ((Expr)exprArrayInit2));
                        ExprFactory.AppendItemToList(exprArrayInit2, ref newArgs, ref last);
                    } else {
                        Expr first = null;
                        Expr last2 = null;
                        int num5 = 0;
                        while (!expressionIterator.AtEnd()) {
                            Expr expr4 = expressionIterator.Current();
                            num5++;
                            ExprNamedArgumentSpecification exprNamedArgumentSpecification2 = expr4 as ExprNamedArgumentSpecification;
                            if (exprNamedArgumentSpecification2 != null)
                                exprNamedArgumentSpecification2.Value = tryConvert(exprNamedArgumentSpecification2.Value, elementType);
                            else
                                expr4 = tryConvert(expr4, elementType);
                            ExprFactory.AppendItemToList(expr4, ref first, ref last2);
                            expressionIterator.MoveNext();
                        }
                        exprArrayInit2.DimensionSizes[0] = num5;
                        exprArrayInit2.OptionalArguments = first;
                        ExprFactory.AppendItemToList(exprArrayInit2, ref newArgs, ref last);
                    }
                }
            }
        }
        internal CType ChooseArrayIndexType(Expr args)
        {
            PredefinedType[] array = s_rgptIntOp;
            foreach (PredefinedType pt in array) {
                CType predefindType = GetPredefindType(pt);
                using (IEnumerator<Expr> enumerator = args.ToEnumerable().GetEnumerator()) {
                    Expr current;
                    do {
                        if (!enumerator.MoveNext())
                            return predefindType;
                        current = enumerator.Current;
                    } while (canConvert(current, predefindType));
                }
            }
            return GetPredefindType(PredefinedType.PT_INT);
        }
        internal static void FillInArgInfoFromArgList(ArgInfos argInfo, Expr args)
        {
            CType[] array = new CType[argInfo.carg];
            argInfo.prgexpr = new List<Expr>();
            int num = 0;
            Expr expr = args;
            while (expr != null) {
                ExprList exprList = expr as ExprList;
                Expr expr2;
                if (exprList != null) {
                    expr2 = exprList.OptionalElement;
                    expr = exprList.OptionalNextListNode;
                } else {
                    expr2 = expr;
                    expr = null;
                }
                array[num] = expr2.Type;
                argInfo.prgexpr.Add(expr2);
                num++;
            }
            argInfo.types = TypeArray.Allocate(array);
        }
        private static bool TryGetExpandedParams(TypeArray params, int count, out TypeArray ppExpandedParams)
        {
            CType[] array;
            if (count < params.Count - 1) {
                array = new CType[params.Count - 1];
                params.CopyItems(0, params.Count - 1, array);
                ppExpandedParams = TypeArray.Allocate(array);
                return true;
            }
            array = new CType[count];
            params.CopyItems(0, params.Count - 1, array);
            CType cType = params[params.Count - 1];
            ArrayType arrayType = cType as ArrayType;
            if (arrayType == null) {
                ppExpandedParams = null;
                return false;
            }
            CType elementType = arrayType.ElementType;
            for (int i = params.Count - 1; i < count; i++) {
                array[i] = elementType;
            }
            ppExpandedParams = TypeArray.Allocate(array);
            return true;
        }
        public static bool IsMethPropCallable(MethodOrPropertySymbol sym, bool requireUC)
        {
            if (!sym.isOverride || sym.isHideByName) {
                if (requireUC)
                    return sym.isUserCallable();
                return true;
            }
            return false;
        }
        private static bool IsConvInTable(List<UdConvInfo> convTable, MethodSymbol meth, AggregateType ats, bool fSrc, bool fDst)
        {
            foreach (UdConvInfo item in convTable) {
                if (item.Meth.Meth() == meth && item.Meth.GetType() == ats && item.SrcImplicit == fSrc && item.DstImplicit == fDst)
                    return true;
            }
            return false;
        }
        private static bool isConstantInRange(ExprConstant exprSrc, CType typeDest)
        {
            return isConstantInRange(exprSrc, typeDest, false);
        }
        private static bool isConstantInRange(ExprConstant exprSrc, CType typeDest, bool realsOk)
        {
            FUNDTYPE fundamentalType = exprSrc.Type.FundamentalType;
            FUNDTYPE fundamentalType2 = typeDest.FundamentalType;
            if (fundamentalType > FUNDTYPE.FT_U8 || fundamentalType2 > FUNDTYPE.FT_U8) {
                if (!realsOk)
                    return false;
                if (fundamentalType > FUNDTYPE.FT_R8 || fundamentalType2 > FUNDTYPE.FT_R8)
                    return false;
            }
            if (fundamentalType2 > FUNDTYPE.FT_U8)
                return true;
            if (fundamentalType > FUNDTYPE.FT_U8) {
                double doubleVal = exprSrc.Val.DoubleVal;
                switch (fundamentalType2) {
                case FUNDTYPE.FT_I1:
                    if (doubleVal > -129 && doubleVal < 128)
                        return true;
                    break;
                case FUNDTYPE.FT_I2:
                    if (doubleVal > -32769 && doubleVal < 32768)
                        return true;
                    break;
                case FUNDTYPE.FT_I4:
                    if (doubleVal > (double)I64(-2147483649) && doubleVal < (double)I64(2147483648))
                        return true;
                    break;
                case FUNDTYPE.FT_I8:
                    if (doubleVal >= -9.223372036854776E+18 && doubleVal < 9.223372036854776E+18)
                        return true;
                    break;
                case FUNDTYPE.FT_U1:
                    if (doubleVal > -1 && doubleVal < 256)
                        return true;
                    break;
                case FUNDTYPE.FT_U2:
                    if (doubleVal > -1 && doubleVal < 65536)
                        return true;
                    break;
                case FUNDTYPE.FT_U4:
                    if (doubleVal > -1 && doubleVal < (double)I64(4294967296))
                        return true;
                    break;
                case FUNDTYPE.FT_U8:
                    if (doubleVal > -1 && doubleVal < 1.8446744073709552E+19)
                        return true;
                    break;
                }
                return false;
            }
            if (fundamentalType == FUNDTYPE.FT_U8) {
                ulong uInt64Value = exprSrc.UInt64Value;
                switch (fundamentalType2) {
                case FUNDTYPE.FT_I1:
                    if (uInt64Value <= 127)
                        return true;
                    break;
                case FUNDTYPE.FT_I2:
                    if (uInt64Value <= 32767)
                        return true;
                    break;
                case FUNDTYPE.FT_I4:
                    if (uInt64Value <= 2147483647)
                        return true;
                    break;
                case FUNDTYPE.FT_I8:
                    if (uInt64Value <= 9223372036854775807)
                        return true;
                    break;
                case FUNDTYPE.FT_U1:
                    if (uInt64Value <= 255)
                        return true;
                    break;
                case FUNDTYPE.FT_U2:
                    if (uInt64Value <= 65535)
                        return true;
                    break;
                case FUNDTYPE.FT_U4:
                    if (uInt64Value <= uint.MaxValue)
                        return true;
                    break;
                case FUNDTYPE.FT_U8:
                    return true;
                }
            } else {
                long int64Value = exprSrc.Int64Value;
                switch (fundamentalType2) {
                case FUNDTYPE.FT_I1:
                    if (int64Value >= -128 && int64Value <= 127)
                        return true;
                    break;
                case FUNDTYPE.FT_I2:
                    if (int64Value >= -32768 && int64Value <= 32767)
                        return true;
                    break;
                case FUNDTYPE.FT_I4:
                    if (int64Value >= I64(-2147483648) && int64Value <= I64(2147483647))
                        return true;
                    break;
                case FUNDTYPE.FT_I8:
                    return true;
                case FUNDTYPE.FT_U1:
                    if (int64Value >= 0 && int64Value <= 255)
                        return true;
                    break;
                case FUNDTYPE.FT_U2:
                    if (int64Value >= 0 && int64Value <= 65535)
                        return true;
                    break;
                case FUNDTYPE.FT_U4:
                    if (int64Value >= 0 && int64Value <= I64(4294967295))
                        return true;
                    break;
                case FUNDTYPE.FT_U8:
                    if (int64Value >= 0)
                        return true;
                    break;
                }
            }
            return false;
        }
        private static Name ExpressionKindName(ExpressionKind ek)
        {
            return NameManager.GetPredefinedName(s_EK2NAME[(int)(ek - 29)]);
        }
        private static void CheckUnsafe(CType type)
        {
            if (type == null || type.IsUnsafe())
                throw ErrorHandling.Error(ErrorCode.ERR_UnsafeNeeded, Array.Empty<ErrArg>());
        }
        private static ExprWrap WrapShortLivedExpression(Expr expr)
        {
            return ExprFactory.CreateWrap(expr);
        }
        private static ExprAssignment GenerateOptimizedAssignment(Expr op1, Expr op2)
        {
            return ExprFactory.CreateAssignment(op1, op2);
        }
        internal static int CountArguments(Expr args)
        {
            int num = 0;
            Expr expr = args;
            while (expr != null) {
                ExprList exprList = expr as ExprList;
                if (exprList != null) {
                    Expr optionalElement = exprList.OptionalElement;
                    expr = exprList.OptionalNextListNode;
                } else {
                    Expr optionalElement = expr;
                    expr = null;
                }
                num++;
            }
            return num;
        }
        private static bool IsNullableConstructor(Expr expr, out ExprCall call)
        {
            ExprCall exprCall = expr as ExprCall;
            if (exprCall != null && exprCall.MemberGroup.OptionalObject == null && (exprCall.MethWithInst?.Meth().IsNullableConstructor() ?? false)) {
                call = exprCall;
                return true;
            }
            call = null;
            return false;
        }
        private static Expr StripNullableConstructor(Expr pExpr)
        {
            ExprCall call;
            while (IsNullableConstructor(pExpr, out call)) {
                pExpr = call.OptionalArguments;
            }
            return pExpr;
        }
        private static Expr BindNubValue(Expr exprSrc)
        {
            if (IsNullableConstructor(exprSrc, out ExprCall call))
                return call.OptionalArguments;
            NullableType nullableType = (NullableType)exprSrc.Type;
            CType underlyingType = nullableType.UnderlyingType;
            AggregateType ats = nullableType.GetAts();
            PropertySymbol property = PredefinedMembers.GetProperty(PREDEFPROP.PP_G_OPTIONAL_VALUE);
            PropWithType property2 = new PropWithType(property, ats);
            MethPropWithInst method = new MethPropWithInst(property, ats);
            ExprMemberGroup memberGroup = ExprFactory.CreateMemGroup(exprSrc, method);
            return ExprFactory.CreateProperty(underlyingType, null, null, memberGroup, property2, null);
        }
        private static ExprCall BindNubNew(Expr exprSrc)
        {
            NullableType nullable = TypeManager.GetNullable(exprSrc.Type);
            AggregateType ats = nullable.GetAts();
            MethodSymbol method = PredefinedMembers.GetMethod(PREDEFMETH.PM_G_OPTIONAL_CTOR);
            MethWithInst method2 = new MethWithInst(method, ats, TypeArray.Empty);
            ExprMemberGroup memberGroup = ExprFactory.CreateMemGroup(null, method2);
            return ExprFactory.CreateCall(EXPRFLAG.EXF_LITERALCONST | EXPRFLAG.EXF_CANTBENULL, nullable, exprSrc, memberGroup, method2);
        }
        private ExprBinOp BindUserDefinedBinOp(ExpressionKind ek, BinOpArgInfo info)
        {
            if (info.pt1 <= PredefinedType.PT_ULONG && info.pt2 <= PredefinedType.PT_ULONG)
                return null;
            MethPropWithInst ppmpwi;
            Expr expr;
            if (info.binopKind == BinOpKind.Logical) {
                ExprCall exprCall = BindUDBinop(ek - 55 + 49, info.arg1, info.arg2, true, out ppmpwi);
                if (exprCall == null)
                    return null;
                expr = BindUserBoolOp(ek, exprCall);
            } else
                expr = BindUDBinop(ek, info.arg1, info.arg2, false, out ppmpwi);
            if (expr == null)
                return null;
            return ExprFactory.CreateUserDefinedBinop(ek, expr.Type, info.arg1, info.arg2, expr, ppmpwi);
        }
        private bool GetSpecialBinopSignatures(List<BinOpFullSig> prgbofs, BinOpArgInfo info)
        {
            if (info.pt1 <= PredefinedType.PT_ULONG && info.pt2 <= PredefinedType.PT_ULONG)
                return false;
            if (!GetDelBinOpSigs(prgbofs, info) && !GetEnumBinOpSigs(prgbofs, info))
                return GetRefEqualSigs(prgbofs, info);
            return true;
        }
        private bool GetStandardAndLiftedBinopSignatures(List<BinOpFullSig> rgbofs, BinOpArgInfo info)
        {
            int num = 0;
            for (int i = 0; i < s_binopSignatures.Length; i++) {
                BinOpSig binOpSig = s_binopSignatures[i];
                if ((binOpSig.mask & info.mask) != 0) {
                    CType cType = GetPredefindType(binOpSig.pt1);
                    CType cType2 = GetPredefindType(binOpSig.pt2);
                    if (cType != null && cType2 != null) {
                        ConvKind convKind = GetConvKind(info.pt1, binOpSig.pt1);
                        ConvKind convKind2 = GetConvKind(info.pt2, binOpSig.pt2);
                        LiftFlags liftFlags = LiftFlags.None;
                        switch (convKind) {
                        case ConvKind.Explicit: {
                            ExprConstant exprConstant = info.arg1 as ExprConstant;
                            if (exprConstant == null)
                                break;
                            if (!canConvert(exprConstant, cType)) {
                                if (i < num || !binOpSig.CanLift())
                                    break;
                                cType = TypeManager.GetNullable(cType);
                                if (!canConvert(exprConstant, cType))
                                    break;
                                ConvKind convKind4 = GetConvKind(info.ptRaw1, binOpSig.pt1);
                                liftFlags = (((uint)(convKind4 - 1) <= 1) ? (liftFlags | LiftFlags.Lift1) : (liftFlags | LiftFlags.Convert1));
                            }
                            goto case ConvKind.Implicit;
                        }
                        case ConvKind.Unknown:
                            if (!canConvert(info.arg1, cType)) {
                                if (i < num || !binOpSig.CanLift())
                                    break;
                                cType = TypeManager.GetNullable(cType);
                                if (!canConvert(info.arg1, cType))
                                    break;
                                ConvKind convKind3 = GetConvKind(info.ptRaw1, binOpSig.pt1);
                                liftFlags = (((uint)(convKind3 - 1) <= 1) ? (liftFlags | LiftFlags.Lift1) : (liftFlags | LiftFlags.Convert1));
                            }
                            goto case ConvKind.Implicit;
                        case ConvKind.Identity:
                            if (convKind2 == ConvKind.Identity) {
                                BinOpFullSig binOpFullSig = new BinOpFullSig(this, binOpSig);
                                if (binOpFullSig.Type1() != null && binOpFullSig.Type2() != null) {
                                    rgbofs.Add(binOpFullSig);
                                    return true;
                                }
                            }
                            goto case ConvKind.Implicit;
                        case ConvKind.Implicit:
                            switch (convKind2) {
                            case ConvKind.Explicit: {
                                ExprConstant exprConstant2 = info.arg2 as ExprConstant;
                                if (exprConstant2 == null)
                                    break;
                                if (!canConvert(exprConstant2, cType2)) {
                                    if (i < num || !binOpSig.CanLift())
                                        break;
                                    cType2 = TypeManager.GetNullable(cType2);
                                    if (!canConvert(exprConstant2, cType2))
                                        break;
                                    ConvKind convKind6 = GetConvKind(info.ptRaw2, binOpSig.pt2);
                                    liftFlags = (((uint)(convKind6 - 1) <= 1) ? (liftFlags | LiftFlags.Lift2) : (liftFlags | LiftFlags.Convert2));
                                }
                                goto case ConvKind.Identity;
                            }
                            case ConvKind.Unknown:
                                if (!canConvert(info.arg2, cType2)) {
                                    if (i < num || !binOpSig.CanLift())
                                        break;
                                    cType2 = TypeManager.GetNullable(cType2);
                                    if (!canConvert(info.arg2, cType2))
                                        break;
                                    ConvKind convKind5 = GetConvKind(info.ptRaw2, binOpSig.pt2);
                                    liftFlags = (((uint)(convKind5 - 1) <= 1) ? (liftFlags | LiftFlags.Lift2) : (liftFlags | LiftFlags.Convert2));
                                }
                                goto case ConvKind.Identity;
                            case ConvKind.Identity:
                            case ConvKind.Implicit:
                                if (liftFlags != 0) {
                                    rgbofs.Add(new BinOpFullSig(cType, cType2, binOpSig.pfn, binOpSig.grfos, liftFlags, binOpSig.fnkind));
                                    num = i + binOpSig.cbosSkip + 1;
                                } else {
                                    rgbofs.Add(new BinOpFullSig(this, binOpSig));
                                    i += binOpSig.cbosSkip;
                                }
                                break;
                            }
                            break;
                        }
                    }
                }
            }
            return false;
        }
        private int FindBestSignatureInList(List<BinOpFullSig> binopSignatures, BinOpArgInfo info)
        {
            if (binopSignatures.Count == 1)
                return 0;
            int num = 0;
            for (int i = 1; i < binopSignatures.Count; i++) {
                if (num < 0)
                    num = i;
                else {
                    int num2 = WhichBofsIsBetter(binopSignatures[num], binopSignatures[i], info.type1, info.type2);
                    if (num2 == 0)
                        num = -1;
                    else if (num2 > 0) {
                        num = i;
                    }
                }
            }
            if (num == -1)
                return -1;
            for (int i = 0; i < binopSignatures.Count; i++) {
                if (i != num && WhichBofsIsBetter(binopSignatures[num], binopSignatures[i], info.type1, info.type2) >= 0)
                    return -1;
            }
            return num;
        }
        private static ExprBinOp BindNullEqualityComparison(ExpressionKind ek, BinOpArgInfo info)
        {
            Expr arg = info.arg1;
            Expr right = info.arg2;
            if (info.binopKind == BinOpKind.Equal) {
                CType predefindType = GetPredefindType(PredefinedType.PT_BOOL);
                ExprBinOp exprBinOp = null;
                if (info.type1 is NullableType && info.type2 is NullType) {
                    right = ExprFactory.CreateZeroInit(info.type1);
                    exprBinOp = ExprFactory.CreateBinop(ek, predefindType, arg, right);
                }
                if (info.type1 is NullType && info.type2 is NullableType) {
                    arg = ExprFactory.CreateZeroInit(info.type2);
                    exprBinOp = ExprFactory.CreateBinop(ek, predefindType, arg, right);
                }
                if (exprBinOp != null) {
                    exprBinOp.IsLifted = true;
                    return exprBinOp;
                }
            }
            throw BadOperatorTypesError(info.arg1, info.arg2);
        }
        public Expr BindStandardBinop(ExpressionKind ek, Expr arg1, Expr arg2)
        {
            (BinOpKind, EXPRFLAG) binopKindAndFlags = GetBinopKindAndFlags(ek);
            BinOpKind item = binopKindAndFlags.Item1;
            EXPRFLAG item2 = binopKindAndFlags.Item2;
            BinOpArgInfo binOpArgInfo = new BinOpArgInfo(arg1, arg2) {
                binopKind = item
            };
            binOpArgInfo.mask = (BinOpMask)(1 << (int)binOpArgInfo.binopKind);
            List<BinOpFullSig> list = new List<BinOpFullSig>();
            ExprBinOp exprBinOp = BindUserDefinedBinOp(ek, binOpArgInfo);
            if (exprBinOp != null)
                return exprBinOp;
            bool flag = GetSpecialBinopSignatures(list, binOpArgInfo);
            if (!flag)
                flag = GetStandardAndLiftedBinopSignatures(list, binOpArgInfo);
            int num;
            if (flag)
                num = list.Count - 1;
            else {
                if (list.Count == 0)
                    return BindNullEqualityComparison(ek, binOpArgInfo);
                num = FindBestSignatureInList(list, binOpArgInfo);
                if (num < 0)
                    throw AmbiguousOperatorError(arg1, arg2);
            }
            return BindStandardBinopCore(binOpArgInfo, list[num], ek, item2);
        }
        private Expr BindStandardBinopCore(BinOpArgInfo info, BinOpFullSig bofs, ExpressionKind ek, EXPRFLAG flags)
        {
            if (bofs.pfn == null)
                throw BadOperatorTypesError(info.arg1, info.arg2);
            if (!bofs.isLifted() || !bofs.AutoLift()) {
                Expr expr = info.arg1;
                Expr expr2 = info.arg2;
                if (bofs.ConvertOperandsBeforeBinding()) {
                    expr = mustConvert(expr, bofs.Type1());
                    expr2 = mustConvert(expr2, bofs.Type2());
                }
                if (bofs.fnkind == BinOpFuncKind.BoolBitwiseOp)
                    return BindBoolBitwiseOp(ek, flags, expr, expr2);
                return bofs.pfn(this, ek, flags, expr, expr2);
            }
            if (IsEnumArithmeticBinOp(ek, info)) {
                Expr expr3 = info.arg1;
                Expr expr4 = info.arg2;
                if (bofs.ConvertOperandsBeforeBinding()) {
                    expr3 = mustConvert(expr3, bofs.Type1());
                    expr4 = mustConvert(expr4, bofs.Type2());
                }
                return BindLiftedEnumArithmeticBinOp(ek, flags, expr3, expr4);
            }
            return BindLiftedStandardBinOp(info, bofs, ek, flags);
        }
        private ExprBinOp BindLiftedStandardBinOp(BinOpArgInfo info, BinOpFullSig bofs, ExpressionKind ek, EXPRFLAG flags)
        {
            Expr arg = info.arg1;
            Expr arg2 = info.arg2;
            Expr expr = null;
            LiftArgument(arg, bofs.Type1(), bofs.ConvertFirst(), out Expr ppLiftedArgument, out Expr ppNonLiftedArgument);
            LiftArgument(arg2, bofs.Type2(), bofs.ConvertSecond(), out Expr ppLiftedArgument2, out Expr ppNonLiftedArgument2);
            if (!ppNonLiftedArgument.isNull() && !ppNonLiftedArgument2.isNull())
                expr = bofs.pfn(this, ek, flags, ppNonLiftedArgument, ppNonLiftedArgument2);
            CType cType;
            if (info.binopKind == BinOpKind.Compare || info.binopKind == BinOpKind.Equal)
                cType = GetPredefindType(PredefinedType.PT_BOOL);
            else {
                cType = ((bofs.fnkind == BinOpFuncKind.EnumBinOp) ? GetEnumBinOpType(ek, ppNonLiftedArgument.Type, ppNonLiftedArgument2.Type, out AggregateType _) : ppLiftedArgument.Type);
                if (!(cType is NullableType))
                    cType = TypeManager.GetNullable(cType);
            }
            ExprBinOp exprBinOp = ExprFactory.CreateBinop(ek, cType, ppLiftedArgument, ppLiftedArgument2);
            mustCast(expr, cType, (CONVERTTYPE)0);
            exprBinOp.IsLifted = true;
            exprBinOp.Flags |= flags;
            return exprBinOp;
        }
        private void LiftArgument(Expr pArgument, CType pParameterType, bool bConvertBeforeLift, out Expr ppLiftedArgument, out Expr ppNonLiftedArgument)
        {
            Expr expr = mustConvert(pArgument, pParameterType);
            if (expr != pArgument)
                MarkAsIntermediateConversion(expr);
            Expr expr2 = pArgument;
            NullableType nullableType = pParameterType as NullableType;
            if (nullableType != null) {
                if (expr2.isNull())
                    expr2 = mustCast(expr2, pParameterType);
                expr2 = mustCast(expr2, nullableType.UnderlyingType);
                if (bConvertBeforeLift)
                    MarkAsIntermediateConversion(expr2);
            } else
                expr2 = expr;
            ppLiftedArgument = expr;
            ppNonLiftedArgument = expr2;
        }
        private bool GetDelBinOpSigs(List<BinOpFullSig> prgbofs, BinOpArgInfo info)
        {
            if (!info.ValidForDelegate() || (!info.type1.IsDelegateType && !info.type2.IsDelegateType))
                return false;
            if (info.type1 == info.type2) {
                prgbofs.Add(new BinOpFullSig(info.type1, info.type2, BindDelBinOp, OpSigFlags.Convert, LiftFlags.None, BinOpFuncKind.DelBinOp));
                return true;
            }
            bool flag = info.type2.IsDelegateType && canConvert(info.arg1, info.type2);
            bool flag2 = info.type1.IsDelegateType && canConvert(info.arg2, info.type1);
            if (flag)
                prgbofs.Add(new BinOpFullSig(info.type2, info.type2, BindDelBinOp, OpSigFlags.Convert, LiftFlags.None, BinOpFuncKind.DelBinOp));
            if (flag2)
                prgbofs.Add(new BinOpFullSig(info.type1, info.type1, BindDelBinOp, OpSigFlags.Convert, LiftFlags.None, BinOpFuncKind.DelBinOp));
            return false;
        }
        private bool CanConvertArg1(BinOpArgInfo info, CType typeDst, out LiftFlags pgrflt, out CType ptypeSig1, out CType ptypeSig2)
        {
            ptypeSig1 = null;
            ptypeSig2 = null;
            if (canConvert(info.arg1, typeDst))
                pgrflt = LiftFlags.None;
            else {
                pgrflt = LiftFlags.None;
                typeDst = TypeManager.GetNullable(typeDst);
                if (!canConvert(info.arg1, typeDst))
                    return false;
                pgrflt = LiftFlags.Convert1;
            }
            ptypeSig1 = typeDst;
            if (info.type2 is NullableType) {
                pgrflt |= LiftFlags.Lift2;
                ptypeSig2 = TypeManager.GetNullable(info.typeRaw2);
            } else
                ptypeSig2 = info.typeRaw2;
            return true;
        }
        private bool CanConvertArg2(BinOpArgInfo info, CType typeDst, out LiftFlags pgrflt, out CType ptypeSig1, out CType ptypeSig2)
        {
            ptypeSig1 = null;
            ptypeSig2 = null;
            if (canConvert(info.arg2, typeDst))
                pgrflt = LiftFlags.None;
            else {
                pgrflt = LiftFlags.None;
                typeDst = TypeManager.GetNullable(typeDst);
                if (!canConvert(info.arg2, typeDst))
                    return false;
                pgrflt = LiftFlags.Convert2;
            }
            ptypeSig2 = typeDst;
            if (info.type1 is NullableType) {
                pgrflt |= LiftFlags.Lift1;
                ptypeSig1 = TypeManager.GetNullable(info.typeRaw1);
            } else
                ptypeSig1 = info.typeRaw1;
            return true;
        }
        private static void RecordBinOpSigFromArgs(List<BinOpFullSig> prgbofs, BinOpArgInfo info)
        {
            LiftFlags liftFlags = LiftFlags.None;
            CType type;
            if (info.type1 != info.typeRaw1) {
                liftFlags |= LiftFlags.Lift1;
                type = TypeManager.GetNullable(info.typeRaw1);
            } else
                type = info.typeRaw1;
            CType type2;
            if (info.type2 != info.typeRaw2) {
                liftFlags |= LiftFlags.Lift2;
                type2 = TypeManager.GetNullable(info.typeRaw2);
            } else
                type2 = info.typeRaw2;
            prgbofs.Add(new BinOpFullSig(type, type2, BindEnumBinOp, OpSigFlags.Value, liftFlags, BinOpFuncKind.EnumBinOp));
        }
        private bool GetEnumBinOpSigs(List<BinOpFullSig> prgbofs, BinOpArgInfo info)
        {
            if (!info.typeRaw1.IsEnumType && !info.typeRaw2.IsEnumType)
                return false;
            CType ptypeSig = null;
            CType ptypeSig2 = null;
            LiftFlags pgrflt = LiftFlags.None;
            if (info.typeRaw1 == info.typeRaw2) {
                if (!info.ValidForEnum())
                    return false;
                RecordBinOpSigFromArgs(prgbofs, info);
                return true;
            }
            if ((!info.typeRaw1.IsEnumType) ? (info.typeRaw1 == info.typeRaw2.UnderlyingEnumType && info.ValidForUnderlyingTypeAndEnum()) : (info.typeRaw2 == info.typeRaw1.UnderlyingEnumType && info.ValidForEnumAndUnderlyingType())) {
                RecordBinOpSigFromArgs(prgbofs, info);
                return true;
            }
            if ((!info.typeRaw1.IsEnumType) ? ((info.ValidForEnum() && CanConvertArg1(info, info.typeRaw2, out pgrflt, out ptypeSig, out ptypeSig2)) || (info.ValidForEnumAndUnderlyingType() && CanConvertArg1(info, info.typeRaw2.UnderlyingEnumType, out pgrflt, out ptypeSig, out ptypeSig2))) : ((info.ValidForEnum() && CanConvertArg2(info, info.typeRaw1, out pgrflt, out ptypeSig, out ptypeSig2)) || (info.ValidForEnumAndUnderlyingType() && CanConvertArg2(info, info.typeRaw1.UnderlyingEnumType, out pgrflt, out ptypeSig, out ptypeSig2))))
                prgbofs.Add(new BinOpFullSig(ptypeSig, ptypeSig2, BindEnumBinOp, OpSigFlags.Value, pgrflt, BinOpFuncKind.EnumBinOp));
            return false;
        }
        private static bool IsEnumArithmeticBinOp(ExpressionKind ek, BinOpArgInfo info)
        {
            switch (ek) {
            case ExpressionKind.Add:
                return info.typeRaw1.IsEnumType ^ info.typeRaw2.IsEnumType;
            case ExpressionKind.Subtract:
                return info.typeRaw1.IsEnumType | info.typeRaw2.IsEnumType;
            default:
                return false;
            }
        }
        private bool GetRefEqualSigs(List<BinOpFullSig> prgbofs, BinOpArgInfo info)
        {
            if (info.mask != BinOpMask.Equal)
                return false;
            if (info.type1 != info.typeRaw1 || info.type2 != info.typeRaw2)
                return false;
            bool result = false;
            CType cType = info.type1;
            CType cType2 = info.type2;
            CType predefindType = GetPredefindType(PredefinedType.PT_OBJECT);
            CType cType3 = null;
            if (cType is NullType && cType2 is NullType) {
                cType3 = predefindType;
                result = true;
            } else {
                CType predefindType2 = GetPredefindType(PredefinedType.PT_DELEGATE);
                if (canConvert(info.arg1, predefindType2) && canConvert(info.arg2, predefindType2) && !cType.IsDelegateType && !cType2.IsDelegateType)
                    prgbofs.Add(new BinOpFullSig(predefindType2, predefindType2, BindDelBinOp, OpSigFlags.Convert, LiftFlags.None, BinOpFuncKind.DelBinOp));
                if (cType.FundamentalType != FUNDTYPE.FT_REF)
                    return false;
                if (cType2 is NullType) {
                    result = true;
                    cType3 = predefindType;
                } else {
                    if (cType2.FundamentalType != FUNDTYPE.FT_REF)
                        return false;
                    if (cType is NullType) {
                        result = true;
                        cType3 = predefindType;
                    } else {
                        if (!canCast(cType, cType2, CONVERTTYPE.NOUDC) && !canCast(cType2, cType, CONVERTTYPE.NOUDC))
                            return false;
                        if (cType.IsInterfaceType || cType.IsPredefType(PredefinedType.PT_STRING) || SymbolLoader.HasBaseConversion(cType, predefindType2))
                            cType = predefindType;
                        else if (cType is ArrayType) {
                            cType = GetPredefindType(PredefinedType.PT_ARRAY);
                        } else if (!cType.IsClassType) {
                            return false;
                        }
                        if (cType2.IsInterfaceType || cType2.IsPredefType(PredefinedType.PT_STRING) || SymbolLoader.HasBaseConversion(cType2, predefindType2))
                            cType2 = predefindType;
                        else if (cType2 is ArrayType) {
                            cType2 = GetPredefindType(PredefinedType.PT_ARRAY);
                        } else if (!cType2.IsClassType) {
                            return false;
                        }
                        if (SymbolLoader.HasBaseConversion(cType2, cType))
                            cType3 = cType;
                        else if (SymbolLoader.HasBaseConversion(cType, cType2)) {
                            cType3 = cType2;
                        }
                    }
                }
            }
            prgbofs.Add(new BinOpFullSig(cType3, cType3, BindRefCmpOp, OpSigFlags.None, LiftFlags.None, BinOpFuncKind.RefCmpOp));
            return result;
        }
        private int WhichBofsIsBetter(BinOpFullSig bofs1, BinOpFullSig bofs2, CType type1, CType type2)
        {
            BetterType betterType;
            BetterType betterType2;
            if (bofs1.FPreDef() && bofs2.FPreDef()) {
                betterType = WhichTypeIsBetter(bofs1.pt1, bofs2.pt1, type1);
                betterType2 = WhichTypeIsBetter(bofs1.pt2, bofs2.pt2, type2);
            } else {
                betterType = WhichTypeIsBetter(bofs1.Type1(), bofs2.Type1(), type1);
                betterType2 = WhichTypeIsBetter(bofs1.Type2(), bofs2.Type2(), type2);
            }
            int num;
            switch (betterType) {
            case BetterType.Left:
                num = -1;
                break;
            case BetterType.Right:
                num = 1;
                break;
            default:
                num = 0;
                break;
            }
            switch (betterType2) {
            case BetterType.Left:
                num--;
                break;
            case BetterType.Right:
                num++;
                break;
            }
            return num;
        }
        private static (ExpressionKind, UnaOpKind, EXPRFLAG) CalculateExprAndUnaryOpKinds(OperatorKind op, bool bChecked)
        {
            EXPRFLAG eXPRFLAG = (EXPRFLAG)0;
            UnaOpKind item;
            ExpressionKind item2;
            switch (op) {
            case OperatorKind.OP_UPLUS:
                item = UnaOpKind.Plus;
                item2 = ExpressionKind.UnaryPlus;
                break;
            case OperatorKind.OP_NEG:
                if (bChecked)
                    eXPRFLAG = EXPRFLAG.EXF_CHECKOVERFLOW;
                item = UnaOpKind.Minus;
                item2 = ExpressionKind.Negate;
                break;
            case OperatorKind.OP_BITNOT:
                item = UnaOpKind.Tilde;
                item2 = ExpressionKind.BitwiseNot;
                break;
            case OperatorKind.OP_LOGNOT:
                item = UnaOpKind.Bang;
                item2 = ExpressionKind.LogicalNot;
                break;
            case OperatorKind.OP_POSTINC:
                eXPRFLAG = EXPRFLAG.EXF_OPERATOR;
                if (bChecked)
                    eXPRFLAG |= EXPRFLAG.EXF_CHECKOVERFLOW;
                item = UnaOpKind.IncDec;
                item2 = ExpressionKind.Add;
                break;
            case OperatorKind.OP_PREINC:
                if (bChecked)
                    eXPRFLAG = EXPRFLAG.EXF_CHECKOVERFLOW;
                item = UnaOpKind.IncDec;
                item2 = ExpressionKind.Add;
                break;
            case OperatorKind.OP_POSTDEC:
                eXPRFLAG = EXPRFLAG.EXF_OPERATOR;
                if (bChecked)
                    eXPRFLAG |= EXPRFLAG.EXF_CHECKOVERFLOW;
                item = UnaOpKind.IncDec;
                item2 = ExpressionKind.Subtract;
                break;
            case OperatorKind.OP_PREDEC:
                if (bChecked)
                    eXPRFLAG = EXPRFLAG.EXF_CHECKOVERFLOW;
                item = UnaOpKind.IncDec;
                item2 = ExpressionKind.Subtract;
                break;
            default:
                throw Error.InternalCompilerError();
            }
            return (item2, item, eXPRFLAG);
        }
        public Expr BindStandardUnaryOperator(OperatorKind op, Expr pArgument)
        {
            CType type = pArgument.Type;
            NullableType nullableType = type as NullableType;
            if (nullableType != null) {
                CType underlyingType = nullableType.UnderlyingType;
                if (underlyingType.IsEnumType) {
                    PredefinedType pt;
                    switch (underlyingType.FundamentalType) {
                    case FUNDTYPE.FT_U4:
                        pt = PredefinedType.PT_UINT;
                        break;
                    case FUNDTYPE.FT_I8:
                        pt = PredefinedType.PT_LONG;
                        break;
                    case FUNDTYPE.FT_U8:
                        pt = PredefinedType.PT_ULONG;
                        break;
                    default:
                        pt = PredefinedType.PT_INT;
                        break;
                    }
                    return mustCast(BindStandardUnaryOperator(op, mustCast(pArgument, TypeManager.GetNullable(GetPredefindType(pt)))), nullableType);
                }
            }
            (ExpressionKind, UnaOpKind, EXPRFLAG) valueTuple = CalculateExprAndUnaryOpKinds(op, Context.Checked);
            ExpressionKind item = valueTuple.Item1;
            UnaOpKind item2 = valueTuple.Item2;
            EXPRFLAG item3 = valueTuple.Item3;
            UnaOpMask unaryOpMask = (UnaOpMask)(1 << (int)item2);
            List<UnaOpFullSig> list = new List<UnaOpFullSig>();
            Expr ppResult;
            UnaryOperatorSignatureFindResult unaryOperatorSignatureFindResult = PopulateSignatureList(pArgument, item2, unaryOpMask, item, item3, list, out ppResult);
            int num = list.Count - 1;
            switch (unaryOperatorSignatureFindResult) {
            case UnaryOperatorSignatureFindResult.Return:
                return ppResult;
            default:
                if (!FindApplicableSignatures(pArgument, unaryOpMask, list)) {
                    if (list.Count == 0)
                        throw BadOperatorTypesError(pArgument, null);
                    num = 0;
                    if (list.Count != 1) {
                        for (int i = 1; i < list.Count; i++) {
                            if (num < 0)
                                num = i;
                            else {
                                int num2 = WhichUofsIsBetter(list[num], list[i], type);
                                if (num2 == 0)
                                    num = -1;
                                else if (num2 > 0) {
                                    num = i;
                                }
                            }
                        }
                        if (num < 0)
                            throw AmbiguousOperatorError(pArgument, null);
                        for (int j = 0; j < list.Count; j++) {
                            if (j != num && WhichUofsIsBetter(list[num], list[j], type) >= 0)
                                throw AmbiguousOperatorError(pArgument, null);
                        }
                    }
                } else
                    num = list.Count - 1;
                break;
            case UnaryOperatorSignatureFindResult.Match:
                break;
            }
            UnaOpFullSig unaOpFullSig = list[num];
            if (unaOpFullSig.pfn == null) {
                if (item2 == UnaOpKind.IncDec)
                    return BindIncOp(item, item3, pArgument, unaOpFullSig);
                throw BadOperatorTypesError(pArgument, null);
            }
            if (unaOpFullSig.isLifted())
                return BindLiftedStandardUnop(item, item3, pArgument, unaOpFullSig);
            if (pArgument is ExprConstant)
                pArgument = ExprFactory.CreateCast(pArgument.Type, pArgument);
            Expr expr = tryConvert(pArgument, unaOpFullSig.GetType());
            if (expr == null)
                expr = mustCast(pArgument, unaOpFullSig.GetType(), CONVERTTYPE.NOUDC);
            return unaOpFullSig.pfn(this, item, item3, expr);
        }
        private UnaryOperatorSignatureFindResult PopulateSignatureList(Expr pArgument, UnaOpKind unaryOpKind, UnaOpMask unaryOpMask, ExpressionKind exprKind, EXPRFLAG flags, List<UnaOpFullSig> pSignatures, out Expr ppResult)
        {
            ppResult = null;
            CType type = pArgument.Type;
            CType cType = type.StripNubs();
            PredefinedType predefinedType = cType.IsPredefined ? cType.PredefinedType : PredefinedType.PT_COUNT;
            if (predefinedType > PredefinedType.PT_ULONG) {
                if (cType.IsEnumType) {
                    if ((unaryOpMask & (UnaOpMask.Tilde | UnaOpMask.IncDec)) != 0) {
                        if (unaryOpKind == UnaOpKind.Tilde)
                            pSignatures.Add(new UnaOpFullSig(((AggregateType)type).OwningAggregate.GetUnderlyingType(), BindEnumUnaOp, LiftFlags.None, UnaOpFuncKind.EnumUnaOp));
                        else
                            pSignatures.Add(new UnaOpFullSig(((AggregateType)type).OwningAggregate.GetUnderlyingType(), null, LiftFlags.None, UnaOpFuncKind.None));
                        return UnaryOperatorSignatureFindResult.Match;
                    }
                } else if (unaryOpKind == UnaOpKind.IncDec) {
                    ExprMultiGet exprMultiGet = ExprFactory.CreateMultiGet((EXPRFLAG)0, type, null);
                    Expr expr = bindUDUnop(exprKind - 42 + 33, exprMultiGet);
                    if (expr != null) {
                        if (expr.Type != null && expr.Type != type)
                            expr = mustConvert(expr, type);
                        ExprMulti exprMulti2 = exprMultiGet.OptionalMulti = ExprFactory.CreateMulti(EXPRFLAG.EXF_ASSGOP | flags, type, pArgument, expr);
                        CheckLvalue(pArgument, CheckLvalueKind.Increment);
                        ppResult = exprMulti2;
                        return UnaryOperatorSignatureFindResult.Return;
                    }
                } else {
                    Expr expr2 = bindUDUnop(exprKind, pArgument);
                    if (expr2 != null) {
                        ppResult = expr2;
                        return UnaryOperatorSignatureFindResult.Return;
                    }
                }
            }
            return UnaryOperatorSignatureFindResult.Continue;
        }
        private bool FindApplicableSignatures(Expr pArgument, UnaOpMask unaryOpMask, List<UnaOpFullSig> pSignatures)
        {
            long num = 0;
            CType type = pArgument.Type;
            CType cType = type.StripNubs();
            PredefinedType ptSrc = type.IsPredefined ? type.PredefinedType : PredefinedType.PT_COUNT;
            PredefinedType ptSrc2 = cType.IsPredefined ? cType.PredefinedType : PredefinedType.PT_COUNT;
            for (int i = 0; i < s_rguos.Length; i++) {
                UnaOpSig unaOpSig = s_rguos[i];
                if ((unaOpSig.grfuom & unaryOpMask) != 0) {
                    ConvKind convKind = GetConvKind(ptSrc, s_rguos[i].pt);
                    CType cType2 = null;
                    switch (convKind) {
                    case ConvKind.Explicit:
                        if (!(pArgument is ExprConstant))
                            break;
                        if (!canConvert(pArgument, cType2 = GetPredefindType(unaOpSig.pt))) {
                            if (i < num)
                                break;
                            cType2 = TypeManager.GetNullable(cType2);
                            if (!canConvert(pArgument, cType2))
                                break;
                        }
                        goto case ConvKind.Implicit;
                    case ConvKind.Unknown:
                        if (!canConvert(pArgument, cType2 = GetPredefindType(unaOpSig.pt))) {
                            if (i < num)
                                break;
                            cType2 = TypeManager.GetNullable(cType2);
                            if (!canConvert(pArgument, cType2))
                                break;
                        }
                        goto case ConvKind.Implicit;
                    case ConvKind.Identity: {
                        UnaOpFullSig unaOpFullSig = new UnaOpFullSig(this, unaOpSig);
                        if (unaOpFullSig.GetType() != null) {
                            pSignatures.Add(unaOpFullSig);
                            return true;
                        }
                        goto case ConvKind.Implicit;
                    }
                    case ConvKind.Implicit:
                        if (cType2 is NullableType) {
                            LiftFlags liftFlags = LiftFlags.None;
                            ConvKind convKind2 = GetConvKind(ptSrc2, unaOpSig.pt);
                            liftFlags = (((uint)(convKind2 - 1) <= 1) ? (liftFlags | LiftFlags.Lift1) : (liftFlags | LiftFlags.Convert1));
                            pSignatures.Add(new UnaOpFullSig(cType2, unaOpSig.pfn, liftFlags, unaOpSig.fnkind));
                            num = i + unaOpSig.cuosSkip + 1;
                        } else {
                            UnaOpFullSig unaOpFullSig2 = new UnaOpFullSig(this, unaOpSig);
                            if (unaOpFullSig2.GetType() != null)
                                pSignatures.Add(unaOpFullSig2);
                            i += unaOpSig.cuosSkip;
                        }
                        break;
                    }
                }
            }
            return false;
        }
        private ExprOperator BindLiftedStandardUnop(ExpressionKind ek, EXPRFLAG flags, Expr arg, UnaOpFullSig uofs)
        {
            NullableType nullableType = uofs.GetType() as NullableType;
            if (arg.Type is NullType)
                throw BadOperatorTypesError(arg, null);
            LiftArgument(arg, uofs.GetType(), uofs.Convert(), out Expr ppLiftedArgument, out Expr ppNonLiftedArgument);
            Expr expr = uofs.pfn(this, ek, flags, ppNonLiftedArgument);
            ExprUnaryOp exprUnaryOp = ExprFactory.CreateUnaryOp(ek, nullableType, ppLiftedArgument);
            mustCast(expr, nullableType, (CONVERTTYPE)0);
            exprUnaryOp.Flags |= flags;
            return exprUnaryOp;
        }
        private int WhichUofsIsBetter(UnaOpFullSig uofs1, UnaOpFullSig uofs2, CType typeArg)
        {
            switch ((!uofs1.FPreDef() || !uofs2.FPreDef()) ? WhichTypeIsBetter(uofs1.GetType(), uofs2.GetType(), typeArg) : WhichTypeIsBetter(uofs1.pt, uofs2.pt, typeArg)) {
            case BetterType.Left:
                return -1;
            case BetterType.Right:
                return 1;
            default:
                return 0;
            }
        }
        private static ExprOperator BindIntBinOp(ExpressionBinder binder, ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2)
        {
            return binder.BindIntOp(ek, flags, arg1, arg2, arg1.Type.PredefinedType);
        }
        private static ExprOperator BindIntUnaOp(ExpressionBinder binder, ExpressionKind ek, EXPRFLAG flags, Expr arg)
        {
            return binder.BindIntOp(ek, flags, arg, null, arg.Type.PredefinedType);
        }
        private static ExprOperator BindRealBinOp(ExpressionBinder binder, ExpressionKind ek, EXPRFLAG _, Expr arg1, Expr arg2)
        {
            return BindFloatOp(ek, arg1, arg2);
        }
        private static ExprOperator BindRealUnaOp(ExpressionBinder binder, ExpressionKind ek, EXPRFLAG _, Expr arg)
        {
            return BindFloatOp(ek, arg, null);
        }
        private Expr BindIncOp(ExpressionKind ek, EXPRFLAG flags, Expr arg, UnaOpFullSig uofs)
        {
            CheckLvalue(arg, CheckLvalueKind.Increment);
            CType cType = uofs.GetType().StripNubs();
            FUNDTYPE fundamentalType = cType.FundamentalType;
            if (fundamentalType == FUNDTYPE.FT_R8 || fundamentalType == FUNDTYPE.FT_R4)
                flags &= ~EXPRFLAG.EXF_CHECKOVERFLOW;
            if (uofs.isLifted())
                return BindLiftedIncOp(ek, flags, arg, uofs);
            return BindNonliftedIncOp(ek, flags, arg, uofs);
        }
        private Expr BindIncOpCore(ExpressionKind ek, EXPRFLAG flags, Expr exprVal, CType type)
        {
            if (type.IsEnumType && type.FundamentalType > FUNDTYPE.FT_U8)
                type = GetPredefindType(PredefinedType.PT_INT);
            ConstVal cv;
            switch (type.FundamentalType) {
            default: {
                PREDEFMETH predefMeth;
                if (ek == ExpressionKind.Add) {
                    ek = ExpressionKind.DecimalInc;
                    predefMeth = PREDEFMETH.PM_DECIMAL_OPINCREMENT;
                } else {
                    ek = ExpressionKind.DecimalDec;
                    predefMeth = PREDEFMETH.PM_DECIMAL_OPDECREMENT;
                }
                return CreateUnaryOpForPredefMethodCall(ek, predefMeth, type, exprVal);
            }
            case FUNDTYPE.FT_I1:
            case FUNDTYPE.FT_I2:
            case FUNDTYPE.FT_U1:
            case FUNDTYPE.FT_U2:
                type = GetPredefindType(PredefinedType.PT_INT);
                cv = ConstVal.Get(1);
                break;
            case FUNDTYPE.FT_I4:
            case FUNDTYPE.FT_U4:
                cv = ConstVal.Get(1);
                break;
            case FUNDTYPE.FT_I8:
            case FUNDTYPE.FT_U8:
                cv = ConstVal.Get(1);
                break;
            case FUNDTYPE.FT_R4:
            case FUNDTYPE.FT_R8:
                cv = ConstVal.Get(1);
                break;
            }
            return LScalar(ek, flags, exprVal, type, cv, type);
        }
        private Expr LScalar(ExpressionKind ek, EXPRFLAG flags, Expr exprVal, CType type, ConstVal cv, CType typeTmp)
        {
            CType cType = type;
            if (cType.IsEnumType)
                cType = cType.UnderlyingEnumType;
            ExprBinOp exprBinOp = ExprFactory.CreateBinop(ek, typeTmp, exprVal, ExprFactory.CreateConstant(cType, cv));
            exprBinOp.Flags |= flags;
            if (typeTmp == type)
                return exprBinOp;
            return mustCast(exprBinOp, type, CONVERTTYPE.NOUDC);
        }
        private ExprMulti BindNonliftedIncOp(ExpressionKind ek, EXPRFLAG flags, Expr arg, UnaOpFullSig uofs)
        {
            ExprMultiGet exprMultiGet = ExprFactory.CreateMultiGet(EXPRFLAG.EXF_ASSGOP, arg.Type, null);
            Expr expr = exprMultiGet;
            CType type = uofs.GetType();
            expr = mustCast(expr, type);
            expr = BindIncOpCore(ek, flags, expr, type);
            Expr op = mustCast(expr, arg.Type, CONVERTTYPE.NOUDC);
            return exprMultiGet.OptionalMulti = ExprFactory.CreateMulti(EXPRFLAG.EXF_ASSGOP | flags, arg.Type, arg, op);
        }
        private ExprMulti BindLiftedIncOp(ExpressionKind ek, EXPRFLAG flags, Expr arg, UnaOpFullSig uofs)
        {
            NullableType nullableType = uofs.GetType() as NullableType;
            ExprMultiGet exprMultiGet = ExprFactory.CreateMultiGet(EXPRFLAG.EXF_ASSGOP, arg.Type, null);
            Expr expr = exprMultiGet;
            Expr expr2 = expr;
            expr2 = mustCast(expr2, nullableType.UnderlyingType);
            Expr expr3 = BindIncOpCore(ek, flags, expr2, nullableType.UnderlyingType);
            expr = mustCast(expr, nullableType);
            ExprUnaryOp exprUnaryOp = ExprFactory.CreateUnaryOp((ek == ExpressionKind.Add) ? ExpressionKind.Inc : ExpressionKind.Dec, arg.Type, expr);
            mustCast(mustCast(expr3, nullableType), arg.Type);
            exprUnaryOp.Flags |= flags;
            return exprMultiGet.OptionalMulti = ExprFactory.CreateMulti(EXPRFLAG.EXF_ASSGOP | flags, arg.Type, arg, exprUnaryOp);
        }
        private static ExprBinOp BindDecBinOp(ExpressionBinder _, ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2)
        {
            CType predefindType = GetPredefindType(PredefinedType.PT_DECIMAL);
            CType type = ((uint)(ek - 36) <= 5) ? GetPredefindType(PredefinedType.PT_BOOL) : (((uint)(ek - 42) <= 4) ? predefindType : null);
            return ExprFactory.CreateBinop(ek, type, arg1, arg2);
        }
        private static ExprUnaryOp BindDecUnaOp(ExpressionBinder _, ExpressionKind ek, EXPRFLAG flags, Expr arg)
        {
            CType predefindType = GetPredefindType(PredefinedType.PT_DECIMAL);
            if (ek == ExpressionKind.Negate) {
                PREDEFMETH predefMeth = PREDEFMETH.PM_DECIMAL_OPUNARYMINUS;
                return CreateUnaryOpForPredefMethodCall(ExpressionKind.DecimalNegate, predefMeth, predefindType, arg);
            }
            return ExprFactory.CreateUnaryOp(ExpressionKind.UnaryPlus, predefindType, arg);
        }
        private static Expr BindStrBinOp(ExpressionBinder _, ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2)
        {
            return BindStringConcat(arg1, arg2);
        }
        private static ExprBinOp BindShiftOp(ExpressionBinder _, ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2)
        {
            PredefinedType predefinedType = arg1.Type.PredefinedType;
            return ExprFactory.CreateBinop(ek, arg1.Type, arg1, arg2);
        }
        private static ExprBinOp BindBoolBinOp(ExpressionBinder _, ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2)
        {
            return ExprFactory.CreateBinop(ek, GetPredefindType(PredefinedType.PT_BOOL), arg1, arg2);
        }
        private ExprOperator BindBoolBitwiseOp(ExpressionKind ek, EXPRFLAG flags, Expr expr1, Expr expr2)
        {
            if (expr1.Type is NullableType || expr2.Type is NullableType) {
                CType predefindType = GetPredefindType(PredefinedType.PT_BOOL);
                CType nullable = TypeManager.GetNullable(predefindType);
                Expr expr3 = StripNullableConstructor(expr1);
                Expr expr4 = StripNullableConstructor(expr2);
                Expr expr5 = null;
                if (!(expr3.Type is NullableType) && !(expr4.Type is NullableType))
                    expr5 = BindBoolBinOp(this, ek, flags, expr3, expr4);
                ExprBinOp exprBinOp = ExprFactory.CreateBinop(ek, nullable, expr1, expr2);
                if (expr5 != null)
                    mustCast(expr5, nullable, (CONVERTTYPE)0);
                exprBinOp.IsLifted = true;
                exprBinOp.Flags |= flags;
                return exprBinOp;
            }
            return BindBoolBinOp(this, ek, flags, expr1, expr2);
        }
        private static Expr BindLiftedBoolBitwiseOp(ExpressionBinder _, ExpressionKind ek, EXPRFLAG flags, Expr expr1, Expr expr2)
        {
            return null;
        }
        private static Expr BindBoolUnaOp(ExpressionBinder _, ExpressionKind ek, EXPRFLAG flags, Expr arg)
        {
            CType predefindType = GetPredefindType(PredefinedType.PT_BOOL);
            Expr const = arg.GetConst();
            if (const == null)
                return ExprFactory.CreateUnaryOp(ExpressionKind.LogicalNot, predefindType, arg);
            return ExprFactory.CreateConstant(predefindType, ConstVal.Get(((ExprConstant)const).Val.Int32Val == 0));
        }
        private static ExprBinOp BindStrCmpOp(ExpressionBinder _, ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2)
        {
            PREDEFMETH predefMeth = (ek == ExpressionKind.Eq) ? PREDEFMETH.PM_STRING_OPEQUALITY : PREDEFMETH.PM_STRING_OPINEQUALITY;
            ek = ((ek == ExpressionKind.Eq) ? ExpressionKind.StringEq : ExpressionKind.StringNotEq);
            return CreateBinopForPredefMethodCall(ek, predefMeth, GetPredefindType(PredefinedType.PT_BOOL), arg1, arg2);
        }
        private static ExprBinOp BindRefCmpOp(ExpressionBinder binder, ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2)
        {
            arg1 = binder.mustConvert(arg1, GetPredefindType(PredefinedType.PT_OBJECT), CONVERTTYPE.NOUDC);
            arg2 = binder.mustConvert(arg2, GetPredefindType(PredefinedType.PT_OBJECT), CONVERTTYPE.NOUDC);
            return ExprFactory.CreateBinop(ek, GetPredefindType(PredefinedType.PT_BOOL), arg1, arg2);
        }
        private static Expr BindDelBinOp(ExpressionBinder _, ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2)
        {
            PREDEFMETH predefMeth = PREDEFMETH.PM_DECIMAL_OPDECREMENT;
            CType retType = null;
            switch (ek) {
            case ExpressionKind.Add:
                predefMeth = PREDEFMETH.PM_DELEGATE_COMBINE;
                retType = arg1.Type;
                ek = ExpressionKind.DelegateAdd;
                break;
            case ExpressionKind.Subtract:
                predefMeth = PREDEFMETH.PM_DELEGATE_REMOVE;
                retType = arg1.Type;
                ek = ExpressionKind.DelegateSubtract;
                break;
            case ExpressionKind.Eq:
                predefMeth = PREDEFMETH.PM_DELEGATE_OPEQUALITY;
                retType = GetPredefindType(PredefinedType.PT_BOOL);
                ek = ExpressionKind.DelegateEq;
                break;
            case ExpressionKind.NotEq:
                predefMeth = PREDEFMETH.PM_DELEGATE_OPINEQUALITY;
                retType = GetPredefindType(PredefinedType.PT_BOOL);
                ek = ExpressionKind.DelegateNotEq;
                break;
            }
            return CreateBinopForPredefMethodCall(ek, predefMeth, retType, arg1, arg2);
        }
        private static Expr BindEnumBinOp(ExpressionBinder binder, ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2)
        {
            AggregateType ppEnumType;
            AggregateType enumBinOpType = GetEnumBinOpType(ek, arg1.Type, arg2.Type, out ppEnumType);
            PredefinedType predefinedType;
            switch (ppEnumType.FundamentalType) {
            default:
                predefinedType = PredefinedType.PT_INT;
                break;
            case FUNDTYPE.FT_U4:
                predefinedType = PredefinedType.PT_UINT;
                break;
            case FUNDTYPE.FT_I8:
                predefinedType = PredefinedType.PT_LONG;
                break;
            case FUNDTYPE.FT_U8:
                predefinedType = PredefinedType.PT_ULONG;
                break;
            }
            CType predefindType = GetPredefindType(predefinedType);
            arg1 = binder.mustCast(arg1, predefindType, CONVERTTYPE.NOUDC);
            arg2 = binder.mustCast(arg2, predefindType, CONVERTTYPE.NOUDC);
            Expr expr = binder.BindIntOp(ek, flags, arg1, arg2, predefinedType);
            if (expr.Type != enumBinOpType)
                expr = binder.mustCast(expr, enumBinOpType, CONVERTTYPE.NOUDC);
            return expr;
        }
        private Expr BindLiftedEnumArithmeticBinOp(ExpressionKind ek, EXPRFLAG flags, Expr arg1, Expr arg2)
        {
            NullableType nullableType = arg1.Type as NullableType;
            CType cType = (nullableType != null) ? nullableType.UnderlyingType : arg1.Type;
            NullableType nullableType2 = arg2.Type as NullableType;
            CType cType2 = (nullableType2 != null) ? nullableType2.UnderlyingType : arg2.Type;
            if (cType is NullType)
                cType = cType2.UnderlyingEnumType;
            else if (cType2 is NullType) {
                cType2 = cType.UnderlyingEnumType;
            }
            AggregateType ppEnumType;
            NullableType nullable = TypeManager.GetNullable(GetEnumBinOpType(ek, cType, cType2, out ppEnumType));
            PredefinedType pt;
            switch (ppEnumType.FundamentalType) {
            default:
                pt = PredefinedType.PT_INT;
                break;
            case FUNDTYPE.FT_U4:
                pt = PredefinedType.PT_UINT;
                break;
            case FUNDTYPE.FT_I8:
                pt = PredefinedType.PT_LONG;
                break;
            case FUNDTYPE.FT_U8:
                pt = PredefinedType.PT_ULONG;
                break;
            }
            NullableType nullable2 = TypeManager.GetNullable(GetPredefindType(pt));
            arg1 = mustCast(arg1, nullable2, CONVERTTYPE.NOUDC);
            arg2 = mustCast(arg2, nullable2, CONVERTTYPE.NOUDC);
            ExprBinOp exprBinOp = ExprFactory.CreateBinop(ek, nullable2, arg1, arg2);
            exprBinOp.IsLifted = true;
            exprBinOp.Flags |= flags;
            if (exprBinOp.Type != nullable)
                return mustCast(exprBinOp, nullable, CONVERTTYPE.NOUDC);
            return exprBinOp;
        }
        private static Expr BindEnumUnaOp(ExpressionBinder binder, ExpressionKind ek, EXPRFLAG flags, Expr arg)
        {
            CType type = ((ExprCast)arg).Argument.Type;
            PredefinedType predefinedType;
            switch (type.FundamentalType) {
            default:
                predefinedType = PredefinedType.PT_INT;
                break;
            case FUNDTYPE.FT_U4:
                predefinedType = PredefinedType.PT_UINT;
                break;
            case FUNDTYPE.FT_I8:
                predefinedType = PredefinedType.PT_LONG;
                break;
            case FUNDTYPE.FT_U8:
                predefinedType = PredefinedType.PT_ULONG;
                break;
            }
            CType predefindType = GetPredefindType(predefinedType);
            arg = binder.mustCast(arg, predefindType, CONVERTTYPE.NOUDC);
            Expr expr = binder.BindIntOp(ek, flags, arg, null, predefinedType);
            return binder.MustCastInUncheckedContext(expr, type, CONVERTTYPE.NOUDC);
        }
        private (BinOpKind, EXPRFLAG) GetBinopKindAndFlags(ExpressionKind ek)
        {
            EXPRFLAG eXPRFLAG = (EXPRFLAG)0;
            BindingContext context;
            BinOpKind item;
            switch (ek) {
            case ExpressionKind.Add:
                context = Context;
                if (context.Checked)
                    eXPRFLAG = EXPRFLAG.EXF_CHECKOVERFLOW;
                item = BinOpKind.Add;
                break;
            case ExpressionKind.Subtract:
                context = Context;
                if (context.Checked)
                    eXPRFLAG = EXPRFLAG.EXF_CHECKOVERFLOW;
                item = BinOpKind.Sub;
                break;
            case ExpressionKind.Divide:
            case ExpressionKind.Modulo:
                eXPRFLAG = EXPRFLAG.EXF_ASSGOP;
                context = Context;
                if (context.Checked)
                    eXPRFLAG |= EXPRFLAG.EXF_CHECKOVERFLOW;
                item = BinOpKind.Mul;
                break;
            case ExpressionKind.Multiply:
                context = Context;
                if (context.Checked)
                    eXPRFLAG = EXPRFLAG.EXF_CHECKOVERFLOW;
                item = BinOpKind.Mul;
                break;
            case ExpressionKind.BitwiseAnd:
            case ExpressionKind.BitwiseOr:
                item = BinOpKind.Bitwise;
                break;
            case ExpressionKind.BitwiseExclusiveOr:
                item = BinOpKind.BitXor;
                break;
            case ExpressionKind.LeftShirt:
            case ExpressionKind.RightShift:
                item = BinOpKind.Shift;
                break;
            case ExpressionKind.LogicalAnd:
            case ExpressionKind.LogicalOr:
                item = BinOpKind.Logical;
                break;
            case ExpressionKind.LessThan:
            case ExpressionKind.LessThanOrEqual:
            case ExpressionKind.GreaterThan:
            case ExpressionKind.GreaterThanOrEqual:
                item = BinOpKind.Compare;
                break;
            case ExpressionKind.Eq:
            case ExpressionKind.NotEq:
                item = BinOpKind.Equal;
                break;
            default:
                throw Error.InternalCompilerError();
            }
            return (item, eXPRFLAG);
        }
        private ExprOperator BindIntOp(ExpressionKind kind, EXPRFLAG flags, Expr op1, Expr op2, PredefinedType ptOp)
        {
            CType predefindType = GetPredefindType(ptOp);
            if (kind == ExpressionKind.Negate)
                return BindIntegerNeg(flags, op1, ptOp);
            CType type = kind.IsRelational() ? GetPredefindType(PredefinedType.PT_BOOL) : predefindType;
            ExprOperator exprOperator = ExprFactory.CreateOperator(kind, type, op1, op2);
            exprOperator.Flags |= flags;
            return exprOperator;
        }
        private ExprOperator BindIntegerNeg(EXPRFLAG flags, Expr op, PredefinedType ptOp)
        {
            CType predefindType = GetPredefindType(ptOp);
            switch (ptOp) {
            case PredefinedType.PT_ULONG:
                throw BadOperatorTypesError(op, null);
            case PredefinedType.PT_UINT:
                if (op.Type.FundamentalType == FUNDTYPE.FT_U4)
                    op = mustConvertCore(op, GetPredefindType(PredefinedType.PT_LONG), CONVERTTYPE.NOUDC);
                break;
            }
            return ExprFactory.CreateNeg(flags, op);
        }
        private static ExprOperator BindFloatOp(ExpressionKind kind, Expr op1, Expr op2)
        {
            CType type = kind.IsRelational() ? GetPredefindType(PredefinedType.PT_BOOL) : op1.Type;
            ExprOperator exprOperator = ExprFactory.CreateOperator(kind, type, op1, op2);
            exprOperator.Flags &= ~EXPRFLAG.EXF_CHECKOVERFLOW;
            return exprOperator;
        }
        private static ExprConcat BindStringConcat(Expr op1, Expr op2)
        {
            return ExprFactory.CreateConcat(op1, op2);
        }
        private static RuntimeBinderException AmbiguousOperatorError(Expr op1, Expr op2)
        {
            string errorString = op1.ErrorString;
            if (op2 == null)
                return ErrorHandling.Error(ErrorCode.ERR_AmbigUnaryOp, errorString, op1.Type);
            return ErrorHandling.Error(ErrorCode.ERR_AmbigBinaryOps, errorString, op1.Type, op2.Type);
        }
        private Expr BindUserBoolOp(ExpressionKind kind, ExprCall pCall)
        {
            CType type = pCall.Type;
            if (!TypeManager.SubstEqualTypes(type, pCall.MethWithInst.Meth().Params[0], type) || !TypeManager.SubstEqualTypes(type, pCall.MethWithInst.Meth().Params[1], type))
                throw ErrorHandling.Error(ErrorCode.ERR_BadBoolOp, pCall.MethWithInst);
            ExprList exprList = (ExprList)pCall.OptionalArguments;
            Expr optionalElement = exprList.OptionalElement;
            ExprWrap exprWrap = (ExprWrap)(exprList.OptionalElement = WrapShortLivedExpression(optionalElement));
            SymbolTable.PopulateSymbolTableWithName("op_True", null, exprWrap.Type.AssociatedSystemType);
            SymbolTable.PopulateSymbolTableWithName("op_False", null, exprWrap.Type.AssociatedSystemType);
            Expr expr2 = bindUDUnop(ExpressionKind.True, exprWrap);
            Expr expr3 = bindUDUnop(ExpressionKind.False, exprWrap);
            if (expr2 == null || expr3 == null)
                throw ErrorHandling.Error(ErrorCode.ERR_MustHaveOpTF, type);
            expr2 = mustConvert(expr2, GetPredefindType(PredefinedType.PT_BOOL));
            expr3 = mustConvert(expr3, GetPredefindType(PredefinedType.PT_BOOL));
            return ExprFactory.CreateUserLogOp(type, (kind == ExpressionKind.LogicalAnd) ? expr3 : expr2, pCall);
        }
        private static AggregateType GetUserDefinedBinopArgumentType(CType type)
        {
            NullableType nullableType = type as NullableType;
            if (nullableType != null)
                type = nullableType.UnderlyingType;
            AggregateType aggregateType = type as AggregateType;
            if (aggregateType != null && (aggregateType.IsClassType || aggregateType.IsStructType) && !aggregateType.OwningAggregate.IsSkipUDOps())
                return aggregateType;
            return null;
        }
        private static int GetUserDefinedBinopArgumentTypes(CType type1, CType type2, AggregateType[] rgats)
        {
            int num = 0;
            rgats[0] = GetUserDefinedBinopArgumentType(type1);
            if (rgats[0] != null)
                num++;
            rgats[num] = GetUserDefinedBinopArgumentType(type2);
            if (rgats[num] != null)
                num++;
            if (num == 2 && rgats[0] == rgats[1])
                num = 1;
            return num;
        }
        private static bool UserDefinedBinaryOperatorCanBeLifted(ExpressionKind ek, MethodSymbol method, AggregateType ats, TypeArray Params)
        {
            if (!Params[0].IsNonNullableValueType || !Params[1].IsNonNullableValueType)
                return false;
            CType cType = TypeManager.SubstType(method.RetType, ats);
            if (!cType.IsNonNullableValueType)
                return false;
            if ((uint)(ek - 36) <= 1) {
                if (!cType.IsPredefType(PredefinedType.PT_BOOL))
                    return false;
                if (Params[0] != Params[1])
                    return false;
                return true;
            }
            if ((uint)(ek - 38) <= 3) {
                if (!cType.IsPredefType(PredefinedType.PT_BOOL))
                    return false;
                return true;
            }
            return true;
        }
        private bool UserDefinedBinaryOperatorIsApplicable(List<CandidateFunctionMember> candidateList, ExpressionKind ek, MethodSymbol method, AggregateType ats, Expr arg1, Expr arg2, bool fDontLift)
        {
            if (!method.isOperator || method.Params.Count != 2)
                return false;
            TypeArray typeArray = TypeManager.SubstTypeArray(method.Params, ats);
            if (canConvert(arg1, typeArray[0]) && canConvert(arg2, typeArray[1])) {
                candidateList.Add(new CandidateFunctionMember(new MethPropWithInst(method, ats, TypeArray.Empty), typeArray, 0, false));
                return true;
            }
            if (fDontLift || !UserDefinedBinaryOperatorCanBeLifted(ek, method, ats, typeArray))
                return false;
            CType[] array = new CType[2] {
                TypeManager.GetNullable(typeArray[0]),
                TypeManager.GetNullable(typeArray[1])
            };
            if (!canConvert(arg1, array[0]) || !canConvert(arg2, array[1]))
                return false;
            candidateList.Add(new CandidateFunctionMember(new MethPropWithInst(method, ats, TypeArray.Empty), TypeArray.Allocate(array), 2, false));
            return true;
        }
        private bool GetApplicableUserDefinedBinaryOperatorCandidates(List<CandidateFunctionMember> candidateList, ExpressionKind ek, AggregateType type, Expr arg1, Expr arg2, bool fDontLift)
        {
            Name name = ExpressionKindName(ek);
            bool result = false;
            for (MethodSymbol methodSymbol = SymbolLoader.LookupAggMember(name, type.OwningAggregate, symbmask_t.MASK_MethodSymbol) as MethodSymbol; methodSymbol != null; methodSymbol = (methodSymbol.LookupNext(symbmask_t.MASK_MethodSymbol) as MethodSymbol)) {
                if (UserDefinedBinaryOperatorIsApplicable(candidateList, ek, methodSymbol, type, arg1, arg2, fDontLift))
                    result = true;
            }
            return result;
        }
        private AggregateType GetApplicableUserDefinedBinaryOperatorCandidatesInBaseTypes(List<CandidateFunctionMember> candidateList, ExpressionKind ek, AggregateType type, Expr arg1, Expr arg2, bool fDontLift, AggregateType atsStop)
        {
            AggregateType aggregateType = type;
            while (aggregateType != null && aggregateType != atsStop) {
                if (GetApplicableUserDefinedBinaryOperatorCandidates(candidateList, ek, aggregateType, arg1, arg2, fDontLift))
                    return aggregateType;
                aggregateType = aggregateType.BaseClass;
            }
            return null;
        }
        private ExprCall BindUDBinop(ExpressionKind ek, Expr arg1, Expr arg2, bool fDontLift, out MethPropWithInst ppmpwi)
        {
            List<CandidateFunctionMember> list = new List<CandidateFunctionMember>();
            ppmpwi = null;
            AggregateType[] array = new AggregateType[2];
            switch (GetUserDefinedBinopArgumentTypes(arg1.Type, arg2.Type, array)) {
            case 0:
                return null;
            case 1:
                GetApplicableUserDefinedBinaryOperatorCandidatesInBaseTypes(list, ek, array[0], arg1, arg2, fDontLift, null);
                break;
            default: {
                AggregateType applicableUserDefinedBinaryOperatorCandidatesInBaseTypes = GetApplicableUserDefinedBinaryOperatorCandidatesInBaseTypes(list, ek, array[0], arg1, arg2, fDontLift, null);
                GetApplicableUserDefinedBinaryOperatorCandidatesInBaseTypes(list, ek, array[1], arg1, arg2, fDontLift, applicableUserDefinedBinaryOperatorCandidatesInBaseTypes);
                break;
            }
            }
            if (list.IsEmpty())
                return null;
            ExprList args = ExprFactory.CreateList(arg1, arg2);
            ArgInfos argInfos = new ArgInfos();
            argInfos.carg = 2;
            FillInArgInfoFromArgList(argInfos, args);
            CandidateFunctionMember methAmbig;
            CandidateFunctionMember methAmbig2;
            CandidateFunctionMember candidateFunctionMember = FindBestMethod(list, null, argInfos, out methAmbig, out methAmbig2);
            if (candidateFunctionMember == null)
                throw ErrorHandling.Error(ErrorCode.ERR_AmbigCall, methAmbig.mpwi, methAmbig2.mpwi);
            ppmpwi = candidateFunctionMember.mpwi;
            if (candidateFunctionMember.ctypeLift != 0)
                return BindLiftedUDBinop(ek, arg1, arg2, candidateFunctionMember.params, candidateFunctionMember.mpwi);
            CType typeRet = TypeManager.SubstType(candidateFunctionMember.mpwi.Meth().RetType, candidateFunctionMember.mpwi.GetType());
            return BindUDBinopCall(arg1, arg2, candidateFunctionMember.params, typeRet, candidateFunctionMember.mpwi);
        }
        private ExprCall BindUDBinopCall(Expr arg1, Expr arg2, TypeArray Params, CType typeRet, MethPropWithInst mpwi)
        {
            arg1 = mustConvert(arg1, Params[0]);
            arg2 = mustConvert(arg2, Params[1]);
            ExprList arguments = ExprFactory.CreateList(arg1, arg2);
            CheckUnsafe(arg1.Type);
            CheckUnsafe(arg2.Type);
            CheckUnsafe(typeRet);
            ExprMemberGroup memberGroup = ExprFactory.CreateMemGroup(null, mpwi);
            ExprCall exprCall = ExprFactory.CreateCall((EXPRFLAG)0, typeRet, arguments, memberGroup, null);
            exprCall.MethWithInst = new MethWithInst(mpwi);
            verifyMethodArgs(exprCall, mpwi.GetType());
            return exprCall;
        }
        private ExprCall BindLiftedUDBinop(ExpressionKind ek, Expr arg1, Expr arg2, TypeArray Params, MethPropWithInst mpwi)
        {
            Expr expr = arg1;
            Expr expr2 = arg2;
            CType cType = TypeManager.SubstType(mpwi.Meth().RetType, mpwi.GetType());
            TypeArray typeArray = TypeManager.SubstTypeArray(mpwi.Meth().Params, mpwi.GetType());
            if (!canConvert(arg1.Type.StripNubs(), typeArray[0], CONVERTTYPE.NOUDC))
                expr = mustConvert(arg1, Params[0]);
            if (!canConvert(arg2.Type.StripNubs(), typeArray[1], CONVERTTYPE.NOUDC))
                expr2 = mustConvert(arg2, Params[1]);
            Expr arg3 = mustCast(expr, typeArray[0]);
            Expr arg4 = mustCast(expr2, typeArray[1]);
            CType cType2 = ((uint)(ek - 36) <= 1) ? cType : (((uint)(ek - 38) <= 3) ? cType : TypeManager.GetNullable(cType));
            ExprCall expr3 = BindUDBinopCall(arg3, arg4, typeArray, cType, mpwi);
            ExprList arguments = ExprFactory.CreateList(expr, expr2);
            ExprMemberGroup memberGroup = ExprFactory.CreateMemGroup(null, mpwi);
            ExprCall exprCall = ExprFactory.CreateCall((EXPRFLAG)0, cType2, arguments, memberGroup, null);
            exprCall.MethWithInst = new MethWithInst(mpwi);
            switch (ek) {
            case ExpressionKind.Eq:
                exprCall.NullableCallLiftKind = NullableCallLiftKind.EqualityOperator;
                break;
            case ExpressionKind.NotEq:
                exprCall.NullableCallLiftKind = NullableCallLiftKind.InequalityOperator;
                break;
            default:
                exprCall.NullableCallLiftKind = NullableCallLiftKind.Operator;
                break;
            }
            exprCall.CastOfNonLiftedResultToLiftedType = mustCast(expr3, cType2, (CONVERTTYPE)0);
            return exprCall;
        }
        private static AggregateType GetEnumBinOpType(ExpressionKind ek, CType argType1, CType argType2, out AggregateType ppEnumType)
        {
            AggregateType aggregateType = argType1 as AggregateType;
            AggregateType aggregateType2 = argType2 as AggregateType;
            AggregateType aggregateType3 = aggregateType.IsEnumType ? aggregateType : aggregateType2;
            AggregateType result = aggregateType3;
            switch (ek) {
            default:
                if ((uint)(ek - 49) > 2)
                    result = GetPredefindType(PredefinedType.PT_BOOL);
                break;
            case ExpressionKind.Subtract:
                if (aggregateType == aggregateType2)
                    result = aggregateType3.UnderlyingEnumType;
                break;
            case ExpressionKind.Add:
                break;
            }
            ppEnumType = aggregateType3;
            return result;
        }
        private static ExprBinOp CreateBinopForPredefMethodCall(ExpressionKind ek, PREDEFMETH predefMeth, CType RetType, Expr arg1, Expr arg2)
        {
            MethodSymbol method = PredefinedMembers.GetMethod(predefMeth);
            ExprBinOp exprBinOp = ExprFactory.CreateBinop(ek, RetType, arg1, arg2);
            AggregateSymbol class = method.getClass();
            AggregateType aggregate = TypeManager.GetAggregate(class, TypeArray.Empty);
            exprBinOp.PredefinedMethodToCall = new MethWithInst(method, aggregate, null);
            exprBinOp.UserDefinedCallMethod = exprBinOp.PredefinedMethodToCall;
            return exprBinOp;
        }
        private static ExprUnaryOp CreateUnaryOpForPredefMethodCall(ExpressionKind ek, PREDEFMETH predefMeth, CType pRetType, Expr pArg)
        {
            MethodSymbol method = PredefinedMembers.GetMethod(predefMeth);
            ExprUnaryOp exprUnaryOp = ExprFactory.CreateUnaryOp(ek, pRetType, pArg);
            AggregateSymbol class = method.getClass();
            AggregateType aggregate = TypeManager.GetAggregate(class, TypeArray.Empty);
            exprUnaryOp.PredefinedMethodToCall = new MethWithInst(method, aggregate, null);
            exprUnaryOp.UserDefinedCallMethod = exprUnaryOp.PredefinedMethodToCall;
            return exprUnaryOp;
        }
    }
}