📄 typesymbol.cs
字号:
}
}
// @todo ....
// If we still haven't found it, do a last effort check of System.Object.
// Since although we have an interface, we know there's really a class
// behind it, and all classes implement Object.
}
// Undefined
if (info.MatchCount == 0)
{
// No header found. So this is really undefined
if (info.NoHeader)
{
ThrowError(SymbolError.MethodNotDefined(location, FullName + "." + stName));
/*
s.ThrowError(SemanticChecker.Code.cMethodNotDefined, location,
"The method '" + FullName + "." + stName + "' is not defined.");
*/
}
// There's a header, so we have some definitions of this method.
// But no acceptable overloads
else
{
ThrowError(SymbolError.NoAcceptableOverload(location, FullName + "." + stDecorated));
/*
s.ThrowError(SemanticChecker.Code.cNoAcceptableOverload, location,
"No acceptable overload for '" + FullName + "." + stDecorated + "' exists");
*/
}
}
// Ambiguous. More than one overload matches.
else if (info.MatchCount > 1)
{
string stList = info.GetOverloadList();
//ThrowError_AmbiguousMethod(s, idName, alParamTypes, stList);
ThrowError(SymbolError.AmbiguousMethod(idName, alParamTypes, stList));
}
// We should have something
Debug.Assert(info.Symbol != null);
fIsVarArg = info.IsVarArgMatch;
sym = info.Symbol;
return sym;
}
#endregion
// Prefix methodheaders to make them an illegal identifier so that a lookup
// fo something else (like a ctor or method w/ 0 parameters) won't
// accidently stumble across the header.
readonly static string m_stMethodHeaderPrefix = "<header>";
// Add a method (decorated) to the scope
public void AddMethodToScope(MethodExpEntry sym)
{
Debug.Assert(sym.IsCtor || sym.RetType != null);
string stDebugClass = sym.SymbolClass.FullName;
// First, see if there's no header
MethodHeaderEntry header = (MethodHeaderEntry) m_scope.LookupSymbolInThisScopeOnly(m_stMethodHeaderPrefix + sym.Name);
if (header == null)
{
header = new MethodHeaderEntry(m_stMethodHeaderPrefix + sym.Name);
m_scope.AddSymbol(header);
}
// Get parameters
#if false
// @todo - don't strip the references
Type [] alParamTypes = sym.ParamTypes(true);
Debug.Assert(alParamTypes != null);
string stDecorated = GetDecoratedParams(sym.Name, alParamTypes);
#else
string stDecorated = GetDecoratedParams(sym);
#endif
m_scope.AddAliasSymbol(stDecorated, sym);
Log.WriteLine(Log.LF.Resolve, "Adding method '{0}' to scope '{1}'", stDecorated, m_scope.m_szDebugName);
// Chain in
header.AddMethodNode(sym);
}
#endregion
// Ensure that we have a hollow scope created/
internal void EnsureScopeCreated()
{
if (m_scope != null)
return;
string stName = (m_genre.ToString()) + m_typeCLR.ToString();
m_scope = new Scope(
stName, // name
this, // ILookupController
null // lexical parent
);
}
// Maintain flag to protect against infinite cycles in EnsureResolved.
//bool m_fResolving;
// Ensure that we have a scope. All user defined classes will already have a scope,
// but imported classes don't have a scope until they're first used (for memory reasons,
// since we import all classes in an assembly but only use a few of them; we don't
// want to allocate a ton of scopes & methods for classes we never use)
public void EnsureResolved(ISemanticResolver s)
{
// If we don't have a scope, then we're either:
// 1. An imported type (in which case clrType is set)
// 2. a user type refered as a base class during the ResolveType phase
// In this case, we don't have our clrType set yet. But that's ok.
// If we're just being refered as a base class in a decl, no one will use us.
// If we do have a scope then we're:
// 1. An imported type that has nested types
// 2. A user type
// 3. An already resolved user or imported type.
if ((m_scope == null) || (!m_scope.IsLocked))
{
// Must let imported types in for refs, arrays, etc to set their element type
#if false
// break on resolving a particular class
if (this.FullName == "System.MulticastDelegate")
{
int x =2;
}
#endif
// If our clr type isn't set yet, then we can't resolve. Someone will call
// us later though.
if (m_typeCLR == null)
return;
Debug.Assert(m_typeCLR != null);
// If we have a ref, then just populate our element type
// Note that a ref's member scope should be the same as it's Elem type's
// member scope (since anything on type T can be called on T&).
if (this.IsRef)
{
TypeEntry elem = this.AsRefType.ElemType;
elem.EnsureResolved(s);
m_scope = elem.m_scope;
return;
}
// If we have element types, make sure those are resolved too
if (IsArray)
{
ArrayTypeEntry a = this.AsArrayType;
TypeEntry elem = a.ElemType;
elem.EnsureResolved(s);
// Don't return here since we still have to populate
// our member scope w/ System.Array stuff
}
// Make sure our base class & inherited interfaces are resolved
if (this.Super != null)
Super.EnsureResolved(s);
foreach(TypeEntry tBase in this.BaseInterfaces)
tBase.EnsureResolved(s);
// By now, we should have resolved all of our depedent classes.
// Can't call this on a user type because we can't query ourselves.
// But that's ok, user types already have a populated scope.
if (!this.IsImported)
return;
Debug.Assert(!(m_typeCLR is System.Reflection.Emit.TypeBuilder), "Can't call EnsureResolved on user type:" + FullName);
// Create scope if we haven't already.
if (m_scope == null)
{
EnsureScopeCreated();
} else {
// Only way scope can already exists is if there are nested
// classes.
// Fails on TypeBuilders, so ignore error check for now.
#if false
int cNestedTypes = m_typeCLR.GetNestedTypes(
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.NonPublic).Length;
Debug.Assert(cNestedTypes != 0);
#endif
}
//Scope sSuper = (this.Super == null) ? null : this.Super.MemberScope;
//m_scope.SetSuperScope(sSuper);
// Use reflection to populate this scope
// @dogfood - allow 'const'
/*const*/ System.Reflection.BindingFlags flags =
System.Reflection.BindingFlags.DeclaredOnly |
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Static |
System.Reflection.BindingFlags.Instance;
// Add each method
System.Reflection.MethodInfo [] alMethods = m_typeCLR.GetMethods(flags);
foreach (System.Reflection.MethodInfo mInfo in alMethods)
{
string stName = mInfo.Name;
if (mInfo.IsPrivate || mInfo.IsAssembly)
continue;
#if false
// ignore all generic methods. Only in v2.0
if (mInfo.ContainsGenericParameters || mInfo.HasGenericArguments || mInfo.IsGenericMethodDefinition)
continue;
#endif
TypeEntry tRetType = s.ResolveCLRTypeToBlueType(mInfo.ReturnType);
//MethodExpEntry symMethod = new MethodExpEntry(stName, mInfo, this, tRetType);
MethodExpEntry symMethod = new MethodExpEntry(s, mInfo);
AddMethodToScope(symMethod);
}
// Properties
foreach(System.Reflection.PropertyInfo pInfo in m_typeCLR.GetProperties())
{
string stName = pInfo.Name;
if (pInfo.GetAccessors()[0].IsPrivate || pInfo.GetAccessors()[0].IsAssembly)
continue;
PropertyExpEntry symProp = new PropertyExpEntry(s, pInfo);
this.m_scope.AddSymbol(symProp);
}
// Ctors
System.Reflection.ConstructorInfo [] alCtors = m_typeCLR.GetConstructors(flags);
foreach(System.Reflection.ConstructorInfo cInfo in alCtors)
{
if (cInfo.IsStatic)
continue; // don't need to add static ctors to scope.
if (cInfo.IsPrivate || cInfo.IsAssembly)
continue;
MethodExpEntry symCtor = new MethodExpEntry(s, cInfo);
AddMethodToScope(symCtor);
}
// Fields
System.Reflection.FieldInfo [] alFields = m_typeCLR.GetFields(flags);
foreach(System.Reflection.FieldInfo fInfo in alFields)
{
FieldExpEntry symField = null;
if (fInfo.IsPrivate || fInfo.IsAssembly)
continue;
// @todo - combine LiteralField w/ Field?
if (fInfo.IsLiteral)
symField = new LiteralFieldExpEntry(s, fInfo);
else
symField = new FieldExpEntry(s, fInfo);
this.m_scope.AddSymbol(symField);
}
// Events
// We may have a private delegate field and an event w/ the same name. Ugg
// But privates aren't imported! Yay.
System.Reflection.EventInfo [] alEvents = m_typeCLR.GetEvents(flags);
foreach(System.Reflection.EventInfo eInfo in alEvents)
{
if (eInfo.GetAddMethod().IsPrivate || eInfo.GetAddMethod().IsAssembly)
continue;
EventExpEntry e = new EventExpEntry(eInfo, s);
this.m_scope.AddSymbol(e);
}
// Nested classes already stubbed when we imported
// Lock the scope. If we had to resolve it, then we shouldn't be adding
// anything new.
this.m_scope.LockScope();
}
else
{
// Scope already exists, there's nothing to do.
}
} // end EnsureResolved
#endregion
} // end class TypeEntry
//-----------------------------------------------------------------------------
// For arrays
//-----------------------------------------------------------------------------
public class ArrayTypeEntry : TypeEntry
{
// @todo - set real interfaces
// For resolving CLR arrays (that don't have an AST node)
// so clrType must be of an array
public ArrayTypeEntry(System.Type clrType, ISemanticResolver s) :
this(s)
{
Debug.Assert(clrType!= null);
Debug.Assert(s != null);
Debug.Assert(clrType.IsArray);
//Debug.Assert(rank == 1, "@todo - allow ranks besides 1");
System.Type clrElem = clrType.GetElementType();
m_typeElem = s.ResolveCLRTypeToBlueType(clrElem);
m_cDimension = clrType.GetArrayRank();
// All arrays must be of type System.Array
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -