source: src/Common/ResolvProtoDump.cpp@ 436bbe5

ADT ast-experimental enum forall-pointer-decay pthread-emulation qualifiedEnum
Last change on this file since 436bbe5 was 55cbff8, checked in by Andrew Beach <ajbeach@…>, 4 years ago

Added new ast resolver prototype support. Not exactly the same but some of those changes might be fixes.

  • Property mode set to 100644
File size: 21.5 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// ResolvProtoDump.cpp -- Prints AST as instances for resolv-proto.
8//
9// Author : Andrew Beach
10// Created On : Wed Oct 6 14:10:00 2021
11// Last Modified By : Andrew Beach
12// Last Modified On : Tue Oct 18 11:23:00 2021
13// Update Count : 0
14//
15
16#include "ResolvProtoDump.hpp"
17
18#include <cctype>
19#include <iostream>
20#include <set>
21#include <unordered_set>
22
23#include "AST/Copy.hpp"
24#include "AST/Pass.hpp"
25#include "AST/TranslationUnit.hpp"
26#include "AST/Type.hpp"
27#include "CodeGen/OperatorTable.h"
28#include "Common/utility.h"
29
30namespace {
31
32/// Add a prefix to an existing name.
33std::string add_prefix( const std::string & prefix, const char * added ) {
34 if ( prefix.empty() ) {
35 return std::string("$") + added;
36 } else {
37 return prefix + added;
38 }
39}
40
41/// Shortens operator names.
42std::string op_name( const std::string & name ) {
43 if ( name.compare( 0, 10, "_operator_" ) == 0 ) {
44 return name.substr( 10 );
45 } else if ( name.compare( "_constructor" ) == 0
46 || name.compare( "_destructor" ) == 0 ) {
47 return name.substr( 1 );
48 } else if ( name.compare( 0, 11, "__operator_" ) == 0 ) {
49 return name.substr( 11 );
50 } else {
51 return name;
52 }
53}
54
55/// Get the resolv-proto names for operators.
56std::string rp_name( const std::string & name, std::string && pre = "" ) {
57 // Check for anonymous names.
58 if ( name.empty() ) {
59 return add_prefix( pre, "anon" );
60 }
61
62 // Replace operator names.
63 const CodeGen::OperatorInfo * opInfo = CodeGen::operatorLookup( name );
64 if ( nullptr != opInfo ) {
65 return add_prefix( pre, "" ) + op_name( opInfo->outputName );
66 }
67
68 // Replace return value prefix.
69 if ( name.compare( 0, 8, "_retval_" ) == 0 ) {
70 return add_prefix( pre, "rtn_" ) + op_name( name.substr( 8 ) );
71 }
72
73 // Default to just name, with first character in lowercase.
74 if ( std::isupper( name[0] ) ) {
75 std::string copy = name;
76 copy[0] = std::tolower( copy[0] );
77 return pre + copy;
78 }
79 return pre + name;
80}
81
82/// Normalise a type instance name.
83std::string ti_name( const std::string & name ) {
84 // Replace built-in names
85 if ( name == "char16_t" || name == "char32_t" || name == "wchar_t" ) {
86 return std::string("#") + name;
87 }
88
89 // Strip leadng underscores.
90 unsigned i = 0;
91 while ( i < name.size() && name[i] == '_' ) { ++i; }
92 if ( i == name.size() ) {
93 return "Anon";
94 }
95
96 std::string stripped = name.substr( i );
97 // Strip trailing generic from autogen names ()
98 static char generic[] = "_generic_";
99 static size_t n_generic = sizeof(generic) - 1;
100 if ( stripped.size() >= n_generic
101 && stripped.substr( stripped.size() - n_generic ) == generic ) {
102 stripped.resize( stripped.size() - n_generic );
103 }
104
105 // Uppercase first character.
106 stripped[0] = std::toupper( stripped[0] );
107 return stripped;
108}
109
110std::vector<ast::ptr<ast::Type>> to_types(
111 const std::vector<ast::ptr<ast::Expr>> & data ) {
112 std::vector<ast::ptr<ast::Type>> ret_val;
113 ret_val.reserve( data.size() );
114 for ( auto entry : data ) {
115 if ( auto * typeExpr = entry.as<ast::TypeExpr>() ) {
116 ret_val.emplace_back( typeExpr->type );
117 }
118 }
119 return ret_val;
120}
121
122enum class septype { separated, terminated, preceded };
123
124template<typename V>
125void build(
126 V & visitor,
127 const std::vector<ast::ptr<ast::Type>> & types,
128 std::stringstream & ss,
129 septype mode );
130
131template<typename V>
132void buildAsTuple(
133 V & visitor, const std::vector<ast::ptr<ast::Type>> & types,
134 std::stringstream & ss );
135
136struct TypePrinter : public ast::WithShortCircuiting, ast::WithVisitorRef<TypePrinter> {
137 /// Accumulator for the printed type.
138 std::stringstream ss;
139 /// Closed type variables.
140 const std::unordered_set<std::string> & closed;
141 /// Depth of nesting from root type.
142 unsigned depth;
143
144 TypePrinter( const std::unordered_set<std::string> & closed ) :
145 ss(), closed(closed), depth(0)
146 {}
147
148 std::string result() const {
149 return ss.str();
150 }
151
152 // Basic type represented as an integer type.
153 // TODO: Maybe hard-code conversion graph and make named type.
154 void previsit( const ast::BasicType * type ) {
155 ss << (int)type->kind;
156 }
157
158 // Pointers (except function pointers) are represented as generic type.
159 void previsit( const ast::PointerType * type ) {
160 if ( nullptr == type->base.as<ast::FunctionType>() ) {
161 ss << "#$ptr<";
162 ++depth;
163 }
164 }
165 void postvisit( const ast::PointerType * type ) {
166 if ( nullptr == type->base.as<ast::FunctionType>() ) {
167 --depth;
168 ss << '>';
169 }
170 }
171
172 // Arrays repersented as pointers.
173 void previsit( const ast::ArrayType * type ) {
174 ss << "#$ptr<";
175 ++depth;
176 type->base->accept( *visitor );
177 --depth;
178 ss << '>';
179 visit_children = false;
180 }
181
182 // Ignore top-level references as they are mostly transparent to resolution.
183 void previsit( const ast::ReferenceType * ) {
184 if ( !atTopLevel() ) { ss << "#$ref<"; }
185 ++depth;
186 }
187 void postvisit( const ast::ReferenceType * ) {
188 --depth;
189 if ( !atTopLevel() ) { ss << '>'; }
190 }
191
192 void previsit( const ast::FunctionType * type ) {
193 ss << '[';
194 ++depth;
195 build( *visitor, type->returns, ss, septype::preceded );
196 ss << " : ";
197 build( *visitor, type->params, ss, septype::terminated );
198 --depth;
199 ss << ']';
200 visit_children = false;
201 }
202
203private:
204 bool atTopLevel() const {
205 return 0 == depth;
206 }
207
208 void handleAggregate( const ast::BaseInstType * type ) {
209 ss << '#' << type->name;
210 if ( !type->params.empty() ) {
211 ss << '<';
212 ++depth;
213 build( *visitor, to_types( type->params ), ss, septype::separated );
214 --depth;
215 ss << '>';
216 }
217 visit_children = false;
218 }
219public:
220
221 void previsit( const ast::StructInstType * type ) {
222 handleAggregate( type );
223 }
224
225 void previsit( const ast::UnionInstType * type ) {
226 handleAggregate( type );
227 }
228
229 void previsit( const ast::EnumInstType * ) {
230 ss << (int)ast::BasicType::SignedInt;
231 }
232
233 void previsit( const ast::TypeInstType * type ) {
234 // Print closed variables as named types.
235 if ( closed.count( type->name ) ) {
236 ss << '#' << type->name;
237 // Otherwise normalize the name.
238 } else {
239 ss << ti_name( type->name );
240 }
241 }
242
243 void previsit( const ast::TupleType * tupleType ) {
244 ++depth;
245 buildAsTuple( *visitor, tupleType->types, ss );
246 --depth;
247 visit_children = false;
248 }
249
250 void previsit( const ast::VarArgsType * ) {
251 if ( atTopLevel() ) ss << "#$varargs";
252 }
253
254 // TODO: Support 0 and 1 with their type names and conversions.
255 void previsit( const ast::ZeroType * ) {
256 ss << (int)ast::BasicType::SignedInt;
257 }
258
259 void previsit( const ast::OneType * ) {
260 ss << (int)ast::BasicType::SignedInt;
261 }
262
263 void previsit( const ast::VoidType * ) {
264 if ( !atTopLevel() ) {
265 ss << "#void";
266 }
267 }
268};
269
270struct ExprPrinter : public ast::WithShortCircuiting, ast::WithVisitorRef<ExprPrinter> {
271 // TODO: Change interface to generate multiple expression canditates.
272 /// Accumulator of the printed expression.
273 std::stringstream ss;
274 /// Set of closed type variables.
275 const std::unordered_set<std::string> & closed;
276
277 ExprPrinter( const std::unordered_set<std::string> & closed ) :
278 ss(), closed( closed )
279 {}
280
281 std::string result() const {
282 return ss.str();
283 }
284
285 void previsit( const ast::NameExpr * expr ) {
286 ss << '&' << rp_name( expr->name );
287 }
288
289 /// Handle already resolved variables as type constants.
290 void previsit( const ast::VariableExpr * expr ) {
291 ss << ast::Pass<TypePrinter>::read( expr->var->get_type(), closed );
292 visit_children = false;
293 }
294
295 void previsit( const ast::UntypedExpr * expr ) {
296 // TODO: Handle name extraction more generally.
297 const ast::NameExpr * name = expr->func.as<ast::NameExpr>();
298
299 // TODO: Incorporate function type into resolv-proto.
300 if ( !name ) {
301 expr->func->accept( *visitor );
302 visit_children = false;
303 return;
304 }
305
306 ss << rp_name( name->name );
307 if ( expr->args.empty() ) {
308 ss << "()";
309 } else {
310 ss << "( ";
311 auto it = expr->args.begin();
312 while (true) {
313 (*it)->accept( *visitor );
314 if ( ++it == expr->args.end() ) break;
315 ss << ' ';
316 }
317 ss << " )";
318 }
319 visit_children = false;
320 }
321
322 void previsit( const ast::ApplicationExpr * expr ) {
323 ss << ast::Pass<TypePrinter>::read( static_cast<const ast::Expr *>( expr ), closed );
324 visit_children = false;
325 }
326
327 void previsit( const ast::AddressExpr * expr ) {
328 ss << "$addr( ";
329 expr->arg->accept( *visitor );
330 ss << " )";
331 visit_children = false;
332 }
333
334 void previsit( const ast::CastExpr * expr ) {
335 ss << ast::Pass<TypePrinter>::read( expr->result.get(), closed );
336 visit_children = false;
337 }
338
339 /// Member access handled as function from aggregate to member.
340 void previsit( const ast::UntypedMemberExpr * expr ) {
341 // TODO: Handle name extraction more generally.
342 const ast::NameExpr * name = expr->member.as<ast::NameExpr>();
343
344 // TODO: Incorporate function type into resolve-proto.
345 if ( !name ) {
346 expr->member->accept( *visitor );
347 visit_children = false;
348 return;
349 }
350
351 ss << rp_name( name->name, "$field_" );
352 ss << "( ";
353 expr->aggregate->accept( *visitor );
354 ss << " )";
355 visit_children = false;
356 }
357
358 /// Constant expression replaced by its type.
359 void previsit( const ast::ConstantExpr * expr ) {
360 ss << ast::Pass<TypePrinter>::read( static_cast<const ast::Expr *>( expr ), closed );
361 visit_children = false;
362 }
363
364 /// sizeof, alignof, & offsetof are replaced by constant type.
365 // TODO: Extra expression to resolve argument.
366 void previsit( const ast::SizeofExpr * ) {
367 ss << (int)ast::BasicType::LongUnsignedInt;
368 visit_children = false;
369 }
370 void previsit( const ast::AlignofExpr * ) {
371 ss << (int)ast::BasicType::LongUnsignedInt;
372 visit_children = false;
373 }
374 void previsit( const ast::UntypedOffsetofExpr * ) {
375 ss << (int)ast::BasicType::LongUnsignedInt;
376 visit_children = false;
377 }
378
379 /// Logical expressions represented as operators.
380 void previsit( const ast::LogicalExpr * expr ) {
381 ss << ( (ast::AndExpr == expr->isAnd) ? "$and( " : "$or( " );
382 expr->arg1->accept( *visitor );
383 ss << ' ';
384 expr->arg2->accept( *visitor );
385 ss << " )";
386 visit_children = false;
387 }
388
389 /// Conditional expression represented as an operator.
390 void previsit( const ast::ConditionalExpr * expr ) {
391 ss << "$if( ";
392 expr->arg1->accept( *visitor );
393 ss << ' ';
394 expr->arg2->accept( *visitor );
395 ss << ' ';
396 expr->arg3->accept( *visitor );
397 ss << " )";
398 visit_children = false;
399 }
400
401 /// Comma expression represented as on operator.
402 void previsit( const ast::CommaExpr * expr ) {
403 ss << "$seq( ";
404 expr->arg1->accept( *visitor );
405 ss << ' ';
406 expr->arg2->accept( *visitor );
407 ss << " )";
408 visit_children = false;
409 }
410
411 // TODO: Handle ignored ImplicitCopyCtorExpr and below.
412};
413
414template<typename V>
415void build(
416 V & visitor,
417 const std::vector<ast::ptr<ast::Type>> & types,
418 std::stringstream & ss,
419 septype mode ) {
420 if ( types.empty() ) return;
421
422 if ( septype::preceded == mode ) { ss << ' '; }
423
424 auto it = types.begin();
425 (*it)->accept( visitor );
426
427 while ( ++it != types.end() ) {
428 ss << ' ';
429 (*it)->accept( visitor );
430 }
431
432 if ( septype::terminated == mode ) { ss << ' '; }
433}
434
435std::string buildType(
436 const std::string & name, const ast::Type * type,
437 const std::unordered_set<std::string> & closed );
438
439/// Build a string representing a function type.
440std::string buildFunctionType(
441 const std::string & name, const ast::FunctionType * type,
442 const std::unordered_set<std::string> & closed ) {
443 ast::Pass<TypePrinter> printer( closed );
444 std::stringstream & ss = printer.core.ss;
445
446 build( printer, type->returns, ss, septype::terminated );
447 ss << rp_name( name );
448 build( printer, type->params, ss, septype::preceded );
449 for ( const auto & assertion : type->assertions ) {
450 auto var = assertion->var;
451 ss << " | " << buildType( var->name, var->get_type(), closed );
452 }
453 return ss.str();
454}
455
456/// Build a description of a type.
457std::string buildType(
458 const std::string & name, const ast::Type * type,
459 const std::unordered_set<std::string> & closed ) {
460 const ast::Type * norefs = type->stripReferences();
461
462 if ( const auto & ptrType = dynamic_cast<const ast::PointerType *>( norefs ) ) {
463 if ( const auto & funcType = ptrType->base.as<ast::FunctionType>() ) {
464 return buildFunctionType( name, funcType, closed );
465 }
466 } else if ( const auto & funcType = dynamic_cast<const ast::FunctionType *>( norefs ) ) {
467 return buildFunctionType( name, funcType, closed );
468 }
469
470 std::stringstream ss;
471 ss << ast::Pass<TypePrinter>::read( norefs, closed );
472 ss << " &" << rp_name( name );
473 return ss.str();
474}
475
476/// Builds description of a field access.
477std::string buildAggregateDecl( const std::string & name,
478 const ast::AggregateDecl * agg, const ast::Type * type,
479 const std::unordered_set<std::string> & closed ) {
480 const ast::Type * norefs = type->stripReferences();
481 std::stringstream ss;
482
483 ss << ast::Pass<TypePrinter>::read( norefs, closed ) << ' ';
484 ss << rp_name( name, "$field_" );
485 ss << " #" << agg->name;
486 if ( !agg->params.empty() ) {
487 ss << '<';
488 auto it = agg->params.begin();
489 while (true) {
490 ss << ti_name( (*it)->name );
491 if ( ++it == agg->params.end() ) break;
492 ss << ' ';
493 }
494 ss << '>';
495 }
496 return ss.str();
497}
498
499template<typename V>
500void buildAsTuple(
501 V & visitor, const std::vector<ast::ptr<ast::Type>> & types,
502 std::stringstream & ss ) {
503 switch ( types.size() ) {
504 case 0:
505 ss << "#void";
506 break;
507 case 1:
508 types.front()->accept( visitor );
509 break;
510 default:
511 ss << "#$" << types.size() << '<';
512 build( visitor, types, ss, septype::separated );
513 ss << '>';
514 break;
515 }
516}
517
518/// Adds a return
519std::string buildReturn(
520 const ast::Type * returnType,
521 const ast::Expr * expr,
522 const std::unordered_set<std::string> & closed ) {
523 std::stringstream ss;
524 ss << "$constructor( ";
525 ss << ast::Pass<TypePrinter>::read( returnType, closed );
526 ss << ' ';
527 ss << ast::Pass<ExprPrinter>::read( expr, closed );
528 ss << " )";
529 return ss.str();
530}
531
532void buildInitComponent(
533 std::stringstream & out, const ast::Init * init,
534 const std::unordered_set<std::string> & closed ) {
535 if ( const auto * s = dynamic_cast<const ast::SingleInit *>( init ) ) {
536 out << ast::Pass<ExprPrinter>::read( s->value.get(), closed ) << ' ';
537 } else if ( const auto * l = dynamic_cast<const ast::ListInit *>( init ) ) {
538 for ( const auto & it : l->initializers ) {
539 buildInitComponent( out, it, closed );
540 }
541 }
542}
543
544/// Build a representation of an initializer.
545std::string buildInitializer(
546 const std::string & name, const ast::Init * init,
547 const std::unordered_set<std::string> & closed ) {
548 std::stringstream ss;
549 ss << "$constructor( &";
550 ss << rp_name( name );
551 ss << ' ';
552 buildInitComponent( ss, init, closed );
553 ss << ')';
554 return ss.str();
555}
556
557/// Visitor for collecting and printing resolver prototype output.
558class ProtoDump : public ast::WithShortCircuiting, ast::WithVisitorRef<ProtoDump> {
559 /// Declarations in this scope.
560 // Set is used for ordering of printing.
561 std::set<std::string> decls;
562 /// Expressions in this scope.
563 std::vector<std::string> exprs;
564 /// Sub-scopes
565 std::vector<ProtoDump> subs;
566 /// Closed type variables
567 std::unordered_set<std::string> closed;
568 /// Outer lexical scope
569 const ProtoDump * parent;
570 /// Return type for this scope
571 ast::ptr<ast::Type> returnType;
572
573 /// Is the declaration in this scope or a parent scope?
574 bool hasDecl( const std::string & decl ) const {
575 return decls.count( decl ) || (parent && parent->hasDecl( decl ));
576 }
577
578 /// Adds a declaration to this scope if it is new.
579 void addDecl( const std::string & decl ) {
580 if ( !hasDecl( decl ) ) decls.insert( decl );
581 }
582
583 /// Adds a new expression to this scope.
584 void addExpr( const std::string & expr ) {
585 if ( !expr.empty() ) exprs.emplace_back( expr );
586 }
587
588 /// Adds a new scope as a child scope.
589 void addSub( ast::Pass<ProtoDump> && pass ) {
590 subs.emplace_back( std::move( pass.core ) );
591 }
592
593 /// Adds all named declaration in a list to the local scope.
594 void addAll( const std::vector<ast::ptr<ast::DeclWithType>> & decls ) {
595 for ( auto decl : decls ) {
596 // Skip anonymous decls.
597 if ( decl->name.empty() ) continue;
598
599 if ( const auto & obj = decl.as<ast::ObjectDecl>() ) {
600 previsit( obj );
601 }
602 }
603 }
604
605public:
606 ProtoDump() :
607 parent( nullptr ), returnType( nullptr )
608 {}
609
610 ProtoDump( const ProtoDump * parent, const ast::Type * returnType ) :
611 closed( parent->closed ), parent( parent ), returnType( returnType )
612 {}
613
614 ProtoDump( const ProtoDump & other ) :
615 decls( other.decls ), exprs( other.exprs ), subs( other.subs ),
616 closed( other.closed ), parent( other.parent ),
617 returnType( other.returnType )
618 {}
619
620 ProtoDump( ProtoDump && ) = default;
621
622 ProtoDump & operator=( const ProtoDump & ) = delete;
623 ProtoDump & operator=( ProtoDump && ) = delete;
624
625 void previsit( const ast::ObjectDecl * decl ) {
626 // Add variable as declaration.
627 addDecl( buildType( decl->name, decl->type, closed ) );
628
629 // Add initializer as expression if applicable.
630 if ( decl->init ) {
631 addExpr( buildInitializer( decl->name, decl->init, closed ) );
632 }
633 }
634
635 void previsit( const ast::FunctionDecl * decl ) {
636 visit_children = false;
637
638 // Skips declarations with ftype parameters.
639 for ( const auto & typeDecl : decl->type->forall ) {
640 if ( ast::TypeDecl::Ftype == typeDecl->kind ) {
641 return;
642 }
643 }
644
645 // Add function as declaration.
646 // NOTE: I'm not sure why the assertions are only present on the
647 // declaration and not the function type. Is that an error?
648 ast::FunctionType * new_type = ast::shallowCopy( decl->type.get() );
649 for ( const ast::ptr<ast::DeclWithType> & assertion : decl->assertions ) {
650 new_type->assertions.push_back(
651 new ast::VariableExpr( assertion->location , assertion )
652 );
653 }
654 addDecl( buildFunctionType( decl->name, new_type, closed ) );
655 delete new_type;
656
657 // Add information body if available.
658 if ( !decl->stmts ) return;
659 const std::vector<ast::ptr<ast::Type>> & returns =
660 decl->type->returns;
661
662 // Add the return statement.
663 ast::ptr<ast::Type> retType = nullptr;
664 if ( 1 == returns.size() ) {
665 if ( !returns.front().as<ast::VoidType>() ) {
666 retType = returns.front();
667 }
668 } else if ( 1 < returns.size() ) {
669 retType = new ast::TupleType( copy( returns ) );
670 }
671 ast::Pass<ProtoDump> body( this, retType.get() );
672
673 // Handle the forall clause (type parameters and assertions).
674 for ( const ast::ptr<ast::TypeDecl> & typeDecl : decl->type_params ) {
675 // Add set of "closed" types to body so that it can print them as NamedType.
676 body.core.closed.insert( typeDecl->name );
677
678 // Add assertions to local scope as declarations as well.
679 for ( const ast::DeclWithType * assertion : typeDecl->assertions ) {
680 assertion->accept( body );
681 }
682 }
683
684 // NOTE: Related to the last NOTE; this is where the assertions are now.
685 for ( const ast::ptr<ast::DeclWithType> & assertion : decl->assertions ) {
686 assertion->accept( body );
687 }
688
689 // Add named parameters and returns to local scope.
690 body.core.addAll( decl->returns );
691 body.core.addAll( decl->params );
692
693 // Add contents of the function to a new scope.
694 decl->stmts->accept( body );
695
696 // Store sub-scope
697 addSub( std::move( body ) );
698 }
699
700private:
701 void addAggregateFields( const ast::AggregateDecl * agg ) {
702 for ( const auto & member : agg->members ) {
703 if ( const ast::ObjectDecl * obj = member.as<ast::ObjectDecl>() ) {
704 addDecl( buildAggregateDecl( obj->name, agg, obj->type, closed ) );
705 }
706 }
707 visit_children = false;
708 }
709
710public:
711
712 void previsit( const ast::StructDecl * decl ) {
713 addAggregateFields( decl );
714 }
715
716 void previsit( const ast::UnionDecl * decl ) {
717 addAggregateFields( decl );
718 }
719
720 void previsit( const ast::EnumDecl * decl ) {
721 for ( const auto & member : decl->members ) {
722 if ( const auto * obj = member.as<ast::ObjectDecl>() ) {
723 previsit( obj );
724 }
725 }
726
727 visit_children = false;
728 }
729
730 void previsit( const ast::ReturnStmt * stmt ) {
731 // Do nothing for void-returning functions or statements returning nothing.
732 if ( !returnType || !stmt->expr ) return;
733
734 // Otherwise constuct the return type from the expression.
735 addExpr( buildReturn( returnType.get(), stmt->expr, closed ) );
736 visit_children = false;
737 }
738
739 void previsit( const ast::AsmStmt * ) {
740 // Skip asm statements.
741 visit_children = false;
742 }
743
744 void previsit( const ast::Expr * expr ) {
745 addExpr( ast::Pass<ExprPrinter>::read( expr, closed ) );
746 visit_children = false;
747 }
748
749private:
750 /// Print the pesudo-declarations not in any scope.
751 void printGlobal( std::ostream & out ) const {
752 // &? Address of operator.
753 out << "#$ptr<T> $addr T" << std::endl;
754 const int intId = (int)ast::BasicType::SignedInt;
755 // ?&&? ?||? ?: Logical operators.
756 out << intId << " $and " << intId << ' ' << intId << std::endl;
757 out << intId << " $or " << intId << ' ' << intId << std::endl;
758 out << "T $if " << intId << " T T" << std::endl;
759 // ?,? Sequencing.
760 out << "T $seq X T" << std::endl;
761 }
762
763 /// Print everything in this scope and its child scopes.
764 void printLocal( std::ostream & out, unsigned indent ) const {
765 const std::string tab( indent, '\t' );
766
767 // Print Declarations:
768 for ( const std::string & decl : decls ) {
769 out << tab << decl << std::endl;
770 }
771
772 // Print Divider:
773 out << '\n' << tab << "%%\n" << std::endl;
774
775 // Print Top-Level Expressions:
776 for ( const std::string & expr : exprs ) {
777 out << tab << expr << std::endl;
778 }
779
780 // Print Children Scopes:
781 ++indent;
782 for ( const ProtoDump & sub : subs ) {
783 out << tab << '{' << std::endl;
784 sub.printLocal( out, indent );
785 out << tab << '}' << std::endl;
786 }
787 }
788public:
789 /// Start printing, the collected information.
790 void print( std::ostream & out ) const {
791 printGlobal( out );
792 printLocal( out, 0 );
793 }
794};
795
796} // namespace
797
798void dumpAsResolverProto( ast::TranslationUnit & transUnit ) {
799 ast::Pass<ProtoDump> dump;
800 accept_all( transUnit, dump );
801 dump.core.print( std::cout );
802}
803
804// Local Variables: //
805// tab-width: 4 //
806// mode: c++ //
807// compile-command: "make install" //
808// End: //
Note: See TracBrowser for help on using the repository browser.