📄 ast.cs
字号:
// Return symbol if found.
// Return null if not found.
public SymEntry LookupSymbol(string stText)
{
SymEntry sym = null;
if (IsAliasType)
{
// For an alias, if the string name matches, then we already have the symbol
// to return. No search needed.
if (stText == m_stAlias)
{
if (m_eNamespace is NamespaceExp)
{
return ((NamespaceExp) m_eNamespace).Symbol;
}
else if (m_eNamespace is TypeExp)
{
return ((TypeExp) m_eNamespace).Symbol;
}
Debug.Assert(false);
}
}
else
{
// Lookup in associated namespace
Scope scope = ((NamespaceExp) m_eNamespace).Symbol.ChildScope;
sym = scope.LookupSymbolInThisScopeOnly(stText);
// We specifically do not look in nested namespaces
// See section 9.3.2 of the C# spec for details
if (sym is NamespaceEntry)
sym = null;
}
return sym;
}
public void Resolve(ISemanticResolver s, Scope scopeNamespace)
{
// Have to see what our namespace / class resolves to.
//m_eNamespace.ResolveExpAsRight(s);
Exp.ResolveExpAsRight(ref m_eNamespace, s);
if (IsAliasType)
{
// Alias could be to either a class or namespace
//Debug.Assert(m_eNamespace.SymbolMode != ObjExp.Mode.cExpEntry);
Debug.Assert(m_eNamespace is TypeExp || m_eNamespace is NamespaceExp);
}
else
{
// Directives can only give us namespaces
//Debug.Assert(m_eNamespace.SymbolMode == ObjExp.Mode.cNamespaceEntry);
Debug.Assert(m_eNamespace is NamespaceExp);
}
}
#endregion
#region Checks
public override void Dump(XmlWriter o)
{
o.WriteStartElement("Using");
if (m_stAlias != null)
o.WriteAttributeString("alias", m_stAlias);
m_eNamespace.Dump(o);
o.WriteEndElement();
}
// Debugging check
public override void DebugCheck(ISemanticResolver s)
{
}
#endregion
}
//-----------------------------------------------------------------------------
// Declare a user namespace
// Note that a single namespace can be declared across multiple NamespaceDecls.
// Each source file is considered to be in the Global Namespace.
// Each namespace block can have its own set of using directives. (So even
// if 2 blocks refer to the same namespace, they can have different using
// directives)
//-----------------------------------------------------------------------------
public class NamespaceDecl : Node, SymbolEngine.ILookupController
{
#region Construction
// Any of the array parameters may be null
public NamespaceDecl(
Identifier idName, // must be non-null
UsingDirective [] arUsingDirectives,
NamespaceDecl[] arNestedNamespaces,
ClassDecl[] arClasses,
TypeDeclBase[] arTypes
)
{
m_idName = idName;
m_arUsingDirectives = (arUsingDirectives == null) ? new UsingDirective [0] : arUsingDirectives;
m_arNestedNamespaces = (arNestedNamespaces == null) ? new NamespaceDecl[0] : arNestedNamespaces;
//m_arClasses = (arClasses == null) ? new ClassDecl[0] : arClasses;
Debug.Assert(arClasses == null);
m_arTypes = (arTypes == null) ? new TypeDeclBase[0] : arTypes;
}
#endregion
#region Other Functions
// Recursively Create a flat list of classes in a program
public void ReportClasses(ArrayList alClasses)
{
// At each stop, we make sure all of our prerequisite types are added
// before us. So it doesn't matter what order we add in here.
foreach(TypeDeclBase e in m_arTypes)
e.ReportClass(alClasses);
// Recursively add all classes from nested namespaces
foreach(NamespaceDecl n in NestedNamespaces)
n.ReportClasses(alClasses);
}
#endregion
#region Properties & Data
Identifier m_idName;
UsingDirective [] m_arUsingDirectives;
NamespaceDecl[] m_arNestedNamespaces;
//ClassDecl[] m_arClasses;
//EnumDecl[] m_arEnums;
// @todo -merge this with classes
TypeDeclBase [] m_arTypes;
UserNamespaceEntry m_symbol;
public string Name
{
get { return m_idName.Text; }
}
public NamespaceDecl[] NestedNamespaces
{
get { return m_arNestedNamespaces; }
}
Scope m_context;
#endregion
#region Resolution
#region Impl ILookupController
// @dogfood - make these explicit interface methods
// Return null if not found.
public SymEntry SmartLookup(string stIdentifier, Scope scope)
{
// Do a normal lookup of things defined directly in this namespace.
SymEntry sym = scope.LookupSymbolInThisScopeOnly(stIdentifier);
if (sym != null)
return sym;
// Look in the using directives associated with this namespace node.
sym = LookupSymbolInUsingDirectives(stIdentifier);
return sym;
}
// Get a node responsible for this scope.
// For imported types, this will be null
public AST.Node OwnerNode {
get { return this; }
}
// 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.m_symbol; }
}
public void DumpScope(Scope scope)
{
if (this.m_arUsingDirectives.Length > 0)
{
Console.Write("[has using...]");
}
return;
}
#endregion
#if true
// Check the using directives in this namespace block.
// Give precedence to an alias over a directive.
// Return null if not found.
// Throw error if ambigious (ie, a symbol can be found refered from multiple
// using directives)
// If we haven't resolved all of our own using directives yet, then return null
// (this is to prevent using directives from affecting each other)
public SymEntry LookupSymbolInUsingDirectives(string stName)
{
if (!m_fResolvedUsing)
return null;
// @todo - resolve ambiguity
SymEntry sym = null;
foreach(UsingDirective u in this.m_arUsingDirectives)
{
sym = u.LookupSymbol(stName);
if (sym != null)
return sym;
}
return null;
}
#endif
// Flag to note if our using decls have been resolved yet
bool m_fResolvedUsing = false;
// Before we can process the classes, we need to add all the namespaces
public void ResolveNamespace(
string stParentNamespace,
ISemanticResolver s,
Scope scopeParent)
{
Debug.Assert(m_symbol == null);
// We can have one namespaces spread across multiple blocks (NamespaceDecl).
// All blocks share the same scope (something defined in any block is visible
// to all blocks), but each block can have its own lexical parent & set
// of using clause.
#if true
m_symbol = (UserNamespaceEntry) scopeParent.LookupSymbolInThisScopeOnly(Name);
if (m_symbol == null)
{
// Create new namespace
string stFullName;
if (stParentNamespace == "")
stFullName = this.Name;
else
stFullName = stParentNamespace + "." + this.Name;
m_symbol = new UserNamespaceEntry(this, stFullName);
scopeParent.AddSymbol(m_symbol);
}
// The symbol has the scope with all the data. But each namespace decl creates
// a proxy scope that links to the symbol's data (Because all blocks share that)
// but has a tie to its own set of using clauses & lexical parent.
m_context = m_symbol.ChildScope.CreateSharedScope(this, scopeParent);
foreach(NamespaceDecl n in NestedNamespaces)
n.ResolveNamespace(m_symbol.FullName, s, m_context);
#else
// Since we can have multiple disjoint namespace decls refer
// to the same namespace, we have to check and see if this
// symbol is already created.
m_symbol = (UserNamespaceEntry) s.GetCurrentScope().LookupSymbolInThisScopeOnly(Name);
if (m_symbol == null)
{
string stFullName;
if (stParentNamespace == "")
stFullName = this.Name;
else
stFullName = stParentNamespace + "." + this.Name;
m_symbol = new UserNamespaceEntry(this, stFullName);
s.GetCurrentScope().AddSymbol(m_symbol);
}
EnterNamespace(s);
foreach(NamespaceDecl n in NestedNamespaces)
n.ResolveNamespace(m_symbol.FullName, s, scopeParent);
ExitNamespace(s);
#endif
}
/*
void EnterNamespace(ISemanticResolver s)
{
m_symbol.SetCurrentNode(this);
s.PushScope(m_symbol.ChildScope);
}
void ExitNamespace(ISemanticResolver s)
{
m_symbol.SetCurrentNode(null);
s.PopScope(m_symbol.ChildScope);
}
*/
// Resolve the using declarations
public void ResolveUsingDecls(ISemanticResolver s)
{
// All using declarations are resolved at global scope,
// so don't enter / exit namespaces here
//EnterNamespace(s);
// Resolve all the using clauses in this namespace block
Scope prev = s.SetCurrentContext(this.m_context);
foreach(UsingDirective u in this.m_arUsingDirectives)
u.Resolve(s, m_context);
s.RestoreContext(prev);
// Recursively add all classes from nested namespaces
foreach(NamespaceDecl n in NestedNamespaces)
n.ResolveUsingDecls(s);
//ExitNamespace(s);
m_fResolvedUsing = true;
}
public void ResolveTypesAsBlueStub(
ISemanticResolver s)
{
//EnterNamespace(s);
// add all classes in this namespace
{
foreach(TypeDeclBase e in m_arTypes)
e.ResolveTypesAsBlueStub(s, this.m_symbol.FullName, m_context);
}
// Recursively add all classes from nested namespaces
foreach(NamespaceDecl n in NestedNamespaces)
n.ResolveTypesAsBlueStub(s);
//ExitNamespace(s);
}
public void ResolveTypesAsCLR(
ISemanticResolver s,
ICLRtypeProvider provider
)
{
// We shouldn't have to update the scope stack since
// we should only be looking at resolved symbols
Scope prev = s.SetCurrentContext(m_context);
// add all classes in this namespace
{
foreach(TypeDeclBase e in m_arTypes)
e.ResolveTypesAsCLR(s, provider);
}
s.RestoreContext(prev);
// Recursively add all classes from nested namespaces
foreach(NamespaceDecl n in NestedNamespaces)
n.ResolveTypesAsCLR(s, provider);
}
public void ResolveMemberDecls(
ISemanticResolver s,
ICLRtypeProvider provider
)
{
// Do for all types in this namespace
foreach(TypeDeclBase e in m_arTypes)
e.ResolveMemberDecls(s, provider);
// Recursively do all classes from nested namespaces
foreach(NamespaceDecl n in NestedNamespaces)
n.ResolveMemberDecls(s, provider);
}
// Resolve the bodies of methods
public void ResolveBodies(ISemanticResolver s)
{
foreach(TypeDeclBase e in m_arTypes)
e.ResolveBodies(s);
// Recursively add all classes from nested namespaces
foreach(NamespaceDecl n in NestedNamespaces)
n.ResolveBodies(s);
}
#endregion
#region Checks
// Dump the AST node contents to an xml file
public override void Dump(XmlWriter o)
{
o.WriteStartElement("Namespace");
o.WriteAttributeString("name", Name);
o.WriteStartElement("UsingDirectives");
foreach(UsingDirective n in m_arUsingDirectives)
n.Dump(o);
o.WriteEndElement();
o.WriteStartElement("NestedNamespaces");
foreach(NamespaceDecl n in m_arNestedNamespaces)
n.Dump(o);
o.WriteEndElement();
/*
o.WriteStartElement("Classes");
foreach(ClassDecl n in m_arClasses)
n.Dump(o);
o.WriteEndElement();
*/
o.WriteStartElement("Types");
foreach(TypeDeclBase e in m_arTypes)
e.Dump(o);
o.WriteEndElement();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -