source: src/AST/SymbolTable.hpp@ 2d6add4

Last change on this file since 2d6add4 was 85855b0, checked in by JiadaL <j82liang@…>, 16 months ago
  1. Implement enum cast; 2. Change valueE so that opague enum returns quasi_void; 3. change enum hiding interpretation and pass visiting scheme
  • Property mode set to 100644
File size: 11.1 KB
RevLine 
[d76c588]1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// SymbolTable.hpp --
8//
9// Author : Aaron B. Moss
10// Created On : Wed May 29 11:00:00 2019
11// Last Modified By : Aaron B. Moss
12// Last Modified On : Wed May 29 11:00:00 2019
13// Update Count : 1
14//
15
16#pragma once
17
18#include <memory> // for shared_ptr, enable_shared_from_this
19#include <vector>
20
21#include "Fwd.hpp"
22#include "Node.hpp" // for ptr, readonly
[c92bdcc]23#include "Common/CodeLocation.hpp"
24#include "Common/PersistentMap.hpp"
[d76c588]25
26namespace ResolvExpr {
27 class Cost;
28}
29
30namespace ast {
31
32/// Builds and stores the symbol table, mapping identifiers to declarations.
33class SymbolTable final : public std::enable_shared_from_this<ast::SymbolTable> {
34public:
[e5c3811]35 /// special functions stored in dedicated tables, with different lookup keys
36 enum SpecialFunctionKind {CTOR, DTOR, ASSIGN, NUMBER_OF_KINDS};
37 static SpecialFunctionKind getSpecialFunctionKind(const std::string & name);
38
[d76c588]39 /// Stored information about a declaration
40 struct IdData {
41 readonly<DeclWithType> id = nullptr; ///< Identifier of declaration
42 readonly<Expr> baseExpr = nullptr; ///< Implied containing aggregate (from WithExpr)
[e67991f]43 readonly<Decl> deleter = nullptr; ///< Node deleting this declaration (if non-null)
[d76c588]44 unsigned long scope = 0; ///< Scope of identifier
45
46 IdData() = default;
[e67991f]47 IdData( const DeclWithType * i, const Expr * base, const Decl * del, unsigned long s )
[d76c588]48 : id( i ), baseExpr( base ), deleter( del ), scope( s ) {}
[e67991f]49
[6a0b043]50 /// Create a new IdData, updating the deleter value.
51 IdData withDeleter( const Decl * decl ) const {
52 return IdData( id, baseExpr, decl, scope );
53 }
[d76c588]54
55 /// Constructs an expression referring to this identifier.
56 /// Increments `cost` by cost of reference conversion
57 Expr * combine( const CodeLocation & loc, ResolvExpr::Cost & cost ) const;
58 };
59
60private:
61 /// wraps a reference to D with a scope
62 template<typename D>
63 struct scoped {
64 readonly<D> decl; ///< wrapped declaration
[e67991f]65 unsigned long scope; ///< scope of this declaration
[d76c588]66
67 scoped(const D * d, unsigned long s) : decl(d), scope(s) {}
68 };
69
70 using MangleTable = PersistentMap< std::string, IdData >;
71 using IdTable = PersistentMap< std::string, MangleTable::Ptr >;
72 using TypeTable = PersistentMap< std::string, scoped<NamedTypeDecl> >;
73 using StructTable = PersistentMap< std::string, scoped<StructDecl> >;
74 using EnumTable = PersistentMap< std::string, scoped<EnumDecl> >;
75 using UnionTable = PersistentMap< std::string, scoped<UnionDecl> >;
76 using TraitTable = PersistentMap< std::string, scoped<TraitDecl> >;
77
78 IdTable::Ptr idTable; ///< identifier namespace
79 TypeTable::Ptr typeTable; ///< type namespace
80 StructTable::Ptr structTable; ///< struct namespace
81 EnumTable::Ptr enumTable; ///< enum namespace
82 UnionTable::Ptr unionTable; ///< union namespace
83 TraitTable::Ptr traitTable; ///< trait namespace
[e5c3811]84 IdTable::Ptr specialFunctionTable[NUMBER_OF_KINDS];
85
86 // using SpecialFuncTable = PersistentMap< std::string, IdTable::Ptr >; // fname (ctor/dtor/assign) - otypekey
87 // SpecialFuncTable::Ptr specialFuncTable;
[d76c588]88
89 using Ptr = std::shared_ptr<const SymbolTable>;
90
[0bd3faf]91 Ptr prevScope; ///< Symbol Table for parent scope
[d76c588]92 unsigned long scope; ///< Scope index of this indexer
93 unsigned long repScope; ///< Scope index of currently represented scope
94
95public:
[b9fe89b]96
97 /// Mode to control when (during which pass) user-caused name-declaration errors get reported.
98 /// The default setting `AssertClean` supports, "I expect all user-caused errors to have been
99 /// reported by now," or, "I wouldn't know what to do with an error; are there even any here?"
100 enum ErrorDetection {
101 AssertClean, ///< invalid user decls => assert fails during addFoo (default)
102 ValidateOnAdd, ///< invalid user decls => calls SemanticError during addFoo
103 IgnoreErrors ///< acts as if unspecified decls were removed, forcing validity
104 };
105
106 explicit SymbolTable(
107 ErrorDetection ///< mode for the lifetime of the symbol table (whole pass)
108 );
109 SymbolTable() : SymbolTable(AssertClean) {}
[d76c588]110 ~SymbolTable();
111
[b9fe89b]112 ErrorDetection getErrorMode() const {
113 return errorMode;
114 }
115
[e67991f]116 // when using an indexer manually (e.g., within a mutator traversal), it is necessary to
[d76c588]117 // tell the indexer explicitly when scopes begin and end
118 void enterScope();
119 void leaveScope();
120
121 /// Gets all declarations with the given ID
122 std::vector<IdData> lookupId( const std::string &id ) const;
[85855b0]123 /// Gets all declarations with the given ID, ignoring hidden members from enumeration
124 std::vector<IdData> lookupIdIgnoreHidden( const std::string &id ) const;
[e5c3811]125 /// Gets special functions associated with a type; if no key is given, returns everything
126 std::vector<IdData> specialLookupId( SpecialFunctionKind kind, const std::string & otypeKey = "" ) const;
[d76c588]127 /// Gets the top-most type declaration with the given ID
128 const NamedTypeDecl * lookupType( const std::string &id ) const;
129 /// Gets the top-most struct declaration with the given ID
130 const StructDecl * lookupStruct( const std::string &id ) const;
131 /// Gets the top-most enum declaration with the given ID
132 const EnumDecl * lookupEnum( const std::string &id ) const;
133 /// Gets the top-most union declaration with the given ID
134 const UnionDecl * lookupUnion( const std::string &id ) const;
135 /// Gets the top-most trait declaration with the given ID
136 const TraitDecl * lookupTrait( const std::string &id ) const;
137
138 /// Gets the type declaration with the given ID at global scope
139 const NamedTypeDecl * globalLookupType( const std::string &id ) const;
140 /// Gets the struct declaration with the given ID at global scope
141 const StructDecl * globalLookupStruct( const std::string &id ) const;
142 /// Gets the union declaration with the given ID at global scope
143 const UnionDecl * globalLookupUnion( const std::string &id ) const;
144 /// Gets the enum declaration with the given ID at global scope
145 const EnumDecl * globalLookupEnum( const std::string &id ) const;
146
147 /// Adds an identifier declaration to the symbol table
148 void addId( const DeclWithType * decl, const Expr * baseExpr = nullptr );
149 /// Adds a deleted identifier declaration to the symbol table
[e67991f]150 void addDeletedId( const DeclWithType * decl, const Decl * deleter );
[d76c588]151
152 /// Adds a type to the symbol table
153 void addType( const NamedTypeDecl * decl );
154 /// Adds a struct declaration to the symbol table by name
[e0069bd]155 void addStructId( const std::string & id );
[d76c588]156 /// Adds a struct declaration to the symbol table
157 void addStruct( const StructDecl * decl );
158 /// Adds an enum declaration to the symbol table
[0e42794]159 void addEnum( const EnumDecl * decl );
[d76c588]160 /// Adds a union declaration to the symbol table by name
[e0069bd]161 void addUnionId( const std::string & id );
[d76c588]162 /// Adds a union declaration to the symbol table
163 void addUnion( const UnionDecl * decl );
164 /// Adds a trait declaration to the symbol table
165 void addTrait( const TraitDecl * decl );
166
167 /// adds all of the IDs from WithStmt exprs
[e67991f]168 void addWith( const std::vector< ptr<Expr> > & withExprs, const Decl * withStmt );
[d76c588]169
170 /// convenience function for adding a list of Ids to the indexer
171 void addIds( const std::vector< ptr<DeclWithType> > & decls );
172
173 /// convenience function for adding a list of forall parameters to the indexer
174 void addTypes( const std::vector< ptr<TypeDecl> > & tds );
175
176 /// convenience function for adding all of the declarations in a function type to the indexer
[490fb92e]177 void addFunction( const FunctionDecl * );
[d76c588]178
179private:
[b9fe89b]180 void OnFindError( CodeLocation location, std::string error ) const;
181
182 template< typename T >
183 void OnFindError( const T * obj, const std::string & error ) const {
184 OnFindError( obj->location, toString( error, obj ) );
185 }
186
187 template< typename T >
188 void OnFindError( CodeLocation location, const T * obj, const std::string & error ) const {
189 OnFindError( location, toString( error, obj ) );
190 }
191
[d76c588]192 /// Ensures that a proper backtracking scope exists before a mutation
193 void lazyInitScope();
194
195 /// Gets the symbol table at a given scope
196 const SymbolTable * atScope( unsigned long i ) const;
197
[e67991f]198 /// Removes matching autogenerated constructors and destructors so that they will not be
[d76c588]199 /// selected. If returns false, passed decl should not be added.
200 bool removeSpecialOverrides( IdData & decl, MangleTable::Ptr & mangleTable );
201
[b9fe89b]202 /// Error detection mode given at construction (pass-specific).
203 /// Logically const, except that the symbol table's push-pop is achieved by autogenerated
204 /// assignment onto self. The feield is left motuable to keep this code-gen simple.
205 /// Conceptual constness is preserved by all SymbolTable in a stack sharing the same mode.
206 ErrorDetection errorMode;
207
208 /// Options for handling identifier conflicts.
209 /// Varies according to AST location during traversal: captures semantics of the construct
210 /// being visited as "would shadow" vs "must not collide."
211 /// At a given AST location, is the same for every pass.
[d76c588]212 struct OnConflict {
213 enum {
[b9fe89b]214 Error, ///< Follow the current pass's ErrorDetection mode (may throw a semantic error)
[d76c588]215 Delete ///< Delete the earlier version with the delete statement
216 } mode;
[e67991f]217 const Decl * deleter; ///< Statement that deletes this expression
[d76c588]218
219 private:
220 OnConflict() : mode(Error), deleter(nullptr) {}
[e67991f]221 OnConflict( const Decl * d ) : mode(Delete), deleter(d) {}
[d76c588]222 public:
223 OnConflict( const OnConflict& ) = default;
224
225 static OnConflict error() { return {}; }
[e67991f]226 static OnConflict deleteWith( const Decl * d ) { return { d }; }
[d76c588]227 };
228
229 /// true if the existing identifier conflicts with the added identifier
230 bool addedIdConflicts(
[e67991f]231 const IdData & existing, const DeclWithType * added, OnConflict handleConflicts,
232 const Decl * deleter );
[d76c588]233
[b9fe89b]234 /// true if redeclaration conflict between two types
235 bool addedTypeConflicts( const NamedTypeDecl * existing, const NamedTypeDecl * added ) const;
236
237 /// true if redeclaration conflict between two aggregate declarations
238 bool addedDeclConflicts( const AggregateDecl * existing, const AggregateDecl * added ) const;
239
[d76c588]240 /// common code for addId, addDeletedId, etc.
[d859a30]241 void addIdCommon(
242 const DeclWithType * decl, OnConflict handleConflicts,
243 const Expr * baseExpr = nullptr, const Decl * deleter = nullptr );
[d76c588]244
[e5c3811]245 /// common code for addId when special decls are placed into separate tables
[d859a30]246 void addIdToTable(
247 const DeclWithType * decl, const std::string & lookupKey,
248 IdTable::Ptr & idTable, OnConflict handleConflicts,
[e5c3811]249 const Expr * baseExpr = nullptr, const Decl * deleter = nullptr);
[d859a30]250
[d76c588]251 /// adds all of the members of the Aggregate (addWith helper)
252 void addMembers( const AggregateDecl * aggr, const Expr * expr, OnConflict handleConflicts );
253
254 /// returns true if there exists a declaration with C linkage and the given name with the same mangled name
255 bool hasCompatibleCDecl( const std::string &id, const std::string &mangleName ) const;
256 /// returns true if there exists a declaration with C linkage and the given name with a different mangled name
257 bool hasIncompatibleCDecl( const std::string &id, const std::string &mangleName ) const;
258};
259
260}
261
[b9fe89b]262
[d76c588]263// Local Variables: //
264// tab-width: 4 //
265// mode: c++ //
266// compile-command: "make install" //
[d859a30]267// End: //
Note: See TracBrowser for help on using the repository browser.