SymbolLoader
using Microsoft.CSharp.RuntimeBinder.Syntax;
namespace Microsoft.CSharp.RuntimeBinder.Semantics
{
internal static class SymbolLoader
{
public static AggregateSymbol GetPredefAgg(PredefinedType pt)
{
return TypeManager.GetPredefAgg(pt);
}
public static AggregateType GetPredefindType(PredefinedType pt)
{
return GetPredefAgg(pt).getThisType();
}
public static Symbol LookupAggMember(Name name, AggregateSymbol agg, symbmask_t mask)
{
return SymbolStore.LookupSym(name, agg, mask);
}
private static bool IsBaseInterface(AggregateType atsDer, AggregateType pBase)
{
if (pBase.IsInterfaceType) {
while (atsDer != null) {
CType[] items = atsDer.IfacesAll.Items;
foreach (CType pType in items) {
if (AreTypesEqualForConversion(pType, pBase))
return true;
}
atsDer = atsDer.BaseClass;
}
}
return false;
}
public static bool IsBaseClassOfClass(CType pDerived, CType pBase)
{
if (pDerived.IsClassType)
return IsBaseClass(pDerived, pBase);
return false;
}
private static bool IsBaseClass(CType pDerived, CType pBase)
{
AggregateType aggregateType = pBase as AggregateType;
if (aggregateType == null || !aggregateType.IsClassType)
return false;
AggregateType aggregateType2 = pDerived as AggregateType;
if (aggregateType2 == null) {
NullableType nullableType = pDerived as NullableType;
if (nullableType == null)
return false;
aggregateType2 = nullableType.GetAts();
}
for (AggregateType baseClass = aggregateType2.BaseClass; baseClass != null; baseClass = baseClass.BaseClass) {
if (baseClass == aggregateType)
return true;
}
return false;
}
private static bool HasCovariantArrayConversion(ArrayType pSource, ArrayType pDest)
{
if (pSource.Rank == pDest.Rank && pSource.IsSZArray == pDest.IsSZArray)
return HasImplicitReferenceConversion(pSource.ElementType, pDest.ElementType);
return false;
}
public static bool HasIdentityOrImplicitReferenceConversion(CType pSource, CType pDest)
{
if (AreTypesEqualForConversion(pSource, pDest))
return true;
return HasImplicitReferenceConversion(pSource, pDest);
}
private static bool AreTypesEqualForConversion(CType pType1, CType pType2)
{
return pType1.Equals(pType2);
}
private static bool HasArrayConversionToInterface(ArrayType pSource, CType pDest)
{
if (!pSource.IsSZArray || !pDest.IsInterfaceType)
return false;
if (pDest.IsPredefType(PredefinedType.PT_IENUMERABLE))
return true;
AggregateType aggregateType = (AggregateType)pDest;
AggregateSymbol owningAggregate = aggregateType.OwningAggregate;
if (!owningAggregate.isPredefAgg(PredefinedType.PT_G_ILIST) && !owningAggregate.isPredefAgg(PredefinedType.PT_G_ICOLLECTION) && !owningAggregate.isPredefAgg(PredefinedType.PT_G_IENUMERABLE) && !owningAggregate.isPredefAgg(PredefinedType.PT_G_IREADONLYCOLLECTION) && !owningAggregate.isPredefAgg(PredefinedType.PT_G_IREADONLYLIST))
return false;
return HasIdentityOrImplicitReferenceConversion(pSource.ElementType, aggregateType.TypeArgsAll[0]);
}
private static bool HasImplicitReferenceConversion(CType pSource, CType pDest)
{
if (pSource.IsReferenceType && pDest.IsPredefType(PredefinedType.PT_OBJECT))
return true;
AggregateType aggregateType = pSource as AggregateType;
if (aggregateType != null) {
AggregateType aggregateType2 = pDest as AggregateType;
if (aggregateType2 != null) {
switch (aggregateType.OwningAggregate.AggKind()) {
case AggKindEnum.Class:
switch (aggregateType2.OwningAggregate.AggKind()) {
case AggKindEnum.Class:
return IsBaseClass(aggregateType, aggregateType2);
case AggKindEnum.Interface:
return HasAnyBaseInterfaceConversion(aggregateType, aggregateType2);
}
break;
case AggKindEnum.Interface:
if (aggregateType2.IsInterfaceType) {
if (!HasAnyBaseInterfaceConversion(aggregateType, aggregateType2))
return HasInterfaceConversion(aggregateType, aggregateType2);
return true;
}
break;
case AggKindEnum.Delegate:
if (aggregateType2.IsPredefType(PredefinedType.PT_MULTIDEL) || aggregateType2.IsPredefType(PredefinedType.PT_DELEGATE) || IsBaseInterface(GetPredefindType(PredefinedType.PT_MULTIDEL), aggregateType2))
return true;
if (pDest.IsDelegateType)
return HasDelegateConversion(aggregateType, aggregateType2);
return false;
}
}
} else {
ArrayType arrayType = pSource as ArrayType;
if (arrayType != null) {
ArrayType arrayType2 = pDest as ArrayType;
if (arrayType2 != null)
return HasCovariantArrayConversion(arrayType, arrayType2);
AggregateType aggregateType3 = pDest as AggregateType;
if (aggregateType3 != null) {
if (aggregateType3.IsPredefType(PredefinedType.PT_ARRAY) || IsBaseInterface(GetPredefindType(PredefinedType.PT_ARRAY), aggregateType3))
return true;
return HasArrayConversionToInterface(arrayType, pDest);
}
} else if (pSource is NullType) {
if (!pDest.IsReferenceType)
return pDest is NullableType;
return true;
}
}
return false;
}
private static bool HasAnyBaseInterfaceConversion(CType pDerived, CType pBase)
{
if (pBase.IsInterfaceType) {
AggregateType aggregateType = pDerived as AggregateType;
if (aggregateType != null) {
AggregateType pDest = (AggregateType)pBase;
while (aggregateType != null) {
CType[] items = aggregateType.IfacesAll.Items;
for (int i = 0; i < items.Length; i++) {
AggregateType pSource = (AggregateType)items[i];
if (HasInterfaceConversion(pSource, pDest))
return true;
}
aggregateType = aggregateType.BaseClass;
}
return false;
}
}
return false;
}
private static bool HasInterfaceConversion(AggregateType pSource, AggregateType pDest)
{
return HasVariantConversion(pSource, pDest);
}
private static bool HasDelegateConversion(AggregateType pSource, AggregateType pDest)
{
return HasVariantConversion(pSource, pDest);
}
private static bool HasVariantConversion(AggregateType pSource, AggregateType pDest)
{
if (pSource == pDest)
return true;
AggregateSymbol owningAggregate = pSource.OwningAggregate;
if (owningAggregate != pDest.OwningAggregate)
return false;
TypeArray typeVarsAll = owningAggregate.GetTypeVarsAll();
TypeArray typeArgsAll = pSource.TypeArgsAll;
TypeArray typeArgsAll2 = pDest.TypeArgsAll;
for (int i = 0; i < typeVarsAll.Count; i++) {
CType cType = typeArgsAll[i];
CType cType2 = typeArgsAll2[i];
if (cType != cType2) {
TypeParameterType typeParameterType = (TypeParameterType)typeVarsAll[i];
if (typeParameterType.Invariant)
return false;
if (typeParameterType.Covariant && !HasImplicitReferenceConversion(cType, cType2))
return false;
if (typeParameterType.Contravariant && !HasImplicitReferenceConversion(cType2, cType))
return false;
}
}
return true;
}
private static bool HasImplicitBoxingConversion(CType pSource, CType pDest)
{
if (!pDest.IsReferenceType)
return false;
NullableType nullableType = pSource as NullableType;
if (nullableType != null)
pSource = nullableType.UnderlyingType;
else if (!pSource.IsValueType) {
return false;
}
if (!IsBaseClass(pSource, pDest))
return HasAnyBaseInterfaceConversion(pSource, pDest);
return true;
}
public static bool HasBaseConversion(CType pSource, CType pDest)
{
if (pSource is AggregateType && pDest.IsPredefType(PredefinedType.PT_OBJECT))
return true;
if (!HasIdentityOrImplicitReferenceConversion(pSource, pDest))
return HasImplicitBoxingConversion(pSource, pDest);
return true;
}
public static bool IsBaseAggregate(AggregateSymbol derived, AggregateSymbol base)
{
if (derived == base)
return true;
if (base.IsInterface()) {
while (derived != null) {
CType[] items = derived.GetIfacesAll().Items;
for (int i = 0; i < items.Length; i++) {
AggregateType aggregateType = (AggregateType)items[i];
if (aggregateType.OwningAggregate == base)
return true;
}
derived = derived.GetBaseAgg();
}
return false;
}
while (derived.GetBaseClass() != null) {
derived = derived.GetBaseClass().OwningAggregate;
if (derived == base)
return true;
}
return false;
}
}
}