source: src/AST/Print.cpp @ 41870a5

ADTast-experimentalenumpthread-emulationqualifiedEnum
Last change on this file since 41870a5 was 3b0bc16, checked in by Peter A. Buhr <pabuhr@…>, 3 years ago

change class name WhileStmt? to WhileDoStmt?, add else clause to WhileDoStmt? and ForStmt?, change names thenPart/ElsePart to then/else_

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