source: src/AST/Print.cpp @ 20a5977

ADTarm-ehast-experimentalcleanup-dtorsenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 20a5977 was 20a5977, checked in by Aaron Moss <a3moss@…>, 5 years ago

Added kind to ConstantExpr? and some Expr prints

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