source: src/AST/Print.cpp@ 68c9165

ADT arm-eh ast-experimental cleanup-dtors enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr pthread-emulation qualifiedEnum stuck-waitfor-destruct
Last change on this file since 68c9165 was 68c9165, checked in by Aaron Moss <a3moss@…>, 7 years ago

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

  • Property mode set to 100644
File size: 21.1 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
62 static const char* Names[];
63
64 struct Names {
65 static constexpr auto FuncSpecifiers = make_array<const char*>(
66 "inline", "_Noreturn", "fortran"
67 );
68
69 static constexpr auto StorageClasses = make_array<const char*>(
70 "extern", "static", "auto", "register", "_Thread_local"
71 );
72
73 static constexpr auto Qualifiers = make_array<const char*>(
74 "const", "restrict", "volatile", "lvalue", "mutex", "_Atomic"
75 );
76 };
77
78 template<typename storage_t, size_t N>
79 void print(const storage_t & storage, const array<const char *, N> & Names ) {
80 if ( storage.any() ) {
81 for ( size_t i = 0; i < Names.size(); i += 1 ) {
82 if ( storage[i] ) {
83 os << Names[i] << ' ';
84 }
85 }
86 }
87 }
88
89 void print( const ast::Function::Specs & specs ) {
90 print(specs, Names::FuncSpecifiers);
91 }
92
93 void print( const ast::Storage::Classes & storage ) {
94 print(storage, Names::StorageClasses);
95 }
96
97 void print( const ast::CV::Qualifiers & qualifiers ) {
98 print(qualifiers, Names::Qualifiers);
99 }
100
101 void print( const ast::ParameterizedType::ForallList & forall ) {
102 if ( forall.empty() ) return;
103 os << "forall" << std::endl;
104 ++indent;
105 printAll( forall );
106 os << indent;
107 --indent;
108 }
109
110 void print( const std::vector<ptr<Attribute>> & attrs ) {
111 if ( attrs.empty() ) return;
112 os << "with attributes" << std::endl;
113 ++indent;
114 printAll( attrs );
115 --indent;
116 }
117
118 void print( const std::vector<ptr<Expr>> & params ) {
119 if ( params.empty() ) return;
120 os << std::endl << indent << "... with parameters" << std::endl;
121 ++indent;
122 printAll( params );
123 --indent;
124 }
125
126 void preprint( const ast::Type * node ) {
127 print( node->qualifiers );
128 }
129
130 void preprint( const ast::ParameterizedType * node ) {
131 print( node->forall );
132 print( node->qualifiers );
133 }
134
135 void preprint( const ast::ReferenceToType * node ) {
136 print( node->forall );
137 print( node->attributes );
138 print( node->qualifiers );
139 }
140
141 void print( const ast::AggregateDecl * node ) {
142 os << node->typeString() << " " << node->name << ":";
143 if ( node->linkage != Linkage::Cforall ) {
144 os << " " << Linkage::name( node->linkage );
145 } // if
146 os << " with body : " << (node->body ? "yes " : "no ");
147
148 if ( ! node->params.empty() ) {
149 os << endl << indent << "... with parameters" << endl;
150 ++indent;
151 printAll( node->params );
152 --indent;
153 } // if
154 if ( ! node->members.empty() ) {
155 os << endl << indent << "... with members" << endl;
156 ++indent;
157 printAll( node->members );
158 --indent;
159 } // if
160 if ( ! node->attributes.empty() ) {
161 os << endl << indent << "... with attributes" << endl;
162 ++indent;
163 printAll( node->attributes );
164 --indent;
165 } // if
166 os << endl;
167 }
168
169 void print( const ast::NamedTypeDecl * node ) {
170 if ( !node->name.empty() ) os << node->name << ": ";
171
172 if ( node->linkage != Linkage::Cforall ) {
173 os << Linkage::name( node->linkage ) << " ";
174 } // if
175 print( node->storage );
176 os << node->typeString();
177 if ( node->base ) {
178 os << " for ";
179 ++indent;
180 node->base->accept( *this );
181 --indent;
182 } // if
183 if ( ! node->params.empty() ) {
184 os << endl << indent << "... with parameters" << endl;
185 ++indent;
186 printAll( node->params );
187 --indent;
188 } // if
189 if ( ! node->assertions.empty() ) {
190 os << endl << indent << "... with assertions" << endl;
191 ++indent;
192 printAll( node->assertions );
193 --indent;
194 } // if
195 }
196
197public:
198 virtual const ast::DeclWithType * visit( const ast::ObjectDecl * node ) {
199 if ( !node->name.empty() ) os << node->name << ": ";
200
201 if ( node->linkage != Linkage::Cforall ) {
202 os << Linkage::name( node->linkage ) << " ";
203 } // if
204
205 print( node->storage );
206
207 if ( node->type ) {
208 node->type->accept( *this );
209 } else {
210 os << " untyped entity ";
211 } // if
212
213 if ( node->init ) {
214 os << " with initializer (" << (
215 node->init->maybeConstructed
216 ? "maybe constructed"
217 : "not constructed"
218 ) << ")" << endl << indent+1;
219
220 ++indent;
221 node->init->accept( *this );
222 --indent;
223 os << endl;
224 } // if
225
226 if ( ! node->attributes.empty() ) {
227 os << endl << indent << "... with attributes:" << endl;
228 ++indent;
229 printAll( node->attributes );
230 --indent;
231 }
232
233 if ( node->bitfieldWidth ) {
234 os << indent << " with bitfield width ";
235 node->bitfieldWidth->accept( *this );
236 } // if
237 return node;
238 }
239
240 virtual const ast::DeclWithType * visit( const ast::FunctionDecl * node ) {
241 if ( !node->name.empty() ) {
242 os << node->name << ": ";
243 } // if
244 if ( node->linkage != Linkage::Cforall ) {
245 os << Linkage::name( node->linkage ) << " ";
246 } // if
247
248 printAll( node->attributes );
249
250 print( node->storage );
251 print( node->funcSpec );
252
253 if ( node->type ) {
254 node->type->accept( *this );
255 } else {
256 os << "untyped entity ";
257 } // if
258
259 if ( node->stmts ) {
260 os << indent << "... with body" << endl << indent+1;
261 ++indent;
262 node->stmts->accept( *this );
263 --indent;
264 } // if
265 return node;
266 }
267
268 virtual const ast::Decl * visit( const ast::StructDecl * node ) {
269 print(node);
270 return node;
271 }
272
273 virtual const ast::Decl * visit( const ast::UnionDecl * node ) {
274 print(node);
275 return node;
276 }
277
278 virtual const ast::Decl * visit( const ast::EnumDecl * node ) {
279 print(node);
280 return node;
281 }
282
283 virtual const ast::Decl * visit( const ast::TraitDecl * node ) {
284 print(node);
285 return node;
286 }
287
288 virtual const ast::Decl * visit( const ast::TypeDecl * node ) {
289 print( node );
290 if ( node->init ) {
291 os << endl << indent << "with type initializer: ";
292 ++indent;
293 node->init->accept( *this );
294 --indent;
295 }
296 return node;
297 }
298
299 virtual const ast::Decl * visit( const ast::TypedefDecl * node ) {
300 print( node );
301 return node;
302 }
303
304 virtual const ast::AsmDecl * visit( const ast::AsmDecl * node ) {
305 node->stmt->accept( *this );
306 return node;
307 }
308
309 virtual const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl * node ) {
310 os << "Static Assert with condition: ";
311 ++indent;
312 node->cond->accept( *this );
313 --indent;
314 os << endl << indent << "and message: ";
315 ++indent;
316 node->msg->accept( *this );
317 --indent;
318 os << endl;
319 return node;
320 }
321
322 virtual const ast::CompoundStmt * visit( const ast::CompoundStmt * node ) {
323 os << "CompoundStmt" << endl;
324 ++indent;
325 printAll( node->kids );
326 --indent;
327 return node;
328 }
329
330 virtual const ast::Stmt * visit( const ast::ExprStmt * node ) {
331 ++indent;
332 os << "Expression Statement:" << endl << indent;
333 node->expr->accept( *this );
334 --indent;
335 return node;
336 }
337
338 virtual const ast::Stmt * visit( const ast::AsmStmt * node ) {
339 os << "Assembler Statement:" << endl;
340 ++indent;
341 os << indent << "instruction: " << endl << indent;
342 node->instruction->accept( *this );
343 if ( ! node->output.empty() ) {
344 os << endl << indent+1 << "output: " << endl;
345 printAll( node->output );
346 } // if
347 if ( ! node->input.empty() ) {
348 os << indent+1 << "input: " << endl;
349 printAll( node->input );
350 } // if
351 if ( ! node->clobber.empty() ) {
352 os << indent+1 << "clobber: " << endl;
353 printAll( node->clobber );
354 } // if
355 --indent;
356 return node;
357 }
358
359 virtual const ast::Stmt * visit( const ast::DirectiveStmt * node ) {
360 os << "GCC Directive:" << node->directive << endl;
361 return node;
362 }
363
364 virtual const ast::Stmt * visit( const ast::IfStmt * node ) {
365 os << "If on condition: " << endl;
366 os << indent+1;
367 ++indent;
368 node->cond->accept( *this );
369 --indent;
370
371 if ( !node->inits.empty() ) {
372 os << indent << "... with initialization: \n";
373 ++indent;
374 for ( const Stmt * stmt : node->inits ) {
375 os << indent;
376 stmt->accept( *this );
377 }
378 --indent;
379 os << endl;
380 }
381
382 os << indent << "... then: " << endl;
383
384 ++indent;
385 os << indent;
386 node->thenPart->accept( *this );
387 --indent;
388
389 if ( node->elsePart != 0 ) {
390 os << indent << "... else: " << endl;
391 ++indent;
392 os << indent;
393 node->elsePart->accept( *this );
394 --indent;
395 } // if
396 return node;
397 }
398
399 virtual const ast::Stmt * visit( const ast::WhileStmt * node ) {
400 return node;
401 }
402
403 virtual const ast::Stmt * visit( const ast::ForStmt * node ) {
404 return node;
405 }
406
407 virtual const ast::Stmt * visit( const ast::SwitchStmt * node ) {
408 return node;
409 }
410
411 virtual const ast::Stmt * visit( const ast::CaseStmt * node ) {
412 return node;
413 }
414
415 virtual const ast::Stmt * visit( const ast::BranchStmt * node ) {
416 return node;
417 }
418
419 virtual const ast::Stmt * visit( const ast::ReturnStmt * node ) {
420 return node;
421 }
422
423 virtual const ast::Stmt * visit( const ast::ThrowStmt * node ) {
424 return node;
425 }
426
427 virtual const ast::Stmt * visit( const ast::TryStmt * node ) {
428 return node;
429 }
430
431 virtual const ast::Stmt * visit( const ast::CatchStmt * node ) {
432 return node;
433 }
434
435 virtual const ast::Stmt * visit( const ast::FinallyStmt * node ) {
436 return node;
437 }
438
439 virtual const ast::Stmt * visit( const ast::WaitForStmt * node ) {
440 return node;
441 }
442
443 virtual const ast::Stmt * visit( const ast::WithStmt * node ) {
444 return node;
445 }
446
447 virtual const ast::NullStmt * visit( const ast::NullStmt * node ) {
448 return node;
449 }
450
451 virtual const ast::Stmt * visit( const ast::DeclStmt * node ) {
452 return node;
453 }
454
455 virtual const ast::Stmt * visit( const ast::ImplicitCtorDtorStmt * node ) {
456 return node;
457 }
458
459 virtual const ast::Expr * visit( const ast::ApplicationExpr * node ) {
460 return node;
461 }
462
463 virtual const ast::Expr * visit( const ast::UntypedExpr * node ) {
464 return node;
465 }
466
467 virtual const ast::Expr * visit( const ast::NameExpr * node ) {
468 return node;
469 }
470
471 virtual const ast::Expr * visit( const ast::AddressExpr * node ) {
472 return node;
473 }
474
475 virtual const ast::Expr * visit( const ast::LabelAddressExpr * node ) {
476 return node;
477 }
478
479 virtual const ast::Expr * visit( const ast::CastExpr * node ) {
480 return node;
481 }
482
483 virtual const ast::Expr * visit( const ast::KeywordCastExpr * node ) {
484 return node;
485 }
486
487 virtual const ast::Expr * visit( const ast::VirtualCastExpr * node ) {
488 return node;
489 }
490
491 virtual const ast::Expr * visit( const ast::UntypedMemberExpr * node ) {
492 return node;
493 }
494
495 virtual const ast::Expr * visit( const ast::MemberExpr * node ) {
496 return node;
497 }
498
499 virtual const ast::Expr * visit( const ast::VariableExpr * node ) {
500 return node;
501 }
502
503 virtual const ast::Expr * visit( const ast::ConstantExpr * node ) {
504 return node;
505 }
506
507 virtual const ast::Expr * visit( const ast::SizeofExpr * node ) {
508 return node;
509 }
510
511 virtual const ast::Expr * visit( const ast::AlignofExpr * node ) {
512 return node;
513 }
514
515 virtual const ast::Expr * visit( const ast::UntypedOffsetofExpr * node ) {
516 return node;
517 }
518
519 virtual const ast::Expr * visit( const ast::OffsetofExpr * node ) {
520 return node;
521 }
522
523 virtual const ast::Expr * visit( const ast::OffsetPackExpr * node ) {
524 return node;
525 }
526
527 virtual const ast::Expr * visit( const ast::LogicalExpr * node ) {
528 return node;
529 }
530
531 virtual const ast::Expr * visit( const ast::ConditionalExpr * node ) {
532 return node;
533 }
534
535 virtual const ast::Expr * visit( const ast::CommaExpr * node ) {
536 return node;
537 }
538
539 virtual const ast::Expr * visit( const ast::TypeExpr * node ) {
540 return node;
541 }
542
543 virtual const ast::Expr * visit( const ast::AsmExpr * node ) {
544 return node;
545 }
546
547 virtual const ast::Expr * visit( const ast::ImplicitCopyCtorExpr * node ) {
548 return node;
549 }
550
551 virtual const ast::Expr * visit( const ast::ConstructorExpr * node ) {
552 return node;
553 }
554
555 virtual const ast::Expr * visit( const ast::CompoundLiteralExpr * node ) {
556 return node;
557 }
558
559 virtual const ast::Expr * visit( const ast::RangeExpr * node ) {
560 return node;
561 }
562
563 virtual const ast::Expr * visit( const ast::UntypedTupleExpr * node ) {
564 return node;
565 }
566
567 virtual const ast::Expr * visit( const ast::TupleExpr * node ) {
568 return node;
569 }
570
571 virtual const ast::Expr * visit( const ast::TupleIndexExpr * node ) {
572 return node;
573 }
574
575 virtual const ast::Expr * visit( const ast::TupleAssignExpr * node ) {
576 return node;
577 }
578
579 virtual const ast::Expr * visit( const ast::StmtExpr * node ) {
580 return node;
581 }
582
583 virtual const ast::Expr * visit( const ast::UniqueExpr * node ) {
584 return node;
585 }
586
587 virtual const ast::Expr * visit( const ast::UntypedInitExpr * node ) {
588 return node;
589 }
590
591 virtual const ast::Expr * visit( const ast::InitExpr * node ) {
592 return node;
593 }
594
595 virtual const ast::Expr * visit( const ast::DeletedExpr * node ) {
596 return node;
597 }
598
599 virtual const ast::Expr * visit( const ast::DefaultArgExpr * node ) {
600 return node;
601 }
602
603 virtual const ast::Expr * visit( const ast::GenericExpr * node ) {
604 return node;
605 }
606
607 virtual const ast::Type * visit( const ast::VoidType * node ) {
608 preprint( node );
609 os << "void";
610 return node;
611 }
612
613 virtual const ast::Type * visit( const ast::BasicType * node ) {
614 preprint( node );
615 os << ast::BasicType::typeNames[ node->kind ];
616 return node;
617 }
618
619 virtual const ast::Type * visit( const ast::PointerType * node ) {
620 preprint( node );
621 if ( ! node->isArray() ) {
622 os << "pointer to ";
623 } else {
624 os << "decayed ";
625 if ( node->isStatic ) {
626 os << "static ";
627 }
628
629 if ( node->isVarLen ) {
630 os << "variable length array of ";
631 } else if ( node->dimension ) {
632 os << "array of ";
633 node->dimension->accept( *this );
634 os << " ";
635 }
636 }
637
638 if ( node->base ) {
639 node->base->accept( *this );
640 } else {
641 os << "UNDEFINED";
642 }
643 return node;
644 }
645
646 virtual const ast::Type * visit( const ast::ArrayType * node ) {
647 preprint( node );
648 if ( node->isStatic ) {
649 os << "static ";
650 }
651
652 if ( node->isVarLen ) {
653 os << "variable length array of ";
654 } else if ( node->dimension ) {
655 os << "array of ";
656 } else {
657 os << "open array of ";
658 }
659
660 if ( node->base ) {
661 node->base->accept( *this );
662 } else {
663 os << "UNDEFINED";
664 }
665
666 if ( node->dimension ) {
667 os << " with dimension of ";
668 node->dimension->accept( *this );
669 }
670
671 return node;
672 }
673
674 virtual const ast::Type * visit( const ast::ReferenceType * node ) {
675 preprint( node );
676
677 os << "reference to ";
678 if ( node->base ) {
679 node->base->accept( *this );
680 } else {
681 os << "UNDEFINED";
682 }
683
684 return node;
685 }
686
687 virtual const ast::Type * visit( const ast::QualifiedType * node ) {
688 preprint( node );
689
690 ++indent;
691 os << "Qualified Type:" << std::endl << indent;
692 node->parent->accept( *this );
693 os << std::endl << indent;
694 node->child->accept( *this );
695 os << std::endl;
696 --indent;
697
698 return node;
699 }
700
701 virtual const ast::Type * visit( const ast::FunctionType * node ) {
702 preprint( node );
703
704 os << "function" << std::endl;
705 if ( ! node->params.empty() ) {
706 os << indent << "... with parameters" << std::endl;
707 ++indent;
708 printAll( node->params );
709 if ( node->isVarArgs ) {
710 os << indent << "and a variable number of other arguments" << std::endl;
711 }
712 --indent;
713 } else if ( node->isVarArgs ) {
714 os << indent+1 << "accepting unspecified arguments" << std::endl;
715 }
716
717 os << indent << "... returning";
718 if ( node->returns.empty() ) {
719 os << " nothing" << std::endl;
720 } else {
721 os << std::endl;
722 ++indent;
723 printAll( node->returns );
724 --indent;
725 }
726
727 return node;
728 }
729
730 virtual const ast::Type * visit( const ast::StructInstType * node ) {
731 preprint( node );
732
733 os << "instance of struct " << node->name;
734 if ( node->base ) {
735 os << " " << ( node->base->body ? "with" : "without" ) << " body";
736 }
737 print( node->params );
738
739 return node;
740 }
741
742 virtual const ast::Type * visit( const ast::UnionInstType * node ) {
743 preprint( node );
744
745 os << "instance of union " << node->name;
746 if ( node->base ) {
747 os << " " << ( node->base->body ? "with" : "without" ) << " body";
748 }
749 print( node->params );
750
751 return node;
752 }
753
754 virtual const ast::Type * visit( const ast::EnumInstType * node ) {
755 preprint( node );
756
757 os << "instance of enum " << node->name;
758 if ( node->base ) {
759 os << " " << ( node->base->body ? "with" : "without" ) << " body";
760 }
761 print( node->params );
762
763 return node;
764 }
765
766 virtual const ast::Type * visit( const ast::TraitInstType * node ) {
767 preprint( node );
768
769 os << "instance of trait " << node->name;
770 print( node->params );
771
772 return node;
773 }
774
775 virtual const ast::Type * visit( const ast::TypeInstType * node ) {
776 preprint( node );
777
778 os << "instance of type " << node->name
779 << " (" << (node->kind == ast::TypeVar::Ftype ? "" : "not ") << "function type)";
780 print( node->params );
781
782 return node;
783 }
784
785 virtual const ast::Type * visit( const ast::TupleType * node ) {
786 preprint( node );
787
788 os << "tuple of types" << std::endl;
789 ++indent;
790 printAll( node->types );
791 --indent;
792
793 return node;
794 }
795
796 virtual const ast::Type * visit( const ast::TypeofType * node ) {
797 preprint( node );
798
799 if ( node->kind == ast::TypeofType::Basetypeof ) { os << "base-"; }
800 os << "type-of expression ";
801 if ( node->expr ) {
802 node->expr->accept( *this );
803 } else {
804 os << "UNDEFINED";
805 }
806
807 return node;
808 }
809
810 virtual const ast::Type * visit( const ast::VarArgsType * node ) {
811 preprint( node );
812 os << "builtin var args pack";
813 return node;
814 }
815
816 virtual const ast::Type * visit( const ast::ZeroType * node ) {
817 preprint( node );
818 os << "zero_t";
819 return node;
820 }
821
822 virtual const ast::Type * visit( const ast::OneType * node ) {
823 preprint( node );
824 os << "one_t";
825 return node;
826 }
827
828 virtual const ast::Type * visit( const ast::GlobalScopeType * node ) {
829 preprint( node );
830 os << "Global Scope Type";
831 return node;
832 }
833
834 virtual const ast::Designation * visit( const ast::Designation * node ) {
835 if ( node->designators.empty() ) return node;
836 os << "... designated by: " << std::endl;
837 ++indent;
838 for ( const ast::Expr * d : node->designators ) {
839 os << indent;
840 d->accept( *this );
841 os << std::endl;
842 }
843 --indent;
844 return node;
845 }
846
847 virtual const ast::Init * visit( const ast::SingleInit * node ) {
848 os << "Simple Initializer: ";
849 node->value->accept( *this );
850 return node;
851 }
852
853 virtual const ast::Init * visit( const ast::ListInit * node ) {
854 os << "Compound initializer: " << std::endl;
855 ++indent;
856 for ( auto p : group_iterate( node->designations, node->initializers ) ) {
857 const ast::Designation * d = std::get<0>(p);
858 const ast::Init * init = std::get<1>(p);
859 os << indent;
860 init->accept( *this );
861 os << std::endl;
862 if ( ! d->designators.empty() ) {
863 os << indent;
864 d->accept( *this );
865 }
866 }
867 --indent;
868 return node;
869 }
870
871 virtual const ast::Init * visit( const ast::ConstructorInit * node ) {
872 os << "Constructor initializer: " << std::endl;
873 if ( node->ctor ) {
874 os << indent << "... initially constructed with ";
875 ++indent;
876 node->ctor->accept( *this );
877 --indent;
878 }
879
880 if ( node->dtor ) {
881 os << indent << "... destructed with ";
882 ++indent;
883 node->dtor->accept( *this );
884 --indent;
885 }
886
887 if ( node->init ) {
888 os << indent << "... with fallback C-style initializer: ";
889 ++indent;
890 node->init->accept( *this );
891 --indent;
892 }
893 return node;
894 }
895
896 virtual const ast::Attribute * visit( const ast::Attribute * node ) {
897 if ( node->empty() ) return node;
898 os << "Attribute with name: " << node->name;
899 if ( node->params.empty() ) return node;
900 os << " with parameters: " << std::endl;
901 ++indent;
902 printAll( node->params );
903 --indent;
904 return node;
905 }
906
907 virtual const ast::TypeSubstitution * visit( const ast::TypeSubstitution * node ) {
908 os << indent << "Types:" << std::endl;
909 for ( const auto& i : *node ) {
910 os << indent+1 << i.first << " -> ";
911 indent += 2;
912 i.second->accept( *this );
913 indent -= 2;
914 os << std::endl;
915 }
916 os << indent << "Non-types:" << std::endl;
917 for ( auto i = node->beginVar(); i != node->endVar(); ++i ) {
918 os << indent+1 << i->first << " -> ";
919 indent += 2;
920 i->second->accept( *this );
921 indent -= 2;
922 os << std::endl;
923 }
924 return node;
925 }
926
927};
928
929void print( ostream & os, const ast::Node * node, Indenter indent ) {
930 Printer printer { os, indent, false };
931 node->accept(printer);
932}
933
934void printShort( ostream & os, const ast::Node * node, Indenter indent ) {
935 Printer printer { os, indent, true };
936 node->accept(printer);
937}
938
939// Annoyingly these needed to be defined out of line to avoid undefined references.
940// The size here needs to be explicit but at least the compiler will produce an error
941// if the wrong size is specified
942constexpr array<const char*, 3> Printer::Names::FuncSpecifiers;
943constexpr array<const char*, 5> Printer::Names::StorageClasses;
944constexpr array<const char*, 6> Printer::Names::Qualifiers;
945}
Note: See TracBrowser for help on using the repository browser.