📄 typesymbol.cs
字号:
protected Modifiers m_mods;
public Modifiers Mods
{
get { return m_mods; }
}
Genre m_genre;
public bool IsClass
{
get { return m_genre == Genre.cClass; }
}
public bool IsInterface
{
get { return m_genre == Genre.cInterface; }
}
public bool IsStruct
{
get { return m_genre == Genre.cStruct;}
}
bool m_fIsImported;
public bool IsImported
{
//get { return (m_attrs & System.Reflection.TypeAttributes.Import) == System.Reflection.TypeAttributes.Import; }
get { return m_fIsImported; }
}
// Array support
public bool IsArray
{
get { return this is ArrayTypeEntry; }
}
// Get the current type as an array type.
// If we're a reference, then ignore the refence and get the nested type
// as an array type.
public ArrayTypeEntry AsArrayType
{
get
{
if (IsRef)
return AsRefType.ElemType.AsArrayType;
else
return this as ArrayTypeEntry;
}
}
public bool IsRef
{
get { return this is RefTypeEntry; }
}
public RefTypeEntry AsRefType
{
get { return this as RefTypeEntry; }
}
// Get string repsentation
public override string ToString()
{
return "Type:" + m_strName;
}
// Fully qualified name including Namespace
protected string m_stFullName;
public string FullName
{
get { return m_stFullName; }
}
// Location in AST where this class is declared
protected AST.ClassDecl m_decl;
public AST.ClassDecl Node
{
get { return m_decl; }
}
// Super class. Must be non-null except for System.Object
protected TypeEntry m_super;
public TypeEntry Super
{
get { return m_super; }
}
protected TypeEntry m_containingClass;
// Interfaces that we implement / derive from
protected TypeEntry [] m_interfaces;
public TypeEntry [] BaseInterfaces
{
get { return m_interfaces; }
}
// Scope containing our members
protected Scope m_scope;
public Scope MemberScope
{
get { return m_scope; }
}
// Track the CLR's corresponding type
// Return null if not yet set
// Set this directly for imported types
// Set this in codegen for emitted types
protected System.Type m_typeCLR;
public System.Type CLRType
{
get { return m_typeCLR; }
}
// If this is a nested type, return the containing type.
// If this is not a nested type, return null
public TypeEntry GetContainingType()
{
return m_containingClass;
}
#endregion
#region Resolution
#region Resolve Method Lookups
#region Decoration
// Convert a function name w/ parameter types into a single decorated string
static public string GetDecoratedParams(string stName, System.Type [] alParamTypes)
{
string stParam = "";
foreach(Type t in alParamTypes)
{
stParam += ((t == null) ? "null" : t.ToString()) + ";";
}
return stName + ":" + stParam;
}
// Get a decorated version right off the method symbol.
// Comparing decorated names will only find an exact match. But because there
// are many implicit conversions between types, different string names can
// still match.
static public string GetDecoratedParams(MethodExpEntry m)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(m.Name);
sb.Append(':');
for(int i = 0; i < m.ParamCount; i++)
{
Type t = m.ParamCLRType(i);
sb.Append((t == null) ? "null" : t.ToString());
sb.Append(';');
}
return sb.ToString();
}
#endregion
#region Internal Lookup helpers
// Helper to look for a method header in an interface
// Recursive. May return true / false.
// Does not throw exceptions
protected bool LookForMethodHeaderInInterface(
string stName
)
{
bool f = false;
if (f)
{
m_scope.DebugConsoleDump();
}
//SymEntry sym = m_scope.LookupSymbol(m_stMethodHeaderPrefix + stName);
MethodHeaderEntry header = LookupMethodHeader(stName);
if (header != null)
return true;
foreach(TypeEntry t in BaseInterfaces)
{
Debug.Assert(t.IsInterface);
if (t.LookForMethodHeaderInInterface(stName))
return true;
}
return false;
}
// Helper to lookup a method in an interface
protected void LookupMethodInInterface(
ISemanticResolver s,
string stDecorated,
OverloadedErrorInfo info
)
{
Debug.Assert(m_scope != null);
// First try a direct match
MethodExpEntry sym = (MethodExpEntry) s.LookupSymbol(m_scope, stDecorated, false);
if (sym != null)
{
info.AddMatch(sym);
}
// Since we did a smart-lookup, the LookupController already checked
// all base interfaces for us, so we don't have to repeat that exercise.
// If we do, we'll double count.
#if false
// Recursively check all inherited interfaces
foreach(TypeEntry t in BaseInterfaces)
{
Debug.Assert(t.IsInterface);
t.LookupMethodInInterface(s, stDecorated, info);
//if (sym != null)
// return sym;
}
#endif
//return null;
}
// Helper to lookup a method in an interface
// Note, stDecorated is a function of stName & alParamTypes. We pass it anyways to avoid
// recompute it at each level.
// Return null if not found
protected void SearchForOverloadInInterface(
ISemanticResolver s,
string stName,
Type [] alParamTypes,
OverloadedErrorInfo info
)
{
Debug.Assert(m_scope != null);
SearchForOverloadedMethodInScope(m_scope, s, stName, alParamTypes, info);
// Recursively check all inherited interfaces
foreach(TypeEntry t in BaseInterfaces)
{
Debug.Assert(t.IsInterface);
t.SearchForOverloadInInterface(s, stName, alParamTypes, info);
//if (sym != null)
// return sym;
}
//return null;
}
/*
// Helper to throw an error
protected void ThrowError_AmbiguousMethod(
ISemanticResolver s,
Identifier idName,
System.Type [] alParamTypes,
string stOverloadList
)
{
string stDecorated = GetDecoratedParams(idName.Text, alParamTypes);
s.ThrowError(SemanticChecker.Code.cAmbiguousMethod,
idName.Location,
"The call to '" + stDecorated + "'is ambiguous between:\n" + stOverloadList
);
}
*/
// Lookup a method header in our class
// return true if found, else false
public bool HasMethodHeader(string stName)
{
//MethodHeaderEntry header = (MethodHeaderEntry) m_scope.LookupSymbolInThisScopeOnly(m_stMethodHeaderPrefix + stName);
MethodHeaderEntry header = LookupMethodHeader(stName);
if (header == null)
return false;
return true;
}
// Helper.
// Return true if the parameters in alCall match a the parameters declared
// in mDecl. Update the info.
// Handles varargs.
protected void AddIfParamsMatch(
System.Type [] alParamTypes,
MethodExpEntry mDecl,
OverloadedErrorInfo info
)
{
// Callsite must have at least as many params as decl site
// Callsite may have more if this is a varargs method
// @todo - Callsite may have 1 less if this is avarargs method
// and the callsite has 0 varargs.
if (alParamTypes.Length < mDecl.ParamCount)
return;
// Check that all params at callsite match with params at decl site
// This loop only checks the params that are at the decl site.
// If this is a varargs call, then there may be params at the callsite
// not yet checked.
int i;
for(i = 0; i < mDecl.ParamCount; i++)
{
System.Type tBase = mDecl.ParamCLRType(i);
System.Type tDerived = alParamTypes[i];
Debug.Assert(tBase != null);
string stBase = tBase.ToString();
string stDerived = (tDerived == null) ? "null" : tDerived.ToString();
//if ((tBase != tDerived) && !tDerived.IsSubclassOf(tBase))
if (!SymbolEngine.TypeEntry.IsAssignable(tDerived, tBase))
break;
} // for each Param
// If all parameters match, (and we've checked all of them)
// then we found an candidate method
if ((i == mDecl.ParamCount) && (mDecl.ParamCount == alParamTypes.Length))
{
info.AddMatch(mDecl);
// Have to continue searching to check for ambiguity
}
// If all params match except the last one, then we may have a
// varargs
if (i == mDecl.ParamCount - 1)
{
System.Type tLastParam = mDecl.ParamCLRType(i);
if (tLastParam.IsArray)
{
System.Type tBase = tLastParam.GetElementType();
Debug.Assert(tBase != null);
// Check remainder of params
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -