📄 scope.cs
字号:
// for finializing scopes after we've resolved a symbol.
// Locking is also a useful flag to implement lazy evaluation because
// it lets us check if a scope has been finished.
bool m_fIsLocked;
internal void LockScope()
{
m_fIsLocked = true;
}
internal bool IsLocked
{
get { return m_fIsLocked; }
}
#endregion
#region Add & Lookup operations
/// <summary>
/// Add a symbol to this scope. (SymEntry contains the string name)
/// <seealso cref="AddAliasSymbol"/>
/// </summary>
/// <remarks>
/// Adds the given Symbol to this scope, and indexes it by the symbol's name.
/// </remarks>
/// <param name="s">The symbol to add</param>
public void AddSymbol(SymEntry s)
{
Debug.Assert(!m_fIsLocked, "Can't add to a locked scope");
Debug.Assert(s != null);
Debug.Assert(s.Name != null);
// If we try to add the symbol and it's already there, we have a Symbol-Redefinition
// error. Hashtable.Add() will throw an exception, we catch that, and then throw our
// own version.
// We choose to catch, rather than to check first, because we optimize for the
// non-error case.
try
{
m_table.Add(s.Name, s); // this already throws
}
catch(ArgumentException)
{
// @todo - How should we handle this error?
Debug.Assert(false, "@todo - symbol already defined");
}
}
/// <summary>
/// Add a symbol under an aliased name.
/// </summary>
/// <remarks>
/// Add an existing symbol entry, but indexed under a new name
/// <para><example>
/// [globalscope].AddAliasSymbol("int", [SymEntry for System.Int32]);
/// </example></para>
/// <seealso cref="AddSymbol"/>
/// </remarks>
/// <param name="stAliasName">Aliased name of the symbol</param>
/// <param name="s">Symbol to add</param>
public void AddAliasSymbol(string stAliasName, SymEntry s)
{
Debug.Assert(!m_fIsLocked, "Can't add to a locked scope");
m_table.Add(stAliasName, s);
}
/// <summary>
/// Do a deep lookup in this scope. This includes super scopes but not lexical parents.
/// </summary>
/// <remarks>
/// <para>If this scope does not have an ILookupController, this is equivalent to
/// just calling <see cref="LookupSymbolInThisScopeOnly"/> </para>
/// <para>else this calls <see cref="ILookupController.SmartLookup"/></para>
/// </remarks>
/// <param name="strName">String name to search for</param>
/// <returns>A symbol added under this name. Null if not found.</returns>
public SymEntry LookupSymbol(string strName)
{
// @todo - we do this when looking for namespaces during import.
// If it's not there, we add it.
// It would be nice to enable this assert though...
//Debug.Assert(m_fIsLocked, "Don't lookup a symbol in an unlocked scope");
if (m_pController == null)
return this.LookupSymbolInThisScopeOnly(strName);
else
return m_pController.SmartLookup(strName, this);
}
/// <summary>
/// Lookup a SymEntry only in this scope. Don't search super scopes or lexical parents.
/// </summary>
/// <remarks>This is a shallow lookup that does not invoke the ILookupController</remarks>
/// <param name="strName">String name to search for.</param>
/// <returns>A symbol added under this name. Null if not found.</returns>
public SymEntry LookupSymbolInThisScopeOnly(string strName)
{
return (SymEntry) m_table[strName];
}
// If we don't know the string name and we need to do a more elaborate
// match (ex, say on parameters), then we have to provide access to our
// values.
// So expose an enumerator for the all the SymEntry in this scope.
public System.Collections.IEnumerator GetEnumerator()
{
return this.m_table.Values.GetEnumerator();
}
#endregion
#region Checks
#if DEBUG
// Dump a tree view of the scope tree that this is a root for.
// Includes the super scopes & lexical parents.
public void DumpTree()
{
Console.WriteLine("** Debug print of current context **");
Scope s = this;
int i = 0;
while (s != null)
{
Console.Write("{0}:#{1},{2}", i, s.m_id, s.m_szDebugName);
if (s.m_pController != null)
{
object o = s.m_pController;
Console.Write("({0})", o.GetType().Name);
s.m_pController.DumpScope(s);
}
Console.WriteLine();
i++;
s = s.LexicalParent;
}
}
// Dump all the raw entries
public void DumpKeys()
{
Console.WriteLine("*** Debug dump of keys in scope #{0},{1} [", this.m_id, this.m_szDebugName);
System.Collections.IDictionaryEnumerator e = m_table.GetEnumerator();
while (e.MoveNext())
{
string str = (string) e.Key;
SymEntry sym = (SymEntry) e.Value;
Console.WriteLine("{0} is a {1}", str, sym.ToString());
}
Console.WriteLine("] End dump");
}
#endif
// Verify integrity of all symbol elements in this scope
public void DebugCheck(ISemanticResolver s)
{
System.Collections.IDictionaryEnumerator e = m_table.GetEnumerator();
while (e.MoveNext())
{
string str = (string) e.Key;
SymEntry sym = (SymEntry) e.Value;
sym.DebugCheck(s);
}
}
// Dump the scope to an xml file
public void Dump(XmlWriter o, bool fRecursive)
{
o.WriteStartElement("scope");
o.WriteAttributeString("name", m_szDebugName);
ILookupController p = this.m_pController;
o.WriteAttributeString("controller", (p == null) ? "none" : ((object) p).GetType().Name);
/*
if (m_SuperScope != null)
{
o.WriteAttributeString("super", m_SuperScope.m_szDebugName);
}
*/
System.Collections.IDictionaryEnumerator e = m_table.GetEnumerator();
while (e.MoveNext())
{
string str = (string) e.Key;
SymEntry sym = (SymEntry) e.Value;
sym.Dump(o, fRecursive);
}
o.WriteEndElement(); // scope
}
// Debug function
public void DebugConsoleDump()
{
XmlWriter o = new XmlTextWriter(Console.Out);
bool f = true;
if (f)
Dump(o, true);
else
Dump(o, false);
o.Close();
}
#endregion
} // end class scope
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -