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;
}
}
}