source: src/AST/Print.cpp @ b0ec971

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

Added ast::Type printers

  • Property mode set to 100644
File size: 19.0 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
26namespace ast {
27
28template <typename C, typename... T>
29constexpr auto make_array(T&&... values) ->
30        std::array<C,sizeof...(T)>
31{
32        return std::array<C,sizeof...(T)>{
33                std::forward<T>(values)...
34        };
35}
36
37class Printer : public Visitor {
38public:
39        std::ostream & os;
40        Indenter indent;
41
42        Printer(std::ostream & os, Indenter indent) : os( os ), indent( indent ) {}
43
44private:
45        template< typename C >
46        void printAll( const C & c ) {
47                for ( const auto & i : c ) {
48                        if ( i ) {
49                                os << indent;
50                                i->accept( *this );
51                                // need an endl after each element because it's not
52                                // easy to know when each individual item should end
53                                os << std::endl;
54                        } // if
55                } // for
56        }
57
58
59        static const char* Names[];
60
61        struct Names {
62                static constexpr auto FuncSpecifiers = make_array<const char*>(
63                        "inline", "_Noreturn", "fortran"
64                );
65
66                static constexpr auto StorageClasses = make_array<const char*>(
67                        "extern", "static", "auto", "register", "_Thread_local"
68                );
69
70                static constexpr auto Qualifiers = make_array<const char*>(
71                        "const", "restrict", "volatile", "lvalue", "mutex", "_Atomic"
72                );
73        };
74
75        template<typename storage_t, size_t N>
76        void print(const storage_t & storage, const std::array<const char *, N> & Names ) {
77                if ( storage.any() ) {
78                        for ( size_t i = 0; i < Names.size(); i += 1 ) {
79                                if ( storage[i] ) {
80                                        os << Names[i] << ' ';
81                                }
82                        }
83                }
84        }
85
86        void print( const ast::Function::Specs & specs ) {
87                print(specs, Names::FuncSpecifiers);
88        }
89
90        void print( const ast::Storage::Classes & storage ) {
91                print(storage, Names::StorageClasses);
92        }
93
94        void print( const ast::CV::Qualifiers & qualifiers ) {
95                print(qualifiers, Names::Qualifiers);
96        }
97
98        void print( const ast::ParameterizedType::ForallList & forall ) {
99                if ( forall.empty() ) return;   
100                os << "forall" << std::endl;
101                ++indent;
102                printAll( forall );
103                os << indent;
104                --indent;
105        }
106
107        void print( const std::vector<ptr<Attribute>> & attrs ) {
108                if ( attrs.empty() ) return;
109                os << "with attributes" << std::endl;
110                ++indent;
111                printAll( attrs );
112                --indent;
113        }
114
115        void print( const std::vector<ptr<Expr>> & params ) {
116                if ( params.empty() ) return;
117                os << std::endl << indent << "... with parameters" << std::endl;
118                ++indent;
119                printAll( params );
120                --indent;
121        }
122
123        void preprint( const ast::Type * node ) {
124                print( node->qualifiers );
125        }
126
127        void preprint( const ast::ParameterizedType * node ) {
128                print( node->forall );
129                print( node->qualifiers );
130        }
131
132        void preprint( const ast::ReferenceToType * node ) {
133                print( node->forall );
134                print( node->attributes );
135                print( node->qualifiers );
136        }
137
138public:
139        virtual const ast::DeclWithType *     visit( const ast::ObjectDecl           * node ) {
140                if ( node->name != "" ) os << node->name << ": ";
141
142                if ( node->linkage != Linkage::Cforall ) {
143                        os << Linkage::name( node->linkage ) << " ";
144                } // if
145
146                print( node->storage );
147
148                if ( node->type ) {
149                        node->type->accept( *this );
150                } else {
151                        os << " untyped entity ";
152                } // if
153
154                if ( node->init ) {
155                        os << " with initializer (" << (
156                                node->init->maybeConstructed
157                                        ? "maybe constructed"
158                                        : "not constructed"
159                                ) << ")" << std::endl << indent+1;
160
161                        ++indent;
162                        node->init->accept( *this );
163                        --indent;
164                        os << std::endl;
165                } // if
166
167                if ( ! node->attributes.empty() ) {
168                        os << std::endl << indent << "... with attributes:" << std::endl;
169                        ++indent;
170                        printAll( node->attributes );
171                        --indent;
172                }
173
174                if ( node->bitfieldWidth ) {
175                        os << indent << " with bitfield width ";
176                        node->bitfieldWidth->accept( *this );
177                } // if
178                return node;
179        }
180
181        virtual const ast::DeclWithType *     visit( const ast::FunctionDecl         * node ) {
182                return node;
183        }
184
185        virtual const ast::Decl *             visit( const ast::StructDecl           * node ) {
186                return node;
187        }
188
189        virtual const ast::Decl *             visit( const ast::UnionDecl            * node ) {
190                return node;
191        }
192
193        virtual const ast::Decl *             visit( const ast::EnumDecl             * node ) {
194                return node;
195        }
196
197        virtual const ast::Decl *             visit( const ast::TraitDecl            * node ) {
198                return node;
199        }
200
201        virtual const ast::Decl *             visit( const ast::TypeDecl             * node ) {
202                return node;
203        }
204
205        virtual const ast::Decl *             visit( const ast::TypedefDecl          * node ) {
206                return node;
207        }
208
209        virtual const ast::AsmDecl *          visit( const ast::AsmDecl              * node ) {
210                return node;
211        }
212
213        virtual const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl     * node ) {
214                return node;
215        }
216
217        virtual const ast::CompoundStmt *     visit( const ast::CompoundStmt         * node ) {
218                return node;
219        }
220
221        virtual const ast::Stmt *             visit( const ast::ExprStmt             * node ) {
222                return node;
223        }
224
225        virtual const ast::Stmt *             visit( const ast::AsmStmt              * node ) {
226                return node;
227        }
228
229        virtual const ast::Stmt *             visit( const ast::DirectiveStmt        * node ) {
230                return node;
231        }
232
233        virtual const ast::Stmt *             visit( const ast::IfStmt               * node ) {
234                return node;
235        }
236
237        virtual const ast::Stmt *             visit( const ast::WhileStmt            * node ) {
238                return node;
239        }
240
241        virtual const ast::Stmt *             visit( const ast::ForStmt              * node ) {
242                return node;
243        }
244
245        virtual const ast::Stmt *             visit( const ast::SwitchStmt           * node ) {
246                return node;
247        }
248
249        virtual const ast::Stmt *             visit( const ast::CaseStmt             * node ) {
250                return node;
251        }
252
253        virtual const ast::Stmt *             visit( const ast::BranchStmt           * node ) {
254                return node;
255        }
256
257        virtual const ast::Stmt *             visit( const ast::ReturnStmt           * node ) {
258                return node;
259        }
260
261        virtual const ast::Stmt *             visit( const ast::ThrowStmt            * node ) {
262                return node;
263        }
264
265        virtual const ast::Stmt *             visit( const ast::TryStmt              * node ) {
266                return node;
267        }
268
269        virtual const ast::Stmt *             visit( const ast::CatchStmt            * node ) {
270                return node;
271        }
272
273        virtual const ast::Stmt *             visit( const ast::FinallyStmt          * node ) {
274                return node;
275        }
276
277        virtual const ast::Stmt *             visit( const ast::WaitForStmt          * node ) {
278                return node;
279        }
280
281        virtual const ast::Stmt *             visit( const ast::WithStmt             * node ) {
282                return node;
283        }
284
285        virtual const ast::NullStmt *         visit( const ast::NullStmt             * node ) {
286                return node;
287        }
288
289        virtual const ast::Stmt *             visit( const ast::DeclStmt             * node ) {
290                return node;
291        }
292
293        virtual const ast::Stmt *             visit( const ast::ImplicitCtorDtorStmt * node ) {
294                return node;
295        }
296
297        virtual const ast::Expr *             visit( const ast::ApplicationExpr      * node ) {
298                return node;
299        }
300
301        virtual const ast::Expr *             visit( const ast::UntypedExpr          * node ) {
302                return node;
303        }
304
305        virtual const ast::Expr *             visit( const ast::NameExpr             * node ) {
306                return node;
307        }
308
309        virtual const ast::Expr *             visit( const ast::AddressExpr          * node ) {
310                return node;
311        }
312
313        virtual const ast::Expr *             visit( const ast::LabelAddressExpr     * node ) {
314                return node;
315        }
316
317        virtual const ast::Expr *             visit( const ast::CastExpr             * node ) {
318                return node;
319        }
320
321        virtual const ast::Expr *             visit( const ast::KeywordCastExpr      * node ) {
322                return node;
323        }
324
325        virtual const ast::Expr *             visit( const ast::VirtualCastExpr      * node ) {
326                return node;
327        }
328
329        virtual const ast::Expr *             visit( const ast::UntypedMemberExpr    * node ) {
330                return node;
331        }
332
333        virtual const ast::Expr *             visit( const ast::MemberExpr           * node ) {
334                return node;
335        }
336
337        virtual const ast::Expr *             visit( const ast::VariableExpr         * node ) {
338                return node;
339        }
340
341        virtual const ast::Expr *             visit( const ast::ConstantExpr         * node ) {
342                return node;
343        }
344
345        virtual const ast::Expr *             visit( const ast::SizeofExpr           * node ) {
346                return node;
347        }
348
349        virtual const ast::Expr *             visit( const ast::AlignofExpr          * node ) {
350                return node;
351        }
352
353        virtual const ast::Expr *             visit( const ast::UntypedOffsetofExpr  * node ) {
354                return node;
355        }
356
357        virtual const ast::Expr *             visit( const ast::OffsetofExpr         * node ) {
358                return node;
359        }
360
361        virtual const ast::Expr *             visit( const ast::OffsetPackExpr       * node ) {
362                return node;
363        }
364
365        virtual const ast::Expr *             visit( const ast::LogicalExpr          * node ) {
366                return node;
367        }
368
369        virtual const ast::Expr *             visit( const ast::ConditionalExpr      * node ) {
370                return node;
371        }
372
373        virtual const ast::Expr *             visit( const ast::CommaExpr            * node ) {
374                return node;
375        }
376
377        virtual const ast::Expr *             visit( const ast::TypeExpr             * node ) {
378                return node;
379        }
380
381        virtual const ast::Expr *             visit( const ast::AsmExpr              * node ) {
382                return node;
383        }
384
385        virtual const ast::Expr *             visit( const ast::ImplicitCopyCtorExpr * node ) {
386                return node;
387        }
388
389        virtual const ast::Expr *             visit( const ast::ConstructorExpr      * node ) {
390                return node;
391        }
392
393        virtual const ast::Expr *             visit( const ast::CompoundLiteralExpr  * node ) {
394                return node;
395        }
396
397        virtual const ast::Expr *             visit( const ast::RangeExpr            * node ) {
398                return node;
399        }
400
401        virtual const ast::Expr *             visit( const ast::UntypedTupleExpr     * node ) {
402                return node;
403        }
404
405        virtual const ast::Expr *             visit( const ast::TupleExpr            * node ) {
406                return node;
407        }
408
409        virtual const ast::Expr *             visit( const ast::TupleIndexExpr       * node ) {
410                return node;
411        }
412
413        virtual const ast::Expr *             visit( const ast::TupleAssignExpr      * node ) {
414                return node;
415        }
416
417        virtual const ast::Expr *             visit( const ast::StmtExpr             * node ) {
418                return node;
419        }
420
421        virtual const ast::Expr *             visit( const ast::UniqueExpr           * node ) {
422                return node;
423        }
424
425        virtual const ast::Expr *             visit( const ast::UntypedInitExpr      * node ) {
426                return node;
427        }
428
429        virtual const ast::Expr *             visit( const ast::InitExpr             * node ) {
430                return node;
431        }
432
433        virtual const ast::Expr *             visit( const ast::DeletedExpr          * node ) {
434                return node;
435        }
436
437        virtual const ast::Expr *             visit( const ast::DefaultArgExpr       * node ) {
438                return node;
439        }
440
441        virtual const ast::Expr *             visit( const ast::GenericExpr          * node ) {
442                return node;
443        }
444
445        virtual const ast::Type *             visit( const ast::VoidType             * node ) {
446                preprint( node );
447                os << "void";
448                return node;
449        }
450
451        virtual const ast::Type *             visit( const ast::BasicType            * node ) {
452                preprint( node );
453                os << ast::BasicType::typeNames[ node->kind ];
454                return node;
455        }
456
457        virtual const ast::Type *             visit( const ast::PointerType          * node ) {
458                preprint( node );
459                if ( ! node->isArray() ) {
460                        os << "pointer to ";
461                } else {
462                        os << "decayed ";
463                        if ( node->isStatic ) {
464                                os << "static ";
465                        }
466
467                        if ( node->isVarLen ) {
468                                os << "variable length array of ";
469                        } else if ( node->dimension ) {
470                                os << "array of ";
471                                node->dimension->accept( *this );
472                                os << " ";
473                        }
474                }
475
476                if ( node->base ) {
477                        node->base->accept( *this );
478                } else {
479                        os << "UNDEFINED";
480                }
481                return node;
482        }
483
484        virtual const ast::Type *             visit( const ast::ArrayType            * node ) {
485                preprint( node );
486                if ( node->isStatic ) {
487                        os << "static ";
488                }
489
490                if ( node->isVarLen ) {
491                        os << "variable length array of ";
492                } else if ( node->dimension ) {
493                        os << "array of ";
494                } else {
495                        os << "open array of ";
496                }
497
498                if ( node->base ) {
499                        node->base->accept( *this );
500                } else {
501                        os << "UNDEFINED";
502                }
503
504                if ( node->dimension ) {
505                        os << " with dimension of ";
506                        node->dimension->accept( *this );
507                }
508
509                return node;
510        }
511
512        virtual const ast::Type *             visit( const ast::ReferenceType        * node ) {
513                preprint( node );
514
515                os << "reference to ";
516                if ( node->base ) {
517                        node->base->accept( *this );
518                } else {
519                        os << "UNDEFINED";
520                }
521
522                return node;
523        }
524
525        virtual const ast::Type *             visit( const ast::QualifiedType        * node ) {
526                preprint( node );
527
528                ++indent;
529                os << "Qualified Type:" << std::endl << indent;
530                node->parent->accept( *this );
531                os << std::endl << indent;
532                node->child->accept( *this );
533                os << std::endl;
534                --indent;
535
536                return node;
537        }
538
539        virtual const ast::Type *             visit( const ast::FunctionType         * node ) {
540                preprint( node );
541
542                os << "function" << std::endl;
543                if ( ! node->params.empty() ) {
544                        os << indent << "... with parameters" << std::endl;
545                        ++indent;
546                        printAll( node->params );
547                        if ( node->isVarArgs ) {
548                                os << indent << "and a variable number of other arguments" << std::endl;
549                        }
550                        --indent;
551                } else if ( node->isVarArgs ) {
552                        os << indent+1 << "accepting unspecified arguments" << std::endl;
553                }
554
555                os << indent << "... returning";
556                if ( node->returns.empty() ) {
557                        os << " nothing" << std::endl;
558                } else {
559                        os << std::endl;
560                        ++indent;
561                        printAll( node->returns );
562                        --indent;
563                }
564
565                return node;
566        }
567
568        virtual const ast::Type *             visit( const ast::StructInstType       * node ) {
569                preprint( node );
570
571                os << "instance of struct " << node->name;
572                if ( node->base ) {
573                        os << " " << ( node->base->body ? "with" : "without" ) << " body";
574                }
575                print( node->params );
576
577                return node;
578        }
579
580        virtual const ast::Type *             visit( const ast::UnionInstType        * node ) {
581                preprint( node );
582
583                os << "instance of union " << node->name;
584                if ( node->base ) {
585                        os << " " << ( node->base->body ? "with" : "without" ) << " body";
586                }
587                print( node->params );
588
589                return node;
590        }
591
592        virtual const ast::Type *             visit( const ast::EnumInstType         * node ) {
593                preprint( node );
594
595                os << "instance of enum " << node->name;
596                if ( node->base ) {
597                        os << " " << ( node->base->body ? "with" : "without" ) << " body";
598                }
599                print( node->params );
600
601                return node;
602        }
603
604        virtual const ast::Type *             visit( const ast::TraitInstType        * node ) {
605                preprint( node );
606
607                os << "instance of trait " << node->name;
608                print( node->params );
609
610                return node;
611        }
612
613        virtual const ast::Type *             visit( const ast::TypeInstType         * node ) {
614                preprint( node );
615
616                os << "instance of type " << node->name
617                   << " (" << (node->kind == ast::TypeVar::Ftype ? "" : "not ") << "function type)";
618                print( node->params );
619
620                return node;
621        }
622
623        virtual const ast::Type *             visit( const ast::TupleType            * node ) {
624                preprint( node );
625
626                os << "tuple of types" << std::endl;
627                ++indent;
628                printAll( node->types );
629                --indent;
630
631                return node;
632        }
633
634        virtual const ast::Type *             visit( const ast::TypeofType           * node ) {
635                preprint( node );
636
637                if ( node->kind == ast::TypeofType::Basetypeof ) { os << "base-"; }
638                os << "type-of expression ";
639                if ( node->expr ) {
640                        node->expr->accept( *this );
641                } else {
642                        os << "UNDEFINED";
643                }
644
645                return node;
646        }
647
648        virtual const ast::Type *             visit( const ast::VarArgsType          * node ) {
649                preprint( node );
650                os << "builtin var args pack";
651                return node;
652        }
653
654        virtual const ast::Type *             visit( const ast::ZeroType             * node ) {
655                preprint( node );
656                os << "zero_t";
657                return node;
658        }
659
660        virtual const ast::Type *             visit( const ast::OneType              * node ) {
661                preprint( node );
662                os << "one_t";
663                return node;
664        }
665
666        virtual const ast::Type *             visit( const ast::GlobalScopeType      * node ) {
667                preprint( node );
668                os << "Global Scope Type";
669                return node;
670        }
671
672        virtual const ast::Designation *      visit( const ast::Designation          * node ) {
673                if ( node->designators.empty() ) return node;
674                os << "... designated by: " << std::endl;
675                ++indent;
676                for ( const ast::Expr * d : node->designators ) {
677                        os << indent;
678                        d->accept( *this );
679                        os << std::endl;
680                }
681                --indent;
682                return node;
683        }
684
685        virtual const ast::Init *             visit( const ast::SingleInit           * node ) {
686                os << "Simple Initializer: ";
687                node->value->accept( *this );
688                return node;
689        }
690
691        virtual const ast::Init *             visit( const ast::ListInit             * node ) {
692                os << "Compound initializer: " << std::endl;
693                ++indent;
694                for ( auto p : group_iterate( node->designations, node->initializers ) ) {
695                        const ast::Designation * d = std::get<0>(p);
696                        const ast::Init * init = std::get<1>(p);
697                        os << indent;
698                        init->accept( *this );
699                        os << std::endl;
700                        if ( ! d->designators.empty() ) {
701                                os << indent;
702                                d->accept( *this );
703                        }
704                }
705                --indent;
706                return node;
707        }
708
709        virtual const ast::Init *             visit( const ast::ConstructorInit      * node ) {
710                os << "Constructor initializer: " << std::endl;
711                if ( node->ctor ) {
712                        os << indent << "... initially constructed with ";
713                        ++indent;
714                        node->ctor->accept( *this );
715                        --indent;
716                }
717
718                if ( node->dtor ) {
719                        os << indent << "... destructed with ";
720                        ++indent;
721                        node->dtor->accept( *this );
722                        --indent;
723                }
724
725                if ( node->init ) {
726                        os << indent << "... with fallback C-style initializer: ";
727                        ++indent;
728                        node->init->accept( *this );
729                        --indent;
730                }
731                return node;
732        }
733
734        virtual const ast::Attribute *        visit( const ast::Attribute            * node ) {
735                if ( node->empty() ) return node;
736                os << "Attribute with name: " << node->name;
737                if ( node->params.empty() ) return node;
738                os << " with parameters: " << std::endl;
739                ++indent;
740                printAll( node->params );
741                --indent;
742                return node;
743        }
744
745        virtual const ast::TypeSubstitution * visit( const ast::TypeSubstitution     * node ) {
746                os << indent << "Types:" << std::endl;
747                for ( const auto& i : *node ) {
748                        os << indent+1 << i.first << " -> ";
749                        indent += 2;
750                        i.second->accept( *this );
751                        indent -= 2;
752                        os << std::endl;
753                }
754                os << indent << "Non-types:" << std::endl;
755                for ( auto i = node->beginVar(); i != node->endVar(); ++i ) {
756                        os << indent+1 << i->first << " -> ";
757                        indent += 2;
758                        i->second->accept( *this );
759                        indent -= 2;
760                        os << std::endl;
761                }
762                return node;
763        }
764
765};
766
767void print( std::ostream & os, const ast::Node * node, Indenter indent ) {
768        Printer printer { os, indent };
769        node->accept(printer);
770}
771
772// Annoyingly these needed to be defined out of line to avoid undefined references.
773// The size here needs to be explicit but at least the compiler will produce an error
774// if the wrong size is specified
775constexpr std::array<const char*, 3> Printer::Names::FuncSpecifiers;
776constexpr std::array<const char*, 5> Printer::Names::StorageClasses;
777constexpr std::array<const char*, 6> Printer::Names::Qualifiers;
778}
Note: See TracBrowser for help on using the repository browser.