📄 typesymbol.cs
字号:
//-----------------------------------------------------------------------------
// Symbols for types
//
// @todo - Note, currently these have a terrible object model. TypeEntry
// should have a lot of virtual functions on it that the derived types
// just override. (Similar to the Type AST nodes). Need to fix this.
//-----------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Xml;
using Blue.Public;
using Log = Blue.Log;
using Modifiers = AST.Modifiers;
namespace SymbolEngine
{
#region Classes for Type Symbols
//-----------------------------------------------------------------------------
// Helper for TypeEntry. Keep overload info for resolving members
//-----------------------------------------------------------------------------
public class OverloadedErrorInfo
{
protected MethodExpEntry m_symbol;
protected MethodExpEntry m_symbolVarArg;
protected int m_count = 0;
protected bool m_fNoHeader;
// Keep a lazy string record of the overloads for error information.
// We don't initialize this until we actually get some ambiguity.
protected System.Text.StringBuilder m_sbOverloads;
#if DEBUG
public static bool m_fLog = false;
#endif
public void SetNoHeader()
{
#if DEBUG
if (m_fLog)
Console.WriteLine("Set no header");
#endif
m_fNoHeader = true;
}
public bool NoHeader
{
get { return m_fNoHeader; }
}
// Return # of matches, giving precedence to non-vararg
public int MatchCount
{
get
{
return (m_count == 0) ?
((m_symbolVarArg == null) ? 0 : 1) :
m_count;
}
}
public string GetOverloadList()
{
return m_sbOverloads.ToString();
}
public void AddMatch(MethodExpEntry symbol)
{
#if DEBUG
if (m_fLog)
{
Console.WriteLine("Adding match:{0}", //TypeEntry.GetDecoratedParams(symbol),
symbol.PrettyDecoratedName);
}
#endif
// If we're ambiguous, then start tracking it for error info
// Don't create the string builder until we hit our first ambiguous overload
if (m_count == 1)
{
m_sbOverloads = new System.Text.StringBuilder();
// Add the first entry
// @dogfood - should be able to match 0 non-varargs
//m_sbOverloads.AppendFormat("\t(1):");
m_sbOverloads.Append("\t(1):");
m_sbOverloads.Append(m_symbol.PrettyDecoratedName);
m_sbOverloads.Append('\n');
}
m_count++;
m_symbol = symbol;
if (m_count > 1)
{
// Keep appending the overload entries
m_sbOverloads.AppendFormat("\t({0}):", m_count);
m_sbOverloads.Append(symbol.PrettyDecoratedName);
m_sbOverloads.Append('\n');
}
}
public void AddVarargMatch(MethodExpEntry symbol)
{
#if DEBUG
if (m_fLog)
Console.WriteLine("Adding vararg match:{0}", TypeEntry.GetDecoratedParams(symbol));
#endif
m_symbolVarArg = symbol;
}
public bool IsVarArgMatch
{
get
{
return (m_symbol == null) && (m_symbolVarArg != null);
}
}
// Return the symbol, giving precedence to the non-vararg version
public MethodExpEntry Symbol
{
get { return (m_symbol == null) ? m_symbolVarArg : m_symbol; }
}
}
#if false
// @todo - this may be a much better hierarchy than what we currently have.
#region TypeEntry base class
//-----------------------------------------------------------------------------
// Abstract base class to represent Blue's notion of a type.
// It's rather silly that we have to maintain an entire symbol table when
// these are so closely related to System.Type, but alas. TypeBuilders are
// not System.Type.
//-----------------------------------------------------------------------------
public abstract class TypeEntry : SymEntry
{
#region Properties
// Get the System.Type associated with this type entry.
System.Type CLRType
{
get;
}
#endregion
}
// A nonreference type
public abstract class NonRefTypeEntry : TypeEntry
{
}
// Referenece to any NonRefType
// Flyweights
public class RefTypeEntry : TypeEntry
{
}
// Array of non-ref types
// These are flyweights.
public class ArrayTypeEntry : NonRefTypeEntry
{
}
// Simple type. These are unique for each type and have a 1:1 match
// with the a System.Type.
public class SimpleTypeEntry : NonRefTypeEntry
{
}
// Enum.
public class EnumTypeEntry : SimpleTypeEntry
{
}
// Imported type already has it's CLRType set.
public class ImportedTypeEntry : NonRefTypeEntry
{
}
#endregion
#endif
//-----------------------------------------------------------------------------
// Represent a type
// Under the CLR, All types are objects and can have members on them
// (even primitives like int)
//-----------------------------------------------------------------------------
public class TypeEntry : SymEntry, ILookupController
{
public enum Genre
{
cClass,
cStruct,
cInterface,
cReference, // A reference isn't a Class/Struct/Interface
}
public static Genre GenreFromClrType(System.Type t)
{
if (t.IsInterface)
return Genre.cInterface;
else if (t.IsValueType)
return Genre.cStruct;
// ...
// This is another bug in the CLR Frameworks. MSDN clearly says that
// typeof(System.Enum).IsClass is supposed to be true
// (even though Enum derives from ValueType).
// But it's not, so we have to special case that.
// In V2,the docs will probably be changed to reflect the behavior
// (because we can't exactly change the behavior at this point). So
// in that sense, this will be converted from a 'bug' into a 'feature'.
else if (t.IsClass || (t == typeof(System.Enum)))
return Genre.cClass;
Debug.Assert(false, "expected Interface,Class, or Struct");
return Genre.cClass;
}
#region Construction
#region User Types
// We need 2-phase initilization
// 1 - Add stubs
// 2 - add rest of data (super class, base interfaces)
// Creating from a classdecl
public TypeEntry(
string stFullName,
AST.ClassDecl nodeDecl,
Genre genre,
Scope scopeParent
)
{
m_strName = (nodeDecl ==null) ? "<empty>" : nodeDecl.Name;
m_stFullName = stFullName;
m_decl = nodeDecl;
m_genre = genre;
if (genre == Genre.cReference)
{
}
else
{
this.m_mods = nodeDecl.Mods;
}
// Create a scope now so that we can add stubs for nested types into it.
// We'll have to set the super-scope later
// ******** need this for nested types ....
if (genre != Genre.cReference)
{
//m_scope = new Scope((m_genre.ToString()) + "_" + m_strName, nodeDecl, scopeParent);
m_scope = new Scope((m_genre.ToString()) + "_" + m_strName, this, scopeParent);
}
}
protected bool m_fIsInit = false;
public void InitLinks(
TypeEntry tSuper,
TypeEntry [] interfaces // can be null
)
{
Debug.Assert(m_fIsInit == false);
Debug.Assert(m_super == null);
m_interfaces = (interfaces == null) ? m_emptyinterfaces : interfaces;
m_super = tSuper;
// Set containing class, based off lexical scope
AST.ClassDecl nodeParent = m_scope.LexicalParent.Node as AST.ClassDecl;
if (nodeParent != null)
{
m_containingClass = nodeParent.Symbol;
Debug.Assert(m_containingClass != null);
}
}
// Sets super scope
public void FinishInit()
{
Debug.Assert(m_fIsInit == false);
// Relies on super classes being inited already
if (m_super != null)
{
Debug.Assert(m_super.m_fIsInit);
}
foreach(TypeEntry t in m_interfaces)
{
Debug.Assert(t.m_fIsInit);
}
// Set scopes
Debug.Assert(IsInterface || (m_super.MemberScope != null));
//Scope sSuper = (m_super == null) ? null : m_super.MemberScope;
//m_scope.SetSuperScope(sSuper);
m_fIsInit = true;
}
#endregion
#region Imported Types
// Return a stub used for importing
static public TypeEntry CreateImportStub(System.Type clrType)
{
return new TypeEntry(clrType);
}
public void FinishImportStub(
TypeEntry tSuper,
TypeEntry [] interfaces, // can be null,
TypeEntry tParent
)
{
m_interfaces = (interfaces == null) ? m_emptyinterfaces : interfaces;
m_super = tSuper;
m_containingClass = tParent;
m_fIsInit = true;
}
// Stub entry
private TypeEntry(System.Type clrType)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -