source: src/AST/Print.cpp @ 68c9165

arm-ehcleanup-dtorsjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-expr
Last change on this file since 68c9165 was 68c9165, checked in by Aaron Moss <a3moss@…>, 3 years ago

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

  • Property mode set to 100644
File size: 21.1 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// Print.cpp --
8//
9// Author           : Thierry Delisle
10// Created On       : Tue May 21 16:20:15 2019
11// Last Modified By :
12// Last Modified On :
13// Update Count     :
14//
15
16#include "Print.hpp"
17
18#include "Decl.hpp"
19#include "Expr.hpp"
20#include "Stmt.hpp"
21#include "Type.hpp"
22#include "TypeSubstitution.hpp"
23
24#include "Common/utility.h" // for group_iterate
25
26using namespace std;
27
28namespace ast {
29
30template <typename C, typename... T>
31constexpr auto make_array(T&&... values) ->
32        array<C,sizeof...(T)>
33{
34        return array<C,sizeof...(T)>{
35                forward<T>(values)...
36        };
37}
38
39class Printer : public Visitor {
40public:
41        ostream & os;
42        Indenter indent;
43        bool short_mode;
44
45        Printer(ostream & os, Indenter indent, bool short_mode) : os( os ), indent( indent ), short_mode(short_mode) {}
46
47private:
48        template< typename C >
49        void printAll( const C & c ) {
50                for ( const auto & i : c ) {
51                        if ( i ) {
52                                os << indent;
53                                i->accept( *this );
54                                // need an endl after each element because it's not
55                                // easy to know when each individual item should end
56                                os << endl;
57                        } // if
58                } // for
59        }
60
61
62        static const char* Names[];
63
64        struct Names {
65                static constexpr auto FuncSpecifiers = make_array<const char*>(
66                        "inline", "_Noreturn", "fortran"
67                );
68
69                static constexpr auto StorageClasses = make_array<const char*>(
70                        "extern", "static", "auto", "register", "_Thread_local"
71                );
72
73                static constexpr auto Qualifiers = make_array<const char*>(
74                        "const", "restrict", "volatile", "lvalue", "mutex", "_Atomic"
75                );
76        };
77
78        template<typename storage_t, size_t N>
79        void print(const storage_t & storage, const array<const char *, N> & Names ) {
80                if ( storage.any() ) {
81                        for ( size_t i = 0; i < Names.size(); i += 1 ) {
82                                if ( storage[i] ) {
83                                        os << Names[i] << ' ';
84                                }
85                        }
86                }
87        }
88
89        void print( const ast::Function::Specs & specs ) {
90                print(specs, Names::FuncSpecifiers);
91        }
92
93        void print( const ast::Storage::Classes & storage ) {
94                print(storage, Names::StorageClasses);
95        }
96
97        void print( const ast::CV::Qualifiers & qualifiers ) {
98                print(qualifiers, Names::Qualifiers);
99        }
100
101        void print( const ast::ParameterizedType::ForallList & forall ) {
102                if ( forall.empty() ) return;   
103                os << "forall" << std::endl;
104                ++indent;
105                printAll( forall );
106                os << indent;
107                --indent;
108        }
109
110        void print( const std::vector<ptr<Attribute>> & attrs ) {
111                if ( attrs.empty() ) return;
112                os << "with attributes" << std::endl;
113                ++indent;
114                printAll( attrs );
115                --indent;
116        }
117
118        void print( const std::vector<ptr<Expr>> & params ) {
119                if ( params.empty() ) return;
120                os << std::endl << indent << "... with parameters" << std::endl;
121                ++indent;
122                printAll( params );
123                --indent;
124        }
125
126        void preprint( const ast::Type * node ) {
127                print( node->qualifiers );
128        }
129
130        void preprint( const ast::ParameterizedType * node ) {
131                print( node->forall );
132                print( node->qualifiers );
133        }
134
135        void preprint( const ast::ReferenceToType * node ) {
136                print( node->forall );
137                print( node->attributes );
138                print( node->qualifiers );
139        }
140       
141        void print( const ast::AggregateDecl * node ) {
142                os << node->typeString() << " " << node->name << ":";
143                if ( node->linkage != Linkage::Cforall ) {
144                        os << " " << Linkage::name( node->linkage );
145                } // if
146                os << " with body : " << (node->body ? "yes " : "no ");
147
148                if ( ! node->params.empty() ) {
149                        os << endl << indent << "... with parameters" << endl;
150                        ++indent;
151                        printAll( node->params );
152                        --indent;
153                } // if
154                if ( ! node->members.empty() ) {
155                        os << endl << indent << "... with members" << endl;
156                        ++indent;
157                        printAll( node->members );
158                        --indent;
159                } // if
160                if ( ! node->attributes.empty() ) {
161                        os << endl << indent << "... with attributes" << endl;
162                        ++indent;
163                        printAll( node->attributes );
164                        --indent;
165                } // if
166                os << endl;
167        }
168
169        void print( const ast::NamedTypeDecl * node ) {
170                if ( !node->name.empty() ) os << node->name << ": ";
171
172                if ( node->linkage != Linkage::Cforall ) {
173                        os << Linkage::name( node->linkage ) << " ";
174                } // if
175                print( node->storage );
176                os << node->typeString();
177                if ( node->base ) {
178                        os << " for ";
179                        ++indent;
180                        node->base->accept( *this );
181                        --indent;
182                } // if
183                if ( ! node->params.empty() ) {
184                        os << endl << indent << "... with parameters" << endl;
185                        ++indent;
186                        printAll( node->params );
187                        --indent;
188                } // if
189                if ( ! node->assertions.empty() ) {
190                        os << endl << indent << "... with assertions" << endl;
191                        ++indent;
192                        printAll( node->assertions );
193                        --indent;
194                } // if
195        }
196
197public:
198        virtual const ast::DeclWithType * visit( const ast::ObjectDecl * node ) {
199                if ( !node->name.empty() ) os << node->name << ": ";
200
201                if ( node->linkage != Linkage::Cforall ) {
202                        os << Linkage::name( node->linkage ) << " ";
203                } // if
204
205                print( node->storage );
206
207                if ( node->type ) {
208                        node->type->accept( *this );
209                } else {
210                        os << " untyped entity ";
211                } // if
212
213                if ( node->init ) {
214                        os << " with initializer (" << (
215                                node->init->maybeConstructed
216                                        ? "maybe constructed"
217                                        : "not constructed"
218                                ) << ")" << endl << indent+1;
219
220                        ++indent;
221                        node->init->accept( *this );
222                        --indent;
223                        os << endl;
224                } // if
225
226                if ( ! node->attributes.empty() ) {
227                        os << endl << indent << "... with attributes:" << endl;
228                        ++indent;
229                        printAll( node->attributes );
230                        --indent;
231                }
232
233                if ( node->bitfieldWidth ) {
234                        os << indent << " with bitfield width ";
235                        node->bitfieldWidth->accept( *this );
236                } // if
237                return node;
238        }
239
240        virtual const ast::DeclWithType * visit( const ast::FunctionDecl * node ) {
241                if ( !node->name.empty() ) {
242                        os << node->name << ": ";
243                } // if
244                if ( node->linkage != Linkage::Cforall ) {
245                        os << Linkage::name( node->linkage ) << " ";
246                } // if
247
248                printAll( node->attributes );
249
250                print( node->storage );
251                print( node->funcSpec );
252
253                if ( node->type ) {
254                        node->type->accept( *this );
255                } else {
256                        os << "untyped entity ";
257                } // if
258
259                if ( node->stmts ) {
260                        os << indent << "... with body" << endl << indent+1;
261                        ++indent;
262                        node->stmts->accept( *this );
263                        --indent;
264                } // if
265                return node;
266        }
267
268        virtual const ast::Decl * visit( const ast::StructDecl * node ) {
269                print(node);
270                return node;
271        }
272
273        virtual const ast::Decl * visit( const ast::UnionDecl * node ) {
274                print(node);
275                return node;
276        }
277
278        virtual const ast::Decl * visit( const ast::EnumDecl * node ) {
279                print(node);
280                return node;
281        }
282
283        virtual const ast::Decl * visit( const ast::TraitDecl * node ) {
284                print(node);
285                return node;
286        }
287
288        virtual const ast::Decl * visit( const ast::TypeDecl * node ) {
289                print( node );
290                if ( node->init ) {
291                        os << endl << indent << "with type initializer: ";
292                        ++indent;
293                        node->init->accept( *this );
294                        --indent;
295                }
296                return node;
297        }
298
299        virtual const ast::Decl * visit( const ast::TypedefDecl * node ) {
300                print( node );
301                return node;
302        }
303
304        virtual const ast::AsmDecl * visit( const ast::AsmDecl * node ) {
305                node->stmt->accept( *this );
306                return node;
307        }
308
309        virtual const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl * node ) {
310                os << "Static Assert with condition: ";
311                ++indent;
312                node->cond->accept( *this );
313                --indent;
314                os << endl << indent << "and message: ";
315                ++indent;
316                node->msg->accept( *this );
317                --indent;
318                os << endl;
319                return node;
320        }
321
322        virtual const ast::CompoundStmt * visit( const ast::CompoundStmt * node ) {
323                os << "CompoundStmt" << endl;
324                ++indent;
325                printAll( node->kids );
326                --indent;
327                return node;
328        }
329
330        virtual const ast::Stmt * visit( const ast::ExprStmt * node ) {
331                ++indent;
332                os << "Expression Statement:" << endl << indent;
333                node->expr->accept( *this );
334                --indent;
335                return node;
336        }
337
338        virtual const ast::Stmt * visit( const ast::AsmStmt * node ) {
339                os << "Assembler Statement:" << endl;
340                ++indent;
341                os << indent << "instruction: " << endl << indent;
342                node->instruction->accept( *this );
343                if ( ! node->output.empty() ) {
344                        os << endl << indent+1 << "output: " << endl;
345                        printAll( node->output );
346                } // if
347                if ( ! node->input.empty() ) {
348                        os << indent+1 << "input: " << endl;
349                        printAll( node->input );
350                } // if
351                if ( ! node->clobber.empty() ) {
352                        os << indent+1 << "clobber: " << endl;
353                        printAll( node->clobber );
354                } // if
355                --indent;
356                return node;
357        }
358
359        virtual const ast::Stmt * visit( const ast::DirectiveStmt * node ) {
360                os << "GCC Directive:" << node->directive << endl;
361                return node;
362        }
363
364        virtual const ast::Stmt * visit( const ast::IfStmt * node ) {
365                os << "If on condition: " << endl;
366                os << indent+1;
367                ++indent;
368                node->cond->accept( *this );
369                --indent;
370
371                if ( !node->inits.empty() ) {
372                        os << indent << "... with initialization: \n";
373                        ++indent;
374                        for ( const Stmt * stmt : node->inits ) {
375                                os << indent;
376                                stmt->accept( *this );
377                        }
378                        --indent;
379                        os << endl;
380                }
381
382                os << indent << "... then: " << endl;
383
384                ++indent;
385                os << indent;
386                node->thenPart->accept( *this );
387                --indent;
388
389                if ( node->elsePart != 0 ) {
390                        os << indent << "... else: " << endl;
391                        ++indent;
392                        os << indent;
393                        node->elsePart->accept( *this );
394                        --indent;
395                } // if
396                return node;
397        }
398
399        virtual const ast::Stmt * visit( const ast::WhileStmt * node ) {
400                return node;
401        }
402
403        virtual const ast::Stmt * visit( const ast::ForStmt * node ) {
404                return node;
405        }
406
407        virtual const ast::Stmt * visit( const ast::SwitchStmt * node ) {
408                return node;
409        }
410
411        virtual const ast::Stmt * visit( const ast::CaseStmt * node ) {
412                return node;
413        }
414
415        virtual const ast::Stmt * visit( const ast::BranchStmt * node ) {
416                return node;
417        }
418
419        virtual const ast::Stmt * visit( const ast::ReturnStmt * node ) {
420                return node;
421        }
422
423        virtual const ast::Stmt * visit( const ast::ThrowStmt * node ) {
424                return node;
425        }
426
427        virtual const ast::Stmt * visit( const ast::TryStmt * node ) {
428                return node;
429        }
430
431        virtual const ast::Stmt * visit( const ast::CatchStmt * node ) {
432                return node;
433        }
434
435        virtual const ast::Stmt * visit( const ast::FinallyStmt * node ) {
436                return node;
437        }
438
439        virtual const ast::Stmt * visit( const ast::WaitForStmt * node ) {
440                return node;
441        }
442
443        virtual const ast::Stmt * visit( const ast::WithStmt * node ) {
444                return node;
445        }
446
447        virtual const ast::NullStmt * visit( const ast::NullStmt * node ) {
448                return node;
449        }
450
451        virtual const ast::Stmt * visit( const ast::DeclStmt * node ) {
452                return node;
453        }
454
455        virtual const ast::Stmt * visit( const ast::ImplicitCtorDtorStmt * node ) {
456                return node;
457        }
458
459        virtual const ast::Expr * visit( const ast::ApplicationExpr * node ) {
460                return node;
461        }
462
463        virtual const ast::Expr * visit( const ast::UntypedExpr * node ) {
464                return node;
465        }
466
467        virtual const ast::Expr * visit( const ast::NameExpr * node ) {
468                return node;
469        }
470
471        virtual const ast::Expr * visit( const ast::AddressExpr * node ) {
472                return node;
473        }
474
475        virtual const ast::Expr * visit( const ast::LabelAddressExpr * node ) {
476                return node;
477        }
478
479        virtual const ast::Expr * visit( const ast::CastExpr * node ) {
480                return node;
481        }
482
483        virtual const ast::Expr * visit( const ast::KeywordCastExpr * node ) {
484                return node;
485        }
486
487        virtual const ast::Expr * visit( const ast::VirtualCastExpr * node ) {
488                return node;
489        }
490
491        virtual const ast::Expr * visit( const ast::UntypedMemberExpr * node ) {
492                return node;
493        }
494
495        virtual const ast::Expr * visit( const ast::MemberExpr * node ) {
496                return node;
497        }
498
499        virtual const ast::Expr * visit( const ast::VariableExpr * node ) {
500                return node;
501        }
502
503        virtual const ast::Expr * visit( const ast::ConstantExpr * node ) {
504                return node;
505        }
506
507        virtual const ast::Expr * visit( const ast::SizeofExpr * node ) {
508                return node;
509        }
510
511        virtual const ast::Expr * visit( const ast::AlignofExpr * node ) {
512                return node;
513        }
514
515        virtual const ast::Expr * visit( const ast::UntypedOffsetofExpr * node ) {
516                return node;
517        }
518
519        virtual const ast::Expr * visit( const ast::OffsetofExpr * node ) {
520                return node;
521        }
522
523        virtual const ast::Expr * visit( const ast::OffsetPackExpr * node ) {
524                return node;
525        }
526
527        virtual const ast::Expr * visit( const ast::LogicalExpr * node ) {
528                return node;
529        }
530
531        virtual const ast::Expr * visit( const ast::ConditionalExpr * node ) {
532                return node;
533        }
534
535        virtual const ast::Expr * visit( const ast::CommaExpr * node ) {
536                return node;
537        }
538
539        virtual const ast::Expr * visit( const ast::TypeExpr * node ) {
540                return node;
541        }
542
543        virtual const ast::Expr * visit( const ast::AsmExpr * node ) {
544                return node;
545        }
546
547        virtual const ast::Expr * visit( const ast::ImplicitCopyCtorExpr * node ) {
548                return node;
549        }
550
551        virtual const ast::Expr * visit( const ast::ConstructorExpr * node ) {
552                return node;
553        }
554
555        virtual const ast::Expr * visit( const ast::CompoundLiteralExpr * node ) {
556                return node;
557        }
558
559        virtual const ast::Expr * visit( const ast::RangeExpr * node ) {
560                return node;
561        }
562
563        virtual const ast::Expr * visit( const ast::UntypedTupleExpr * node ) {
564                return node;
565        }
566
567        virtual const ast::Expr * visit( const ast::TupleExpr * node ) {
568                return node;
569        }
570
571        virtual const ast::Expr * visit( const ast::TupleIndexExpr * node ) {
572                return node;
573        }
574
575        virtual const ast::Expr * visit( const ast::TupleAssignExpr * node ) {
576                return node;
577        }
578
579        virtual const ast::Expr * visit( const ast::StmtExpr * node ) {
580                return node;
581        }
582
583        virtual const ast::Expr * visit( const ast::UniqueExpr * node ) {
584                return node;
585        }
586
587        virtual const ast::Expr * visit( const ast::UntypedInitExpr * node ) {
588                return node;
589        }
590
591        virtual const ast::Expr * visit( const ast::InitExpr * node ) {
592                return node;
593        }
594
595        virtual const ast::Expr * visit( const ast::DeletedExpr * node ) {
596                return node;
597        }
598
599        virtual const ast::Expr * visit( const ast::DefaultArgExpr * node ) {
600                return node;
601        }
602
603        virtual const ast::Expr * visit( const ast::GenericExpr * node ) {
604                return node;
605        }
606
607        virtual const ast::Type * visit( const ast::VoidType * node ) {
608                preprint( node );
609                os << "void";
610                return node;
611        }
612
613        virtual const ast::Type * visit( const ast::BasicType * node ) {
614                preprint( node );
615                os << ast::BasicType::typeNames[ node->kind ];
616                return node;
617        }
618
619        virtual const ast::Type * visit( const ast::PointerType * node ) {
620                preprint( node );
621                if ( ! node->isArray() ) {
622                        os << "pointer to ";
623                } else {
624                        os << "decayed ";
625                        if ( node->isStatic ) {
626                                os << "static ";
627                        }
628
629                        if ( node->isVarLen ) {
630                                os << "variable length array of ";
631                        } else if ( node->dimension ) {
632                                os << "array of ";
633                                node->dimension->accept( *this );
634                                os << " ";
635                        }
636                }
637
638                if ( node->base ) {
639                        node->base->accept( *this );
640                } else {
641                        os << "UNDEFINED";
642                }
643                return node;
644        }
645
646        virtual const ast::Type * visit( const ast::ArrayType * node ) {
647                preprint( node );
648                if ( node->isStatic ) {
649                        os << "static ";
650                }
651
652                if ( node->isVarLen ) {
653                        os << "variable length array of ";
654                } else if ( node->dimension ) {
655                        os << "array of ";
656                } else {
657                        os << "open array of ";
658                }
659
660                if ( node->base ) {
661                        node->base->accept( *this );
662                } else {
663                        os << "UNDEFINED";
664                }
665
666                if ( node->dimension ) {
667                        os << " with dimension of ";
668                        node->dimension->accept( *this );
669                }
670
671                return node;
672        }
673
674        virtual const ast::Type * visit( const ast::ReferenceType * node ) {
675                preprint( node );
676
677                os << "reference to ";
678                if ( node->base ) {
679                        node->base->accept( *this );
680                } else {
681                        os << "UNDEFINED";
682                }
683
684                return node;
685        }
686
687        virtual const ast::Type * visit( const ast::QualifiedType * node ) {
688                preprint( node );
689
690                ++indent;
691                os << "Qualified Type:" << std::endl << indent;
692                node->parent->accept( *this );
693                os << std::endl << indent;
694                node->child->accept( *this );
695                os << std::endl;
696                --indent;
697
698                return node;
699        }
700
701        virtual const ast::Type * visit( const ast::FunctionType * node ) {
702                preprint( node );
703
704                os << "function" << std::endl;
705                if ( ! node->params.empty() ) {
706                        os << indent << "... with parameters" << std::endl;
707                        ++indent;
708                        printAll( node->params );
709                        if ( node->isVarArgs ) {
710                                os << indent << "and a variable number of other arguments" << std::endl;
711                        }
712                        --indent;
713                } else if ( node->isVarArgs ) {
714                        os << indent+1 << "accepting unspecified arguments" << std::endl;
715                }
716
717                os << indent << "... returning";
718                if ( node->returns.empty() ) {
719                        os << " nothing" << std::endl;
720                } else {
721                        os << std::endl;
722                        ++indent;
723                        printAll( node->returns );
724                        --indent;
725                }
726
727                return node;
728        }
729
730        virtual const ast::Type * visit( const ast::StructInstType * node ) {
731                preprint( node );
732
733                os << "instance of struct " << node->name;
734                if ( node->base ) {
735                        os << " " << ( node->base->body ? "with" : "without" ) << " body";
736                }
737                print( node->params );
738
739                return node;
740        }
741
742        virtual const ast::Type * visit( const ast::UnionInstType * node ) {
743                preprint( node );
744
745                os << "instance of union " << node->name;
746                if ( node->base ) {
747                        os << " " << ( node->base->body ? "with" : "without" ) << " body";
748                }
749                print( node->params );
750
751                return node;
752        }
753
754        virtual const ast::Type * visit( const ast::EnumInstType * node ) {
755                preprint( node );
756
757                os << "instance of enum " << node->name;
758                if ( node->base ) {
759                        os << " " << ( node->base->body ? "with" : "without" ) << " body";
760                }
761                print( node->params );
762
763                return node;
764        }
765
766        virtual const ast::Type * visit( const ast::TraitInstType * node ) {
767                preprint( node );
768
769                os << "instance of trait " << node->name;
770                print( node->params );
771
772                return node;
773        }
774
775        virtual const ast::Type * visit( const ast::TypeInstType * node ) {
776                preprint( node );
777
778                os << "instance of type " << node->name
779                   << " (" << (node->kind == ast::TypeVar::Ftype ? "" : "not ") << "function type)";
780                print( node->params );
781
782                return node;
783        }
784
785        virtual const ast::Type * visit( const ast::TupleType * node ) {
786                preprint( node );
787
788                os << "tuple of types" << std::endl;
789                ++indent;
790                printAll( node->types );
791                --indent;
792
793                return node;
794        }
795
796        virtual const ast::Type * visit( const ast::TypeofType * node ) {
797                preprint( node );
798
799                if ( node->kind == ast::TypeofType::Basetypeof ) { os << "base-"; }
800                os << "type-of expression ";
801                if ( node->expr ) {
802                        node->expr->accept( *this );
803                } else {
804                        os << "UNDEFINED";
805                }
806
807                return node;
808        }
809
810        virtual const ast::Type * visit( const ast::VarArgsType * node ) {
811                preprint( node );
812                os << "builtin var args pack";
813                return node;
814        }
815
816        virtual const ast::Type * visit( const ast::ZeroType * node ) {
817                preprint( node );
818                os << "zero_t";
819                return node;
820        }
821
822        virtual const ast::Type * visit( const ast::OneType * node ) {
823                preprint( node );
824                os << "one_t";
825                return node;
826        }
827
828        virtual const ast::Type * visit( const ast::GlobalScopeType * node ) {
829                preprint( node );
830                os << "Global Scope Type";
831                return node;
832        }
833
834        virtual const ast::Designation * visit( const ast::Designation * node ) {
835                if ( node->designators.empty() ) return node;
836                os << "... designated by: " << std::endl;
837                ++indent;
838                for ( const ast::Expr * d : node->designators ) {
839                        os << indent;
840                        d->accept( *this );
841                        os << std::endl;
842                }
843                --indent;
844                return node;
845        }
846
847        virtual const ast::Init * visit( const ast::SingleInit * node ) {
848                os << "Simple Initializer: ";
849                node->value->accept( *this );
850                return node;
851        }
852
853        virtual const ast::Init * visit( const ast::ListInit * node ) {
854                os << "Compound initializer: " << std::endl;
855                ++indent;
856                for ( auto p : group_iterate( node->designations, node->initializers ) ) {
857                        const ast::Designation * d = std::get<0>(p);
858                        const ast::Init * init = std::get<1>(p);
859                        os << indent;
860                        init->accept( *this );
861                        os << std::endl;
862                        if ( ! d->designators.empty() ) {
863                                os << indent;
864                                d->accept( *this );
865                        }
866                }
867                --indent;
868                return node;
869        }
870
871        virtual const ast::Init * visit( const ast::ConstructorInit * node ) {
872                os << "Constructor initializer: " << std::endl;
873                if ( node->ctor ) {
874                        os << indent << "... initially constructed with ";
875                        ++indent;
876                        node->ctor->accept( *this );
877                        --indent;
878                }
879
880                if ( node->dtor ) {
881                        os << indent << "... destructed with ";
882                        ++indent;
883                        node->dtor->accept( *this );
884                        --indent;
885                }
886
887                if ( node->init ) {
888                        os << indent << "... with fallback C-style initializer: ";
889                        ++indent;
890                        node->init->accept( *this );
891                        --indent;
892                }
893                return node;
894        }
895
896        virtual const ast::Attribute * visit( const ast::Attribute * node ) {
897                if ( node->empty() ) return node;
898                os << "Attribute with name: " << node->name;
899                if ( node->params.empty() ) return node;
900                os << " with parameters: " << std::endl;
901                ++indent;
902                printAll( node->params );
903                --indent;
904                return node;
905        }
906
907        virtual const ast::TypeSubstitution * visit( const ast::TypeSubstitution * node ) {
908                os << indent << "Types:" << std::endl;
909                for ( const auto& i : *node ) {
910                        os << indent+1 << i.first << " -> ";
911                        indent += 2;
912                        i.second->accept( *this );
913                        indent -= 2;
914                        os << std::endl;
915                }
916                os << indent << "Non-types:" << std::endl;
917                for ( auto i = node->beginVar(); i != node->endVar(); ++i ) {
918                        os << indent+1 << i->first << " -> ";
919                        indent += 2;
920                        i->second->accept( *this );
921                        indent -= 2;
922                        os << std::endl;
923                }
924                return node;
925        }
926
927};
928
929void print( ostream & os, const ast::Node * node, Indenter indent ) {
930        Printer printer { os, indent, false };
931        node->accept(printer);
932}
933
934void printShort( ostream & os, const ast::Node * node, Indenter indent ) {
935        Printer printer { os, indent, true };
936        node->accept(printer);
937}
938
939// Annoyingly these needed to be defined out of line to avoid undefined references.
940// The size here needs to be explicit but at least the compiler will produce an error
941// if the wrong size is specified
942constexpr array<const char*, 3> Printer::Names::FuncSpecifiers;
943constexpr array<const char*, 5> Printer::Names::StorageClasses;
944constexpr array<const char*, 6> Printer::Names::Qualifiers;
945}
Note: See TracBrowser for help on using the repository browser.