// 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 }
// Semantic checking // Stubs can be resolved in any order. public override void ResolveTypesAsBlueStub( ISemanticResolver s, string stNamespace, Scope scopeParent ) { // Get our name. Nested classes are separated with a '+' // Namespaces are separated with a '.' string stFullName = (stNamespace == "") ? (m_strName) : (stNamespace + "." + m_strName); // Are we a nested class? if (scopeParent.Node is ClassDecl) { Debug.Assert(stNamespace != ""); stFullName = stNamespace + "+" + m_strName; } // Create a stub sym entry to add to current scope m_symbol = new TypeEntry(stFullName, this, m_genre, scopeParent); scopeParent.AddSymbol(m_symbol); // Stub on nested types //s.PushScope(m_symbol.MemberScope); // Our context is the same as the scope on our symbol Scope context = m_symbol.MemberScope; Debug.Assert(context != null); s.SetCurrentClass(m_symbol); foreach(TypeDeclBase t in this.m_alNestedTypes) { t.ResolveTypesAsBlueStub(s, stFullName, context); } s.SetCurrentClass(null); //s.PopScope(m_symbol.MemberScope); }
//----------------------------------------------------------------------------- // 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
// Semantic checking // Stubs can be resolved in any order. public override void ResolveTypesAsBlueStub( ISemanticResolver s, string stNamespace, Scope scopeParent ) { // Get our name. Nested classes are separated with a '+' // Namespaces are separated with a '.' string stFullName = (stNamespace == "") ? (Name.Text) : (stNamespace + "." + Name.Text); // Are we a nested class? if (scopeParent.Node is ClassDecl) { Debug.Assert(stNamespace != ""); stFullName = stNamespace + "+" + Name.Text; } // Create a stub sym entry to add to current scope m_symbol = new EnumTypeEntry(Name.Text, stFullName, s, m_mods, this, scopeParent); scopeParent.AddSymbol(m_symbol); }
//----------------------------------------------------------------------------- // Create the scopes for an imported types //----------------------------------------------------------------------------- Scope CreateImportedContext(System.Type tImport) { // Traverse namespaces to find scope Scope scope = m_scopeGlobal; string s = tImport.ToString(); // In a type's string name, the '.' separates namespaces, // the '+' separates for nested classes. // Valid form: // i.i.i+i+i+i int iStart = 0; 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; }