📄 semanticchecker.cs
字号:
int i = s.IndexOf('.');
// Search past namespaces
while(i != -1)
{
string stNamespace = s.Substring(iStart, i - iStart);
SymEntry sym = LookupSymbol(scope, stNamespace, false);
if (sym == null)
{
ImportedNamespaceEntry nsImported = new ImportedNamespaceEntry(
stNamespace,
s.Substring(0, i)
);
scope.AddSymbol(nsImported);
scope = nsImported.ChildScope;
}
else
{
// If the symbol already exists, must be a namespace
if (sym is NamespaceEntry)
{
scope = ((NamespaceEntry) sym).ChildScope;
}
else
{
ThrowError(SymbolError.IllegalAssembly(tImport.Assembly, "Illegal type: " + s));
}
}
iStart = i + 1;
i = s.IndexOf('.', iStart);
}
// If we're not a nested type, then we can return the scope now
if (tImport.DeclaringType == null)
{
Debug.Assert(s.Substring(iStart) == tImport.Name);
return scope;
}
// Containing class should have already been added.
Debug.Assert(TryLookupCLRType(tImport.DeclaringType) != null);
// Else we have to traverse the class scopes to find out containing scope.
// n.n. c1+c2
i = s.IndexOf('+', iStart);
while (i != -1)
{
string stClass = s.Substring(iStart, i - iStart);
TypeEntry tBlue = (TypeEntry) LookupSymbol(scope, stClass, true);
scope = tBlue.MemberScope;
Debug.Assert(scope != null);
iStart = i + 1;
i = s.IndexOf('+', iStart);
}
Debug.Assert(s.Substring(iStart) == tImport.Name);
return scope;
}
// Test to tell if a given type is generic.
static bool IsGenericType(System.Type t)
{
// Since Blue must compile on v1.1 CLR, the methods on Type to explicitly ask if it's generic are not available.
// So we use this hack: Generic types in C# have a backtick (`) before the type parameter.
return t.FullName.IndexOf('`') > 0;
}
//-----------------------------------------------------------------------------
// Helper to import the specific type and return a TypeEntry.
// This will recursively import all base types.
// Returns null if we can't import the type.
//-----------------------------------------------------------------------------
protected TypeEntry AddImportedType(System.Type tImport)
{
#if true
// Don't import non-public classes
// be wary of nesting
//if (tImport.IsClass || tImport.IsValueType)
{
if (tImport.DeclaringType == null)
{
// Not nested
if (!tImport.IsPublic)
return null;
} else {
// If Nested, check topmost containing class.
System.Type t = tImport;
while (t.DeclaringType != null)
{
t = t.DeclaringType;
}
if (!t.IsPublic)
return null;
}
}
#endif
// If we've already imported this, then nothing to do.
{
TypeEntry t = TryLookupCLRType(tImport);
if (t != null)
return t;
}
// Blue doesn't handle Generics (from V2.0 CLR), so just ignore them when imported.
if (IsGenericType(tImport))
{
Console.WriteLine("Skipping Generic type:" + tImport.FullName);
return null;
}
#if false
// Debugging facility. Userbreakpoint when we import a specific class.
if (tImport.Name == "IDictionaryEnumerator")
System.Diagnostics.Debugger.Break();
#endif
// Stub immediately to avoid infinite cycles.
TypeEntry tBlue = TypeEntry.CreateImportStub(tImport);
m_hashClrType.Add(tImport, tBlue);
// If we're a nested type, make sure our containing type is imported.
if (tImport.DeclaringType != null)
{
AddImportedType(tImport.DeclaringType);
}
Scope scope = this.CreateImportedContext(tImport);
string stClass = tImport.Name;
// Already check for multiple imports
//if (LookupSymbol(scope, stClass, false) == null)
{
// Add Base class
TypeEntry tSuper = null;
if (tImport.BaseType != null)
{
tSuper = AddImportedType(tImport.BaseType);
}
// Add interfaces, removing all interfaces that we can't access
System.Type [] tCLRInterfaces = tImport.GetInterfaces();
ArrayList al = new ArrayList(tCLRInterfaces.Length);
foreach(System.Type tInterface in tCLRInterfaces)
{
TypeEntry t = AddImportedType(tInterface);
if (t != null)
al.Add(t);
}
TypeEntry [] tBlueInterfaces = (TypeEntry[]) al.ToArray(typeof(TypeEntry));
TypeEntry tParent = (tImport.DeclaringType == null) ?
null :
this.ResolveCLRTypeToBlueType(tImport.DeclaringType);
// @todo - do we have to check if we've been imported again?
// We create the symbol, but don't add the scope until we need to.
// (else that would be a lot of scopes to add that we'd never use)
// Note that this must be done on the same reference that we added at the top
// because by now, the other types have links to that original reference.
tBlue.FinishImportStub(tSuper, tBlueInterfaces, tParent);
scope.AddSymbol(tBlue);
#if true
// If we have any nested classes, add them.
// This will require us to create the class scope.
System.Type [] tNestedTypes = tImport.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic);
if (tNestedTypes.Length > 0)
{
tBlue.EnsureScopeCreated();
foreach(System.Type tNested in tNestedTypes)
{
AddImportedType(tNested);
}
}
#endif
return tBlue;
}
/*
else
{
ThrowError(SymbolError.IllegalAssembly(tImport.Assembly,
"Class '" + tImport.FullName + "' defined multiple times"));
return null;
}
*/
} // end function
//-----------------------------------------------------------------------------
// Populate the symbol table with just the TypeEntry for all classes exposed
// through the given assembly. (Implicitly, this will add ImportedNamespaceEntries)
// The actual TypeEntry scopes will be populated on first access
//-----------------------------------------------------------------------------
protected void ImportAssembly(Assembly a)
{
// LoadFrom used for exact filename
// Load will look in the gac, etc
Log.WriteLine(Log.LF.Verbose, "Importing assembly:" + a.ToString());
Type [] typeList = a.GetTypes();
foreach(Type t in typeList)
{
if (t.IsNotPublic)
continue;
AddImportedType(t);
}
} // end ImportAssembly
protected Assembly GetMscorlib()
{
return Assembly.Load("mscorlib.dll");
}
#endregion
Scope m_scopeGlobal;
#region Mapping between CLR & Blue types
//-----------------------------------------------------------------------------
// Resolve a CLR type to a Blue Type
// How to handle array types?
//-----------------------------------------------------------------------------
public TypeEntry ResolveCLRTypeToBlueType(System.Type t)
{
Debug.Assert(t != null);
Debug.Assert(!IsGenericType(t), "Can't resolve CLR generic type:" + t.FullName);
if (t.IsArray)
{
ArrayTypeEntry a = new ArrayTypeEntry(t, this);
return a;
}
if (t.IsByRef)
{
System.Type clrElem = t.GetElementType();
TypeEntry blueElem = ResolveCLRTypeToBlueType(clrElem);
return new RefTypeEntry(blueElem, this);
}
TypeEntry type = (TypeEntry) m_hashClrType[t];
Debug.Assert(type != null, "type '" + t.ToString() + "' is unresolve in blue");
if (type == null)
{
Console.WriteLine("Dump: [");
IDictionaryEnumerator e = m_hashClrType.GetEnumerator();
while(e.MoveNext())
{
Console.WriteLine("{0}\t\t{1}", e.Key, e.Value);
}
Console.WriteLine("] End Dump");
}
return type;
}
// Return the Blue type for the clr interface
// May return null if we haven't added it yet.
protected TypeEntry TryLookupCLRType(System.Type t)
{
//Debug.Assert(t.IsInterface);
TypeEntry type = (TypeEntry) m_hashClrType[t];
return type;
}
public void AddClrResolvedType(TypeEntry sym)
{
Debug.Assert(sym != null);
Debug.Assert(sym.CLRType != null);
// Make sure the blue & CLR types actually match.
Debug.Assert(sym.FullName == sym.CLRType.FullName);
///////
System.Type tEnum = sym.CLRType;
/*
int iEnum1 = tEnum.GetHashCode();
int iEnum2 = ((object) tEnum).GetHashCode();
int iInt1 = typeof(int).GetHashCode();
int iInt2 = ((object) typeof(int)).GetHashCode();
bool fFlag1 = Object.Equals(tEnum, typeof(int));
bool fFlag2 = Object.Equals(typeof(int), tEnum);
bool f3 = (tEnum == typeof(int));
bool f4 = (typeof(int) == tEnum);
*/
//////////
try
{
m_hashClrType.Add(sym.CLRType, sym);
}
catch (System.Exception e)
{
object o = m_hashClrType[sym.CLRType];
Debug.Assert(false, "Exception:"+ e.Message);
}
}
//-----------------------------------------------------------------------------
// ...
// Another bug in the frameworks (10/29/01). System.Type has bad implementions
// of GetHashCode() and Equals() that make them unsuitable for use with
// a Hashtable. In particular, a TypeBuilder on an enum is viewed the same
// as the it's underlying type.
// So we have to have our own comparer that actually works.
//-----------------------------------------------------------------------------
class TypeHashProvider : IComparer, IHashCodeProvider
{
public virtual int GetHashCode(object obj)
{
return obj.ToString().GetHashCode();
}
// return 0 if (a==b), else 1
public virtual int Compare(object objA, object objB)
{
Debug.Assert(objA is Type);
Debug.Assert(objB is Type);
#if false
int iActual = CompareFast(objA, objB);
#if DEBUG
// Our comparison should be functionally equivalent to comparing
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -