📄 typesymbol.cs
字号:
m_typeCLR = clrType;
m_stFullName = clrType.FullName;
m_strName = clrType.Name;
m_genre = GenreFromClrType(clrType);
m_fIsImported = true;
m_fIsInit = false;
}
#endregion
#region Compound types (Array, Enum, Delegate)
// Protected constructor used by Derived TypeEntry to initialize this
// to a standard type (ex: Array, Enum, Delegate)
protected TypeEntry(
ISemanticResolver s,
System.Type clrBaseType
)
{
// Common properties
this.m_fIsImported = false; // @todo - is this right?
this.m_genre = Genre.cClass;
// Need to set everything based of the backing type
if (clrBaseType == typeof(System.Array))
{
Debug.Assert(this.IsArray);
// Must get the CLR type from the provider
TypeEntry tArray = s.LookupSystemType("Array");
this.m_scope = tArray.m_scope;
this.m_interfaces = tArray.m_interfaces;
this.m_super = tArray;
this.m_fIsImported = false; // @todo - is this right?
// ClrType will be set in ArrayType's FinalInit()
this.m_typeCLR = null;
// Not done init yet. Must call FinishArrayInit();
}
else if (clrBaseType == typeof(System.Enum))
{
Debug.Assert(this is SymbolEngine.EnumTypeEntry);
// Must get the CLR type from the provider
TypeEntry tEnum = s.LookupSystemType("Enum");
//this.m_scope = tEnum.m_scope;
this.m_interfaces = tEnum.m_interfaces;
this.m_super = tEnum;
// ClrType will be set in FinalInit()
this.m_typeCLR = null;
}
else
{
Debug.Assert(false, "Illegal use of TypeEntry ctor");
}
}
#endregion
public bool IsInit
{
get { return m_fIsInit; }
}
#endregion
#region Other Methods
public void SetCLRType(ICLRtypeProvider provider)
{
m_typeCLR = provider.CreateCLRClass(this);
}
// Return true if we can assisgn on object of type cFrom to an
// object of type cTo. Else false.
// We should be able to do this w/ System.Type.IsAssignableFrom,
// but the current implementation is buggy.
//
// Implicit conversion if:
// - cFrom == cTo
// - cFrom is a derived class of cTo
// - cTo is a base interface of cFrom
// - cFrom is 'null' and cTo is not a value type
// - cTo is 'Object'
public static bool IsAssignable(System.Type cFrom, System.Type cTo)
{
if (cTo == typeof(object))
return true;
// @todo - IsValueType the proper check?
if (cFrom == null && !cTo.IsValueType)
return true;
if (cFrom == null || cTo == null)
return false;
// First strip off References (since we can implicitly assign between
// refs & values).
// Also, we can have T[]& <- T[], so strip refs before matching arrays.
// (Note we _can't_ have T&[])
// If A <- B, then we can assign A <- B&, A& <- B, and A& <- B&.
// Codegen will deal with the indirection.
if (cFrom.IsByRef)
cFrom = cFrom.GetElementType();
if (cTo.IsByRef)
cTo = cTo.GetElementType();
#if false
// These are good checks, but we don't have to do them yet...
// Check pointers
if (cFrom.IsPointer && !cTo.IsPointer)
return false;
if (!cFrom.IsPointer && cTo.IsPointer)
return false;
if (cFrom.IsPointer && cTo.IsPointer)
{
cFrom = cFrom.GetElementType();
cTo = cTo.GetElementType();
return IsAssignable(cFrom, cTo);
}
#endif
// Check for arrays. Note that we can only do real comparisons on non-array
// types. (ie, compare object references for equality, query for interfaces,
// etc).
// We can always assign from T[] --> System.Array
if (cFrom.IsArray && (cTo == typeof(System.Array)))
return true;
// If one's an array, and the other's not, then we can't assign
if (cFrom.IsArray && !cTo.IsArray)
return false;
if (!cFrom.IsArray && cTo.IsArray)
return false;
// Can assign A[] -> B[] if we can assign A->B & the ranks are the same
if (cFrom.IsArray && cTo.IsArray)
{
if (cFrom.GetArrayRank() != cTo.GetArrayRank())
return false;
Type cFrom1 = cFrom.GetElementType();
Type cTo1 = cTo.GetElementType();
bool fOk = IsAssignable(cFrom1, cTo1);
return fOk;
}
// At this point, we're not an array/pointer
if (cFrom == cTo)
return true;
// Check implicit conversions
if (HasImplicitConversion(cFrom, cTo))
return true;
if (cFrom.IsSubclassOf(cTo))
return true;
if (SearchInterfaces(cFrom, cTo))
return true;
return false;
}
private static bool HasImplicitConversion(System.Type cFrom, System.Type cTo)
{
// Check for implicit numeric conversions:
if (cFrom == typeof(char) && cTo == typeof(int))
return true;
// Check for implicit operator-overload conversions
return false;
}
// Helper for IsAssignableFrom
// Search transitive closure of interfaces
private static bool SearchInterfaces(System.Type cFrom, System.Type cTo)
{
System.Type [] tI = cFrom.GetInterfaces();
foreach(System.Type t in tI)
{
if (t == cTo)
return true;
if (SearchInterfaces(t, cTo))
return true;
}
// check base class
if (cFrom.BaseType != null)
{
if (SearchInterfaces(cFrom.BaseType, cTo))
return true;
}
return false;
}
#endregion
#region ILookupController
// Search up the super class chain, base interfaces
// Return if found.
public SymEntry SmartLookup(string stIdentifier, Scope scope)
{
if (this.IsInterface)
{
SymEntry sym = this.MemberScope.LookupSymbolInThisScopeOnly(stIdentifier);
if (sym != null)
return sym;
Debug.Assert(this.Super == null, "No base class on interface");
// Check base interfaces
foreach(TypeEntry ti in BaseInterfaces)
{
sym = ti.SmartLookup(stIdentifier, null);
if (sym != null)
return sym;
}
} else {
TypeEntry tSearch = this;
while(tSearch != null)
{
SymEntry sym = tSearch.MemberScope.LookupSymbolInThisScopeOnly(stIdentifier);
if (sym != null)
return sym;
tSearch = tSearch.Super;
}
}
return null;
}
// Get a node responsible for this scope.
// For imported types, this will be null
public AST.Node OwnerNode {
get { return this.Node; }
}
// Get a symbol responsible for this scope.
// This may be null. (If this is null, then OwnerNode should not be null).
public SymEntry OwnerSymbol {
get { return this; }
}
// For debugging purposes. Used by DumpTree();
public void DumpScope(Scope scope)
{
if (this.IsInterface)
{
// Interface. No superclass, multiple base classes
// Have to dump a whole tree here
Console.Write("->{");
bool f = false;
foreach(TypeEntry ti in this.BaseInterfaces)
{
if (f)
Console.Write(",");
Console.Write(ti.Name);
ILookupController p = ti;
p.DumpScope(ti.MemberScope); // recursive
f = true;
}
Console.Write("}");
} else {
// Class, struct w/ Super class chain.
// Just dump a list
TypeEntry tSearch = this.Super;
while(tSearch != null)
{
Console.Write("->{0}", tSearch.MemberScope.m_szDebugName);
tSearch = tSearch.Super;
}
}
}
#endregion
#region Checks
// Debugging support. Since this is a graph traversal, we need a flag
// to note if we've already checked this (and prevent an infinite loop)
protected bool m_fDebugChecked = false;
public override void DebugCheck(ISemanticResolver s)
{
if (m_fDebugChecked)
return;
Debug.Assert(m_fIsInit);
m_fDebugChecked = true; // set flag before the recursion
Debug.Assert(AST.Node.m_DbgAllowNoCLRType || m_typeCLR != null);
if (Node != null)
{
Debug.Assert(Node.Symbol == this);
}
// Scope can be null (if we're not resolved)
if (m_scope != null)
{
m_scope.DebugCheck(s);
}
}
// Write out this Entry's name, attributes, (and if fRecursive, then nested scope too)
public override void Dump(XmlWriter o, bool fRecursive)
{
o.WriteStartElement("TypeEntry");
o.WriteAttributeString("name", this.m_strName);
if (fRecursive && (m_scope != null))
{
m_scope.Dump(o, true);
}
o.WriteEndElement();
}
#endregion
#region Properties and Data
static readonly TypeEntry [] m_emptyinterfaces = new TypeEntry[0];
// Attributes on this type.
// @todo - use reflection's attributes or our own?
// System.Reflection.TypeAttributes m_attrs = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -