source: src/AST/Print.cpp @ 08e0d65

Last change on this file since 08e0d65 was b6f2e7ab, checked in by Andrew Beach <ajbeach@…>, 2 months ago

Removed SizeofExpr::expr and AlignofExpr::expr, expressions that would be stored there are wrapped in TypeofType? and stored in the type field. Some special cases to hide the typeof in code generation were added. In addition, initializer length is calculated in more cases so that the full type of more arrays is known sooner. Other than that, most of the code changes were just stripping out the conditional code and checks no longer needed. Some tests had to be updated, because the typeof is not hidden in dumps and the resolver replaces known typeof expressions with the type. The extension case caused some concern but it appears that just hides warnings in the expression which no longer exists.

  • Property mode set to 100644
File size: 41.6 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 -- Print an AST (or sub-tree) to a stream.
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 "Attribute.hpp"
19#include "Decl.hpp"
20#include "Expr.hpp"
21#include "Init.hpp"
22#include "Stmt.hpp"
23#include "Type.hpp"
24#include "TypeSubstitution.hpp"
25#include "CompilationState.hpp"
26#include "Common/Iterate.hpp"
27
28using namespace std;
29
30namespace ast {
31
32namespace {
33
34template<typename C, typename... T>
35constexpr array<C, sizeof...(T)> make_array( T&&... values ) {
36        return array<C, sizeof...(T)>{ std::forward<T>( values )... };
37}
38
39namespace Names {
40        static constexpr auto FuncSpecifiers = make_array<const char*>(
41                "inline", "_Noreturn", "fortran"
42        );
43
44        static constexpr auto StorageClasses = make_array<const char*>(
45                "extern", "static", "auto", "register", "__thread", "_Thread_local"
46        );
47
48        static constexpr auto Qualifiers = make_array<const char*>(
49                "const", "restrict", "volatile", "mutex", "_Atomic"
50        );
51}
52
53template<typename bits_t, size_t N>
54void print( ostream & os, const bits_t & bits,
55                const array<const char *, N> & names ) {
56        if ( !bits.any() ) return;
57        for ( size_t i = 0 ; i < N ; i += 1 ) {
58                if ( bits[i] ) {
59                        os << names[i] << ' ';
60                }
61        }
62}
63
64class Printer final : public Visitor {
65public:
66        ostream & os;
67        Indenter indent;
68        bool short_mode;
69
70        Printer(ostream & os, Indenter indent, bool short_mode) : os( os ), indent( indent ), short_mode(short_mode) {}
71
72private:
73        template< typename C >
74        void printAll( const C & c ) {
75                for ( const auto & i : c ) {
76                        if ( i ) {
77                                os << indent;
78                                i->accept( *this );
79                                // need an endl after each element because it's not
80                                // easy to know when each individual item should end
81                                os << endl;
82                        } // if
83                } // for
84        }
85
86        /// call if mandatory field is missing
87        void undefined() {
88                os << "UNDEFINED";
89        }
90
91        /// call for fields that should be mandatory
92        void safe_print( const ast::Node * n ) {
93                if ( n ) n->accept( *this );
94                else undefined();
95        }
96
97        /// call to print short form. Incorporates features of safe_print()
98        void short_print( const ast::Decl * n ) {
99                if ( ! n ) { undefined(); return; }
100                bool old_short = short_mode; short_mode = true;
101                n->accept( *this );
102                short_mode = old_short;
103        }
104
105        void print( const std::vector<ast::Label> & labels ) {
106                if ( labels.empty() ) return;
107                os << indent << "... Labels: {";
108                bool isFirst = true;
109                for ( const Label & l : labels ) {
110                        if ( isFirst ) { isFirst = false; } else { os << ","; }
111                        os << l;
112                }
113                os << "}" << endl;
114        }
115
116        void print( const ast::Expr::InferUnion & inferred, unsigned level = 0 ) {
117                if (inferred.data.resnSlots && !inferred.data.resnSlots->empty()) {
118                        os << indent << "with " << inferred.data.resnSlots->size()
119                           << " pending inference slots" << endl;
120                }
121                if (inferred.data.inferParams && !inferred.data.inferParams->empty()) {
122                        os << indent << "with inferred parameters " << level << ":" << endl;
123                        ++indent;
124                        for ( const auto & i : *inferred.data.inferParams ) {
125                                os << indent;
126                                short_print( i.second.declptr );
127                                os << endl;
128                                print( i.second.expr->inferred, level+1 );
129                        }
130                        --indent;
131                }
132        }
133
134        void print( const ast::FunctionType::ForallList & forall ) {
135                if ( forall.empty() ) return;
136                os << "forall" << endl;
137                ++indent;
138                printAll( forall );
139                os << indent;
140                --indent;
141        }
142
143        void print( const ast::FunctionType::AssertionList & assts ) {
144                if (assts.empty()) return;
145                os << "with assertions" << endl;
146                ++indent;
147                printAll(assts);
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" << 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 << endl << indent << "... with parameters" << endl;
163                ++indent;
164                printAll( params );
165                --indent;
166        }
167
168        void print( const ast::AggregateDecl * node ) {
169                os << node->typeString() << " " << node->name;
170
171                if ( ! short_mode && node->linkage != Linkage::Cforall ) {
172                        os << " " << Linkage::name( node->linkage );
173                }
174
175                auto ptrToEnum = dynamic_cast<const ast::EnumDecl *>(node);
176                if ( ! short_mode && ptrToEnum && ptrToEnum->base ) {
177                        os << endl << indent << "... with base type" << endl;
178                        ++indent;
179                        os << indent;
180                        ptrToEnum->base->accept( *this );
181                        --indent;
182                }
183
184                os << " " << (node->body ? "with" : "without") << " body";
185
186                if ( ! node->params.empty() ) {
187                        os << endl << indent << "... with parameters" << endl;
188                        ++indent;
189                        printAll( node->params );
190                        --indent;
191                }
192
193                if ( ! short_mode && ! node->members.empty() ) {
194                        os << endl << indent << "... with members" << endl;
195                        ++indent;
196                        printAll( node->members );
197                        --indent;
198                }
199
200                if ( ! short_mode && ! node->attributes.empty() ) {
201                        os << endl << indent << "... with attributes" << endl;
202                        ++indent;
203                        printAll( node->attributes );
204                        --indent;
205                }
206
207
208
209                os << endl;
210        }
211
212        void print( const ast::WaitStmt * node ) {
213                if ( node->timeout_time ) {
214                        os << indent-1 << "timeout of:" << endl;
215                        node->timeout_time->accept( *this );
216
217                        if ( node->timeout_stmt ) {
218                                os << indent-1 << "... with statment:" << endl;
219                                node->timeout_stmt->accept( *this );
220                        }
221
222                        if ( node->timeout_cond ) {
223                                os << indent-1 << "... with condition:" << endl;
224                                node->timeout_cond->accept( *this );
225                        }
226                }
227
228                if ( node->else_stmt ) {
229                        os << indent-1 << "else:" << endl;
230                        node->else_stmt->accept( *this );
231
232                        if ( node->else_cond ) {
233                                os << indent-1 << "... with condition:" << endl;
234                                node->else_cond->accept( *this );
235                        }
236                }
237        }
238
239        void preprint( const ast::NamedTypeDecl * node ) {
240                if ( ! node->name.empty() ) {
241                        os << node->name << ": ";
242                }
243
244                if ( ! short_mode && node->linkage != Linkage::Cforall ) {
245                        os << Linkage::name( node->linkage ) << " ";
246                }
247
248                ast::print( os, node->storage );
249                os << node->typeString();
250
251                if ( node->base ) {
252                        os << " for ";
253                        ++indent;
254                        node->base->accept( *this );
255                        --indent;
256                }
257
258                if ( ! node->assertions.empty() ) {
259                        os << endl << indent << "... with assertions" << endl;
260                        ++indent;
261                        printAll( node->assertions );
262                        --indent;
263                }
264        }
265
266        void postprint( const ast::Expr * node ) {
267                print( node->inferred );
268
269                if ( node->result ) {
270                        os << endl << indent << "... with resolved type:" << endl;
271                        ++indent;
272                        os << indent;
273                        node->result->accept( *this );
274                        --indent;
275                }
276
277                if ( node->env ) {
278                        os << endl << indent << "... with environment:" << endl;
279                        ++indent;
280                        node->env->accept( *this );
281                        --indent;
282                }
283
284                if ( node->extension ) {
285                        os << endl << indent << "... with extension";
286                }
287        }
288
289        void preprint( const ast::Type * node ) {
290                ast::print( os, node->qualifiers );
291        }
292
293        void preprint( const ast::FunctionType * node ) {
294                print( node->forall );
295                print( node->assertions );
296                ast::print( os, node->qualifiers );
297        }
298
299        void preprint( const ast::BaseInstType * node ) {
300                print( node->attributes );
301                ast::print( os, node->qualifiers );
302        }
303
304public:
305        virtual const ast::DeclWithType * visit( const ast::ObjectDecl * node ) override final {
306                if ( ! node->name.empty() ) os << node->name << ": ";
307
308                if ( ! short_mode && node->linkage != Linkage::Cforall ) {
309                        os << Linkage::name( node->linkage ) << " ";
310                }
311
312                ast::print( os, node->storage );
313
314                if ( node->type ) {
315                        node->type->accept( *this );
316                } else {
317                        os << "untyped entity";
318                }
319
320                if ( ! short_mode && node->init ) {
321                        ++indent;
322                        os << " with initializer (" << (
323                                node->init->maybeConstructed
324                                        ? "maybe constructed"
325                                        : "not constructed"
326                                ) << ")" << endl << indent;
327                        node->init->accept( *this );
328                        --indent;
329                        os << endl;
330                }
331
332                if ( ! short_mode && ! node->attributes.empty() ) {
333                        os << endl << indent << "... with attributes:" << endl;
334                        ++indent;
335                        printAll( node->attributes );
336                        --indent;
337                }
338
339                if ( node->bitfieldWidth ) {
340                        os << indent << " with bitfield width ";
341                        node->bitfieldWidth->accept( *this );
342                }
343
344                return node;
345        }
346
347        virtual const ast::DeclWithType * visit( const ast::FunctionDecl * node ) override final {
348                if ( !node->name.empty() ) os << node->name << ": ";
349
350                if ( ! short_mode && node->linkage != Linkage::Cforall ) {
351                        os << Linkage::name( node->linkage ) << " ";
352                }
353
354                if ( ! short_mode ) printAll( node->attributes );
355
356                ast::print( os, node->storage );
357                ast::print( os, node->funcSpec );
358
359                if ( node->type && node->isTypeFixed ) {
360                        node->type->accept( *this );
361                } else {
362                        if (!node->type_params.empty()) {
363                                os << "forall" << endl;
364                                ++indent;
365                                printAll(node->type_params);
366                                os << indent;
367                                --indent;
368
369                                if (!node->assertions.empty()) {
370                                        os << "with assertions" << endl;
371                                        ++indent;
372                                        printAll(node->assertions);
373                                        os << indent;
374                                        --indent;
375                                }
376                        }
377
378                        os << "function" << endl;
379                        if ( ! node->params.empty() ) {
380                                os << indent << "... with parameters" << endl;
381                                ++indent;
382                                printAll( node->params );
383                                if ( node->type->isVarArgs ) {
384                                        os << indent << "and a variable number of other arguments" << endl;
385                                }
386                                --indent;
387                        } else if ( node->type->isVarArgs ) {
388                                os << indent+1 << "accepting unspecified arguments" << endl;
389                        }
390
391                        os << indent << "... returning";
392                        if ( node->returns.empty() ) {
393                                os << " nothing" << endl;
394                        } else {
395                                os << endl;
396                                ++indent;
397                                printAll( node->returns );
398                                --indent;
399                        }
400                }
401
402                if ( ! node->withExprs.empty() ) {
403                        // Not with a clause, but the 'with clause'.
404                        ++indent;
405                        os << " with clause" << endl << indent;
406                        printAll( node->withExprs );
407                        --indent;
408                }
409
410                if ( ! short_mode && node->stmts ) {
411                        ++indent;
412                        os << " with body" << endl << indent;
413                        node->stmts->accept( *this );
414                        --indent;
415                }
416
417                return node;
418        }
419
420        virtual const ast::Decl * visit( const ast::StructDecl * node ) override final {
421                print(node);
422                return node;
423        }
424
425        virtual const ast::DeclWithType * visit( const ast::InlineMemberDecl * node ) override final {
426                os << "inline ";
427                if ( ! node->name.empty() ) os << node->name;
428
429                return node;
430        }
431
432        virtual const ast::Decl * visit( const ast::UnionDecl * node ) override final {
433                print(node);
434                return node;
435        }
436
437        virtual const ast::Decl * visit( const ast::EnumDecl * node ) override final {
438                print(node);
439                return node;
440        }
441
442        virtual const ast::Decl * visit( const ast::TraitDecl * node ) override final {
443                print(node);
444                return node;
445        }
446
447        virtual const ast::Decl * visit( const ast::TypeDecl * node ) override final {
448                preprint( node );
449                if ( ! short_mode && node->init ) {
450                        os << endl << indent << "with type initializer: ";
451                        ++indent;
452                        node->init->accept( *this );
453                        --indent;
454                }
455
456                return node;
457        }
458
459        virtual const ast::Decl * visit( const ast::TypedefDecl * node ) override final {
460                preprint( node );
461                return node;
462        }
463
464        virtual const ast::AsmDecl * visit( const ast::AsmDecl * node ) override final {
465                safe_print( node->stmt );
466                return node;
467        }
468
469        virtual const ast::DirectiveDecl * visit( const ast::DirectiveDecl * node ) override final {
470                safe_print( node->stmt );
471                return node;
472        }
473
474        virtual const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl * node ) override final {
475                os << "Static Assert with condition: ";
476                ++indent;
477                safe_print( node->cond );
478                os << endl << indent-1 << "and message: ";
479                safe_print( node->msg );
480                --indent;
481                os << endl;
482
483                return node;
484        }
485
486        virtual const ast::CompoundStmt * visit( const ast::CompoundStmt * node ) override final {
487                os << "Compound Statement:" << endl;
488                ++indent;
489                printAll( node->kids );
490                --indent;
491                return node;
492        }
493
494        virtual const ast::Stmt * visit( const ast::ExprStmt * node ) override final {
495                ++indent;
496                os << "Expression Statement:" << endl << indent;
497                safe_print( node->expr );
498                --indent;
499                return node;
500        }
501
502        virtual const ast::Stmt * visit( const ast::AsmStmt * node ) override final {
503                os << "Assembler Statement:" << endl;
504                ++indent;
505                os << indent-1 << "instruction:" << endl << indent;
506                safe_print( node->instruction );
507                if ( ! node->output.empty() ) {
508                        os << endl << indent << "output:" << endl;
509                        printAll( node->output );
510                } // if
511                if ( ! node->input.empty() ) {
512                        os << indent << "input:" << endl;
513                        printAll( node->input );
514                } // if
515                if ( ! node->clobber.empty() ) {
516                        os << indent << "clobber:" << endl;
517                        printAll( node->clobber );
518                } // if
519                --indent;
520                return node;
521        }
522
523        virtual const ast::Stmt * visit( const ast::DirectiveStmt * node ) override final {
524                os << "GCC Directive: " << node->directive << endl;
525                return node;
526        }
527
528        virtual const ast::Stmt * visit( const ast::IfStmt * node ) override final {
529                os << "If on condition:" << endl;
530                ++indent;
531                os << indent;
532                safe_print( node->cond );
533                --indent;
534
535                if ( ! node->inits.empty() ) {
536                        os << indent << "... with initialization:" << endl;
537                        ++indent;
538                        for ( const ast::Stmt * stmt : node->inits ) {
539                                os << indent;
540                                safe_print( stmt );
541                        }
542                        --indent;
543                        os << endl;
544                }
545
546                os << indent << "... then:" << endl;
547
548                ++indent;
549                os << indent;
550                safe_print( node->then );
551                --indent;
552
553                if ( node->else_ != 0 ) {
554                        os << indent << "... else:" << endl;
555                        ++indent;
556                        os << indent;
557                        node->else_->accept( *this );
558                        --indent;
559                } // if
560                return node;
561        }
562
563        virtual const ast::Stmt * visit( const ast::WhileDoStmt * node ) override final {
564                if ( node->isDoWhile ) { os << "Do-"; }
565                os << "While on condition:" << endl;
566                ++indent;
567                safe_print( node->cond );
568
569                if ( ! node->inits.empty() ) {
570                        os << indent-1 << "... with inits:" << endl;
571                        printAll( node->inits );
572                }
573
574                os << indent-1 << "... with body:" << endl;
575                safe_print( node->body );
576
577                if ( node->else_ ) {
578                        os << indent-1 << "... with else:" << endl;
579                        os << indent;
580                        node->else_->accept( *this );
581                }
582
583                --indent;
584
585                return node;
586        }
587
588        virtual const ast::Stmt * visit( const ast::ForStmt * node ) override final {
589                os << "For Statement" << endl;
590
591                if ( ! node->inits.empty() ) {
592                        os << indent << "... initialization:" << endl;
593                        ++indent;
594                        for ( const ast::Stmt * stmt : node->inits ) {
595                                os << indent+1;
596                                safe_print( stmt );
597                        }
598                        --indent;
599                }
600
601                if ( node->cond ) {
602                        os << indent << "... condition:" << endl;
603                        ++indent;
604                        os << indent;
605                        node->cond->accept( *this );
606                        --indent;
607                }
608
609                if ( node->inc ) {
610                        os << indent << "... increment:" << endl;
611                        ++indent;
612                        os << indent;
613                        node->inc->accept( *this );
614                        --indent;
615                }
616
617                if ( node->body ) {
618                        os << indent << "... with body:" << endl;
619                        ++indent;
620                        os << indent;
621                        node->body->accept( *this );
622                        --indent;
623                }
624
625                if ( node->else_ ) {
626                        os << indent << "... with else:" << endl;
627                        ++indent;
628                        os << indent;
629                        node->else_->accept( *this );
630                        --indent;
631                }
632
633                os << endl;
634                print( node->labels );
635
636                return node;
637        }
638
639        virtual const ast::Stmt * visit( const ast::SwitchStmt * node ) override final {
640                os << "Switch on condition: ";
641                safe_print( node->cond );
642                os << endl;
643
644                ++indent;
645                for ( const ast::CaseClause * stmt : node->cases ) {
646                        stmt->accept( *this );
647                }
648                --indent;
649
650                return node;
651        }
652
653        virtual const ast::CaseClause * visit( const ast::CaseClause * node ) override final {
654                if ( node->isDefault() ) {
655                        os << indent << "Default ";
656                } else {
657                        os << indent << "Case ";
658                        safe_print( node->cond );
659                } // if
660                os << endl;
661
662                ++indent;
663                for ( const ast::Stmt * stmt : node->stmts ) {
664                        os << indent;
665                        stmt->accept( *this );
666                }
667                --indent;
668
669                return node;
670        }
671
672        virtual const ast::Stmt * visit( const ast::BranchStmt * node ) override final {
673                os << "Branch (" << node->kindName() << ")" << endl;
674                ++indent;
675                if ( ! node->target.empty() ) {
676                        os << indent << "with target: " << node->target << endl;
677                }
678
679                if ( ! node->originalTarget.empty() ) {
680                        os << indent << "with original target: " << node->originalTarget << endl;
681                }
682
683                if ( node->computedTarget ) {
684                        os << indent << "with computed target: ";
685                        node->computedTarget->accept( *this );
686                        os << endl;
687                }
688                --indent;
689
690                return node;
691        }
692
693        virtual const ast::Stmt * visit( const ast::ReturnStmt * node ) override final {
694                os << "Return Statement, returning";
695                if ( node->expr ) {
696                        ++indent;
697                        os << ":" << endl << indent;
698                        node->expr->accept( *this );
699                        --indent;
700                } else {
701                        os << " void";
702                }
703                os << endl;
704
705                return node;
706        }
707
708        virtual const ast::Stmt * visit( const ast::ThrowStmt * node ) override final {
709                if ( node->target ) os << "Non-Local ";
710
711                switch( node->kind ) {
712                case ast::ExceptionKind::Terminate: os << "Terminate "; break;
713                case ast::ExceptionKind::Resume:    os << "Resume ";    break;
714                }
715
716                ++indent;
717                os << "Throw Statement, raising: ";
718                safe_print( node->expr );
719                if ( node->target ) {
720                        os << "... at: ";
721                        node->target->accept( *this );
722                }
723                --indent;
724
725                return node;
726        }
727
728        virtual const ast::Stmt * visit( const ast::TryStmt * node ) override final {
729                ++indent;
730                os << "Try Statement" << endl << indent-1
731                   << "... with block:" << endl << indent;
732                safe_print( node->body );
733
734                os << indent-1 << "... and handlers:" << endl;
735                for ( const ast::CatchClause * stmt : node->handlers ) {
736                        os << indent;
737                        stmt->accept( *this );
738                }
739
740                if ( node->finally ) {
741                        os << indent-1 << "... and finally:" << endl << indent;
742                        node->finally->accept( *this );
743                }
744                --indent;
745
746                return node;
747        }
748
749        virtual const ast::CatchClause * visit( const ast::CatchClause * node ) override final {
750                os << "Catch ";
751                switch ( node->kind ) {
752                case ast::ExceptionKind::Terminate: os << "Terminate "; break;
753                case ast::ExceptionKind::Resume:    os << "Resume ";    break;
754                }
755                os << "Statement" << endl << indent;
756
757                ++indent;
758                os << "... catching: ";
759                short_print( node->decl );
760                os << endl;
761
762                if ( node->cond ) {
763                        os << indent-1 << "... with conditional:" << endl << indent;
764                        node->cond->accept( *this );
765                }
766
767                os << indent-1 << "... with block:" << endl << indent;
768                safe_print( node->body );
769                --indent;
770
771                return node;
772        }
773
774        virtual const ast::FinallyClause * visit( const ast::FinallyClause * node ) override final {
775                os << "Finally Statement" << endl;
776                os << indent << "... with block:" << endl;
777                ++indent;
778                os << indent;
779                safe_print( node->body );
780                --indent;
781
782                return node;
783        }
784
785        virtual const ast::Stmt * visit( const ast::SuspendStmt * node ) override final {
786                os << "Suspend Statement";
787                switch (node->kind) {
788                case ast::SuspendStmt::None     : os << " with implicit target"; break;
789                case ast::SuspendStmt::Generator: os << " for generator"; break;
790                case ast::SuspendStmt::Coroutine: os << " for coroutine"; break;
791                }
792                os << endl;
793
794                ++indent;
795                if(node->then) {
796                        os << indent << " with post statement :" << endl;
797                        safe_print( node->then );
798                }
799                ++indent;
800
801                return node;
802        }
803
804        virtual const ast::WhenClause * visit( const ast::WhenClause * node ) override final {
805                os << indent-1 << "target: ";
806                safe_print( node->target );
807
808                if ( node->stmt ) {
809                        os << indent-1 << "... with statment:" << endl;
810                        node->stmt->accept( *this );
811                }
812
813                if ( node->when_cond ) {
814                        os << indent-1 << "... with when condition:" << endl;
815                        node->when_cond->accept( *this );
816                }
817
818                return node;
819        }
820
821        virtual const ast::Stmt * visit( const ast::WaitForStmt * node ) override final {
822                os << "Waitfor Statement" << endl;
823                indent += 2;
824                for( const auto & clause : node->clauses ) {
825                        clause->accept( *this );
826                }
827
828                if ( node->timeout_time ) {
829                        os << indent-1 << "timeout of:" << endl;
830                        node->timeout_time->accept( *this );
831
832                        if ( node->timeout_stmt ) {
833                                os << indent-1 << "... with statment:" << endl;
834                                node->timeout_stmt->accept( *this );
835                        }
836
837                        if ( node->timeout_cond ) {
838                                os << indent-1 << "... with condition:" << endl;
839                                node->timeout_cond->accept( *this );
840                        }
841                }
842
843                if ( node->else_stmt ) {
844                        os << indent-1 << "else:" << endl;
845                        node->else_stmt->accept( *this );
846
847                        if ( node->else_cond ) {
848                                os << indent-1 << "... with condition:" << endl;
849                                node->else_cond->accept( *this );
850                        }
851                }
852
853                return node;
854        }
855
856        virtual const ast::WaitForClause * visit( const ast::WaitForClause * node ) override final {
857                os << indent-1 << "target function: ";
858                safe_print( node->target );
859
860                if ( !node->target_args.empty() ) {
861                        os << endl << indent-1 << "... with arguments:" << endl;
862                        for( const ast::Expr * arg : node->target_args ) {
863                                arg->accept( *this );
864                        }
865                }
866
867                if ( node->stmt ) {
868                        os << indent-1 << "... with statment:" << endl;
869                        node->stmt->accept( *this );
870                }
871
872                if ( node->when_cond ) {
873                        os << indent-1 << "... with condition:" << endl;
874                        node->when_cond->accept( *this );
875                }
876
877                return node;
878        }
879
880        virtual const ast::Stmt * visit( const ast::WaitUntilStmt * node ) override final {
881                os << "Waituntil Statement" << endl;
882                indent += 2;
883                for( const auto & clause : node->clauses ) {
884                        clause->accept( *this );
885                }
886                // calls print( const ast::WaitStmt * node )
887                print(node);
888                return node;
889        }
890
891        virtual const ast::Decl * visit( const ast::WithStmt * node ) override final {
892                os << "With statement" << endl;
893                os << indent << "... with expressions:" << endl;
894                ++indent;
895                printAll( node->exprs );
896                os << indent-1 << "... with statement:" << endl << indent;
897                safe_print( node->stmt );
898                --indent;
899
900                return node;
901        }
902
903        virtual const ast::NullStmt * visit( const ast::NullStmt * node ) override final {
904                os << "Null Statement" << endl;
905                print( node->labels );
906
907                return node;
908        }
909
910        virtual const ast::Stmt * visit( const ast::DeclStmt * node ) override final {
911                os << "Declaration of ";
912                safe_print( node->decl );
913
914                return node;
915        }
916
917        virtual const ast::Stmt * visit( const ast::ImplicitCtorDtorStmt * node ) override final {
918                os << "Implicit Ctor Dtor Statement" << endl;
919                os << indent << "... with Ctor/Dtor: ";
920                ++indent;
921                safe_print( node->callStmt );
922                --indent;
923                os << endl;
924
925                return node;
926        }
927
928        virtual const ast::Stmt * visit( const ast::MutexStmt * node ) override final {
929                os << "Mutex Statement" << endl;
930                os << indent << "... with Mutex Parameters: ";
931                ++indent;
932                printAll( node->mutexObjs );
933                --indent;
934                os << indent << "... with Statement: ";
935                ++indent;
936                safe_print( node->stmt );
937                --indent;
938                os << endl;
939
940                return node;
941        }
942
943        virtual const ast::Stmt * visit( const ast::CorunStmt * node ) override final {
944                os << "Corun Statement" << endl;
945                os << indent << "... with Statement: ";
946                ++indent;
947                safe_print( node->stmt );
948                --indent;
949                os << endl;
950
951                return node;
952        }
953
954        virtual const ast::Stmt * visit( const ast::CoforStmt * node ) override final {
955                os << "Cofor Statement" << endl;
956
957                if ( ! node->inits.empty() ) {
958                        os << indent << "... initialization:" << endl;
959                        ++indent;
960                        for ( const ast::Stmt * stmt : node->inits ) {
961                                os << indent+1;
962                                safe_print( stmt );
963                        }
964                        --indent;
965                }
966
967                if ( node->cond ) {
968                        os << indent << "... condition:" << endl;
969                        ++indent;
970                        os << indent;
971                        node->cond->accept( *this );
972                        --indent;
973                }
974
975                if ( node->inc ) {
976                        os << indent << "... increment:" << endl;
977                        ++indent;
978                        os << indent;
979                        node->inc->accept( *this );
980                        --indent;
981                }
982
983                if ( node->body ) {
984                        os << indent << "... with body:" << endl;
985                        ++indent;
986                        os << indent;
987                        node->body->accept( *this );
988                        --indent;
989                }
990                os << endl;
991                print( node->labels );
992
993                return node;
994        }
995
996        virtual const ast::Expr * visit( const ast::ApplicationExpr * node ) override final {
997                ++indent;
998                os << "Application of" << endl << indent;
999                safe_print( node->func );
1000                os << endl;
1001                if ( ! node->args.empty() ) {
1002                        os << indent << "... to arguments" << endl;
1003                        printAll( node->args );
1004                }
1005                --indent;
1006                postprint( node );
1007
1008                return node;
1009        }
1010
1011        virtual const ast::Expr * visit( const ast::UntypedExpr * node ) override final {
1012                ++indent;
1013                os << "Applying untyped:" << endl;
1014                os << indent;
1015                safe_print( node->func );
1016                os << endl << indent-1 << "...to:" << endl;
1017                printAll( node->args );
1018                --indent;
1019                postprint( node );
1020
1021                return node;
1022        }
1023
1024        virtual const ast::Expr * visit( const ast::NameExpr * node ) override final {
1025                os << "Name: " << node->name;
1026                postprint( node );
1027
1028                return node;
1029        }
1030
1031        virtual const ast::Expr * visit( const ast::QualifiedNameExpr * node ) override final {
1032                os << "QualifiedNameExpr: " << std::endl;
1033                os << ++indent << "Type: ";
1034                safe_print( node->type_decl );
1035                os << std::endl;
1036                os <<  indent << "Name: " << node->name  << std::endl;
1037                --indent;
1038                postprint( node );
1039                return node;
1040        }
1041
1042        virtual const ast::Expr * visit( const ast::AddressExpr * node ) override final {
1043                os << "Address of:" << endl;
1044                ++indent;
1045                os << indent;
1046                safe_print( node->arg );
1047
1048                --indent;
1049
1050                return node;
1051        }
1052
1053        virtual const ast::Expr * visit( const ast::LabelAddressExpr * node ) override final {
1054                os << "Address of label:" << node->arg;
1055
1056                return node;
1057        }
1058
1059        virtual const ast::Expr * visit( const ast::CastExpr * node ) override final {
1060                ++indent;
1061                os << (node->isGenerated ? "Generated" : "Explicit") << " Cast of:" << endl << indent;
1062                safe_print( node->arg );
1063                os << endl << indent-1 << "... to:";
1064                if ( ! node->result ) {
1065                        os << " ";
1066                        undefined();
1067                } else if ( node->result->isVoid() ) {
1068                        os << " nothing";
1069                } else {
1070                        os << endl << indent;
1071                        node->result->accept( *this );
1072                } // if
1073                --indent;
1074                postprint( node );
1075
1076                return node;
1077        }
1078
1079        virtual const ast::Expr * visit( const ast::KeywordCastExpr * node ) override final {
1080                ++indent;
1081                os << "Keyword Cast of:" << endl << indent;
1082                safe_print( node->arg );
1083                --indent;
1084                os << endl << indent << "... to: " << node->targetString();
1085                postprint( node );
1086
1087                return node;
1088        }
1089
1090        virtual const ast::Expr * visit( const ast::VirtualCastExpr * node ) override final {
1091                ++indent;
1092                os << "Virtual Cast of:" << endl << indent;
1093                safe_print( node->arg );
1094                os << endl << indent-1 << "... to:";
1095                if ( ! node->result ) {
1096                        os << " unknown";
1097                } else {
1098                        os << endl << indent;
1099                        node->result->accept( *this );
1100                }
1101                --indent;
1102                postprint( node );
1103
1104                return node;
1105        }
1106
1107        virtual const ast::Expr * visit( const ast::UntypedMemberExpr * node ) override final {
1108                ++indent;
1109                os << "Untyped Member Expression, with field: " << endl << indent;
1110                safe_print( node->member );
1111                os << indent-1 << "... from aggregate:" << endl << indent;
1112                safe_print( node->aggregate );
1113                --indent;
1114                postprint( node );
1115
1116                return node;
1117        }
1118
1119        virtual const ast::Expr * visit( const ast::MemberExpr * node ) override final {
1120                ++indent;
1121                os << "Member Expression, with field:" << endl << indent;
1122                safe_print( node->member );
1123                os << endl << indent-1 << "... from aggregate:" << endl << indent;
1124                safe_print( node->aggregate );
1125                --indent;
1126                postprint( node );
1127
1128                return node;
1129        }
1130
1131        virtual const ast::Expr * visit( const ast::VariableExpr * node ) override final {
1132                os << "Variable Expression: ";
1133                short_print( node->var );
1134                postprint( node );
1135
1136                return node;
1137        }
1138
1139        virtual const ast::Expr * visit( const ast::ConstantExpr * node ) override final {
1140                os << "Constant Expression (" << node->rep;
1141                if ( node->result ) {
1142                        os << ": ";
1143                        node->result->accept( *this );
1144                }
1145                os << ")";
1146                postprint( node );
1147
1148                return node;
1149        }
1150
1151        virtual const ast::Expr * visit( const ast::SizeofExpr * node ) override final {
1152                os << "Sizeof Expression on: ";
1153                ++indent;
1154                node->type->accept( *this );
1155                --indent;
1156                postprint( node );
1157
1158                return node;
1159        }
1160
1161        virtual const ast::Expr * visit( const ast::CountExpr * node ) override final {
1162                os << "Count Expression on: ";
1163                ++indent;
1164                if ( node->type ) node->type->accept( *this );
1165                else safe_print( node->expr );
1166                --indent;
1167                postprint( node );
1168                return node;
1169        }
1170
1171        virtual const ast::Expr * visit( const ast::AlignofExpr * node ) override final {
1172                os << "Alignof Expression on: ";
1173                ++indent;
1174                node->type->accept( *this );
1175                --indent;
1176                postprint( node );
1177
1178                return node;
1179        }
1180
1181        virtual const ast::Expr * visit( const ast::UntypedOffsetofExpr * node ) override final {
1182                os << "Untyped Offsetof Expression on member " << node->member << " of ";
1183                ++indent;
1184                safe_print( node->type );
1185                --indent;
1186                postprint( node );
1187
1188                return node;
1189        }
1190
1191        virtual const ast::Expr * visit( const ast::OffsetofExpr * node ) override final {
1192                os << "Offsetof Expression on member " << node->member->name << " of ";
1193                ++indent;
1194                safe_print( node->type );
1195                --indent;
1196                postprint( node );
1197
1198                return node;
1199        }
1200
1201        virtual const ast::Expr * visit( const ast::OffsetPackExpr * node ) override final {
1202                os << "Offset Pack Expression on: ";
1203                ++indent;
1204                safe_print( node->type );
1205                --indent;
1206                postprint( node );
1207
1208                return node;
1209        }
1210
1211        virtual const ast::Expr * visit( const ast::LogicalExpr * node ) override final {
1212                os << "Short-circuited operation (" << (node->isAnd ? "and" : "or") << ") on: ";
1213                safe_print( node->arg1 );
1214                os << " and ";
1215                safe_print( node->arg2 );
1216                postprint( node );
1217
1218                return node;
1219        }
1220
1221        virtual const ast::Expr * visit( const ast::ConditionalExpr * node ) override final {
1222                ++indent;
1223                os << "Conditional expression on:" << endl << indent;
1224                safe_print( node->arg1 );
1225                os << indent-1 << "First alternative:" << endl << indent;
1226                safe_print( node->arg2 );
1227                os << indent-1 << "Second alternative:" << endl << indent;
1228                safe_print( node->arg3 );
1229                --indent;
1230                postprint( node );
1231
1232                return node;
1233        }
1234
1235        virtual const ast::Expr * visit( const ast::CommaExpr * node ) override final {
1236                ++indent;
1237                os << "Comma Expression:" << endl << indent;
1238                safe_print( node->arg1 );
1239                os << endl << indent;
1240                safe_print( node->arg2 );
1241                --indent;
1242                postprint( node );
1243
1244                return node;
1245        }
1246
1247        virtual const ast::Expr * visit( const ast::TypeExpr * node ) override final {
1248                safe_print( node->type );
1249                postprint( node );
1250
1251                return node;
1252        }
1253
1254        virtual const ast::Expr * visit( const ast::DimensionExpr * node ) override final {
1255                os << "Type-Sys Value: " << node->name;
1256                postprint( node );
1257
1258                return node;
1259        }
1260
1261        virtual const ast::Expr * visit( const ast::AsmExpr * node ) override final {
1262                os << "Asm Expression:" << endl;
1263                ++indent;
1264                if ( !node->inout.empty() ) os << "[" << node->inout << "] ";
1265                if ( node->constraint ) node->constraint->accept( *this );
1266                if ( node->operand ) node->operand->accept( *this );
1267                --indent;
1268
1269                return node;
1270        }
1271
1272        virtual const ast::Expr * visit( const ast::ImplicitCopyCtorExpr * node ) override final {
1273                ++indent;
1274                os << "Implicit Copy Constructor Expression:" << endl << indent;
1275                safe_print( node->callExpr );
1276                --indent;
1277                postprint( node );
1278
1279                return node;
1280        }
1281
1282        virtual const ast::Expr * visit( const ast::ConstructorExpr * node ) override final {
1283                os <<  "Constructor Expression:" << endl << indent+1;
1284                indent += 2;
1285                safe_print( node->callExpr );
1286                indent -= 2;
1287                postprint( node );
1288
1289                return node;
1290        }
1291
1292        virtual const ast::Expr * visit( const ast::CompoundLiteralExpr * node ) override final {
1293                ++indent;
1294                os << "Compound Literal Expression: " << endl << indent;
1295                safe_print( node->result );
1296                os << indent;
1297                safe_print( node->init );
1298                --indent;
1299                postprint( node );
1300
1301                return node;
1302        }
1303
1304        virtual const ast::Expr * visit( const ast::RangeExpr * node ) override final {
1305                os << "Range Expression: ";
1306                safe_print( node->low );
1307                os << " ... ";
1308                safe_print( node->high );
1309                postprint( node );
1310
1311                return node;
1312        }
1313
1314        virtual const ast::Expr * visit( const ast::UntypedTupleExpr * node ) override final {
1315                os << "Untyped Tuple:" << endl;
1316                ++indent;
1317                printAll( node->exprs );
1318                --indent;
1319                postprint( node );
1320
1321                return node;
1322        }
1323
1324        virtual const ast::Expr * visit( const ast::TupleExpr * node ) override final {
1325                os << "Tuple:" << endl;
1326                ++indent;
1327                printAll( node->exprs );
1328                --indent;
1329                postprint( node );
1330
1331                return node;
1332        }
1333
1334        virtual const ast::Expr * visit( const ast::TupleIndexExpr * node ) override final {
1335                os << "Tuple Index Expression, with tuple:" << endl;
1336                ++indent;
1337                os << indent;
1338                safe_print( node->tuple );
1339                os << indent << "with index: " << node->index << endl;
1340                --indent;
1341                postprint( node );
1342
1343                return node;
1344        }
1345
1346        virtual const ast::Expr * visit( const ast::TupleAssignExpr * node ) override final {
1347                os << "Tuple Assignment Expression, with stmt expr:" << endl;
1348                ++indent;
1349                os << indent;
1350                safe_print( node->stmtExpr );
1351                --indent;
1352                postprint( node );
1353
1354                return node;
1355        }
1356
1357        virtual const ast::Expr * visit( const ast::StmtExpr * node ) override final {
1358                ++indent;
1359                os << "Statement Expression:" << endl << indent;
1360                safe_print( node->stmts );
1361                if ( ! node->returnDecls.empty() ) {
1362                        os << indent << "... with returnDecls: ";
1363                        printAll( node->returnDecls );
1364                }
1365                if ( ! node->dtors.empty() ) {
1366                        os << indent << "... with dtors: ";
1367                        printAll( node->dtors );
1368                }
1369                --indent;
1370                postprint( node );
1371
1372                return node;
1373        }
1374
1375        virtual const ast::Expr * visit( const ast::UniqueExpr * node ) override final {
1376                ++indent;
1377                os << "Unique Expression with id: " << node->id << endl << indent;
1378                safe_print( node->expr );
1379                if ( node->object ) {
1380                        os << indent-1 << "... with decl: ";
1381                        short_print( node->object );
1382                }
1383                --indent;
1384                postprint( node );
1385
1386                return node;
1387        }
1388
1389        virtual const ast::Expr * visit( const ast::UntypedInitExpr * node ) override final {
1390                ++indent;
1391                os << "Untyped Init Expression" << endl << indent;
1392                safe_print( node->expr );
1393                if ( ! node->initAlts.empty() ) {
1394                        for ( const InitAlternative & alt : node->initAlts ) {
1395                                os << indent <<  "InitAlternative: ";
1396                                safe_print( alt.type );
1397                                safe_print( alt.designation );
1398                        }
1399                }
1400                --indent;
1401
1402                return node;
1403        }
1404
1405        virtual const ast::Expr * visit( const ast::InitExpr * node ) override final {
1406                ++indent;
1407                os << "Init Expression" << endl << indent;
1408                safe_print( node->expr );
1409                os << indent << "... with designation: ";
1410                safe_print( node->designation );
1411                --indent;
1412
1413                return node;
1414        }
1415
1416        virtual const ast::Expr * visit( const ast::DeletedExpr * node ) override final {
1417                ++indent;
1418                os << "Deleted Expression" << endl << indent;
1419                safe_print( node->expr );
1420                os << endl << indent << "... deleted by: ";
1421                safe_print( node->deleteStmt );
1422                --indent;
1423
1424                return node;
1425        }
1426
1427        virtual const ast::Expr * visit( const ast::DefaultArgExpr * node ) override final {
1428                ++indent;
1429                os << "Default Argument Expression" << endl << indent;
1430                safe_print( node->expr );
1431                --indent;
1432
1433                return node;
1434        }
1435
1436        virtual const ast::Expr * visit( const ast::GenericExpr * node ) override final {
1437                ++indent;
1438                os << "C11 _Generic Expression" << endl << indent;
1439                safe_print( node->control );
1440                os << endl << indent << "... with associations:" << endl;
1441                for ( const auto & assoc : node->associations ) {
1442                        os << indent;
1443                        if ( assoc.type ) {
1444                                os << "... type: ";
1445                                assoc.type->accept( *this );
1446                                os << endl << indent << "... expression: ";
1447                                safe_print( assoc.expr );
1448                        } else {
1449                                os << "... default: ";
1450                                safe_print( assoc.expr );
1451                        }
1452                        os << endl;
1453                }
1454                --indent;
1455
1456                return node;
1457        }
1458
1459        virtual const ast::Type * visit( const ast::VoidType * node ) override final {
1460                preprint( node );
1461                os << "void";
1462                return node;
1463        }
1464
1465        virtual const ast::Type * visit( const ast::BasicType * node ) override final {
1466                preprint( node );
1467                os << ast::BasicType::typeNames[ node->kind ];
1468                return node;
1469        }
1470
1471        virtual const ast::Type * visit( const ast::PointerType * node ) override final {
1472                preprint( node );
1473                if ( ! node->isArray() ) {
1474                        os << "pointer to ";
1475                } else {
1476                        os << "decayed ";
1477                        if ( node->isStatic ) {
1478                                os << "static ";
1479                        }
1480
1481                        if ( node->isVarLen ) {
1482                                os << "variable length array of ";
1483                        } else if ( node->dimension ) {
1484                                os << "array of ";
1485                                node->dimension->accept( *this );
1486                                os << " ";
1487                        }
1488                }
1489                safe_print( node->base );
1490
1491                return node;
1492        }
1493
1494        virtual const ast::Type * visit( const ast::ArrayType * node ) override final {
1495                preprint( node );
1496                if ( node->isStatic ) {
1497                        os << "static ";
1498                }
1499
1500                if ( node->isVarLen ) {
1501                        os << "variable length array of ";
1502                } else if ( node->dimension ) {
1503                        os << "array of ";
1504                } else {
1505                        os << "open array of ";
1506                }
1507
1508                safe_print( node->base );
1509
1510                if ( node->dimension ) {
1511                        os << " with dimension of ";
1512                        node->dimension->accept( *this );
1513                }
1514
1515                return node;
1516        }
1517
1518        virtual const ast::Type * visit( const ast::ReferenceType * node ) override final {
1519                preprint( node );
1520                os << "reference to ";
1521                safe_print( node->base );
1522
1523                return node;
1524        }
1525
1526        virtual const ast::Type * visit( const ast::QualifiedType * node ) override final {
1527                preprint( node );
1528                ++indent;
1529                os << "Qualified Type:" << endl << indent;
1530                safe_print( node->parent );
1531                os << endl << indent;
1532                safe_print( node->child );
1533                os << endl;
1534                --indent;
1535
1536                return node;
1537        }
1538
1539        virtual const ast::Type * visit( const ast::FunctionType * node ) override final {
1540                preprint( node );
1541
1542                os << "function" << endl;
1543                if ( ! node->params.empty() ) {
1544                        os << indent << "... with parameters" << endl;
1545                        ++indent;
1546                        printAll( node->params );
1547                        if ( node->isVarArgs ) {
1548                                os << indent << "and a variable number of other arguments" << endl;
1549                        }
1550                        --indent;
1551                } else if ( node->isVarArgs ) {
1552                        os << indent+1 << "accepting unspecified arguments" << endl;
1553                }
1554
1555                os << indent << "... returning";
1556                if ( node->returns.empty() ) {
1557                        os << " nothing" << endl;
1558                } else {
1559                        os << endl;
1560                        ++indent;
1561                        printAll( node->returns );
1562                        --indent;
1563                }
1564
1565                return node;
1566        }
1567
1568        virtual const ast::Type * visit( const ast::StructInstType * node ) override final {
1569                preprint( node );
1570                os << "instance of struct " << node->name;
1571                if ( node->base ) {
1572                        os << " " << ( node->base->body ? "with" : "without" ) << " body";
1573                }
1574                print( node->params );
1575
1576                return node;
1577        }
1578
1579        virtual const ast::Type * visit( const ast::UnionInstType * node ) override final {
1580                preprint( node );
1581                os << "instance of union " << node->name;
1582                if ( node->base ) {
1583                        os << " " << ( node->base->body ? "with" : "without" ) << " body";
1584                }
1585                print( node->params );
1586
1587                return node;
1588        }
1589
1590        virtual const ast::Type * visit( const ast::EnumInstType * node ) override final {
1591                preprint( node );
1592                os << "instance of enum " << node->name;
1593                if ( node->base ) {
1594                        os << " " << ( node->base->body ? "with" : "without" ) << " body";
1595                }
1596                print( node->params );
1597
1598                return node;
1599        }
1600
1601        virtual const ast::Type * visit( const ast::TraitInstType * node ) override final {
1602                preprint( node );
1603                os << "instance of trait " << node->name;
1604                print( node->params );
1605
1606                return node;
1607        }
1608
1609        virtual const ast::Type * visit( const ast::TypeInstType * node ) override final {
1610                preprint( node );
1611                const auto & _name = deterministic_output && isUnboundType(node) ? "[unbound]" : node->typeString();
1612                os << "instance of type " << _name
1613                   << " (" << (node->kind == ast::TypeDecl::Ftype ? "" : "not ") << "function type)";
1614                print( node->params );
1615
1616                return node;
1617        }
1618
1619        virtual const ast::Type * visit( const ast::TupleType * node ) override final {
1620                preprint( node );
1621                os << "tuple of types" << endl;
1622                ++indent;
1623                printAll( node->types );
1624                --indent;
1625
1626                return node;
1627        }
1628
1629        virtual const ast::Type * visit( const ast::TypeofType * node ) override final {
1630                preprint( node );
1631                if ( node->kind == ast::TypeofType::Basetypeof ) { os << "base-"; }
1632                os << "type-of expression ";
1633                safe_print( node->expr );
1634
1635                return node;
1636        }
1637
1638        virtual const ast::Type * visit( const ast::VTableType * node ) override final {
1639                preprint( node );
1640                os << "vtable for ";
1641                safe_print( node->base );
1642
1643                return node;
1644        }
1645
1646        virtual const ast::Type * visit( const ast::VarArgsType * node ) override final {
1647                preprint( node );
1648                os << "builtin var args pack";
1649                return node;
1650        }
1651
1652        virtual const ast::Type * visit( const ast::ZeroType * node ) override final {
1653                preprint( node );
1654                os << "zero_t";
1655                return node;
1656        }
1657
1658        virtual const ast::Type * visit( const ast::OneType * node ) override final {
1659                preprint( node );
1660                os << "one_t";
1661                return node;
1662        }
1663
1664        virtual const ast::Type * visit( const ast::GlobalScopeType * node ) override final {
1665                preprint( node );
1666                os << "Global Scope Type";
1667                return node;
1668        }
1669
1670        virtual const ast::Designation * visit( const ast::Designation * node ) override final {
1671                if ( node->designators.empty() ) return node;
1672                os << "... designated by: " << endl;
1673                ++indent;
1674                for ( const ast::Expr * d : node->designators ) {
1675                        os << indent;
1676                        d->accept( *this );
1677                        os << endl;
1678                }
1679                --indent;
1680                return node;
1681        }
1682
1683        virtual const ast::Init * visit( const ast::SingleInit * node ) override final {
1684                os << "Simple Initializer: ";
1685                safe_print( node->value );
1686                return node;
1687        }
1688
1689        virtual const ast::Init * visit( const ast::ListInit * node ) override final {
1690                os << "Compound initializer: " << endl;
1691                ++indent;
1692                for ( auto p : group_iterate( node->designations, node->initializers ) ) {
1693                        const ast::Designation * d = std::get<0>(p);
1694                        const ast::Init * init = std::get<1>(p);
1695                        os << indent;
1696                        init->accept( *this );
1697                        os << endl;
1698                        if ( ! d->designators.empty() ) {
1699                                os << indent;
1700                                d->accept( *this );
1701                        }
1702                }
1703                --indent;
1704                return node;
1705        }
1706
1707        virtual const ast::Init * visit( const ast::ConstructorInit * node ) override final {
1708                os << "Constructor initializer: " << endl;
1709                if ( node->ctor ) {
1710                        os << indent << "... initially constructed with ";
1711                        ++indent;
1712                        node->ctor->accept( *this );
1713                        --indent;
1714                }
1715
1716                if ( node->dtor ) {
1717                        os << indent << "... destructed with ";
1718                        ++indent;
1719                        node->dtor->accept( *this );
1720                        --indent;
1721                }
1722
1723                if ( node->init ) {
1724                        os << indent << "... with fallback C-style initializer: ";
1725                        ++indent;
1726                        node->init->accept( *this );
1727                        --indent;
1728                }
1729                return node;
1730        }
1731
1732        virtual const ast::Attribute * visit( const ast::Attribute * node ) override final {
1733                if ( node->empty() ) return node;
1734                os << "Attribute with name: " << node->name;
1735                if ( node->params.empty() ) return node;
1736                os << " with parameters: " << endl;
1737                ++indent;
1738                printAll( node->params );
1739                --indent;
1740                return node;
1741        }
1742
1743        virtual const ast::TypeSubstitution * visit( const ast::TypeSubstitution * node ) override final {
1744                os << indent << "Types:" << endl;
1745                for ( const auto& i : *node ) {
1746                        os << indent+1 << i.first.typeString() << " -> ";
1747                        indent += 2;
1748                        safe_print( i.second );
1749                        indent -= 2;
1750                        os << endl;
1751                }
1752                return node;
1753        }
1754
1755};
1756
1757} // namespace
1758
1759void print( ostream & os, const ast::Node * node, Indenter indent ) {
1760        Printer printer { os, indent, false };
1761        node->accept(printer);
1762}
1763
1764void printShort( ostream & os, const ast::Decl * node, Indenter indent ) {
1765        Printer printer { os, indent, true };
1766        node->accept(printer);
1767}
1768
1769void print( ostream & os, Function::Specs specs ) {
1770        print( os, specs, Names::FuncSpecifiers );
1771}
1772
1773void print( ostream & os, Storage::Classes storage ) {
1774        print( os, storage, Names::StorageClasses );
1775}
1776
1777void print( ostream & os, CV::Qualifiers qualifiers ) {
1778        print( os, qualifiers, Names::Qualifiers );
1779}
1780
1781} // namespace ast
Note: See TracBrowser for help on using the repository browser.