source: translator/SymTab/Indexer.cc @ a32b204

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsctordeferred_resndemanglerenumforall-pointer-decaygc_noraiijacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newstringwith_gc
Last change on this file since a32b204 was d4778a6, checked in by Rob Schluntz <rschlunt@…>, 9 years ago

for loop initializers are hoisted properly and for loops a level of scope

  • Property mode set to 100644
File size: 8.2 KB
Line 
1#include "SynTree/Declaration.h"
2#include "SynTree/Type.h"
3#include "SynTree/Expression.h"
4#include "SynTree/Initializer.h"
5#include "SynTree/Statement.h"
6#include "Indexer.h"
7#include <typeinfo>
8#include "utility.h"
9
10#define debugPrint(x) if ( doDebug ) { std::cout << x; }
11
12namespace SymTab {
13    Indexer::Indexer( bool useDebug ) : doDebug( useDebug ) {}
14
15    Indexer::~Indexer() {}
16
17    void Indexer::visit( ObjectDecl *objectDecl ) {
18        maybeAccept( objectDecl->get_type(), *this );
19        maybeAccept( objectDecl->get_init(), *this );
20        maybeAccept( objectDecl->get_bitfieldWidth(), *this );
21        if ( objectDecl->get_name() != "" ) {
22            debugPrint( "Adding object " << objectDecl->get_name() << std::endl );
23            idTable.addDecl( objectDecl );
24        }
25    }
26
27    void Indexer::visit( FunctionDecl *functionDecl ) {
28        if ( functionDecl->get_name() == "" ) return;
29        debugPrint( "Adding function " << functionDecl->get_name() << std::endl );
30        idTable.addDecl( functionDecl );
31        enterScope();
32        maybeAccept( functionDecl->get_functionType(), *this );
33        acceptAll( functionDecl->get_oldDecls(), *this );
34        maybeAccept( functionDecl->get_statements(), *this );
35        leaveScope();
36    }
37
38/********
39 * A NOTE ON THE ORDER OF TRAVERSAL
40 *
41 * Types and typedefs have their base types visited before they are added to the type table.
42 * This is ok, since there is no such thing as a recursive type or typedef.
43 *             typedef struct { T *x; } T; // never allowed
44 *
45 * for structs/unions, it is possible to have recursion, so the decl should be added as if it's
46 * incomplete to begin, the members are traversed, and then the complete type should be added
47 * (assuming the type is completed by this particular declaration).
48 *             struct T { struct T *x; }; // allowed
49 *
50 * It's important to add the complete type to the symbol table *after* the members/base has been
51 * traversed, since that traversal may modify the definition of the type and these modifications
52 * should be visible when the symbol table is queried later in this pass.
53 *
54 * TODO: figure out whether recursive contexts are sensible/possible/reasonable.
55 */
56
57    void Indexer::visit( TypeDecl *typeDecl ) {
58        // see A NOTE ON THE ORDER OF TRAVERSAL, above
59        // note that assertions come after the type is added to the symtab, since they aren't part
60        // of the type proper and may depend on the type itself
61        enterScope();
62        acceptAll( typeDecl->get_parameters(), *this );
63        maybeAccept( typeDecl->get_base(), *this );
64        leaveScope();
65        debugPrint( "Adding type " << typeDecl->get_name() << std::endl );
66        typeTable.add( typeDecl );
67        acceptAll( typeDecl->get_assertions(), *this );
68    }
69
70    void Indexer::visit( TypedefDecl *typeDecl ) {
71        enterScope();
72        acceptAll( typeDecl->get_parameters(), *this );
73        maybeAccept( typeDecl->get_base(), *this );
74        leaveScope();
75        debugPrint( "Adding typedef " << typeDecl->get_name() << std::endl );
76        typeTable.add( typeDecl );
77    }
78
79    void Indexer::visit( StructDecl *aggregateDecl ) {
80        // make up a forward declaration and add it before processing the members
81        StructDecl fwdDecl( aggregateDecl->get_name() );
82        cloneAll( aggregateDecl->get_parameters(), fwdDecl.get_parameters() );
83        debugPrint( "Adding fwd decl for struct " << fwdDecl.get_name() << std::endl );
84        structTable.add( &fwdDecl );
85 
86        enterScope();
87        acceptAll( aggregateDecl->get_parameters(), *this );
88        acceptAll( aggregateDecl->get_members(), *this );
89        leaveScope();
90 
91        debugPrint( "Adding struct " << aggregateDecl->get_name() << std::endl );
92        // this addition replaces the forward declaration
93        structTable.add( aggregateDecl );
94    }
95
96    void Indexer::visit( UnionDecl *aggregateDecl ) {
97        // make up a forward declaration and add it before processing the members
98        UnionDecl fwdDecl( aggregateDecl->get_name() );
99        cloneAll( aggregateDecl->get_parameters(), fwdDecl.get_parameters() );
100        debugPrint( "Adding fwd decl for union " << fwdDecl.get_name() << std::endl );
101        unionTable.add( &fwdDecl );
102 
103        enterScope();
104        acceptAll( aggregateDecl->get_parameters(), *this );
105        acceptAll( aggregateDecl->get_members(), *this );
106        leaveScope();
107 
108        debugPrint( "Adding union " << aggregateDecl->get_name() << std::endl );
109        unionTable.add( aggregateDecl );
110    }
111
112    void Indexer::visit( EnumDecl *aggregateDecl ) {
113        debugPrint( "Adding enum " << aggregateDecl->get_name() << std::endl );
114        enumTable.add( aggregateDecl );
115        // unlike structs, contexts, and unions, enums inject their members into the global scope
116        acceptAll( aggregateDecl->get_members(), *this );
117    }
118
119    void Indexer::visit( ContextDecl *aggregateDecl ) {
120        enterScope();
121        acceptAll( aggregateDecl->get_parameters(), *this );
122        acceptAll( aggregateDecl->get_members(), *this );
123        leaveScope();
124 
125        debugPrint( "Adding context " << aggregateDecl->get_name() << std::endl );
126        contextTable.add( aggregateDecl );
127    }
128
129    void Indexer::visit( CompoundStmt *compoundStmt ) {
130        enterScope();
131        acceptAll( compoundStmt->get_kids(), *this );
132        leaveScope();
133    }
134
135    void Indexer::visit( ContextInstType *contextInst ) {
136        acceptAll( contextInst->get_parameters(), *this );
137        acceptAll( contextInst->get_members(), *this );
138    }
139
140    void Indexer::visit( StructInstType *structInst ) {
141        if ( ! structTable.lookup( structInst->get_name() ) ) {
142            debugPrint( "Adding struct " << structInst->get_name() << " from implicit forward declaration" << std::endl );
143            structTable.add( structInst->get_name() );
144        }
145        enterScope();
146        acceptAll( structInst->get_parameters(), *this );
147        leaveScope();
148    }
149
150    void Indexer::visit( UnionInstType *unionInst ) {
151        if ( ! unionTable.lookup( unionInst->get_name() ) ) {
152            debugPrint( "Adding union " << unionInst->get_name() << " from implicit forward declaration" << std::endl );
153            unionTable.add( unionInst->get_name() );
154        }
155        enterScope();
156        acceptAll( unionInst->get_parameters(), *this );
157        leaveScope();
158    }
159
160    void Indexer::visit( ForStmt *forStmt ) {
161        // for statements introduce a level of scope
162        enterScope();
163        Visitor::visit( forStmt );
164        leaveScope();
165    }
166
167
168    void Indexer::lookupId( const std::string &id, std::list< DeclarationWithType* > &list ) const {
169        idTable.lookupId( id, list );
170    }
171
172    DeclarationWithType* Indexer::lookupId( const std::string &id) const {
173        return idTable.lookupId(id);
174    }
175
176    NamedTypeDecl *Indexer::lookupType( const std::string &id ) const {
177        return typeTable.lookup( id );
178    }
179
180    StructDecl *Indexer::lookupStruct( const std::string &id ) const {
181        return structTable.lookup( id );
182    }
183
184    EnumDecl *Indexer::lookupEnum( const std::string &id ) const {
185        return enumTable.lookup( id );
186    }
187
188    UnionDecl *Indexer::lookupUnion( const std::string &id ) const {
189        return unionTable.lookup( id );
190    }
191
192    ContextDecl  * Indexer::lookupContext( const std::string &id ) const {
193        return contextTable.lookup( id );
194    }
195
196    void Indexer::enterScope() {
197        if ( doDebug ) {
198            std::cout << "--- Entering scope" << std::endl;
199        }
200        idTable.enterScope();
201        typeTable.enterScope();
202        structTable.enterScope();
203        enumTable.enterScope();
204        unionTable.enterScope();
205        contextTable.enterScope();
206    }
207
208    void Indexer::leaveScope() {
209        using std::cout;
210        using std::endl;
211 
212        if ( doDebug ) {
213            cout << "--- Leaving scope containing" << endl;
214            idTable.dump( cout );
215            typeTable.dump( cout );
216            structTable.dump( cout );
217            enumTable.dump( cout );
218            unionTable.dump( cout );
219            contextTable.dump( cout );
220        }
221        idTable.leaveScope();
222        typeTable.leaveScope();
223        structTable.leaveScope();
224        enumTable.leaveScope();
225        unionTable.leaveScope();
226        contextTable.leaveScope();
227    }
228
229    void Indexer::print( std::ostream &os, int indent ) const {
230        using std::cerr;
231        using std::endl;
232
233        cerr << "===idTable===" << endl;
234        idTable.dump( os );
235        cerr << "===typeTable===" << endl;
236        typeTable.dump( os );
237        cerr << "===structTable===" << endl;
238        structTable.dump( os );
239        cerr << "===enumTable===" << endl;
240        enumTable.dump( os );
241        cerr << "===unionTable===" << endl;
242        unionTable.dump( os );
243        cerr << "===contextTable===" << endl;
244        contextTable.dump( os );
245#if 0
246        idTable.dump( os );
247        typeTable.dump( os );
248        structTable.dump( os );
249        enumTable.dump( os );
250        unionTable.dump( os );
251        contextTable.dump( os );
252#endif
253    }
254} // namespace SymTab
Note: See TracBrowser for help on using the repository browser.