📄 scope.cs
字号:
//-----------------------------------------------------------------------------
// Scope.cs
// Represent a scope
//-----------------------------------------------------------------------------
using System;
using System.Diagnostics;
using System.Xml;
using Blue.Public;
namespace SymbolEngine
{
//-----------------------------------------------------------------------------
/// <summary>
/// IScopeLookup is used by a <see cref="Scope"/> to do a smart lookup.
/// <seealso cref="Scope"/>
/// </summary>
/// <remarks>
/// While all scopes have the same notion of 'lexical' parent, each type of
/// scope has its own notion of 'super' or 'inherited' parent. For example:
/// <list type="bullet">
/// <item>BlockStatement, Method - 0 parents </item>
/// <item>Class - 1 parent, for the base class</item>
/// <item>Interfaces - multiple parents, 1 parent for each base interface</item>
/// <item>Namespace - A pseudo-parent from each using clauses.</item>
/// </list>
///
/// Either Nodes or Symbols may implement IScopeLookup, depending on which
/// can best provide the super class.
/// Only a Scope should have a reference to these.
///</remarks>
//-----------------------------------------------------------------------------
public interface ILookupController
{
// @todo - can I remove the Scope paremeters to this and DumpScope?
// The main worker function.
// Look for the given identifier in the given scope.
// This is a smart lookup because it can use extra information to search
// the scope's dynamic range (ex: super classes, using-clauses)
// Return Null if not found. (Don't throw an exception).
SymEntry SmartLookup(string stIdentifier, Scope scope);
// Get a node responsible for this scope.
// For imported types, this will be null
AST.Node OwnerNode { get ; }
// Get a symbol responsible for this scope.
// This may be null. (If this is null, then OwnerNode should not be null).
SymEntry OwnerSymbol { get; }
// For debugging purposes. Used by DumpTree();
void DumpScope(Scope scope);
}
//-----------------------------------------------------------------------------
/// <summary>
/// A scope is a low-level object to associate <see cref="Identifier"/> objects
/// with <see cref="SymEntry"/> objects.
/// <seealso cref="ILookupController"/>
/// </summary>
/// <remarks>
///
/// <para>Every scope has a lexical parent. The following list shows what type
/// of scopes can be lexically nested in which other scopes:
/// <list type="bullet">
/// <item>block -> block, method</item>
/// <item>method -> class</item>
/// <item>class -> class, interface, namespace</item>
/// <item>interface -> namespace </item>
/// <item>namespace -> namespace</item>
/// </list> </para>
///
/// <para> Scopes have no knowledge of either the higher level type-system nor any
/// object derived from <see cref="SymEntry"/>. </para>
///
/// <para> Each of the different scopes above may also inherit items from super scopes
/// A class's scope inherits from its base class. An interface inherits from all of
/// its base interfaces. Some scopes, such as those for blocks and methods, only have
/// a lexical parent, but no logical parent to inherit from.</para>
/// <para>Because a scope is a 'dumb' object, it can't be aware of its super scopes.
/// So a scope uses an <see cref="ILookupController"/> to do smart lookups in
/// super scopes.</para>
/// </remarks>
//-----------------------------------------------------------------------------
public class Scope
{
#region Construction
private Scope()
{
m_fIsLocked = false;
m_pController = null;
#if DEBUG
// Set unique id
m_id = m_count;
m_count++;
#endif
}
/// <summary>
/// Create a Scope object
/// <seealso cref="CreateSharedScope"/>
/// </summary>
/// <param name="szDebugName">A string name to identify the scope for debugging uses.</param>
/// <param name="pController">An ILookupController to allow the scope to do smart lookups. (can be null)</param>
/// <param name="scopeLexicalParent">The lexical parent of the scope. (may be null). </param>
public Scope(string szDebugName, ILookupController pController, Scope scopeLexicalParent)
: this()
{
#if false
if (szDebugName == "cClass_")
System.Diagnostics.Debugger.Break();
#endif
m_szDebugName = szDebugName;
m_pController = pController;
m_LexicalParent = scopeLexicalParent;
m_table = new System.Collections.Hashtable();
}
/// <summary>
/// Create a scope that has its own controller and lexical parent, but shares
/// a set of symbols with an existing scope.
/// </summary>
/// <remark>
/// We may want multiple Scopes with different controllers but that share
/// the same symbol set.
/// <para>Ex: A namespace can be declared in multiple blocks. All sections reside
/// in the same scope. However, each block has its own set of using
/// directives. So we want multiple scopes that share the same set of symbols,
/// but each scope needs its own controller to handle its own set of using directives</para>
/// </remark>
/// <param name="pController">The controller for the new scope</param>
/// <param name="scopeLexicalParent"></param>
/// <returns>A new scope with the specified lexical parent and owned by the given
/// controller, but sharing the same set of symbols as the current scope.</returns>
public Scope CreateSharedScope(ILookupController pController, Scope scopeLexicalParent)
{
Scope s = new Scope();
s.m_szDebugName = m_szDebugName;
s.m_pController = pController;
s.m_LexicalParent = scopeLexicalParent;
// Both scopes share the same table.
s.m_table = m_table;
return s;
}
#endregion
#region Properties & Data
// All for debugging:
public string m_szDebugName;
// Provide unique ids for each scope.
#if DEBUG
private static int m_count = 0;
private int m_id;
#endif
// A scope's only link to the higher level world.
ILookupController m_pController;
/// <summary><value>
/// A symbol associated with this scope.
/// </value></summary>
public SymEntry Symbol
{
get { return m_pController.OwnerSymbol; }
}
/// <summary><value>
/// An AST node associated with this scope.
/// </value></summary>
public AST.Node Node
{
get { return m_pController.OwnerNode; }
}
// Store the actual SymEntrys in a hash.
protected System.Collections.Hashtable m_table;
// m_LexicalParent - our lexical parent scope. Non-null except for single global scope.
internal Scope m_LexicalParent;
/// <summary><value>
/// The lexical parent of this scope.
/// </value></summary>
/// <remarks>
/// Scopes are identified on the source level and they can be lexically nested within
/// each other. The chain of lexical parents form a context.
/// <para>Imported types have no lexical parent because they have no source.</para>
/// </remarks>
public Scope LexicalParent
{
get { return m_LexicalParent; }
}
#endregion
#region Locking
// A locked scope can't be added too. Useful for imported scopes, and
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -