source: src/SymTab/Indexer.cc @ 52c2a72

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 52c2a72 was 52c2a72, checked in by Aaron Moss <a3moss@…>, 8 years ago

Fold StackTable? variants into indexer

  • Property mode set to 100644
File size: 22.0 KB
Line 
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// Indexer.cc --
8//
9// Author           : Richard C. Bilson
10// Created On       : Sun May 17 21:37:33 2015
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Wed Mar  2 17:31:29 2016
13// Update Count     : 11
14//
15
16#include "Indexer.h"
17
18#include <string>
19#include <typeinfo>
20#include <unordered_map>
21#include <utility>
22
23#include "IdTable.h"
24
25#include "SynTree/Declaration.h"
26#include "SynTree/Type.h"
27#include "SynTree/Expression.h"
28#include "SynTree/Initializer.h"
29#include "SynTree/Statement.h"
30
31#include "Common/utility.h"
32
33#define debugPrint(x) if ( doDebug ) { std::cout << x; }
34
35namespace SymTab {
36        template< typename Container, typename VisitorType >
37        inline void acceptAllNewScope( Container &container, VisitorType &visitor ) {
38                visitor.enterScope();
39                acceptAll( container, visitor );
40                visitor.leaveScope();
41        }
42
43        typedef std::unordered_map< std::string, NamedTypeDecl* > TypeTable;
44        typedef std::unordered_map< std::string, StructDecl* > StructTable;
45        typedef std::unordered_map< std::string, EnumDecl* > EnumTable;
46        typedef std::unordered_map< std::string, UnionDecl* > UnionTable;
47        typedef std::unordered_map< std::string, TraitDecl* > TraitTable;
48
49        template< typename Decl >
50        void dump( const std::unordered_map< std::string, Decl* > &table, std::ostream &os ) {
51                for ( typename std::unordered_map< std::string, Decl* >::const_iterator it = table.begin(); it != table.end(); ++it ) {
52                        os << it->second << std::endl;
53                } // for
54        }
55       
56        struct Indexer::Impl {
57                Impl( unsigned long _scope ) : refCount(1), scope( _scope ), size( 0 ), base(),
58                                idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable() {}
59                Impl( unsigned long _scope, Indexer &&_base ) : refCount(1), scope( _scope ), size( 0 ), base( _base ),
60                                idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable() {}
61                unsigned long refCount;   ///< Number of references to these tables
62                unsigned long scope;      ///< Scope these tables are associated with
63                unsigned long size;       ///< Number of elements stored in this table
64                const Indexer base;       ///< Base indexer this extends
65               
66                IdTable idTable;          ///< Identifier namespace
67                TypeTable typeTable;      ///< Type namespace
68                StructTable structTable;  ///< Struct namespace
69                EnumTable enumTable;      ///< Enum namespace
70                UnionTable unionTable;    ///< Union namespace
71                TraitTable traitTable;    ///< Trait namespace
72        };
73
74        Indexer::Impl *Indexer::newRef( Indexer::Impl *toClone ) {
75                if ( ! toClone ) return 0;
76
77                // shorten the search chain by skipping empty links
78                Indexer::Impl *ret = toClone->size == 0 ? toClone->base.tables : toClone;
79                if ( ret ) { ++ret->refCount; }
80
81                return ret;
82        }
83
84        void Indexer::deleteRef( Indexer::Impl *toFree ) {
85                if ( ! toFree ) return;
86
87                if ( --toFree->refCount == 0 ) delete toFree;
88        }
89
90        void Indexer::makeWritable() {
91                if ( ! tables ) {
92                        // create indexer if not yet set
93                        tables = new Indexer::Impl( scope );
94                } else if ( tables->refCount > 1 || tables->scope != scope ) {
95                        // make this indexer the base of a fresh indexer at the current scope
96                        tables = new Indexer::Impl( scope, std::move( *this ) );
97                }
98        }
99
100        Indexer::Indexer( bool _doDebug ) : tables( 0 ), scope( 0 ), doDebug( _doDebug ) {}
101
102        Indexer::Indexer( const Indexer &that ) : tables( newRef( that.tables ) ), scope( that.scope ), doDebug( that.doDebug ) {}
103
104        Indexer::Indexer( Indexer &&that ) : tables( that.tables ), scope( that.scope ), doDebug( that.doDebug ) {
105                that.tables = 0;
106        }
107
108        Indexer::~Indexer() {
109                deleteRef( tables );
110        }
111
112        Indexer& Indexer::operator= ( const Indexer &that ) {
113                deleteRef( tables );
114
115                tables = newRef( that.tables );
116                scope = that.scope;
117                doDebug = that.doDebug;
118
119                return *this;
120        }
121
122        Indexer& Indexer::operator= ( Indexer &&that ) {
123                deleteRef( tables );
124
125                tables = that.tables;
126                scope = that.scope;
127                doDebug = that.doDebug;
128
129                that.tables = 0;
130
131                return *this;
132        }
133
134        void Indexer::visit( ObjectDecl *objectDecl ) {
135                enterScope();
136                maybeAccept( objectDecl->get_type(), *this );
137                leaveScope();
138                maybeAccept( objectDecl->get_init(), *this );
139                maybeAccept( objectDecl->get_bitfieldWidth(), *this );
140                if ( objectDecl->get_name() != "" ) {
141                        debugPrint( "Adding object " << objectDecl->get_name() << std::endl );
142                        addId( objectDecl );
143                } // if
144        }
145
146        void Indexer::visit( FunctionDecl *functionDecl ) {
147                if ( functionDecl->get_name() == "" ) return;
148                debugPrint( "Adding function " << functionDecl->get_name() << std::endl );
149                addId( functionDecl );
150                enterScope();
151                maybeAccept( functionDecl->get_functionType(), *this );
152                acceptAll( functionDecl->get_oldDecls(), *this );
153                maybeAccept( functionDecl->get_statements(), *this );
154                leaveScope();
155        }
156
157
158// A NOTE ON THE ORDER OF TRAVERSAL
159//
160// Types and typedefs have their base types visited before they are added to the type table.  This is ok, since there is
161// no such thing as a recursive type or typedef.
162//
163//             typedef struct { T *x; } T; // never allowed
164//
165// for structs/unions, it is possible to have recursion, so the decl should be added as if it's incomplete to begin, the
166// members are traversed, and then the complete type should be added (assuming the type is completed by this particular
167// declaration).
168//
169//             struct T { struct T *x; }; // allowed
170//
171// It is important to add the complete type to the symbol table *after* the members/base has been traversed, since that
172// traversal may modify the definition of the type and these modifications should be visible when the symbol table is
173// queried later in this pass.
174//
175// TODO: figure out whether recursive contexts are sensible/possible/reasonable.
176
177
178        void Indexer::visit( TypeDecl *typeDecl ) {
179                // see A NOTE ON THE ORDER OF TRAVERSAL, above
180                // note that assertions come after the type is added to the symtab, since they are not part of the type proper
181                // and may depend on the type itself
182                enterScope();
183                acceptAll( typeDecl->get_parameters(), *this );
184                maybeAccept( typeDecl->get_base(), *this );
185                leaveScope();
186                debugPrint( "Adding type " << typeDecl->get_name() << std::endl );
187                addType( typeDecl );
188                acceptAll( typeDecl->get_assertions(), *this );
189        }
190
191        void Indexer::visit( TypedefDecl *typeDecl ) {
192                enterScope();
193                acceptAll( typeDecl->get_parameters(), *this );
194                maybeAccept( typeDecl->get_base(), *this );
195                leaveScope();
196                debugPrint( "Adding typedef " << typeDecl->get_name() << std::endl );
197                addType( typeDecl );
198        }
199
200        void Indexer::visit( StructDecl *aggregateDecl ) {
201                // make up a forward declaration and add it before processing the members
202                StructDecl fwdDecl( aggregateDecl->get_name() );
203                cloneAll( aggregateDecl->get_parameters(), fwdDecl.get_parameters() );
204                debugPrint( "Adding fwd decl for struct " << fwdDecl.get_name() << std::endl );
205                addStruct( &fwdDecl );
206 
207                enterScope();
208                acceptAll( aggregateDecl->get_parameters(), *this );
209                acceptAll( aggregateDecl->get_members(), *this );
210                leaveScope();
211 
212                debugPrint( "Adding struct " << aggregateDecl->get_name() << std::endl );
213                // this addition replaces the forward declaration
214                addStruct( aggregateDecl );
215        }
216
217        void Indexer::visit( UnionDecl *aggregateDecl ) {
218                // make up a forward declaration and add it before processing the members
219                UnionDecl fwdDecl( aggregateDecl->get_name() );
220                cloneAll( aggregateDecl->get_parameters(), fwdDecl.get_parameters() );
221                debugPrint( "Adding fwd decl for union " << fwdDecl.get_name() << std::endl );
222                addUnion( &fwdDecl );
223 
224                enterScope();
225                acceptAll( aggregateDecl->get_parameters(), *this );
226                acceptAll( aggregateDecl->get_members(), *this );
227                leaveScope();
228 
229                debugPrint( "Adding union " << aggregateDecl->get_name() << std::endl );
230                addUnion( aggregateDecl );
231        }
232
233        void Indexer::visit( EnumDecl *aggregateDecl ) {
234                debugPrint( "Adding enum " << aggregateDecl->get_name() << std::endl );
235                addEnum( aggregateDecl );
236                // unlike structs, contexts, and unions, enums inject their members into the global scope
237                acceptAll( aggregateDecl->get_members(), *this );
238        }
239
240        void Indexer::visit( TraitDecl *aggregateDecl ) {
241                enterScope();
242                acceptAll( aggregateDecl->get_parameters(), *this );
243                acceptAll( aggregateDecl->get_members(), *this );
244                leaveScope();
245 
246                debugPrint( "Adding context " << aggregateDecl->get_name() << std::endl );
247                addTrait( aggregateDecl );
248        }
249
250        void Indexer::visit( CompoundStmt *compoundStmt ) {
251                enterScope();
252                acceptAll( compoundStmt->get_kids(), *this );
253                leaveScope();
254        }
255
256
257        void Indexer::visit( ApplicationExpr *applicationExpr ) {
258                acceptAllNewScope( applicationExpr->get_results(), *this );
259                maybeAccept( applicationExpr->get_function(), *this );
260                acceptAll( applicationExpr->get_args(), *this );
261        }
262
263        void Indexer::visit( UntypedExpr *untypedExpr ) {
264                acceptAllNewScope( untypedExpr->get_results(), *this );
265                acceptAll( untypedExpr->get_args(), *this );
266        }
267
268        void Indexer::visit( NameExpr *nameExpr ) {
269                acceptAllNewScope( nameExpr->get_results(), *this );
270        }
271
272        void Indexer::visit( AddressExpr *addressExpr ) {
273                acceptAllNewScope( addressExpr->get_results(), *this );
274                maybeAccept( addressExpr->get_arg(), *this );
275        }
276
277        void Indexer::visit( LabelAddressExpr *labAddressExpr ) {
278                acceptAllNewScope( labAddressExpr->get_results(), *this );
279                maybeAccept( labAddressExpr->get_arg(), *this );
280        }
281
282        void Indexer::visit( CastExpr *castExpr ) {
283                acceptAllNewScope( castExpr->get_results(), *this );
284                maybeAccept( castExpr->get_arg(), *this );
285        }
286
287        void Indexer::visit( UntypedMemberExpr *memberExpr ) {
288                acceptAllNewScope( memberExpr->get_results(), *this );
289                maybeAccept( memberExpr->get_aggregate(), *this );
290        }
291
292        void Indexer::visit( MemberExpr *memberExpr ) {
293                acceptAllNewScope( memberExpr->get_results(), *this );
294                maybeAccept( memberExpr->get_aggregate(), *this );
295        }
296
297        void Indexer::visit( VariableExpr *variableExpr ) {
298                acceptAllNewScope( variableExpr->get_results(), *this );
299        }
300
301        void Indexer::visit( ConstantExpr *constantExpr ) {
302                acceptAllNewScope( constantExpr->get_results(), *this );
303                maybeAccept( constantExpr->get_constant(), *this );
304        }
305
306        void Indexer::visit( SizeofExpr *sizeofExpr ) {
307                acceptAllNewScope( sizeofExpr->get_results(), *this );
308                if ( sizeofExpr->get_isType() ) {
309                        maybeAccept( sizeofExpr->get_type(), *this );
310                } else {
311                        maybeAccept( sizeofExpr->get_expr(), *this );
312                }
313        }
314
315        void Indexer::visit( AlignofExpr *alignofExpr ) {
316                acceptAllNewScope( alignofExpr->get_results(), *this );
317                if ( alignofExpr->get_isType() ) {
318                        maybeAccept( alignofExpr->get_type(), *this );
319                } else {
320                        maybeAccept( alignofExpr->get_expr(), *this );
321                }
322        }
323
324        void Indexer::visit( UntypedOffsetofExpr *offsetofExpr ) {
325                acceptAllNewScope( offsetofExpr->get_results(), *this );
326                maybeAccept( offsetofExpr->get_type(), *this );
327        }
328
329        void Indexer::visit( OffsetofExpr *offsetofExpr ) {
330                acceptAllNewScope( offsetofExpr->get_results(), *this );
331                maybeAccept( offsetofExpr->get_type(), *this );
332                maybeAccept( offsetofExpr->get_member(), *this );
333        }
334
335        void Indexer::visit( AttrExpr *attrExpr ) {
336                acceptAllNewScope( attrExpr->get_results(), *this );
337                if ( attrExpr->get_isType() ) {
338                        maybeAccept( attrExpr->get_type(), *this );
339                } else {
340                        maybeAccept( attrExpr->get_expr(), *this );
341                }
342        }
343
344        void Indexer::visit( LogicalExpr *logicalExpr ) {
345                acceptAllNewScope( logicalExpr->get_results(), *this );
346                maybeAccept( logicalExpr->get_arg1(), *this );
347                maybeAccept( logicalExpr->get_arg2(), *this );
348        }
349
350        void Indexer::visit( ConditionalExpr *conditionalExpr ) {
351                acceptAllNewScope( conditionalExpr->get_results(), *this );
352                maybeAccept( conditionalExpr->get_arg1(), *this );
353                maybeAccept( conditionalExpr->get_arg2(), *this );
354                maybeAccept( conditionalExpr->get_arg3(), *this );
355        }
356
357        void Indexer::visit( CommaExpr *commaExpr ) {
358                acceptAllNewScope( commaExpr->get_results(), *this );
359                maybeAccept( commaExpr->get_arg1(), *this );
360                maybeAccept( commaExpr->get_arg2(), *this );
361        }
362
363        void Indexer::visit( TupleExpr *tupleExpr ) {
364                acceptAllNewScope( tupleExpr->get_results(), *this );
365                acceptAll( tupleExpr->get_exprs(), *this );
366        }
367
368        void Indexer::visit( SolvedTupleExpr *tupleExpr ) {
369                acceptAllNewScope( tupleExpr->get_results(), *this );
370                acceptAll( tupleExpr->get_exprs(), *this );
371        }
372
373        void Indexer::visit( TypeExpr *typeExpr ) {
374                acceptAllNewScope( typeExpr->get_results(), *this );
375                maybeAccept( typeExpr->get_type(), *this );
376        }
377
378        void Indexer::visit( AsmExpr *asmExpr ) {
379                maybeAccept( asmExpr->get_inout(), *this );
380                maybeAccept( asmExpr->get_constraint(), *this );
381                maybeAccept( asmExpr->get_operand(), *this );
382        }
383
384        void Indexer::visit( UntypedValofExpr *valofExpr ) {
385                acceptAllNewScope( valofExpr->get_results(), *this );
386                maybeAccept( valofExpr->get_body(), *this );
387        }
388
389
390        void Indexer::visit( TraitInstType *contextInst ) {
391                acceptAll( contextInst->get_parameters(), *this );
392                acceptAll( contextInst->get_members(), *this );
393        }
394
395        void Indexer::visit( StructInstType *structInst ) {
396                if ( ! lookupStruct( structInst->get_name() ) ) {
397                        debugPrint( "Adding struct " << structInst->get_name() << " from implicit forward declaration" << std::endl );
398                        addStruct( structInst->get_name() );
399                }
400                enterScope();
401                acceptAll( structInst->get_parameters(), *this );
402                leaveScope();
403        }
404
405        void Indexer::visit( UnionInstType *unionInst ) {
406                if ( ! lookupUnion( unionInst->get_name() ) ) {
407                        debugPrint( "Adding union " << unionInst->get_name() << " from implicit forward declaration" << std::endl );
408                        addUnion( unionInst->get_name() );
409                }
410                enterScope();
411                acceptAll( unionInst->get_parameters(), *this );
412                leaveScope();
413        }
414
415        void Indexer::visit( ForStmt *forStmt ) {
416            // for statements introduce a level of scope
417            enterScope();
418            Visitor::visit( forStmt );
419            leaveScope();
420        }
421
422
423        void Indexer::lookupId( const std::string &id, std::list< DeclarationWithType* > &list ) const {
424                if ( ! tables ) return;
425               
426                tables->idTable.lookupId( id, list );
427                tables->base.lookupId( id, list );
428        }
429
430        DeclarationWithType* Indexer::lookupId( const std::string &id) const {
431                if ( ! tables ) return 0;
432               
433                DeclarationWithType *ret = tables->idTable.lookupId(id);
434                return ret ? ret : tables->base.lookupId(id);
435        }
436
437        NamedTypeDecl *Indexer::lookupType( const std::string &id ) const {
438                if ( ! tables ) return 0;
439
440                TypeTable::const_iterator ret = tables->typeTable.find( id );
441                return ret != tables->typeTable.end() ? ret->second : tables->base.lookupType( id );
442        }
443
444        StructDecl *Indexer::lookupStruct( const std::string &id ) const {
445                if ( ! tables ) return 0;
446
447                StructTable::const_iterator ret = tables->structTable.find( id );
448                return ret != tables->structTable.end() ? ret->second : tables->base.lookupStruct( id );
449        }
450
451        EnumDecl *Indexer::lookupEnum( const std::string &id ) const {
452                if ( ! tables ) return 0;
453
454                EnumTable::const_iterator ret = tables->enumTable.find( id );
455                return ret != tables->enumTable.end() ? ret->second : tables->base.lookupEnum( id );
456        }
457
458        UnionDecl *Indexer::lookupUnion( const std::string &id ) const {
459                if ( ! tables ) return 0;
460
461                UnionTable::const_iterator ret = tables->unionTable.find( id );
462                return ret != tables->unionTable.end() ? ret->second : tables->base.lookupUnion( id );
463        }
464
465        TraitDecl *Indexer::lookupTrait( const std::string &id ) const {
466                if ( ! tables ) return 0;
467
468                TraitTable::const_iterator ret = tables->traitTable.find( id );
469                return ret != tables->traitTable.end() ? ret->second : tables->base.lookupTrait( id );
470        }
471
472        NamedTypeDecl *Indexer::lookupTypeAtScope( const std::string &id, unsigned long scope ) const {
473                if ( ! tables ) return 0;
474                if ( tables->scope < scope ) return 0;
475
476                TypeTable::const_iterator ret = tables->typeTable.find( id );
477                return ret != tables->typeTable.end() ? ret->second : tables->base.lookupTypeAtScope( id, scope );
478        }
479       
480        StructDecl *Indexer::lookupStructAtScope( const std::string &id, unsigned long scope ) const {
481                if ( ! tables ) return 0;
482                if ( tables->scope < scope ) return 0;
483
484                StructTable::const_iterator ret = tables->structTable.find( id );
485                return ret != tables->structTable.end() ? ret->second : tables->base.lookupStructAtScope( id, scope );
486        }
487       
488        EnumDecl *Indexer::lookupEnumAtScope( const std::string &id, unsigned long scope ) const {
489                if ( ! tables ) return 0;
490                if ( tables->scope < scope ) return 0;
491
492                EnumTable::const_iterator ret = tables->enumTable.find( id );
493                return ret != tables->enumTable.end() ? ret->second : tables->base.lookupEnumAtScope( id, scope );
494        }
495       
496        UnionDecl *Indexer::lookupUnionAtScope( const std::string &id, unsigned long scope ) const {
497                if ( ! tables ) return 0;
498                if ( tables->scope < scope ) return 0;
499
500                UnionTable::const_iterator ret = tables->unionTable.find( id );
501                return ret != tables->unionTable.end() ? ret->second : tables->base.lookupUnionAtScope( id, scope );
502        }
503       
504        TraitDecl *Indexer::lookupTraitAtScope( const std::string &id, unsigned long scope ) const {
505                if ( ! tables ) return 0;
506                if ( tables->scope < scope ) return 0;
507
508                TraitTable::const_iterator ret = tables->traitTable.find( id );
509                return ret != tables->traitTable.end() ? ret->second : tables->base.lookupTraitAtScope( id, scope );
510        }
511
512        void Indexer::addId( DeclarationWithType *decl ) {
513                makeWritable();
514                tables->idTable.addDecl( decl );
515                ++tables->size;
516        }
517
518        bool addedTypeConflicts( NamedTypeDecl *existing, NamedTypeDecl *added ) {
519                if ( existing->get_base() == 0 ) {
520                        return false;
521                } else if ( added->get_base() == 0 ) {
522                        return true;
523                } else {
524                        throw SemanticError( "redeclaration of ", added );
525                }
526        }
527       
528        void Indexer::addType( NamedTypeDecl *decl ) {
529                makeWritable();
530
531                const std::string &id = decl->get_name();
532                TypeTable::iterator existing = tables->typeTable.find( id );
533                if ( existing == tables->typeTable.end() ) {
534                        NamedTypeDecl *parent = tables->base.lookupTypeAtScope( id, scope );
535                        if ( ! parent || ! addedTypeConflicts( parent, decl ) ) {
536                                tables->typeTable.insert( existing, std::make_pair( id, decl ) );
537                                ++tables->size;
538                        }
539                } else {
540                        if ( ! addedTypeConflicts( existing->second, decl ) ) {
541                                existing->second = decl;
542                        }
543                }
544        }
545
546        bool addedDeclConflicts( AggregateDecl *existing, AggregateDecl *added ) {
547                if ( existing->get_members().empty() ) {
548                        return false;
549                } else if ( ! added->get_members().empty() ) {
550                        throw SemanticError( "redeclaration of ", added );
551                } // if
552                return true;
553        }
554
555        void Indexer::addStruct( const std::string &id ) {
556                addStruct( new StructDecl( id ) );
557        }
558       
559        void Indexer::addStruct( StructDecl *decl ) {
560                makeWritable();
561
562                const std::string &id = decl->get_name();
563                StructTable::iterator existing = tables->structTable.find( id );
564                if ( existing == tables->structTable.end() ) {
565                        StructDecl *parent = tables->base.lookupStructAtScope( id, scope );
566                        if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
567                                tables->structTable.insert( existing, std::make_pair( id, decl ) );
568                                ++tables->size;
569                        }
570                } else {
571                        if ( ! addedDeclConflicts( existing->second, decl ) ) {
572                                existing->second = decl;
573                        }
574                }
575        }
576       
577        void Indexer::addEnum( EnumDecl *decl ) {
578                makeWritable();
579
580                const std::string &id = decl->get_name();
581                EnumTable::iterator existing = tables->enumTable.find( id );
582                if ( existing == tables->enumTable.end() ) {
583                        EnumDecl *parent = tables->base.lookupEnumAtScope( id, scope );
584                        if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
585                                tables->enumTable.insert( existing, std::make_pair( id, decl ) );
586                                ++tables->size;
587                        }
588                } else {
589                        if ( ! addedDeclConflicts( existing->second, decl ) ) {
590                                existing->second = decl;
591                        }
592                }
593        }
594
595        void Indexer::addUnion( const std::string &id ) {
596                addUnion( new UnionDecl( id ) );
597        }
598       
599        void Indexer::addUnion( UnionDecl *decl ) {
600                makeWritable();
601
602                const std::string &id = decl->get_name();
603                UnionTable::iterator existing = tables->unionTable.find( id );
604                if ( existing == tables->unionTable.end() ) {
605                        UnionDecl *parent = tables->base.lookupUnionAtScope( id, scope );
606                        if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
607                                tables->unionTable.insert( existing, std::make_pair( id, decl ) );
608                                ++tables->size;
609                        }
610                } else {
611                        if ( ! addedDeclConflicts( existing->second, decl ) ) {
612                                existing->second = decl;
613                        }
614                }
615        }
616       
617        void Indexer::addTrait( TraitDecl *decl ) {
618                makeWritable();
619
620                const std::string &id = decl->get_name();
621                TraitTable::iterator existing = tables->traitTable.find( id );
622                if ( existing == tables->traitTable.end() ) {
623                        TraitDecl *parent = tables->base.lookupTraitAtScope( id, scope );
624                        if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
625                                tables->traitTable.insert( existing, std::make_pair( id, decl ) );
626                                ++tables->size;
627                        }
628                } else {
629                        if ( ! addedDeclConflicts( existing->second, decl ) ) {
630                                existing->second = decl;
631                        }
632                }
633        }
634
635        void Indexer::enterScope() {
636                ++scope;
637               
638                if ( doDebug ) {
639                        std::cout << "--- Entering scope " << scope << std::endl;
640                }
641        }
642
643        void Indexer::leaveScope() {
644                using std::cout;
645
646                assert( scope > 0 && "cannot leave initial scope" );
647                --scope;
648
649                while ( tables && tables->scope > scope ) {
650                        if ( doDebug ) {
651                                cout << "--- Leaving scope " << tables->scope << " containing" << std::endl;
652                                tables->idTable.dump( cout );
653                                dump( tables->typeTable, cout );
654                                dump( tables->structTable, cout );
655                                dump( tables->enumTable, cout );
656                                dump( tables->unionTable, cout );
657                                dump( tables->traitTable, cout );
658                        }
659
660                        // swap tables for base table until we find one at an appropriate scope
661                        Indexer::Impl *base = newRef( tables->base.tables );
662                        deleteRef( tables );
663                        tables = base;
664                }
665        }
666
667        void Indexer::print( std::ostream &os, int indent ) const {
668            using std::cerr;
669
670            cerr << "===idTable===" << std::endl;
671            if ( tables ) tables->idTable.dump( os );
672            cerr << "===typeTable===" << std::endl;
673            if ( tables ) dump( tables->typeTable, os );
674            cerr << "===structTable===" << std::endl;
675            if ( tables ) dump( tables->structTable, os );
676            cerr << "===enumTable===" << std::endl;
677            if ( tables ) dump( tables->enumTable, os );
678            cerr << "===unionTable===" << std::endl;
679            if ( tables ) dump( tables->unionTable, os );
680            cerr << "===contextTable===" << std::endl;
681            if ( tables ) dump( tables->traitTable, os );
682        }
683} // namespace SymTab
684
685// Local Variables: //
686// tab-width: 4 //
687// mode: c++ //
688// compile-command: "make install" //
689// End: //
Note: See TracBrowser for help on using the repository browser.