source: src/CodeTools/ResolvProtoDump.cc@ 8a1d62b6

Last change on this file since 8a1d62b6 was fc134a48, checked in by JiadaL <j82liang@…>, 3 years ago

Implement the struct enum

  • Property mode set to 100644
File size: 22.6 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.cc -- Translates CFA resolver instances into resolv-proto instances
8//
9// Author : Aaron Moss
10// Created On : Tue Sep 11 09:04:00 2018
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Sat Feb 15 13:50:11 2020
13// Update Count : 3
14//
15
16#include <algorithm>
17#include <cctype>
18#include <iostream>
19#include <memory>
20#include <list>
21#include <set>
22#include <sstream>
23#include <string>
24#include <unordered_set>
25#include <utility>
26#include <vector>
27
28#include "Common/PassVisitor.h"
29#include "Common/utility.h"
30#include "CodeGen/OperatorTable.h"
31#include "SynTree/Declaration.h"
32#include "SynTree/Expression.h"
33#include "SynTree/Initializer.h"
34#include "SynTree/Statement.h"
35#include "SynTree/Type.h"
36
37namespace CodeTools {
38
39 /// Visitor for dumping resolver prototype output
40 class ProtoDump : public WithShortCircuiting, public WithVisitorRef<ProtoDump> {
41 std::set<std::string> decls; ///< Declarations in this scope
42 std::vector<std::string> exprs; ///< Expressions in this scope
43 std::vector<ProtoDump> subs; ///< Sub-scopes
44 std::unordered_set<std::string> closed; ///< Closed type variables
45 const ProtoDump* parent; ///< Outer lexical scope
46 std::unique_ptr<Type> rtnType; ///< Return type for this scope
47
48 public:
49 /// Default constructor for root ProtoDump
50 ProtoDump() : decls(), exprs(), subs(), closed(), parent(nullptr), rtnType(nullptr) {}
51
52 /// Child constructor
53 ProtoDump(const ProtoDump* p, Type* r)
54 : decls(), exprs(), subs(), closed(p->closed), parent(p), rtnType(r) {}
55
56 // Fix copy issues
57 ProtoDump(const ProtoDump& o)
58 : decls(o.decls), exprs(o.exprs), subs(o.subs), closed(o.closed), parent(o.parent),
59 rtnType(maybeClone(o.rtnType.get())) {}
60 ProtoDump( ProtoDump&& ) = default;
61
62 ProtoDump& operator= (const ProtoDump& o) {
63 if ( this == &o ) return *this;
64
65 decls = o.decls;
66 exprs = o.exprs;
67 subs = o.subs;
68 closed = o.closed;
69 parent = o.parent;
70 rtnType.reset( maybeClone(o.rtnType.get()) );
71
72 return *this;
73 }
74 ProtoDump& operator= (ProtoDump&&) = delete;
75
76 private:
77 /// checks if this declaration is contained in the scope or one of its parents
78 bool hasDecl( const std::string& s ) const {
79 if ( decls.count( s ) ) return true;
80 if ( parent ) return parent->hasDecl( s );
81 return false;
82 }
83
84 /// adds a new declaration to this scope, providing it does not already exist
85 void addDecl( const std::string& s ) {
86 if ( ! hasDecl( s ) ) decls.insert( s );
87 }
88
89 /// adds a new expression to this scope
90 void addExpr( const std::string& s ) {
91 if ( ! s.empty() ) { exprs.emplace_back( s ); }
92 }
93
94 /// adds a new subscope to this scope, returning a reference
95 void addSub( PassVisitor<ProtoDump>&& sub ) {
96 subs.emplace_back( std::move(sub.pass) );
97 }
98
99 /// Whether lists should be separated, terminated, or preceded by their separator
100 enum septype { separated, terminated, preceded };
101
102 /// builds space-separated list of types
103 template<typename V>
104 static void build( V& visitor, const std::list< Type* >& tys, std::stringstream& ss,
105 septype mode = separated ) {
106 if ( tys.empty() ) return;
107
108 if ( mode == preceded ) { ss << ' '; }
109
110 auto it = tys.begin();
111 (*it)->accept( visitor );
112
113 while ( ++it != tys.end() ) {
114 ss << ' ';
115 (*it)->accept( visitor );
116 }
117
118 if ( mode == terminated ) { ss << ' '; }
119 }
120
121 /// builds list of types wrapped as tuple type
122 template<typename V>
123 static void buildAsTuple( V& visitor, const std::list< Type* >& tys,
124 std::stringstream& ss ) {
125 switch ( tys.size() ) {
126 case 0: ss << "#void"; break;
127 case 1: tys.front()->accept( visitor ); break;
128 default:
129 ss << "#$" << tys.size() << '<';
130 build( visitor, tys, ss );
131 ss << '>';
132 break;
133 }
134 }
135
136 /// gets types from DWT list
137 static std::list< Type* > from_decls( const std::list< DeclarationWithType* >& decls ) {
138 std::list< Type* > tys;
139 for ( auto decl : decls ) { tys.emplace_back( decl->get_type() ); }
140 return tys;
141 }
142
143 /// gets types from TypeExpr list
144 static std::list< Type* > from_exprs( const std::list< Expression* >& exprs ) {
145 std::list< Type* > tys;
146 for ( auto expr : exprs ) {
147 if ( TypeExpr* tyExpr = dynamic_cast<TypeExpr*>(expr) ) {
148 tys.emplace_back( tyExpr->type );
149 }
150 }
151 return tys;
152 }
153
154 /// builds prefixes for rp_name
155 static std::string new_prefix( const std::string& old, const char* added ) {
156 if ( old.empty() ) return std::string{"$"} + added;
157 return old + added;
158 }
159
160 /// shortens operator names
161 static void op_name( const std::string& name, std::stringstream& ss ) {
162 if ( name.compare( 0, 10, "_operator_" ) == 0 ) {
163 ss << name.substr(10);
164 } else if ( name.compare( "_constructor" ) == 0
165 || name.compare( "_destructor" ) == 0 ) {
166 ss << name.substr(1);
167 } else if ( name.compare( 0, 11, "__operator_" ) == 0 ) {
168 ss << name.substr(11);
169 } else {
170 ss << name;
171 }
172 }
173
174 /// replaces operators with resolv-proto names
175 static void rp_name( const std::string& name, std::stringstream& ss,
176 std::string&& pre = "" ) {
177 // safety check for anonymous names
178 if ( name.empty() ) {
179 ss << new_prefix(pre, "anon");
180 return;
181 }
182
183 // replace operator names
184 const CodeGen::OperatorInfo * opInfo = CodeGen::operatorLookup( name );
185 if ( opInfo ) {
186 ss << new_prefix(pre, "");
187 op_name( opInfo->outputName, ss );
188 return;
189 }
190
191 // replace retval names
192 if ( name.compare( 0, 8, "_retval_" ) == 0 ) {
193 ss << new_prefix(pre, "rtn_");
194 op_name( name.substr(8), ss );
195 return;
196 }
197
198 // default to just name, with first character in lowercase
199 ss << pre
200 << (char)std::tolower( static_cast<unsigned char>(name[0]) )
201 << (name.c_str() + 1);
202 }
203
204 /// ensures type inst names are uppercase
205 static void ti_name( const std::string& name, std::stringstream& ss ) {
206 // replace built-in wide character types with named types
207 if ( name == "char16_t" || name == "char32_t" || name == "wchar_t" ) {
208 ss << "#" << name;
209 return;
210 }
211
212 // strip leading underscore
213 unsigned i = 0;
214 while ( i < name.size() && name[i] == '_' ) { ++i; }
215 if ( i == name.size() ) {
216 ss << "Anon";
217 return;
218 }
219
220 std::string stripped = name.substr(i);
221 // strip trailing "_generic_" from autogen names (avoids some user-generation issues)
222 char generic[] = "_generic_"; size_t n_generic = sizeof(generic) - 1;
223 if ( stripped.size() >= n_generic
224 && stripped.substr( stripped.size() - n_generic ) == generic ) {
225 stripped.resize( stripped.size() - n_generic );
226 }
227
228 // uppercase first character
229 ss << (char)std::toupper( static_cast<unsigned char>(stripped[0]) )
230 << (stripped.c_str() + 1);
231 }
232
233 /// Visitor for printing types
234 struct TypePrinter : public WithShortCircuiting, WithVisitorRef<TypePrinter>, WithGuards {
235 std::stringstream& ss; ///< Output to print to
236 const std::unordered_set<std::string>& closed; ///< Closed type variables
237 unsigned depth; ///< Depth of nesting from root type
238
239 TypePrinter( const std::unordered_set<std::string>& closed, std::stringstream& ss )
240 : ss(ss), closed(closed), depth(0) {}
241
242 // basic type represented as integer type
243 // TODO maybe hard-code conversion graph and make named type
244 void previsit( BasicType* bt ) { ss << (int)bt->get_kind(); }
245
246 // pointers (except function pointers) represented as generic type
247 void previsit( PointerType* pt ) {
248 if ( ! dynamic_cast<FunctionType*>(pt->base) ) { ss << "#$ptr<"; ++depth; }
249 }
250 void postvisit( PointerType* pt ) {
251 if ( ! dynamic_cast<FunctionType*>(pt->base) ) { --depth; ss << '>'; }
252 }
253
254 // arrays represented as generic pointers
255 void previsit( ArrayType* at ) {
256 ss << "#$ptr<";
257 ++depth;
258 at->base->accept( *visitor );
259 --depth;
260 ss << '>';
261 visit_children = false;
262 }
263
264 // ignore top-level reference types, they're mostly transparent to resolution
265 void previsit( ReferenceType* ) {
266 if ( depth > 0 ) { ss << "#$ref<"; }
267 ++depth;
268 }
269 void postvisit( ReferenceType* ) {
270 --depth;
271 if ( depth > 0 ) { ss << '>'; }
272 }
273
274 // print function types using prototype syntax
275 void previsit( FunctionType* ft ) {
276 ss << '[';
277 ++depth;
278 build( *visitor, from_decls( ft->returnVals ), ss, preceded );
279 ss << " : ";
280 build( *visitor, from_decls( ft->parameters ), ss, terminated );
281 --depth;
282 ss << ']';
283 visit_children = false;
284 }
285
286 private:
287 // prints aggregate type name as NamedType with optional paramters
288 void handleAggregate( ReferenceToType* at ) {
289 ss << '#' << at->name;
290 if ( ! at->parameters.empty() ) {
291 ss << '<';
292 ++depth;
293 build( *visitor, from_exprs( at->parameters ), ss );
294 --depth;
295 ss << '>';
296 }
297 visit_children = false;
298 }
299
300 public:
301 // handle aggregate types using NamedType
302 void previsit( StructInstType* st ) { handleAggregate( st ); }
303 void previsit( UnionInstType* ut ) { handleAggregate( ut ); }
304
305 // replace enums with int
306 void previsit( EnumInstType* ) {
307 // TODO: add the meaningful representation of typed int
308 ss << (int)BasicType::SignedInt;
309 }
310
311 void previsit( TypeInstType* vt ) {
312 // print closed variables as named types
313 if ( closed.count( vt->name ) ) { ss << '#' << vt->name; }
314 // otherwise make sure first letter is capitalized
315 else { ti_name( vt->name, ss ); }
316 }
317
318 // flattens empty and singleton tuples
319 void previsit( TupleType* tt ) {
320 ++depth;
321 buildAsTuple( *visitor, tt->types, ss );
322 --depth;
323 visit_children = false;
324 }
325
326 // TODO support variable args for functions
327 void previsit( VarArgsType* ) {
328 // only include varargs for top level (argument type)
329 if ( depth == 0 ) { ss << "#$varargs"; }
330 }
331
332 // replace 0 and 1 with int
333 // TODO support 0 and 1 with their proper type names and conversions
334 void previsit( ZeroType* ) { ss << (int)BasicType::SignedInt; }
335 void previsit( OneType* ) { ss << (int)BasicType::SignedInt; }
336
337 // only print void type if not at top level
338 void previsit( VoidType* ) {
339 if ( depth > 0 ) { ss << "#void"; }
340 }
341 };
342
343 /// builds description of function
344 void build( const std::string& name, FunctionType* fnTy, std::stringstream& ss ) {
345 PassVisitor<TypePrinter> printTy{ closed, ss };
346 // print return values
347 build( printTy, from_decls( fnTy->returnVals ), ss, terminated );
348 // print name
349 rp_name( name, ss );
350 // print parameters
351 build( printTy, from_decls( fnTy->parameters ), ss, preceded );
352 // print assertions
353 for ( TypeDecl* tyvar : fnTy->forall ) {
354 for ( DeclarationWithType* assn : tyvar->assertions ) {
355 ss << " | ";
356 build( assn->name, assn->get_type(), ss );
357 }
358 }
359 }
360
361 /// builds description of a variable (falls back to function if function type)
362 void build( const std::string& name, Type* ty, std::stringstream& ss ) {
363 // ignore top-level references
364 Type *norefs = ty->stripReferences();
365
366 // fall back to function declaration if function type
367 if ( PointerType* pTy = dynamic_cast< PointerType* >(norefs) ) {
368 if ( FunctionType* fnTy = dynamic_cast< FunctionType* >(pTy->base) ) {
369 build( name, fnTy, ss );
370 return;
371 }
372 } else if ( FunctionType* fnTy = dynamic_cast< FunctionType* >(norefs) ) {
373 build( name, fnTy, ss );
374 return;
375 }
376
377 // print variable declaration in prototype syntax
378 PassVisitor<TypePrinter> printTy{ closed, ss };
379 norefs->accept( printTy );
380 ss << " &";
381 rp_name( name, ss );
382 }
383
384 /// builds description of a field access
385 void build( const std::string& name, AggregateDecl* agg, Type* ty, std::stringstream& ss ) {
386 // ignore top-level references
387 Type *norefs = ty->stripReferences();
388
389 // print access as new field name
390 PassVisitor<TypePrinter> printTy{ closed, ss };
391 norefs->accept( printTy );
392 ss << ' ';
393 rp_name( name, ss, "$field_" );
394 ss << " #" << agg->name;
395 // handle type parameters
396 if ( ! agg->parameters.empty() ) {
397 ss << '<';
398 auto it = agg->parameters.begin();
399 while (true) {
400 ti_name( (*it)->name, ss );
401 if ( ++it == agg->parameters.end() ) break;
402 ss << ' ';
403 }
404 ss << '>';
405 }
406 }
407
408 /// Visitor for printing expressions
409 struct ExprPrinter : WithShortCircuiting, WithVisitorRef<ExprPrinter> {
410 // TODO change interface to generate multiple expression candidates
411 const std::unordered_set<std::string>& closed; ///< set of closed type vars
412 std::stringstream& ss; ///< Output to print to
413
414 ExprPrinter( const std::unordered_set<std::string>& closed, std::stringstream& ss )
415 : closed(closed), ss(ss) {}
416
417 /// Names handled as name expressions
418 void previsit( NameExpr* expr ) {
419 ss << '&';
420 rp_name( expr->name, ss );
421 }
422
423 /// Handle already-resolved variables as type constants
424 void previsit( VariableExpr* expr ) {
425 PassVisitor<TypePrinter> tyPrinter{ closed, ss };
426 expr->var->get_type()->accept( tyPrinter );
427 visit_children = false;
428 }
429
430 /// Calls handled as calls
431 void previsit( UntypedExpr* expr ) {
432 // TODO handle name extraction more generally
433 NameExpr* name = dynamic_cast<NameExpr*>(expr->function);
434
435 // fall back on just resolving call to function name
436 // TODO incorporate function type into resolv-proto
437 if ( ! name ) {
438 expr->function->accept( *visitor );
439 visit_children = false;
440 return;
441 }
442
443 rp_name( name->name, ss );
444 if ( expr->args.empty() ) {
445 ss << "()";
446 } else {
447 ss << "( ";
448 auto it = expr->args.begin();
449 while (true) {
450 (*it)->accept( *visitor );
451 if ( ++it == expr->args.end() ) break;
452 ss << ' ';
453 }
454 ss << " )";
455 }
456 visit_children = false;
457 }
458
459 /// Already-resolved calls reduced to their type constant
460 void previsit( ApplicationExpr* expr ) {
461 PassVisitor<TypePrinter> tyPrinter{ closed, ss };
462 expr->result->accept( tyPrinter );
463 visit_children = false;
464 }
465
466 /// Address-of handled as operator
467 void previsit( AddressExpr* expr ) {
468 ss << "$addr( ";
469 expr->arg->accept( *visitor );
470 ss << " )";
471 visit_children = false;
472 }
473
474 /// Casts replaced with result type
475 /// TODO put cast target functions in, and add second expression for target
476 void previsit( CastExpr* cast ) {
477 PassVisitor<TypePrinter> tyPrinter{ closed, ss };
478 cast->result->accept( tyPrinter );
479 visit_children = false;
480 }
481
482 /// Member access handled as function from aggregate to member
483 void previsit( UntypedMemberExpr* expr ) {
484 // TODO handle name extraction more generally
485 NameExpr* name = dynamic_cast<NameExpr*>(expr->member);
486
487 // fall back on just resolving call to member name
488 // TODO incorporate function type into resolv-proto
489 if ( ! name ) {
490 expr->member->accept( *visitor );
491 visit_children = false;
492 return;
493 }
494
495 rp_name( name->name, ss, "$field_" );
496 ss << "( ";
497 expr->aggregate->accept( *visitor );
498 ss << " )";
499 visit_children = false;
500 }
501
502 /// Constant expression replaced by its type
503 void previsit( ConstantExpr* expr ) {
504 PassVisitor<TypePrinter> tyPrinter{ closed, ss };
505 expr->constant.get_type()->accept( tyPrinter );
506 visit_children = false;
507 }
508
509 /// sizeof( ... ), alignof( ... ), offsetof( ... ) replaced by unsigned long constant
510 /// TODO extra expression to resolve argument
511 void previsit( SizeofExpr* ) {
512 ss << (int)BasicType::LongUnsignedInt;
513 visit_children = false;
514 }
515 void previsit( AlignofExpr* ) {
516 ss << (int)BasicType::LongUnsignedInt;
517 visit_children = false;
518 }
519 void previsit( UntypedOffsetofExpr* ) {
520 ss << (int)BasicType::LongUnsignedInt;
521 visit_children = false;
522 }
523
524 /// Logical expressions represented as operators
525 void previsit( LogicalExpr* expr ) {
526 ss << '$' << ( expr->get_isAnd() ? "and" : "or" ) << "( ";
527 expr->arg1->accept( *visitor );
528 ss << ' ';
529 expr->arg2->accept( *visitor );
530 ss << " )";
531 visit_children = false;
532 }
533
534 /// Conditional expression represented as operator
535 void previsit( ConditionalExpr* expr ) {
536 ss << "$if( ";
537 expr->arg1->accept( *visitor );
538 ss << ' ';
539 expr->arg2->accept( *visitor );
540 ss << ' ';
541 expr->arg3->accept( *visitor );
542 ss << " )";
543 visit_children = false;
544 }
545
546 /// Comma expression represented as operator
547 void previsit( CommaExpr* expr ) {
548 ss << "$seq( ";
549 expr->arg1->accept( *visitor );
550 ss << ' ';
551 expr->arg2->accept( *visitor );
552 ss << " )";
553 visit_children = false;
554 }
555
556 // TODO handle ignored ImplicitCopyCtorExpr and below
557 };
558
559 void build( Initializer* init, std::stringstream& ss ) {
560 if ( SingleInit* si = dynamic_cast<SingleInit*>(init) ) {
561 PassVisitor<ExprPrinter> exprPrinter{ closed, ss };
562 si->value->accept( exprPrinter );
563 ss << ' ';
564 } else if ( ListInit* li = dynamic_cast<ListInit*>(init) ) {
565 for ( Initializer* it : li->initializers ) {
566 build( it, ss );
567 }
568 }
569 }
570
571 /// Adds an object initializer to the list of expressions
572 void build( const std::string& name, Initializer* init, std::stringstream& ss ) {
573 ss << "$constructor( &";
574 rp_name( name, ss );
575 ss << ' ';
576 build( init, ss );
577 ss << ')';
578 }
579
580 /// Adds a return expression to the list of expressions
581 void build( Type* rtnType, Expression* expr, std::stringstream& ss ) {
582 ss << "$constructor( ";
583 PassVisitor<TypePrinter> tyPrinter{ closed, ss };
584 rtnType->accept( tyPrinter );
585 ss << ' ';
586 PassVisitor<ExprPrinter> exprPrinter{ closed, ss };
587 expr->accept( exprPrinter );
588 ss << " )";
589 }
590
591 /// Adds all named declarations in a list to the local scope
592 void addAll( const std::list<DeclarationWithType*>& decls ) {
593 for ( auto decl : decls ) {
594 // skip anonymous decls
595 if ( decl->name.empty() ) continue;
596
597 // handle objects
598 if ( ObjectDecl* obj = dynamic_cast< ObjectDecl* >( decl ) ) {
599 previsit( obj );
600 }
601 }
602 }
603
604 /// encode field access as function
605 void addAggregateFields( AggregateDecl* agg ) {
606 // make field names functions
607 for ( Declaration* member : agg->members ) {
608 if ( ObjectDecl* obj = dynamic_cast< ObjectDecl* >(member) ) {
609 std::stringstream ss;
610 build( obj->name, agg, obj->type, ss );
611 addDecl( ss.str() );
612 }
613 }
614
615 visit_children = false;
616 }
617
618 public:
619 void previsit( ObjectDecl *obj ) {
620 // add variable as declaration
621 std::stringstream ss;
622 build( obj->name, obj->type, ss );
623 addDecl( ss.str() );
624
625 // add initializer as expression if applicable
626 if ( obj->init ) {
627 std::stringstream ss;
628 build( obj->name, obj->init, ss );
629 addExpr( ss.str() );
630 }
631 }
632
633 void previsit( FunctionDecl *decl ) {
634 // skip decls with ftype parameters
635 for ( TypeDecl* tyvar : decl->type->forall ) {
636 if ( tyvar->get_kind() == TypeDecl::Ftype ) {
637 visit_children = false;
638 return;
639 }
640 }
641
642 // add function as declaration
643 std::stringstream ss;
644 build( decl->name, decl->type, ss );
645 addDecl( ss.str() );
646
647 // add body if available
648 if ( decl->statements ) {
649 std::list<Type*> rtns = from_decls( decl->type->returnVals );
650 Type* rtn = nullptr;
651 if ( rtns.size() == 1 ) {
652 if ( ! dynamic_cast<VoidType*>(rtns.front()) ) rtn = rtns.front()->clone();
653 } else if ( rtns.size() > 1 ) {
654 rtn = new TupleType{ Type::Qualifiers{}, rtns };
655 }
656 PassVisitor<ProtoDump> body{ this, rtn };
657
658 for ( TypeDecl* tyvar : decl->type->forall ) {
659 // add set of "closed" types to body so that it can print them as NamedType
660 body.pass.closed.insert( tyvar->name );
661
662 // add assertions to local scope as declarations as well
663 for ( DeclarationWithType* assn : tyvar->assertions ) {
664 assn->accept( body );
665 }
666 }
667
668 // add named parameters and returns to local scope
669 body.pass.addAll( decl->type->returnVals );
670 body.pass.addAll( decl->type->parameters );
671
672 // add contents of function to new scope
673 decl->statements->accept( body );
674
675 // store sub-scope
676 addSub( std::move(body) );
677 }
678
679 visit_children = false;
680 }
681
682 void previsit( StructDecl* sd ) { addAggregateFields(sd); }
683 void previsit( UnionDecl* ud ) { addAggregateFields(ud); }
684
685 void previsit( EnumDecl* ed ) {
686 std::unique_ptr<Type> eType =
687 std::make_unique<BasicType>( Type::Qualifiers{}, BasicType::SignedInt );
688
689 // add field names directly to enclosing scope
690 for ( Declaration* member : ed->members ) {
691 if ( ObjectDecl* obj = dynamic_cast< ObjectDecl* >(member) ) {
692 previsit(obj);
693 }
694 }
695
696 visit_children = false;
697 }
698
699 void previsit( ReturnStmt* stmt ) {
700 // do nothing for void-returning functions or statements returning nothing
701 if ( ! rtnType || ! stmt->expr ) return;
702
703 // otherwise construct the return type from the expression
704 std::stringstream ss;
705 build( rtnType.get(), stmt->expr, ss );
706 addExpr( ss.str() );
707 visit_children = false;
708 }
709
710 void previsit( AsmStmt* ) {
711 // skip asm statements
712 visit_children = false;
713 }
714
715 void previsit( Expression* expr ) {
716 std::stringstream ss;
717 PassVisitor<ExprPrinter> exPrinter{ closed, ss };
718 expr->accept( exPrinter );
719 addExpr( ss.str() );
720 visit_children = false;
721 }
722
723 /// Print non-prelude global declarations for resolv proto
724 void printGlobals() const {
725 std::cout << "#$ptr<T> $addr T" << std::endl; // &?
726 int i = (int)BasicType::SignedInt;
727 std::cout << i << " $and " << i << ' ' << i << std::endl; // ?&&?
728 std::cout << i << " $or " << i << ' ' << i << std::endl; // ?||?
729 std::cout << "T $if " << i << " T T" << std::endl; // ternary operator
730 std::cout << "T $seq X T" << std::endl; // ?,?
731 }
732
733 public:
734 /// Prints this ProtoDump instance
735 void print(unsigned indent = 0) const {
736 // print globals at root level
737 if ( ! parent ) printGlobals();
738 // print decls
739 std::string tab( indent, '\t' );
740 for ( const std::string& d : decls ) {
741 std::cout << tab << d << std::endl;
742 }
743 // print divider
744 std::cout << '\n' << tab << "%%\n" << std::endl;
745 // print top-level expressions
746 for ( const std::string& e : exprs ) {
747 std::cout << tab << e << std::endl;
748 }
749 // print child scopes
750 ++indent;
751 for ( const ProtoDump & s : subs ) {
752 std::cout << tab << '{' << std::endl;
753 s.print( indent );
754 std::cout << tab << '}' << std::endl;
755 }
756 }
757 };
758
759 void dumpAsResolvProto( std::list< Declaration * > &translationUnit ) {
760 PassVisitor<ProtoDump> dump;
761 acceptAll( translationUnit, dump );
762 dump.pass.print();
763 }
764
765} // namespace CodeTools
766
767// Local Variables: //
768// tab-width: 4 //
769// mode: c++ //
770// compile-command: "make install" //
771// End: //
Note: See TracBrowser for help on using the repository browser.