public void DumpScope(Scope scope) { if (this.m_arUsingDirectives.Length > 0) { Console.Write("[has using...]"); } return; }
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); } }
// @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; }
// 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); }
public void ResolveNamespace(ISemanticResolver s, Scope scopeGlobal) { // First must do namespaces so that type stubs even // have a context. foreach(NamespaceDecl n in m_nGlobal) n.ResolveNamespace("", s, scopeGlobal); // Next, resolve type stubs so that using alias at least // has stub types to refer to ResolveTypeStubs(s); // Now resolve Using decls. Have to do this before we // try and use any types (since using decls will affect resolution) foreach(NamespaceDecl n in m_nGlobal) n.ResolveUsingDecls(s); }
/// <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(); }
// Global namespace has "" name. public UserNamespaceEntry(AST.NamespaceDecl node, string stFullName) { Debug.Assert(node != null); Debug.Assert(stFullName != null); m_strName = node.Name; m_stFullName = stFullName; // Create the real scope for the namespace. This scope just has the symbols, // but it can't be attached to a particular node or lexical parent // since it's shared by all blocks for that namespace. if (IsGlobal) { // Add filename as a debugging hint string stFilename = node.Location.Filename; m_scope = new Scope("global " + stFilename, null, null); } else { m_scope = new Scope("user_namespace:" + node.Name, null, null); } //m_node = node; m_node = null; }
public virtual void RestoreContext(Scope scopePreviousContext) { m_CurrentContext = scopePreviousContext; }
// Semantic resolution public override void ResolveStatement(ISemanticResolver s) { Scope prev = null; if (this.m_arLocals.Length != 0) { //s.PushScope(m_scopeLocals); m_scopeLocals = new Scope("block_scope", null, s.GetCurrentContext()); prev = s.SetCurrentContext(m_scopeLocals); } foreach(LocalVarDecl v in Locals) { v.ResolveVarDecl(s); } foreach(Statement stmt in Statements) { stmt.ResolveStatement(s); } if (m_scopeLocals != null) //s.PopScope(m_scopeLocals); s.RestoreContext(prev); }
// Get rid of this function public SymEntry LookupSymbol(Scope scope, string st, bool fMustExist) { SymEntry s = scope.LookupSymbol(st); bool f= false; if (f) { System.Xml.XmlWriter o = new System.Xml.XmlTextWriter(new System.IO.StreamWriter("dump.xml")); scope.Dump(o, true); o.Close(); } if (fMustExist && s == null) { FileRange range = new FileRange(); range.Filename = "<not specified>"; Identifier id = new Identifier(st, range); //ThrowError_UndefinedSymbol(id); ThrowError(SymbolError.UndefinedSymbol(id)); } return s; }
// Sets the current context that we lookup symbols against. // Returns the previous current context, which should be // passed to RestoreContext() public virtual Scope SetCurrentContext(Scope scopeNewContext) { Scope prev = m_CurrentContext; m_CurrentContext = scopeNewContext; return prev; }
// We only need Lookup() during the resolve phase (because that's the only time // we need to convert text into symbols) // After that, we can just use the symbols directly // Lookup an entry in a specific scope // If it doesn't exist, then return null if !fMustExist and throw if fMustExist public SymEntry LookupSymbol(Scope scope, Identifier id, bool fMustExist) { SymEntry s = scope.LookupSymbol(id.Text); if (fMustExist && s == null) { ThrowError(SymbolError.UndefinedSymbol(id)); } return s; }
//----------------------------------------------------------------------------- // Main checking routine // Return true if successful, else false //----------------------------------------------------------------------------- public bool DoCheck( AST.ProgramDecl p, ICLRtypeProvider provider, Assembly [] refs ) { Debug.Assert(provider != null); Debug.Assert(p != null); m_provider = provider; string stSubPhase = ""; try { m_scopeGlobal = new Scope("Global", null, null); // Import symbols stSubPhase = "importing assemblies"; ImportAssembly(GetMscorlib()); AddDefaultTypes(m_scopeGlobal); foreach(Assembly a in refs) { ImportAssembly(a); } // Pass 1 - Resolve the namespaces and stub the types. // This will stub all scopes and create a lexical-scope tree. stSubPhase = "resolving namespaces"; p.ResolveNamespace(this, m_scopeGlobal); // Pass 2 - Resolve Types (to both CLR & Blue) stSubPhase = "resolving to clr types"; p.ResolveTypes(this, provider); // Pass 3 - resolve class member declarations (Methods & fields) stSubPhase = "resolving member declarations"; p.ResolveMemberDecls(this, provider); // Pass 4 - resolve method bodies stSubPhase = "resolving member bodies"; p.ResolveBodies(this); // Final Debug verify before codegen stSubPhase = "final debug check"; p.DebugCheck(this); m_scopeGlobal.DebugCheck(this); p.NotifyResolutionDone(); return true; } // Strip away SymbolErrors; we've already reported them when we first threw them. catch (SymbolError.SymbolErrorException) { return false; } catch(System.Exception e) { Blue.Driver.PrintError_InternalError(e, "Symbol Resolution(" + stSubPhase + ")"); return false; } }
//----------------------------------------------------------------------------- // Add aliases for the default types // Must have loaded mscorlib.dll first //----------------------------------------------------------------------------- protected void AddDefaultTypes(Scope scopeGlobal) { // Alias scopeGlobal.AddAliasSymbol("int", LookupSystemType("Int32")); scopeGlobal.AddAliasSymbol("void", LookupSystemType("Void")); scopeGlobal.AddAliasSymbol("char", LookupSystemType("Char")); scopeGlobal.AddAliasSymbol("bool", LookupSystemType("Boolean")); scopeGlobal.AddAliasSymbol("string", LookupSystemType("String")); scopeGlobal.AddAliasSymbol("object", LookupSystemType("Object")); // Ensure that compound types that are backed by a core clr type are resovled. // (mainly Array, Enum, Delegate) TypeEntry tArray = LookupSystemType("Array"); tArray.EnsureResolved(this); TypeEntry tEnum = LookupSystemType("Enum"); tEnum.EnsureResolved(this); TypeEntry tDelegate = LookupSystemType("MulticastDelegate"); tDelegate.EnsureResolved(this); }
// 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 }
// Resolution functions public override void ResolveTypesAsBlueStub( ISemanticResolver s, string stNamespace, // namespace that a type goes in. Includes nested classes. Scope scopeParent ) { CreateProxyType(s); this.m_nodeProxy.ResolveTypesAsBlueStub(s, stNamespace, scopeParent); // We can go ahead and resolve the rest because we know that a Delegate // doesn't inherit / implement interfaces for other user-defined classes. //this.m_nodeProxy.ResolveTypesAsBlueLinks(s); //this.m_nodeProxy.ResolveTypesAsBlueFinal(s); }
// Resolution is the act of changing strings (in a parse tree) into symbols. // Symbols are associated with the appropriate object in the System.Reflection] // namespace. public abstract void ResolveTypesAsBlueStub( ISemanticResolver s, string stNamespace, // namespace that a type goes in. Includes nested classes. Scope scopeParent // our Lexical parent's scope that we should add ourselves too. );
// 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); }
/// <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; }
// assembly we're imported from? public ImportedNamespaceEntry(string stNamespace, string stFullName) { m_strName = stNamespace; m_stFullName = stFullName; m_scope = new Scope("imported_namespace:" + stFullName, null, null); }