source: src/AST/Print.cpp @ a16e246

arm-ehcleanup-dtorsenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since a16e246 was a16e246, checked in by Aaron Moss <a3moss@…>, 4 years ago

Finish Expr printers

  • Property mode set to 100644
File size: 29.4 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// Print.cpp --
8//
9// Author           : Thierry Delisle
10// Created On       : Tue May 21 16:20:15 2019
11// Last Modified By :
12// Last Modified On :
13// Update Count     :
14//
15
16#include "Print.hpp"
17
18#include "Decl.hpp"
19#include "Expr.hpp"
20#include "Stmt.hpp"
21#include "Type.hpp"
22#include "TypeSubstitution.hpp"
23
24#include "Common/utility.h" // for group_iterate
25
26using namespace std;
27
28namespace ast {
29
30template <typename C, typename... T>
31constexpr auto make_array(T&&... values) ->
32        array<C,sizeof...(T)>
33{
34        return array<C,sizeof...(T)>{
35                forward<T>(values)...
36        };
37}
38
39class Printer : public Visitor {
40public:
41        ostream & os;
42        Indenter indent;
43        bool short_mode;
44
45        Printer(ostream & os, Indenter indent, bool short_mode) : os( os ), indent( indent ), short_mode(short_mode) {}
46
47private:
48        template< typename C >
49        void printAll( const C & c ) {
50                for ( const auto & i : c ) {
51                        if ( i ) {
52                                os << indent;
53                                i->accept( *this );
54                                // need an endl after each element because it's not
55                                // easy to know when each individual item should end
56                                os << endl;
57                        } // if
58                } // for
59        }
60
61        /// call if mandatory field is missing
62        void undefined() {
63                os << "UNDEFINED";
64        }
65
66        /// call for fields that should be mandatory
67        void safe_print( const ast::Node * n ) {
68                if ( n ) n->accept( *this );
69                else undefined();
70        }
71
72        /// call to print short form. Incorporates features of safe_print()
73        void short_print( const ast::Node * n ) {
74                if ( ! n ) { undefined(); return; }
75                bool old_short = short_mode; short_mode = true;
76                n->accept( *this );
77                short_mode = old_short;
78        }
79
80
81        static const char* Names[];
82
83        struct Names {
84                static constexpr auto FuncSpecifiers = make_array<const char*>(
85                        "inline", "_Noreturn", "fortran"
86                );
87
88                static constexpr auto StorageClasses = make_array<const char*>(
89                        "extern", "static", "auto", "register", "_Thread_local"
90                );
91
92                static constexpr auto Qualifiers = make_array<const char*>(
93                        "const", "restrict", "volatile", "lvalue", "mutex", "_Atomic"
94                );
95        };
96
97        template<typename storage_t, size_t N>
98        void print(const storage_t & storage, const array<const char *, N> & Names ) {
99                if ( storage.any() ) {
100                        for ( size_t i = 0; i < Names.size(); i += 1 ) {
101                                if ( storage[i] ) {
102                                        os << Names[i] << ' ';
103                                }
104                        }
105                }
106        }
107
108        void print( const ast::Function::Specs & specs ) {
109                print(specs, Names::FuncSpecifiers);
110        }
111
112        void print( const ast::Storage::Classes & storage ) {
113                print(storage, Names::StorageClasses);
114        }
115
116        void print( const ast::CV::Qualifiers & qualifiers ) {
117                print(qualifiers, Names::Qualifiers);
118        }
119
120        void print( const ast::Expr::InferUnion & inferred, unsigned level = 0 ) {
121                switch ( inferred.mode ) {
122                case ast::Expr::InferUnion::Empty: return;
123                case ast::Expr::InferUnion::Slots: {
124                        os << indent << "with " << inferred.data.resnSlots.size() << " pending inference slots" 
125                           << std::endl;
126                        return;
127                }
128                case ast::Expr::InferUnion::Params: {
129                        os << indent << "with inferred parameters " << level << ":" << std::endl;
130                        ++indent;
131                        for ( const auto & i : inferred.data.inferParams ) {
132                                os << indent;
133                                short_print( Decl::fromId( i.second.decl ) );
134                                os << std::endl;
135                                print( i.second.expr->inferred, level+1 );
136                        }
137                        --indent;
138                        return;
139                }
140                }
141        }
142
143        void print( const ast::ParameterizedType::ForallList & forall ) {
144                if ( forall.empty() ) return;   
145                os << "forall" << std::endl;
146                ++indent;
147                printAll( forall );
148                os << indent;
149                --indent;
150        }
151
152        void print( const std::vector<ptr<Attribute>> & attrs ) {
153                if ( attrs.empty() ) return;
154                os << "with attributes" << std::endl;
155                ++indent;
156                printAll( attrs );
157                --indent;
158        }
159
160        void print( const std::vector<ptr<Expr>> & params ) {
161                if ( params.empty() ) return;
162                os << std::endl << indent << "... with parameters" << std::endl;
163                ++indent;
164                printAll( params );
165                --indent;
166        }
167
168        void print( const ast::AggregateDecl * node ) {
169                os << node->typeString() << " " << node->name << ":";
170                if ( node->linkage != Linkage::Cforall ) {
171                        os << " " << Linkage::name( node->linkage );
172                } // if
173                os << " with body : " << (node->body ? "yes " : "no ");
174
175                if ( ! node->params.empty() ) {
176                        os << endl << indent << "... with parameters" << endl;
177                        ++indent;
178                        printAll( node->params );
179                        --indent;
180                } // if
181                if ( ! node->members.empty() ) {
182                        os << endl << indent << "... with members" << endl;
183                        ++indent;
184                        printAll( node->members );
185                        --indent;
186                } // if
187                if ( ! node->attributes.empty() ) {
188                        os << endl << indent << "... with attributes" << endl;
189                        ++indent;
190                        printAll( node->attributes );
191                        --indent;
192                } // if
193                os << endl;
194        }
195
196        void print( const ast::NamedTypeDecl * node ) {
197                if ( !node->name.empty() ) os << node->name << ": ";
198
199                if ( node->linkage != Linkage::Cforall ) {
200                        os << Linkage::name( node->linkage ) << " ";
201                } // if
202                print( node->storage );
203                os << node->typeString();
204                if ( node->base ) {
205                        os << " for ";
206                        ++indent;
207                        node->base->accept( *this );
208                        --indent;
209                } // if
210                if ( ! node->params.empty() ) {
211                        os << endl << indent << "... with parameters" << endl;
212                        ++indent;
213                        printAll( node->params );
214                        --indent;
215                } // if
216                if ( ! node->assertions.empty() ) {
217                        os << endl << indent << "... with assertions" << endl;
218                        ++indent;
219                        printAll( node->assertions );
220                        --indent;
221                } // if
222        }
223
224        void postprint( const ast::Expr * node ) {
225                print( node->inferred );
226
227                if ( node->env ) {
228                        os << std::endl << indent << "... with environment:" << std::endl;
229                        ++indent;
230                        node->env->accept( *this );
231                        --indent;
232                }
233
234                if ( node->extension ) {
235                        os << std::endl << indent << "... with extension";
236                }
237        }
238
239        void preprint( const ast::Type * node ) {
240                print( node->qualifiers );
241        }
242
243        void preprint( const ast::ParameterizedType * node ) {
244                print( node->forall );
245                print( node->qualifiers );
246        }
247
248        void preprint( const ast::ReferenceToType * node ) {
249                print( node->forall );
250                print( node->attributes );
251                print( node->qualifiers );
252        }
253
254public:
255        virtual const ast::DeclWithType * visit( const ast::ObjectDecl * node ) {
256                if ( !node->name.empty() ) os << node->name << ": ";
257
258                if ( node->linkage != Linkage::Cforall ) {
259                        os << Linkage::name( node->linkage ) << " ";
260                } // if
261
262                print( node->storage );
263
264                if ( node->type ) {
265                        node->type->accept( *this );
266                } else {
267                        os << "untyped entity";
268                } // if
269
270                if ( node->init ) {
271                        os << " with initializer (" << (
272                                node->init->maybeConstructed
273                                        ? "maybe constructed"
274                                        : "not constructed"
275                                ) << ")" << endl << indent+1;
276
277                        ++indent;
278                        node->init->accept( *this );
279                        --indent;
280                        os << endl;
281                } // if
282
283                if ( ! node->attributes.empty() ) {
284                        os << endl << indent << "... with attributes:" << endl;
285                        ++indent;
286                        printAll( node->attributes );
287                        --indent;
288                }
289
290                if ( node->bitfieldWidth ) {
291                        os << indent << " with bitfield width ";
292                        node->bitfieldWidth->accept( *this );
293                } // if
294                return node;
295        }
296
297        virtual const ast::DeclWithType * visit( const ast::FunctionDecl * node ) {
298                if ( !node->name.empty() ) {
299                        os << node->name << ": ";
300                } // if
301                if ( node->linkage != Linkage::Cforall ) {
302                        os << Linkage::name( node->linkage ) << " ";
303                } // if
304
305                printAll( node->attributes );
306
307                print( node->storage );
308                print( node->funcSpec );
309
310                if ( node->type ) {
311                        node->type->accept( *this );
312                } else {
313                        os << "untyped entity";
314                } // if
315
316                if ( node->stmts ) {
317                        os << indent << "... with body" << endl << indent+1;
318                        ++indent;
319                        node->stmts->accept( *this );
320                        --indent;
321                } // if
322                return node;
323        }
324
325        virtual const ast::Decl * visit( const ast::StructDecl * node ) {
326                print(node);
327                return node;
328        }
329
330        virtual const ast::Decl * visit( const ast::UnionDecl * node ) {
331                print(node);
332                return node;
333        }
334
335        virtual const ast::Decl * visit( const ast::EnumDecl * node ) {
336                print(node);
337                return node;
338        }
339
340        virtual const ast::Decl * visit( const ast::TraitDecl * node ) {
341                print(node);
342                return node;
343        }
344
345        virtual const ast::Decl * visit( const ast::TypeDecl * node ) {
346                print( node );
347                if ( node->init ) {
348                        os << endl << indent << "with type initializer: ";
349                        ++indent;
350                        node->init->accept( *this );
351                        --indent;
352                }
353                return node;
354        }
355
356        virtual const ast::Decl * visit( const ast::TypedefDecl * node ) {
357                print( node );
358                return node;
359        }
360
361        virtual const ast::AsmDecl * visit( const ast::AsmDecl * node ) {
362                node->stmt->accept( *this );
363                return node;
364        }
365
366        virtual const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl * node ) {
367                os << "Static Assert with condition: ";
368                ++indent;
369                node->cond->accept( *this );
370                --indent;
371                os << endl << indent << "and message: ";
372                ++indent;
373                node->msg->accept( *this );
374                --indent;
375                os << endl;
376                return node;
377        }
378
379        virtual const ast::CompoundStmt * visit( const ast::CompoundStmt * node ) {
380                os << "CompoundStmt" << endl;
381                ++indent;
382                printAll( node->kids );
383                --indent;
384                return node;
385        }
386
387        virtual const ast::Stmt * visit( const ast::ExprStmt * node ) {
388                ++indent;
389                os << "Expression Statement:" << endl << indent;
390                safe_print( node->expr );
391                --indent;
392                return node;
393        }
394
395        virtual const ast::Stmt * visit( const ast::AsmStmt * node ) {
396                os << "Assembler Statement:" << endl;
397                ++indent;
398                os << indent << "instruction: " << endl << indent;
399                node->instruction->accept( *this );
400                if ( ! node->output.empty() ) {
401                        os << endl << indent+1 << "output: " << endl;
402                        printAll( node->output );
403                } // if
404                if ( ! node->input.empty() ) {
405                        os << indent+1 << "input: " << endl;
406                        printAll( node->input );
407                } // if
408                if ( ! node->clobber.empty() ) {
409                        os << indent+1 << "clobber: " << endl;
410                        printAll( node->clobber );
411                } // if
412                --indent;
413                return node;
414        }
415
416        virtual const ast::Stmt * visit( const ast::DirectiveStmt * node ) {
417                os << "GCC Directive:" << node->directive << endl;
418                return node;
419        }
420
421        virtual const ast::Stmt * visit( const ast::IfStmt * node ) {
422                os << "If on condition: " << endl;
423                os << indent+1;
424                ++indent;
425                safe_print( node->cond );
426                --indent;
427
428                if ( !node->inits.empty() ) {
429                        os << indent << "... with initialization: \n";
430                        ++indent;
431                        for ( const Stmt * stmt : node->inits ) {
432                                os << indent;
433                                stmt->accept( *this );
434                        }
435                        --indent;
436                        os << endl;
437                }
438
439                os << indent << "... then: " << endl;
440
441                ++indent;
442                os << indent;
443                safe_print( node->thenPart );
444                --indent;
445
446                if ( node->elsePart != 0 ) {
447                        os << indent << "... else: " << endl;
448                        ++indent;
449                        os << indent;
450                        node->elsePart->accept( *this );
451                        --indent;
452                } // if
453                return node;
454        }
455
456        virtual const ast::Stmt * visit( const ast::WhileStmt * node ) {
457                return node;
458        }
459
460        virtual const ast::Stmt * visit( const ast::ForStmt * node ) {
461                return node;
462        }
463
464        virtual const ast::Stmt * visit( const ast::SwitchStmt * node ) {
465                return node;
466        }
467
468        virtual const ast::Stmt * visit( const ast::CaseStmt * node ) {
469                return node;
470        }
471
472        virtual const ast::Stmt * visit( const ast::BranchStmt * node ) {
473                return node;
474        }
475
476        virtual const ast::Stmt * visit( const ast::ReturnStmt * node ) {
477                return node;
478        }
479
480        virtual const ast::Stmt * visit( const ast::ThrowStmt * node ) {
481                return node;
482        }
483
484        virtual const ast::Stmt * visit( const ast::TryStmt * node ) {
485                return node;
486        }
487
488        virtual const ast::Stmt * visit( const ast::CatchStmt * node ) {
489                return node;
490        }
491
492        virtual const ast::Stmt * visit( const ast::FinallyStmt * node ) {
493                return node;
494        }
495
496        virtual const ast::Stmt * visit( const ast::WaitForStmt * node ) {
497                return node;
498        }
499
500        virtual const ast::Stmt * visit( const ast::WithStmt * node ) {
501                return node;
502        }
503
504        virtual const ast::NullStmt * visit( const ast::NullStmt * node ) {
505                return node;
506        }
507
508        virtual const ast::Stmt * visit( const ast::DeclStmt * node ) {
509                return node;
510        }
511
512        virtual const ast::Stmt * visit( const ast::ImplicitCtorDtorStmt * node ) {
513                return node;
514        }
515
516        virtual const ast::Expr * visit( const ast::ApplicationExpr * node ) {
517                ++indent;
518                os << "Application of" << std::endl << indent;
519                safe_print( node->func );
520                os << std::endl;
521                if ( ! node->args.empty() ) {
522                        os << indent << "... to arguments" << std::endl;
523                        printAll( node->args );
524                }
525                --indent;
526                postprint( node );
527
528                return node;
529        }
530
531        virtual const ast::Expr * visit( const ast::UntypedExpr * node ) {
532                ++indent;
533                os << "Applying untyped:" << std::endl;
534                os << indent;
535                safe_print( node->func );
536                os << std::endl << indent-1 << "...to:" << std::endl;
537                printAll( node->args );
538                --indent;
539                postprint( node );
540
541                return node;
542        }
543
544        virtual const ast::Expr * visit( const ast::NameExpr * node ) {
545                os << "Name: " << node->name;
546                postprint( node );
547               
548                return node;
549        }
550
551        virtual const ast::Expr * visit( const ast::AddressExpr * node ) {
552                os << "Address of:" << std::endl;
553                ++indent;
554                os << indent;
555                safe_print( node->arg );
556
557                --indent;
558
559                return node;
560        }
561
562        virtual const ast::Expr * visit( const ast::LabelAddressExpr * node ) {
563                os << "Address of label:" << node->arg;
564
565                return node;
566        }
567
568        virtual const ast::Expr * visit( const ast::CastExpr * node ) {
569                ++indent;
570                os << (node->isGenerated ? "Generated" : "Explicit") << " cast of:" << std::endl << indent;
571                safe_print( node->arg );
572                os << std::endl << indent-1 << "... to:";
573                if ( ! node->result ) {
574                        os << " ";
575                        undefined();
576                } else if ( node->result->isVoid() ) {
577                        os << " nothing";
578                } else {
579                        os << std::endl << indent;
580                        node->result->accept( *this );
581                } // if
582                --indent;
583                postprint( node );
584
585                return node;
586        }
587
588        virtual const ast::Expr * visit( const ast::KeywordCastExpr * node ) {
589                ++indent;
590                os << "Keyword Cast of:" << std::endl << indent;
591                safe_print( node->arg );
592                --indent;
593                os << std::endl << indent << "... to: " << node->targetString();
594                postprint( node );
595
596                return node;
597        }
598
599        virtual const ast::Expr * visit( const ast::VirtualCastExpr * node ) {
600                ++indent;
601                os << "Virtual Cast of:" << std::endl << indent;
602                safe_print( node->arg );
603                os << std::endl << indent-1 << "... to:";
604                if ( ! node->result ) {
605                        os << " unknown";
606                } else {
607                        os << std::endl << indent;
608                        node->result->accept( *this );
609                }
610                --indent;
611                postprint( node );
612
613                return node;
614        }
615
616        virtual const ast::Expr * visit( const ast::UntypedMemberExpr * node ) {
617                ++indent;
618                os << "Untyped Member Expression, with field: " << std::endl << indent;
619                safe_print( node->member );
620                os << indent-1 << "... from aggregate:" << std::endl << indent;
621                safe_print( node->aggregate );
622                --indent;
623                postprint( node );
624
625                return node;
626        }
627
628        virtual const ast::Expr * visit( const ast::MemberExpr * node ) {
629                ++indent;
630                os << "Member Expression, with field:" << std::endl << indent;
631                safe_print( node->member );
632                os << std::endl << indent-1 << "... from aggregate:" << std::endl << indent;
633                safe_print( node->aggregate );
634                --indent;
635                postprint( node );
636
637                return node;
638        }
639
640        virtual const ast::Expr * visit( const ast::VariableExpr * node ) {
641                os << "Variable Expression: ";
642                short_print( node->var );
643                postprint( node );
644
645                return node;
646        }
647
648        virtual const ast::Expr * visit( const ast::ConstantExpr * node ) {
649                os << "Constant Expression (" << node->rep;
650                if ( node->result ) {
651                        os << ": ";
652                        node->result->accept( *this );
653                }
654                os << ")";
655                postprint( node );
656
657                return node;
658        }
659
660        virtual const ast::Expr * visit( const ast::SizeofExpr * node ) {
661                os << "Sizeof Expression on: ";
662                ++indent;
663                if ( node->type ) node->type->accept( *this );
664                else safe_print( node->expr );
665                --indent;
666                postprint( node );
667
668                return node;
669        }
670
671        virtual const ast::Expr * visit( const ast::AlignofExpr * node ) {
672                os << "Alignof Expression on: ";
673                ++indent;
674                if ( node->type ) node->type->accept( *this );
675                else safe_print( node->expr );
676                --indent;
677                postprint( node );
678               
679                return node;
680        }
681
682        virtual const ast::Expr * visit( const ast::UntypedOffsetofExpr * node ) {
683                os << "Untyped Offsetof Expression on member " << node->member << " of ";
684                ++indent;
685                safe_print( node->type );
686                --indent;
687                postprint( node );
688
689                return node;
690        }
691
692        virtual const ast::Expr * visit( const ast::OffsetofExpr * node ) {
693                os << "Offsetof Expression on member " << node->member->name << " of ";
694                ++indent;
695                safe_print( node->type );
696                --indent;
697                postprint( node );
698
699                return node;
700        }
701
702        virtual const ast::Expr * visit( const ast::OffsetPackExpr * node ) {
703                os << "Offset Pack Expression on: ";
704                ++indent;
705                safe_print( node->type );
706                --indent;
707                postprint( node );
708
709                return node;
710        }
711
712        virtual const ast::Expr * visit( const ast::LogicalExpr * node ) {
713                os << "Short-circuited operation (" << (node->isAnd ? "and" : "or") << ") on: ";
714                safe_print( node->arg1 );
715                os << " and ";
716                safe_print( node->arg2 );
717                postprint( node );
718
719                return node;
720        }
721
722        virtual const ast::Expr * visit( const ast::ConditionalExpr * node ) {
723                ++indent;
724                os << "Conditional expression on:" << std::endl << indent;
725                safe_print( node->arg1 );
726                os << indent-1 << "First alternative:" << std::endl << indent;
727                safe_print( node->arg2 );
728                os << indent-1 << "Second alternative:" << std::endl << indent;
729                safe_print( node->arg3 );
730                --indent;
731                postprint( node );
732
733                return node;
734        }
735
736        virtual const ast::Expr * visit( const ast::CommaExpr * node ) {
737                ++indent;
738                os << "Comma Expression:" << std::endl << indent;
739                safe_print( node->arg1 );
740                os << std::endl << indent;
741                safe_print( node->arg2 );
742                --indent;
743                postprint( node );
744
745                return node;
746        }
747
748        virtual const ast::Expr * visit( const ast::TypeExpr * node ) {
749                safe_print( node->type );
750                postprint( node );
751
752                return node;
753        }
754
755        virtual const ast::Expr * visit( const ast::AsmExpr * node ) {
756                os << "Asm Expression:" << std::endl;
757                ++indent;
758                if ( node->inout ) node->inout->accept( *this );
759                if ( node->constraint ) node->constraint->accept( *this );
760                if ( node->operand ) node->operand->accept( *this );
761                --indent;
762               
763                return node;
764        }
765
766        virtual const ast::Expr * visit( const ast::ImplicitCopyCtorExpr * node ) {
767                ++indent;
768                os << "Implicit Copy Constructor Expression:" << std::endl << indent;
769                safe_print( node->callExpr );
770                os << std::endl << indent-1 << "... with temporaries:" << std::endl;
771                printAll( node->tempDecls );
772                os << std::endl << indent-1 << "... with return temporaries:" << std::endl;
773                printAll( node->returnDecls );
774                --indent;
775                postprint( node );
776
777                return node;
778        }
779
780        virtual const ast::Expr * visit( const ast::ConstructorExpr * node ) {
781                os <<  "Constructor Expression:" << std::endl << indent+1;
782                indent += 2;
783                safe_print( node->callExpr );
784                indent -= 2;
785                postprint( node );
786
787                return node;
788        }
789
790        virtual const ast::Expr * visit( const ast::CompoundLiteralExpr * node ) {
791                ++indent;
792                os << "Compound Literal Expression: " << std::endl << indent;
793                safe_print( node->result );
794                os << indent;
795                safe_print( node->init );
796                --indent;
797                postprint( node );
798
799                return node;
800        }
801
802        virtual const ast::Expr * visit( const ast::RangeExpr * node ) {
803                os << "Range Expression: ";
804                safe_print( node->low );
805                os << " ... ";
806                safe_print( node->high );
807                postprint( node );
808
809                return node;
810        }
811
812        virtual const ast::Expr * visit( const ast::UntypedTupleExpr * node ) {
813                os << "Untyped Tuple:" << std::endl;
814                ++indent;
815                printAll( node->exprs );
816                --indent;
817                postprint( node );
818
819                return node;
820        }
821
822        virtual const ast::Expr * visit( const ast::TupleExpr * node ) {
823                os << "Tuple:" << std::endl;
824                ++indent;
825                printAll( node->exprs );
826                --indent;
827                postprint( node );
828
829                return node;
830        }
831
832        virtual const ast::Expr * visit( const ast::TupleIndexExpr * node ) {
833                os << "Tuple Index Expression, with tuple:" << std::endl;
834                ++indent;
835                os << indent;
836                safe_print( node->tuple );
837                os << indent << "with index: " << node->index << std::endl;
838                --indent;
839                postprint( node );
840               
841                return node;
842        }
843
844        virtual const ast::Expr * visit( const ast::TupleAssignExpr * node ) {
845                os << "Tuple Assignment Expression, with stmt expr:" << std::endl;
846                ++indent;
847                os << indent;
848                safe_print( node->stmtExpr );
849                --indent;
850                postprint( node );
851
852                return node;
853        }
854
855        virtual const ast::Expr * visit( const ast::StmtExpr * node ) {
856                ++indent;
857                os << "Statement Expression:" << std::endl << indent;
858                safe_print( node->stmts );
859                if ( ! node->returnDecls.empty() ) {
860                        os << indent << "... with returnDecls: ";
861                        printAll( node->returnDecls );
862                }
863                if ( ! node->dtors.empty() ) {
864                        os << indent << "... with dtors: ";
865                        printAll( node->dtors );
866                }
867                --indent;
868                postprint( node );
869
870                return node;
871        }
872
873        virtual const ast::Expr * visit( const ast::UniqueExpr * node ) {
874                ++indent;
875                os << "Unique Expression with id: " << node->id << std::endl << indent;
876                safe_print( node->expr );
877                if ( node->object ) {
878                        os << indent-1 << "... with decl: ";
879                        short_print( node->object );
880                }
881                --indent;
882                postprint( node );
883
884                return node;
885        }
886
887        virtual const ast::Expr * visit( const ast::UntypedInitExpr * node ) {
888                ++indent;
889                os << "Untyped Init Expression" << std::endl << indent;
890                safe_print( node->expr );
891                if ( ! node->initAlts.empty() ) {
892                        for ( const InitAlternative & alt : node->initAlts ) {
893                                os << indent <<  "InitAlternative: ";
894                                safe_print( alt.type );
895                                safe_print( alt.designation );
896                        }
897                }
898                --indent;
899
900                return node;
901        }
902
903        virtual const ast::Expr * visit( const ast::InitExpr * node ) {
904                ++indent;
905                os << "Init Expression" << std::endl << indent;
906                safe_print( node->expr );
907                os << indent << "... with designation: ";
908                safe_print( node->designation );
909                --indent;
910
911                return node;
912        }
913
914        virtual const ast::Expr * visit( const ast::DeletedExpr * node ) {
915                ++indent;
916                os << "Deleted Expression" << std::endl << indent;
917                safe_print( node->expr );
918                os << std::endl << indent << "... deleted by: ";
919                safe_print( node->deleteStmt );
920                --indent;
921
922                return node;
923        }
924
925        virtual const ast::Expr * visit( const ast::DefaultArgExpr * node ) {
926                ++indent;
927                os << "Default Argument Expression" << std::endl << indent;
928                safe_print( node->expr );
929                --indent;
930
931                return node;
932        }
933
934        virtual const ast::Expr * visit( const ast::GenericExpr * node ) {
935                ++indent;
936                os << "C11 _Generic Expression" << std::endl << indent;
937                safe_print( node->control );
938                os << std::endl << indent << "... with associations:" << std::endl;
939                for ( const auto & assoc : node->associations ) {
940                        os << indent;
941                        if ( assoc.type ) {
942                                os << "... type: ";
943                                assoc.type->accept( *this );
944                                os << std::endl << indent << "... expression: ";
945                                safe_print( assoc.expr );
946                        } else {
947                                os << "... default: ";
948                                safe_print( assoc.expr );
949                        }
950                        os << std::endl;
951                }
952                --indent;
953
954                return node;
955        }
956
957        virtual const ast::Type * visit( const ast::VoidType * node ) {
958                preprint( node );
959                os << "void";
960                return node;
961        }
962
963        virtual const ast::Type * visit( const ast::BasicType * node ) {
964                preprint( node );
965                os << ast::BasicType::typeNames[ node->kind ];
966                return node;
967        }
968
969        virtual const ast::Type * visit( const ast::PointerType * node ) {
970                preprint( node );
971                if ( ! node->isArray() ) {
972                        os << "pointer to ";
973                } else {
974                        os << "decayed ";
975                        if ( node->isStatic ) {
976                                os << "static ";
977                        }
978
979                        if ( node->isVarLen ) {
980                                os << "variable length array of ";
981                        } else if ( node->dimension ) {
982                                os << "array of ";
983                                node->dimension->accept( *this );
984                                os << " ";
985                        }
986                }
987                safe_print( node->base );
988
989                return node;
990        }
991
992        virtual const ast::Type * visit( const ast::ArrayType * node ) {
993                preprint( node );
994                if ( node->isStatic ) {
995                        os << "static ";
996                }
997
998                if ( node->isVarLen ) {
999                        os << "variable length array of ";
1000                } else if ( node->dimension ) {
1001                        os << "array of ";
1002                } else {
1003                        os << "open array of ";
1004                }
1005
1006                safe_print( node->base );
1007
1008                if ( node->dimension ) {
1009                        os << " with dimension of ";
1010                        node->dimension->accept( *this );
1011                }
1012
1013                return node;
1014        }
1015
1016        virtual const ast::Type * visit( const ast::ReferenceType * node ) {
1017                preprint( node );
1018                os << "reference to ";
1019                safe_print( node->base );
1020
1021                return node;
1022        }
1023
1024        virtual const ast::Type * visit( const ast::QualifiedType * node ) {
1025                preprint( node );
1026                ++indent;
1027                os << "Qualified Type:" << std::endl << indent;
1028                safe_print( node->parent );
1029                os << std::endl << indent;
1030                safe_print( node->child );
1031                os << std::endl;
1032                --indent;
1033
1034                return node;
1035        }
1036
1037        virtual const ast::Type * visit( const ast::FunctionType * node ) {
1038                preprint( node );
1039               
1040                os << "function" << std::endl;
1041                if ( ! node->params.empty() ) {
1042                        os << indent << "... with parameters" << std::endl;
1043                        ++indent;
1044                        printAll( node->params );
1045                        if ( node->isVarArgs ) {
1046                                os << indent << "and a variable number of other arguments" << std::endl;
1047                        }
1048                        --indent;
1049                } else if ( node->isVarArgs ) {
1050                        os << indent+1 << "accepting unspecified arguments" << std::endl;
1051                }
1052
1053                os << indent << "... returning";
1054                if ( node->returns.empty() ) {
1055                        os << " nothing" << std::endl;
1056                } else {
1057                        os << std::endl;
1058                        ++indent;
1059                        printAll( node->returns );
1060                        --indent;
1061                }
1062
1063                return node;
1064        }
1065
1066        virtual const ast::Type * visit( const ast::StructInstType * node ) {
1067                preprint( node );
1068                os << "instance of struct " << node->name;
1069                if ( node->base ) {
1070                        os << " " << ( node->base->body ? "with" : "without" ) << " body";
1071                }
1072                print( node->params );
1073
1074                return node;
1075        }
1076
1077        virtual const ast::Type * visit( const ast::UnionInstType * node ) {
1078                preprint( node );
1079                os << "instance of union " << node->name;
1080                if ( node->base ) {
1081                        os << " " << ( node->base->body ? "with" : "without" ) << " body";
1082                }
1083                print( node->params );
1084
1085                return node;
1086        }
1087
1088        virtual const ast::Type * visit( const ast::EnumInstType * node ) {
1089                preprint( node );
1090                os << "instance of enum " << node->name;
1091                if ( node->base ) {
1092                        os << " " << ( node->base->body ? "with" : "without" ) << " body";
1093                }
1094                print( node->params );
1095
1096                return node;
1097        }
1098
1099        virtual const ast::Type * visit( const ast::TraitInstType * node ) {
1100                preprint( node );
1101                os << "instance of trait " << node->name;
1102                print( node->params );
1103
1104                return node;
1105        }
1106
1107        virtual const ast::Type * visit( const ast::TypeInstType * node ) {
1108                preprint( node );
1109                os << "instance of type " << node->name
1110                   << " (" << (node->kind == ast::TypeVar::Ftype ? "" : "not ") << "function type)";
1111                print( node->params );
1112
1113                return node;
1114        }
1115
1116        virtual const ast::Type * visit( const ast::TupleType * node ) {
1117                preprint( node );
1118                os << "tuple of types" << std::endl;
1119                ++indent;
1120                printAll( node->types );
1121                --indent;
1122
1123                return node;
1124        }
1125
1126        virtual const ast::Type * visit( const ast::TypeofType * node ) {
1127                preprint( node );
1128                if ( node->kind == ast::TypeofType::Basetypeof ) { os << "base-"; }
1129                os << "type-of expression ";
1130                safe_print( node->expr );
1131
1132                return node;
1133        }
1134
1135        virtual const ast::Type * visit( const ast::VarArgsType * node ) {
1136                preprint( node );
1137                os << "builtin var args pack";
1138                return node;
1139        }
1140
1141        virtual const ast::Type * visit( const ast::ZeroType * node ) {
1142                preprint( node );
1143                os << "zero_t";
1144                return node;
1145        }
1146
1147        virtual const ast::Type * visit( const ast::OneType * node ) {
1148                preprint( node );
1149                os << "one_t";
1150                return node;
1151        }
1152
1153        virtual const ast::Type * visit( const ast::GlobalScopeType * node ) {
1154                preprint( node );
1155                os << "Global Scope Type";
1156                return node;
1157        }
1158
1159        virtual const ast::Designation * visit( const ast::Designation * node ) {
1160                if ( node->designators.empty() ) return node;
1161                os << "... designated by: " << std::endl;
1162                ++indent;
1163                for ( const ast::Expr * d : node->designators ) {
1164                        os << indent;
1165                        d->accept( *this );
1166                        os << std::endl;
1167                }
1168                --indent;
1169                return node;
1170        }
1171
1172        virtual const ast::Init * visit( const ast::SingleInit * node ) {
1173                os << "Simple Initializer: ";
1174                safe_print( node->value );
1175                return node;
1176        }
1177
1178        virtual const ast::Init * visit( const ast::ListInit * node ) {
1179                os << "Compound initializer: " << std::endl;
1180                ++indent;
1181                for ( auto p : group_iterate( node->designations, node->initializers ) ) {
1182                        const ast::Designation * d = std::get<0>(p);
1183                        const ast::Init * init = std::get<1>(p);
1184                        os << indent;
1185                        init->accept( *this );
1186                        os << std::endl;
1187                        if ( ! d->designators.empty() ) {
1188                                os << indent;
1189                                d->accept( *this );
1190                        }
1191                }
1192                --indent;
1193                return node;
1194        }
1195
1196        virtual const ast::Init * visit( const ast::ConstructorInit * node ) {
1197                os << "Constructor initializer: " << std::endl;
1198                if ( node->ctor ) {
1199                        os << indent << "... initially constructed with ";
1200                        ++indent;
1201                        node->ctor->accept( *this );
1202                        --indent;
1203                }
1204
1205                if ( node->dtor ) {
1206                        os << indent << "... destructed with ";
1207                        ++indent;
1208                        node->dtor->accept( *this );
1209                        --indent;
1210                }
1211
1212                if ( node->init ) {
1213                        os << indent << "... with fallback C-style initializer: ";
1214                        ++indent;
1215                        node->init->accept( *this );
1216                        --indent;
1217                }
1218                return node;
1219        }
1220
1221        virtual const ast::Attribute * visit( const ast::Attribute * node ) {
1222                if ( node->empty() ) return node;
1223                os << "Attribute with name: " << node->name;
1224                if ( node->params.empty() ) return node;
1225                os << " with parameters: " << std::endl;
1226                ++indent;
1227                printAll( node->params );
1228                --indent;
1229                return node;
1230        }
1231
1232        virtual const ast::TypeSubstitution * visit( const ast::TypeSubstitution * node ) {
1233                os << indent << "Types:" << std::endl;
1234                for ( const auto& i : *node ) {
1235                        os << indent+1 << i.first << " -> ";
1236                        indent += 2;
1237                        safe_print( i.second );
1238                        indent -= 2;
1239                        os << std::endl;
1240                }
1241                os << indent << "Non-types:" << std::endl;
1242                for ( auto i = node->beginVar(); i != node->endVar(); ++i ) {
1243                        os << indent+1 << i->first << " -> ";
1244                        indent += 2;
1245                        safe_print( i->second );
1246                        indent -= 2;
1247                        os << std::endl;
1248                }
1249                return node;
1250        }
1251
1252};
1253
1254void print( ostream & os, const ast::Node * node, Indenter indent ) {
1255        Printer printer { os, indent, false };
1256        node->accept(printer);
1257}
1258
1259void printShort( ostream & os, const ast::Node * node, Indenter indent ) {
1260        Printer printer { os, indent, true };
1261        node->accept(printer);
1262}
1263
1264// Annoyingly these needed to be defined out of line to avoid undefined references.
1265// The size here needs to be explicit but at least the compiler will produce an error
1266// if the wrong size is specified
1267constexpr array<const char*, 3> Printer::Names::FuncSpecifiers;
1268constexpr array<const char*, 5> Printer::Names::StorageClasses;
1269constexpr array<const char*, 6> Printer::Names::Qualifiers;
1270}
Note: See TracBrowser for help on using the repository browser.