source: src/AST/Print.cpp @ 5b7fea7

ADTast-experimentalenumpthread-emulationqualifiedEnum
Last change on this file since 5b7fea7 was 400b8be, checked in by Andrew Beach <ajbeach@…>, 3 years ago

Added StmtClause? and converted the existing nodes that should be clauses.

  • Property mode set to 100644
File size: 37.9 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 "Decl.hpp"
19#include "Expr.hpp"
20#include "Stmt.hpp"
21#include "Type.hpp"
22#include "TypeSubstitution.hpp"
23#include "CompilationState.h"
24
25#include "Common/utility.h" // for group_iterate
26
27using namespace std;
28
29namespace ast {
30
31template <typename C, typename... T>
32constexpr array<C,sizeof...(T)> make_array(T&&... values)
33{
34        return array<C,sizeof...(T)>{
35                forward<T>(values)...
36        };
37}
38
39class Printer final : public Visitor {
40public:
41        ostream & os;
42        Indenter indent;
43        bool short_mode;
44
45        Printer(ostream & os, Indenter indent, bool short_mode) : os( os ), indent( indent ), short_mode(short_mode) {}
46
47private:
48        template< typename C >
49        void printAll( const C & c ) {
50                for ( const auto & i : c ) {
51                        if ( i ) {
52                                os << indent;
53                                i->accept( *this );
54                                // need an endl after each element because it's not
55                                // easy to know when each individual item should end
56                                os << endl;
57                        } // if
58                } // for
59        }
60
61        /// call if mandatory field is missing
62        void undefined() {
63                os << "UNDEFINED";
64        }
65
66        /// call for fields that should be mandatory
67        void safe_print( const ast::Node * n ) {
68                if ( n ) n->accept( *this );
69                else undefined();
70        }
71
72        /// call to print short form. Incorporates features of safe_print()
73        void short_print( const ast::Decl * n ) {
74                if ( ! n ) { undefined(); return; }
75                bool old_short = short_mode; short_mode = true;
76                n->accept( *this );
77                short_mode = old_short;
78        }
79
80        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>
97        void print(const storage_t & storage, const array<const char *, N> & Names ) {
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
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
130        void print( const ast::Expr::InferUnion & inferred, unsigned level = 0 ) {
131                if (inferred.data.resnSlots && !inferred.data.resnSlots->empty()) {
132                        os << indent << "with " << inferred.data.resnSlots->size()
133                           << " pending inference slots" << endl;
134                }
135                if (inferred.data.inferParams && !inferred.data.inferParams->empty()) {
136                        os << indent << "with inferred parameters " << level << ":" << endl;
137                        ++indent;
138                        for ( const auto & i : *inferred.data.inferParams ) {
139                                os << indent;
140                                short_print( i.second.declptr );
141                                os << endl;
142                                print( i.second.expr->inferred, level+1 );
143                        }
144                        --indent;
145                }
146        }
147
148        void print( const ast::FunctionType::ForallList & forall ) {
149                if ( forall.empty() ) return;
150                os << "forall" << endl;
151                ++indent;
152                printAll( forall );
153                os << indent;
154                --indent;
155        }
156
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
166        void print( const std::vector<ptr<Attribute>> & attrs ) {
167                if ( attrs.empty() ) return;
168                os << "with attributes" << endl;
169                ++indent;
170                printAll( attrs );
171                --indent;
172        }
173
174        void print( const std::vector<ptr<Expr>> & params ) {
175                if ( params.empty() ) return;
176                os << endl << indent << "... with parameters" << endl;
177                ++indent;
178                printAll( params );
179                --indent;
180        }
181
182        void print( const ast::AggregateDecl * node ) {
183                os << node->typeString() << " " << node->name;
184
185                if ( ! short_mode && node->linkage != Linkage::Cforall ) {
186                        os << " " << Linkage::name( node->linkage );
187                }
188
189                os << " " << (node->body ? "with" : "without") << " body";
190
191                if ( ! node->params.empty() ) {
192                        os << endl << indent << "... with parameters" << endl;
193                        ++indent;
194                        printAll( node->params );
195                        --indent;
196                }
197
198                if ( ! short_mode && ! node->members.empty() ) {
199                        os << endl << indent << "... with members" << endl;
200                        ++indent;
201                        printAll( node->members );
202                        --indent;
203                }
204
205                if ( ! short_mode && ! node->attributes.empty() ) {
206                        os << endl << indent << "... with attributes" << endl;
207                        ++indent;
208                        printAll( node->attributes );
209                        --indent;
210                }
211
212                os << endl;
213        }
214
215        void preprint( const ast::NamedTypeDecl * node ) {
216                if ( ! node->name.empty() ) {
217                        os << node->name << ": ";
218                }
219
220                if ( ! short_mode && node->linkage != Linkage::Cforall ) {
221                        os << Linkage::name( node->linkage ) << " ";
222                }
223
224                print( node->storage );
225                os << node->typeString();
226
227                if ( node->base ) {
228                        os << " for ";
229                        ++indent;
230                        node->base->accept( *this );
231                        --indent;
232                }
233
234                if ( ! node->assertions.empty() ) {
235                        os << endl << indent << "... with assertions" << endl;
236                        ++indent;
237                        printAll( node->assertions );
238                        --indent;
239                }
240        }
241
242        void postprint( const ast::Expr * node ) {
243                print( node->inferred );
244
245                if ( node->result ) {
246                        os << endl << indent << "... with resolved type:" << endl;
247                        ++indent;
248                        os << indent;
249                        node->result->accept( *this );
250                        --indent;
251                }
252
253                if ( node->env ) {
254                        os << endl << indent << "... with environment:" << endl;
255                        ++indent;
256                        node->env->accept( *this );
257                        --indent;
258                }
259
260                if ( node->extension ) {
261                        os << endl << indent << "... with extension";
262                }
263        }
264
265        void preprint( const ast::Type * node ) {
266                print( node->qualifiers );
267        }
268
269        void preprint( const ast::FunctionType * node ) {
270                print( node->forall );
271                print( node->assertions );
272                print( node->qualifiers );
273        }
274
275        void preprint( const ast::BaseInstType * node ) {
276                print( node->attributes );
277                print( node->qualifiers );
278        }
279
280public:
281        virtual const ast::DeclWithType * visit( const ast::ObjectDecl * node ) override final {
282                if ( ! node->name.empty() ) os << node->name << ": ";
283
284                if ( ! short_mode && node->linkage != Linkage::Cforall ) {
285                        os << Linkage::name( node->linkage ) << " ";
286                }
287
288                print( node->storage );
289
290                if ( node->type ) {
291                        node->type->accept( *this );
292                } else {
293                        os << "untyped entity";
294                }
295
296                if ( ! short_mode && node->init ) {
297                        ++indent;
298                        os << " with initializer (" << (
299                                node->init->maybeConstructed
300                                        ? "maybe constructed"
301                                        : "not constructed"
302                                ) << ")" << endl << indent;
303                        node->init->accept( *this );
304                        --indent;
305                        os << endl;
306                }
307
308                if ( ! short_mode && ! node->attributes.empty() ) {
309                        os << endl << indent << "... with attributes:" << endl;
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 );
318                }
319
320                return node;
321        }
322
323        virtual const ast::DeclWithType * visit( const ast::FunctionDecl * node ) override final {
324                if ( !node->name.empty() ) os << node->name << ": ";
325
326                if ( ! short_mode && node->linkage != Linkage::Cforall ) {
327                        os << Linkage::name( node->linkage ) << " ";
328                }
329
330                if ( ! short_mode ) printAll( node->attributes );
331
332                print( node->storage );
333                print( node->funcSpec );
334
335
336
337                if ( node->type && node->isTypeFixed ) {
338                        node->type->accept( *this );
339                } else {
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                        }
378                }
379
380                if ( ! short_mode && node->stmts ) {
381                        ++indent;
382                        os << " with body" << endl << indent;
383                        node->stmts->accept( *this );
384                        --indent;
385                }
386
387                return node;
388        }
389
390        virtual const ast::Decl * visit( const ast::StructDecl * node ) override final {
391                print(node);
392                return node;
393        }
394
395        virtual const ast::Decl * visit( const ast::UnionDecl * node ) override final {
396                print(node);
397                return node;
398        }
399
400        virtual const ast::Decl * visit( const ast::EnumDecl * node ) override final {
401                print(node);
402                return node;
403        }
404
405        virtual const ast::Decl * visit( const ast::TraitDecl * node ) override final {
406                print(node);
407                return node;
408        }
409
410        virtual const ast::Decl * visit( const ast::TypeDecl * node ) override final {
411                preprint( node );
412                if ( ! short_mode && node->init ) {
413                        os << endl << indent << "with type initializer: ";
414                        ++indent;
415                        node->init->accept( *this );
416                        --indent;
417                }
418
419                return node;
420        }
421
422        virtual const ast::Decl * visit( const ast::TypedefDecl * node ) override final {
423                preprint( node );
424                return node;
425        }
426
427        virtual const ast::AsmDecl * visit( const ast::AsmDecl * node ) override final {
428                safe_print( node->stmt );
429                return node;
430        }
431
432        virtual const ast::DirectiveDecl * visit( const ast::DirectiveDecl * node ) override final {
433                safe_print( node->stmt );
434                return node;
435        }
436
437        virtual const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl * node ) override final {
438                os << "Static Assert with condition: ";
439                ++indent;
440                safe_print( node->cond );
441                os << endl << indent-1 << "and message: ";
442                safe_print( node->msg );
443                --indent;
444                os << endl;
445
446                return node;
447        }
448
449        virtual const ast::CompoundStmt * visit( const ast::CompoundStmt * node ) override final {
450                os << "Compound Statement:" << endl;
451                ++indent;
452                printAll( node->kids );
453                --indent;
454                return node;
455        }
456
457        virtual const ast::Stmt * visit( const ast::ExprStmt * node ) override final {
458                ++indent;
459                os << "Expression Statement:" << endl << indent;
460                safe_print( node->expr );
461                --indent;
462                return node;
463        }
464
465        virtual const ast::Stmt * visit( const ast::AsmStmt * node ) override final {
466                os << "Assembler Statement:" << endl;
467                ++indent;
468                os << indent-1 << "instruction:" << endl << indent;
469                safe_print( node->instruction );
470                if ( ! node->output.empty() ) {
471                        os << endl << indent << "output:" << endl;
472                        printAll( node->output );
473                } // if
474                if ( ! node->input.empty() ) {
475                        os << indent << "input:" << endl;
476                        printAll( node->input );
477                } // if
478                if ( ! node->clobber.empty() ) {
479                        os << indent << "clobber:" << endl;
480                        printAll( node->clobber );
481                } // if
482                --indent;
483                return node;
484        }
485
486        virtual const ast::Stmt * visit( const ast::DirectiveStmt * node ) override final {
487                os << "GCC Directive: " << node->directive << endl;
488                return node;
489        }
490
491        virtual const ast::Stmt * visit( const ast::IfStmt * node ) override final {
492                os << "If on condition:" << endl;
493                ++indent;
494                os << indent;
495                safe_print( node->cond );
496                --indent;
497
498                if ( ! node->inits.empty() ) {
499                        os << indent << "... with initialization:" << endl;
500                        ++indent;
501                        for ( const ast::Stmt * stmt : node->inits ) {
502                                os << indent;
503                                safe_print( stmt );
504                        }
505                        --indent;
506                        os << endl;
507                }
508
509                os << indent << "... then:" << endl;
510
511                ++indent;
512                os << indent;
513                safe_print( node->then );
514                --indent;
515
516                if ( node->else_ != 0 ) {
517                        os << indent << "... else:" << endl;
518                        ++indent;
519                        os << indent;
520                        node->else_->accept( *this );
521                        --indent;
522                } // if
523                return node;
524        }
525
526        virtual const ast::Stmt * visit( const ast::WhileDoStmt * node ) override final {
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
540                return node;
541        }
542
543        virtual const ast::Stmt * visit( const ast::ForStmt * node ) override final {
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
582                return node;
583        }
584
585        virtual const ast::Stmt * visit( const ast::SwitchStmt * node ) override final {
586                os << "Switch on condition: ";
587                safe_print( node->cond );
588                os << endl;
589
590                ++indent;
591                for ( const ast::CaseClause * stmt : node->cases ) {
592                        stmt->accept( *this );
593                }
594                --indent;
595
596                return node;
597        }
598
599        virtual const ast::CaseClause * visit( const ast::CaseClause * node ) override final {
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
615                return node;
616        }
617
618        virtual const ast::Stmt * visit( const ast::BranchStmt * node ) override final {
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
636                return node;
637        }
638
639        virtual const ast::Stmt * visit( const ast::ReturnStmt * node ) override final {
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
651                return node;
652        }
653
654        virtual const ast::Stmt * visit( const ast::ThrowStmt * node ) override final {
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
671                return node;
672        }
673
674        virtual const ast::Stmt * visit( const ast::TryStmt * node ) override final {
675                ++indent;
676                os << "Try Statement" << endl << indent-1
677                   << "... with block:" << endl << indent;
678                safe_print( node->body );
679
680                os << indent-1 << "... and handlers:" << endl;
681                for ( const ast::CatchClause * 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
692                return node;
693        }
694
695        virtual const ast::CatchClause * visit( const ast::CatchClause * node ) override final {
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;
716
717                return node;
718        }
719
720        virtual const ast::FinallyClause * visit( const ast::FinallyClause * node ) override final {
721                os << "Finally Statement" << endl;
722                os << indent << "... with block:" << endl;
723                ++indent;
724                os << indent;
725                safe_print( node->body );
726                --indent;
727
728                return node;
729        }
730
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
750        virtual const ast::Stmt * visit( const ast::WaitForStmt * node ) override final {
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 );
756
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
801                return node;
802        }
803
804        virtual const ast::Decl * visit( const ast::WithStmt * node ) override final {
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
813                return node;
814        }
815
816        virtual const ast::NullStmt * visit( const ast::NullStmt * node ) override final {
817                os << "Null Statement" << endl;
818                print( node->labels );
819
820                return node;
821        }
822
823        virtual const ast::Stmt * visit( const ast::DeclStmt * node ) override final {
824                os << "Declaration of ";
825                safe_print( node->decl );
826
827                return node;
828        }
829
830        virtual const ast::Stmt * visit( const ast::ImplicitCtorDtorStmt * node ) override final {
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
838                return node;
839        }
840
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
856        virtual const ast::Expr * visit( const ast::ApplicationExpr * node ) override final {
857                ++indent;
858                os << "Application of" << endl << indent;
859                safe_print( node->func );
860                os << endl;
861                if ( ! node->args.empty() ) {
862                        os << indent << "... to arguments" << endl;
863                        printAll( node->args );
864                }
865                --indent;
866                postprint( node );
867
868                return node;
869        }
870
871        virtual const ast::Expr * visit( const ast::UntypedExpr * node ) override final {
872                ++indent;
873                os << "Applying untyped:" << endl;
874                os << indent;
875                safe_print( node->func );
876                os << endl << indent-1 << "...to:" << endl;
877                printAll( node->args );
878                --indent;
879                postprint( node );
880
881                return node;
882        }
883
884        virtual const ast::Expr * visit( const ast::NameExpr * node ) override final {
885                os << "Name: " << node->name;
886                postprint( node );
887
888                return node;
889        }
890
891        virtual const ast::Expr * visit( const ast::AddressExpr * node ) override final {
892                os << "Address of:" << endl;
893                ++indent;
894                os << indent;
895                safe_print( node->arg );
896
897                --indent;
898
899                return node;
900        }
901
902        virtual const ast::Expr * visit( const ast::LabelAddressExpr * node ) override final {
903                os << "Address of label:" << node->arg;
904
905                return node;
906        }
907
908        virtual const ast::Expr * visit( const ast::CastExpr * node ) override final {
909                ++indent;
910                os << (node->isGenerated ? "Generated" : "Explicit") << " Cast of:" << endl << indent;
911                safe_print( node->arg );
912                os << endl << indent-1 << "... to:";
913                if ( ! node->result ) {
914                        os << " ";
915                        undefined();
916                } else if ( node->result->isVoid() ) {
917                        os << " nothing";
918                } else {
919                        os << endl << indent;
920                        node->result->accept( *this );
921                } // if
922                --indent;
923                postprint( node );
924
925                return node;
926        }
927
928        virtual const ast::Expr * visit( const ast::KeywordCastExpr * node ) override final {
929                ++indent;
930                os << "Keyword Cast of:" << endl << indent;
931                safe_print( node->arg );
932                --indent;
933                os << endl << indent << "... to: " << node->targetString();
934                postprint( node );
935
936                return node;
937        }
938
939        virtual const ast::Expr * visit( const ast::VirtualCastExpr * node ) override final {
940                ++indent;
941                os << "Virtual Cast of:" << endl << indent;
942                safe_print( node->arg );
943                os << endl << indent-1 << "... to:";
944                if ( ! node->result ) {
945                        os << " unknown";
946                } else {
947                        os << endl << indent;
948                        node->result->accept( *this );
949                }
950                --indent;
951                postprint( node );
952
953                return node;
954        }
955
956        virtual const ast::Expr * visit( const ast::UntypedMemberExpr * node ) override final {
957                ++indent;
958                os << "Untyped Member Expression, with field: " << endl << indent;
959                safe_print( node->member );
960                os << indent-1 << "... from aggregate:" << endl << indent;
961                safe_print( node->aggregate );
962                --indent;
963                postprint( node );
964
965                return node;
966        }
967
968        virtual const ast::Expr * visit( const ast::MemberExpr * node ) override final {
969                ++indent;
970                os << "Member Expression, with field:" << endl << indent;
971                safe_print( node->member );
972                os << endl << indent-1 << "... from aggregate:" << endl << indent;
973                safe_print( node->aggregate );
974                --indent;
975                postprint( node );
976
977                return node;
978        }
979
980        virtual const ast::Expr * visit( const ast::VariableExpr * node ) override final {
981                os << "Variable Expression: ";
982                short_print( node->var );
983                postprint( node );
984
985                return node;
986        }
987
988        virtual const ast::Expr * visit( const ast::ConstantExpr * node ) override final {
989                os << "Constant Expression (" << node->rep;
990                if ( node->result ) {
991                        os << ": ";
992                        node->result->accept( *this );
993                }
994                os << ")";
995                postprint( node );
996
997                return node;
998        }
999
1000        virtual const ast::Expr * visit( const ast::SizeofExpr * node ) override final {
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
1008                return node;
1009        }
1010
1011        virtual const ast::Expr * visit( const ast::AlignofExpr * node ) override final {
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 );
1018
1019                return node;
1020        }
1021
1022        virtual const ast::Expr * visit( const ast::UntypedOffsetofExpr * node ) override final {
1023                os << "Untyped Offsetof Expression on member " << node->member << " of ";
1024                ++indent;
1025                safe_print( node->type );
1026                --indent;
1027                postprint( node );
1028
1029                return node;
1030        }
1031
1032        virtual const ast::Expr * visit( const ast::OffsetofExpr * node ) override final {
1033                os << "Offsetof Expression on member " << node->member->name << " of ";
1034                ++indent;
1035                safe_print( node->type );
1036                --indent;
1037                postprint( node );
1038
1039                return node;
1040        }
1041
1042        virtual const ast::Expr * visit( const ast::OffsetPackExpr * node ) override final {
1043                os << "Offset Pack Expression on: ";
1044                ++indent;
1045                safe_print( node->type );
1046                --indent;
1047                postprint( node );
1048
1049                return node;
1050        }
1051
1052        virtual const ast::Expr * visit( const ast::LogicalExpr * node ) override final {
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
1059                return node;
1060        }
1061
1062        virtual const ast::Expr * visit( const ast::ConditionalExpr * node ) override final {
1063                ++indent;
1064                os << "Conditional expression on:" << endl << indent;
1065                safe_print( node->arg1 );
1066                os << indent-1 << "First alternative:" << endl << indent;
1067                safe_print( node->arg2 );
1068                os << indent-1 << "Second alternative:" << endl << indent;
1069                safe_print( node->arg3 );
1070                --indent;
1071                postprint( node );
1072
1073                return node;
1074        }
1075
1076        virtual const ast::Expr * visit( const ast::CommaExpr * node ) override final {
1077                ++indent;
1078                os << "Comma Expression:" << endl << indent;
1079                safe_print( node->arg1 );
1080                os << endl << indent;
1081                safe_print( node->arg2 );
1082                --indent;
1083                postprint( node );
1084
1085                return node;
1086        }
1087
1088        virtual const ast::Expr * visit( const ast::TypeExpr * node ) override final {
1089                safe_print( node->type );
1090                postprint( node );
1091
1092                return node;
1093        }
1094
1095        virtual const ast::Expr * visit( const ast::AsmExpr * node ) override final {
1096                os << "Asm Expression:" << endl;
1097                ++indent;
1098                if ( !node->inout.empty() ) os << "[" << node->inout << "] ";
1099                if ( node->constraint ) node->constraint->accept( *this );
1100                if ( node->operand ) node->operand->accept( *this );
1101                --indent;
1102
1103                return node;
1104        }
1105
1106        virtual const ast::Expr * visit( const ast::ImplicitCopyCtorExpr * node ) override final {
1107                ++indent;
1108                os << "Implicit Copy Constructor Expression:" << endl << indent;
1109                safe_print( node->callExpr );
1110                --indent;
1111                postprint( node );
1112
1113                return node;
1114        }
1115
1116        virtual const ast::Expr * visit( const ast::ConstructorExpr * node ) override final {
1117                os <<  "Constructor Expression:" << endl << indent+1;
1118                indent += 2;
1119                safe_print( node->callExpr );
1120                indent -= 2;
1121                postprint( node );
1122
1123                return node;
1124        }
1125
1126        virtual const ast::Expr * visit( const ast::CompoundLiteralExpr * node ) override final {
1127                ++indent;
1128                os << "Compound Literal Expression: " << endl << indent;
1129                safe_print( node->result );
1130                os << indent;
1131                safe_print( node->init );
1132                --indent;
1133                postprint( node );
1134
1135                return node;
1136        }
1137
1138        virtual const ast::Expr * visit( const ast::RangeExpr * node ) override final {
1139                os << "Range Expression: ";
1140                safe_print( node->low );
1141                os << " ... ";
1142                safe_print( node->high );
1143                postprint( node );
1144
1145                return node;
1146        }
1147
1148        virtual const ast::Expr * visit( const ast::UntypedTupleExpr * node ) override final {
1149                os << "Untyped Tuple:" << endl;
1150                ++indent;
1151                printAll( node->exprs );
1152                --indent;
1153                postprint( node );
1154
1155                return node;
1156        }
1157
1158        virtual const ast::Expr * visit( const ast::TupleExpr * node ) override final {
1159                os << "Tuple:" << endl;
1160                ++indent;
1161                printAll( node->exprs );
1162                --indent;
1163                postprint( node );
1164
1165                return node;
1166        }
1167
1168        virtual const ast::Expr * visit( const ast::TupleIndexExpr * node ) override final {
1169                os << "Tuple Index Expression, with tuple:" << endl;
1170                ++indent;
1171                os << indent;
1172                safe_print( node->tuple );
1173                os << indent << "with index: " << node->index << endl;
1174                --indent;
1175                postprint( node );
1176
1177                return node;
1178        }
1179
1180        virtual const ast::Expr * visit( const ast::TupleAssignExpr * node ) override final {
1181                os << "Tuple Assignment Expression, with stmt expr:" << endl;
1182                ++indent;
1183                os << indent;
1184                safe_print( node->stmtExpr );
1185                --indent;
1186                postprint( node );
1187
1188                return node;
1189        }
1190
1191        virtual const ast::Expr * visit( const ast::StmtExpr * node ) override final {
1192                ++indent;
1193                os << "Statement Expression:" << endl << indent;
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
1206                return node;
1207        }
1208
1209        virtual const ast::Expr * visit( const ast::UniqueExpr * node ) override final {
1210                ++indent;
1211                os << "Unique Expression with id: " << node->id << endl << indent;
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
1220                return node;
1221        }
1222
1223        virtual const ast::Expr * visit( const ast::UntypedInitExpr * node ) override final {
1224                ++indent;
1225                os << "Untyped Init Expression" << endl << indent;
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
1236                return node;
1237        }
1238
1239        virtual const ast::Expr * visit( const ast::InitExpr * node ) override final {
1240                ++indent;
1241                os << "Init Expression" << endl << indent;
1242                safe_print( node->expr );
1243                os << indent << "... with designation: ";
1244                safe_print( node->designation );
1245                --indent;
1246
1247                return node;
1248        }
1249
1250        virtual const ast::Expr * visit( const ast::DeletedExpr * node ) override final {
1251                ++indent;
1252                os << "Deleted Expression" << endl << indent;
1253                safe_print( node->expr );
1254                os << endl << indent << "... deleted by: ";
1255                safe_print( node->deleteStmt );
1256                --indent;
1257
1258                return node;
1259        }
1260
1261        virtual const ast::Expr * visit( const ast::DefaultArgExpr * node ) override final {
1262                ++indent;
1263                os << "Default Argument Expression" << endl << indent;
1264                safe_print( node->expr );
1265                --indent;
1266
1267                return node;
1268        }
1269
1270        virtual const ast::Expr * visit( const ast::GenericExpr * node ) override final {
1271                ++indent;
1272                os << "C11 _Generic Expression" << endl << indent;
1273                safe_print( node->control );
1274                os << endl << indent << "... with associations:" << endl;
1275                for ( const auto & assoc : node->associations ) {
1276                        os << indent;
1277                        if ( assoc.type ) {
1278                                os << "... type: ";
1279                                assoc.type->accept( *this );
1280                                os << endl << indent << "... expression: ";
1281                                safe_print( assoc.expr );
1282                        } else {
1283                                os << "... default: ";
1284                                safe_print( assoc.expr );
1285                        }
1286                        os << endl;
1287                }
1288                --indent;
1289
1290                return node;
1291        }
1292
1293        virtual const ast::Type * visit( const ast::VoidType * node ) override final {
1294                preprint( node );
1295                os << "void";
1296                return node;
1297        }
1298
1299        virtual const ast::Type * visit( const ast::BasicType * node ) override final {
1300                preprint( node );
1301                os << ast::BasicType::typeNames[ node->kind ];
1302                return node;
1303        }
1304
1305        virtual const ast::Type * visit( const ast::PointerType * node ) override final {
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                }
1323                safe_print( node->base );
1324
1325                return node;
1326        }
1327
1328        virtual const ast::Type * visit( const ast::ArrayType * node ) override final {
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
1342                safe_print( node->base );
1343
1344                if ( node->dimension ) {
1345                        os << " with dimension of ";
1346                        node->dimension->accept( *this );
1347                }
1348
1349                return node;
1350        }
1351
1352        virtual const ast::Type * visit( const ast::ReferenceType * node ) override final {
1353                preprint( node );
1354                os << "reference to ";
1355                safe_print( node->base );
1356
1357                return node;
1358        }
1359
1360        virtual const ast::Type * visit( const ast::QualifiedType * node ) override final {
1361                preprint( node );
1362                ++indent;
1363                os << "Qualified Type:" << endl << indent;
1364                safe_print( node->parent );
1365                os << endl << indent;
1366                safe_print( node->child );
1367                os << endl;
1368                --indent;
1369
1370                return node;
1371        }
1372
1373        virtual const ast::Type * visit( const ast::FunctionType * node ) override final {
1374                preprint( node );
1375
1376                os << "function" << endl;
1377                if ( ! node->params.empty() ) {
1378                        os << indent << "... with parameters" << endl;
1379                        ++indent;
1380                        printAll( node->params );
1381                        if ( node->isVarArgs ) {
1382                                os << indent << "and a variable number of other arguments" << endl;
1383                        }
1384                        --indent;
1385                } else if ( node->isVarArgs ) {
1386                        os << indent+1 << "accepting unspecified arguments" << endl;
1387                }
1388
1389                os << indent << "... returning";
1390                if ( node->returns.empty() ) {
1391                        os << " nothing" << endl;
1392                } else {
1393                        os << endl;
1394                        ++indent;
1395                        printAll( node->returns );
1396                        --indent;
1397                }
1398
1399                return node;
1400        }
1401
1402        virtual const ast::Type * visit( const ast::StructInstType * node ) override final {
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
1410                return node;
1411        }
1412
1413        virtual const ast::Type * visit( const ast::UnionInstType * node ) override final {
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
1421                return node;
1422        }
1423
1424        virtual const ast::Type * visit( const ast::EnumInstType * node ) override final {
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
1432                return node;
1433        }
1434
1435        virtual const ast::Type * visit( const ast::TraitInstType * node ) override final {
1436                preprint( node );
1437                os << "instance of trait " << node->name;
1438                print( node->params );
1439
1440                return node;
1441        }
1442
1443        virtual const ast::Type * visit( const ast::TypeInstType * node ) override final {
1444                preprint( node );
1445                const auto & _name = deterministic_output && isUnboundType(node) ? "[unbound]" : node->typeString();
1446                os << "instance of type " << _name
1447                   << " (" << (node->kind == ast::TypeDecl::Ftype ? "" : "not ") << "function type)";
1448                print( node->params );
1449
1450                return node;
1451        }
1452
1453        virtual const ast::Type * visit( const ast::TupleType * node ) override final {
1454                preprint( node );
1455                os << "tuple of types" << endl;
1456                ++indent;
1457                printAll( node->types );
1458                --indent;
1459
1460                return node;
1461        }
1462
1463        virtual const ast::Type * visit( const ast::TypeofType * node ) override final {
1464                preprint( node );
1465                if ( node->kind == ast::TypeofType::Basetypeof ) { os << "base-"; }
1466                os << "type-of expression ";
1467                safe_print( node->expr );
1468
1469                return node;
1470        }
1471
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
1480        virtual const ast::Type * visit( const ast::VarArgsType * node ) override final {
1481                preprint( node );
1482                os << "builtin var args pack";
1483                return node;
1484        }
1485
1486        virtual const ast::Type * visit( const ast::ZeroType * node ) override final {
1487                preprint( node );
1488                os << "zero_t";
1489                return node;
1490        }
1491
1492        virtual const ast::Type * visit( const ast::OneType * node ) override final {
1493                preprint( node );
1494                os << "one_t";
1495                return node;
1496        }
1497
1498        virtual const ast::Type * visit( const ast::GlobalScopeType * node ) override final {
1499                preprint( node );
1500                os << "Global Scope Type";
1501                return node;
1502        }
1503
1504        virtual const ast::Designation * visit( const ast::Designation * node ) override final {
1505                if ( node->designators.empty() ) return node;
1506                os << "... designated by: " << endl;
1507                ++indent;
1508                for ( const ast::Expr * d : node->designators ) {
1509                        os << indent;
1510                        d->accept( *this );
1511                        os << endl;
1512                }
1513                --indent;
1514                return node;
1515        }
1516
1517        virtual const ast::Init * visit( const ast::SingleInit * node ) override final {
1518                os << "Simple Initializer: ";
1519                safe_print( node->value );
1520                return node;
1521        }
1522
1523        virtual const ast::Init * visit( const ast::ListInit * node ) override final {
1524                os << "Compound initializer: " << endl;
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 );
1531                        os << endl;
1532                        if ( ! d->designators.empty() ) {
1533                                os << indent;
1534                                d->accept( *this );
1535                        }
1536                }
1537                --indent;
1538                return node;
1539        }
1540
1541        virtual const ast::Init * visit( const ast::ConstructorInit * node ) override final {
1542                os << "Constructor initializer: " << endl;
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                }
1563                return node;
1564        }
1565
1566        virtual const ast::Attribute * visit( const ast::Attribute * node ) override final {
1567                if ( node->empty() ) return node;
1568                os << "Attribute with name: " << node->name;
1569                if ( node->params.empty() ) return node;
1570                os << " with parameters: " << endl;
1571                ++indent;
1572                printAll( node->params );
1573                --indent;
1574                return node;
1575        }
1576
1577        virtual const ast::TypeSubstitution * visit( const ast::TypeSubstitution * node ) override final {
1578                os << indent << "Types:" << endl;
1579                for ( const auto& i : *node ) {
1580                        os << indent+1 << i.first.typeString() << " -> ";
1581                        indent += 2;
1582                        safe_print( i.second );
1583                        indent -= 2;
1584                        os << endl;
1585                }
1586                return node;
1587        }
1588
1589};
1590
1591void print( ostream & os, const ast::Node * node, Indenter indent ) {
1592        Printer printer { os, indent, false };
1593        node->accept(printer);
1594}
1595
1596void printShort( ostream & os, const ast::Decl * node, Indenter indent ) {
1597        Printer printer { os, indent, true };
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
1604constexpr array<const char*, 3> Printer::Names::FuncSpecifiers;
1605constexpr array<const char*, 5> Printer::Names::StorageClasses;
1606constexpr array<const char*, 6> Printer::Names::Qualifiers;
1607}
Note: See TracBrowser for help on using the repository browser.