source: src/CodeTools/ResolvProtoDump.cc@ 436bbe5

ADT ast-experimental enum forall-pointer-decay pthread-emulation qualifiedEnum
Last change on this file since 436bbe5 was bc179fd3, checked in by Thierry Delisle <tdelisle@…>, 4 years ago

Removed more gcc11 warnings

  • Property mode set to 100644
File size: 22.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.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* ) { ss << (int)BasicType::SignedInt; }
307
308 void previsit( TypeInstType* vt ) {
309 // print closed variables as named types
310 if ( closed.count( vt->name ) ) { ss << '#' << vt->name; }
311 // otherwise make sure first letter is capitalized
312 else { ti_name( vt->name, ss ); }
313 }
314
315 // flattens empty and singleton tuples
316 void previsit( TupleType* tt ) {
317 ++depth;
318 buildAsTuple( *visitor, tt->types, ss );
319 --depth;
320 visit_children = false;
321 }
322
323 // TODO support variable args for functions
324 void previsit( VarArgsType* ) {
325 // only include varargs for top level (argument type)
326 if ( depth == 0 ) { ss << "#$varargs"; }
327 }
328
329 // replace 0 and 1 with int
330 // TODO support 0 and 1 with their proper type names and conversions
331 void previsit( ZeroType* ) { ss << (int)BasicType::SignedInt; }
332 void previsit( OneType* ) { ss << (int)BasicType::SignedInt; }
333
334 // only print void type if not at top level
335 void previsit( VoidType* ) {
336 if ( depth > 0 ) { ss << "#void"; }
337 }
338 };
339
340 /// builds description of function
341 void build( const std::string& name, FunctionType* fnTy, std::stringstream& ss ) {
342 PassVisitor<TypePrinter> printTy{ closed, ss };
343 // print return values
344 build( printTy, from_decls( fnTy->returnVals ), ss, terminated );
345 // print name
346 rp_name( name, ss );
347 // print parameters
348 build( printTy, from_decls( fnTy->parameters ), ss, preceded );
349 // print assertions
350 for ( TypeDecl* tyvar : fnTy->forall ) {
351 for ( DeclarationWithType* assn : tyvar->assertions ) {
352 ss << " | ";
353 build( assn->name, assn->get_type(), ss );
354 }
355 }
356 }
357
358 /// builds description of a variable (falls back to function if function type)
359 void build( const std::string& name, Type* ty, std::stringstream& ss ) {
360 // ignore top-level references
361 Type *norefs = ty->stripReferences();
362
363 // fall back to function declaration if function type
364 if ( PointerType* pTy = dynamic_cast< PointerType* >(norefs) ) {
365 if ( FunctionType* fnTy = dynamic_cast< FunctionType* >(pTy->base) ) {
366 build( name, fnTy, ss );
367 return;
368 }
369 } else if ( FunctionType* fnTy = dynamic_cast< FunctionType* >(norefs) ) {
370 build( name, fnTy, ss );
371 return;
372 }
373
374 // print variable declaration in prototype syntax
375 PassVisitor<TypePrinter> printTy{ closed, ss };
376 norefs->accept( printTy );
377 ss << " &";
378 rp_name( name, ss );
379 }
380
381 /// builds description of a field access
382 void build( const std::string& name, AggregateDecl* agg, Type* ty, std::stringstream& ss ) {
383 // ignore top-level references
384 Type *norefs = ty->stripReferences();
385
386 // print access as new field name
387 PassVisitor<TypePrinter> printTy{ closed, ss };
388 norefs->accept( printTy );
389 ss << ' ';
390 rp_name( name, ss, "$field_" );
391 ss << " #" << agg->name;
392 // handle type parameters
393 if ( ! agg->parameters.empty() ) {
394 ss << '<';
395 auto it = agg->parameters.begin();
396 while (true) {
397 ti_name( (*it)->name, ss );
398 if ( ++it == agg->parameters.end() ) break;
399 ss << ' ';
400 }
401 ss << '>';
402 }
403 }
404
405 /// Visitor for printing expressions
406 struct ExprPrinter : WithShortCircuiting, WithVisitorRef<ExprPrinter> {
407 // TODO change interface to generate multiple expression candidates
408 const std::unordered_set<std::string>& closed; ///< set of closed type vars
409 std::stringstream& ss; ///< Output to print to
410
411 ExprPrinter( const std::unordered_set<std::string>& closed, std::stringstream& ss )
412 : closed(closed), ss(ss) {}
413
414 /// Names handled as name expressions
415 void previsit( NameExpr* expr ) {
416 ss << '&';
417 rp_name( expr->name, ss );
418 }
419
420 /// Handle already-resolved variables as type constants
421 void previsit( VariableExpr* expr ) {
422 PassVisitor<TypePrinter> tyPrinter{ closed, ss };
423 expr->var->get_type()->accept( tyPrinter );
424 visit_children = false;
425 }
426
427 /// Calls handled as calls
428 void previsit( UntypedExpr* expr ) {
429 // TODO handle name extraction more generally
430 NameExpr* name = dynamic_cast<NameExpr*>(expr->function);
431
432 // fall back on just resolving call to function name
433 // TODO incorporate function type into resolv-proto
434 if ( ! name ) {
435 expr->function->accept( *visitor );
436 visit_children = false;
437 return;
438 }
439
440 rp_name( name->name, ss );
441 if ( expr->args.empty() ) {
442 ss << "()";
443 } else {
444 ss << "( ";
445 auto it = expr->args.begin();
446 while (true) {
447 (*it)->accept( *visitor );
448 if ( ++it == expr->args.end() ) break;
449 ss << ' ';
450 }
451 ss << " )";
452 }
453 visit_children = false;
454 }
455
456 /// Already-resolved calls reduced to their type constant
457 void previsit( ApplicationExpr* expr ) {
458 PassVisitor<TypePrinter> tyPrinter{ closed, ss };
459 expr->result->accept( tyPrinter );
460 visit_children = false;
461 }
462
463 /// Address-of handled as operator
464 void previsit( AddressExpr* expr ) {
465 ss << "$addr( ";
466 expr->arg->accept( *visitor );
467 ss << " )";
468 visit_children = false;
469 }
470
471 /// Casts replaced with result type
472 /// TODO put cast target functions in, and add second expression for target
473 void previsit( CastExpr* cast ) {
474 PassVisitor<TypePrinter> tyPrinter{ closed, ss };
475 cast->result->accept( tyPrinter );
476 visit_children = false;
477 }
478
479 /// Member access handled as function from aggregate to member
480 void previsit( UntypedMemberExpr* expr ) {
481 // TODO handle name extraction more generally
482 NameExpr* name = dynamic_cast<NameExpr*>(expr->member);
483
484 // fall back on just resolving call to member name
485 // TODO incorporate function type into resolv-proto
486 if ( ! name ) {
487 expr->member->accept( *visitor );
488 visit_children = false;
489 return;
490 }
491
492 rp_name( name->name, ss, "$field_" );
493 ss << "( ";
494 expr->aggregate->accept( *visitor );
495 ss << " )";
496 visit_children = false;
497 }
498
499 /// Constant expression replaced by its type
500 void previsit( ConstantExpr* expr ) {
501 PassVisitor<TypePrinter> tyPrinter{ closed, ss };
502 expr->constant.get_type()->accept( tyPrinter );
503 visit_children = false;
504 }
505
506 /// sizeof( ... ), alignof( ... ), offsetof( ... ) replaced by unsigned long constant
507 /// TODO extra expression to resolve argument
508 void previsit( SizeofExpr* ) {
509 ss << (int)BasicType::LongUnsignedInt;
510 visit_children = false;
511 }
512 void previsit( AlignofExpr* ) {
513 ss << (int)BasicType::LongUnsignedInt;
514 visit_children = false;
515 }
516 void previsit( UntypedOffsetofExpr* ) {
517 ss << (int)BasicType::LongUnsignedInt;
518 visit_children = false;
519 }
520
521 /// Logical expressions represented as operators
522 void previsit( LogicalExpr* expr ) {
523 ss << '$' << ( expr->get_isAnd() ? "and" : "or" ) << "( ";
524 expr->arg1->accept( *visitor );
525 ss << ' ';
526 expr->arg2->accept( *visitor );
527 ss << " )";
528 visit_children = false;
529 }
530
531 /// Conditional expression represented as operator
532 void previsit( ConditionalExpr* expr ) {
533 ss << "$if( ";
534 expr->arg1->accept( *visitor );
535 ss << ' ';
536 expr->arg2->accept( *visitor );
537 ss << ' ';
538 expr->arg3->accept( *visitor );
539 ss << " )";
540 visit_children = false;
541 }
542
543 /// Comma expression represented as operator
544 void previsit( CommaExpr* expr ) {
545 ss << "$seq( ";
546 expr->arg1->accept( *visitor );
547 ss << ' ';
548 expr->arg2->accept( *visitor );
549 ss << " )";
550 visit_children = false;
551 }
552
553 // TODO handle ignored ImplicitCopyCtorExpr and below
554 };
555
556 void build( Initializer* init, std::stringstream& ss ) {
557 if ( SingleInit* si = dynamic_cast<SingleInit*>(init) ) {
558 PassVisitor<ExprPrinter> exprPrinter{ closed, ss };
559 si->value->accept( exprPrinter );
560 ss << ' ';
561 } else if ( ListInit* li = dynamic_cast<ListInit*>(init) ) {
562 for ( Initializer* it : li->initializers ) {
563 build( it, ss );
564 }
565 }
566 }
567
568 /// Adds an object initializer to the list of expressions
569 void build( const std::string& name, Initializer* init, std::stringstream& ss ) {
570 ss << "$constructor( &";
571 rp_name( name, ss );
572 ss << ' ';
573 build( init, ss );
574 ss << ')';
575 }
576
577 /// Adds a return expression to the list of expressions
578 void build( Type* rtnType, Expression* expr, std::stringstream& ss ) {
579 ss << "$constructor( ";
580 PassVisitor<TypePrinter> tyPrinter{ closed, ss };
581 rtnType->accept( tyPrinter );
582 ss << ' ';
583 PassVisitor<ExprPrinter> exprPrinter{ closed, ss };
584 expr->accept( exprPrinter );
585 ss << " )";
586 }
587
588 /// Adds all named declarations in a list to the local scope
589 void addAll( const std::list<DeclarationWithType*>& decls ) {
590 for ( auto decl : decls ) {
591 // skip anonymous decls
592 if ( decl->name.empty() ) continue;
593
594 // handle objects
595 if ( ObjectDecl* obj = dynamic_cast< ObjectDecl* >( decl ) ) {
596 previsit( obj );
597 }
598 }
599 }
600
601 /// encode field access as function
602 void addAggregateFields( AggregateDecl* agg ) {
603 // make field names functions
604 for ( Declaration* member : agg->members ) {
605 if ( ObjectDecl* obj = dynamic_cast< ObjectDecl* >(member) ) {
606 std::stringstream ss;
607 build( obj->name, agg, obj->type, ss );
608 addDecl( ss.str() );
609 }
610 }
611
612 visit_children = false;
613 }
614
615 public:
616 void previsit( ObjectDecl *obj ) {
617 // add variable as declaration
618 std::stringstream ss;
619 build( obj->name, obj->type, ss );
620 addDecl( ss.str() );
621
622 // add initializer as expression if applicable
623 if ( obj->init ) {
624 std::stringstream ss;
625 build( obj->name, obj->init, ss );
626 addExpr( ss.str() );
627 }
628 }
629
630 void previsit( FunctionDecl *decl ) {
631 // skip decls with ftype parameters
632 for ( TypeDecl* tyvar : decl->type->forall ) {
633 if ( tyvar->get_kind() == TypeDecl::Ftype ) {
634 visit_children = false;
635 return;
636 }
637 }
638
639 // add function as declaration
640 std::stringstream ss;
641 build( decl->name, decl->type, ss );
642 addDecl( ss.str() );
643
644 // add body if available
645 if ( decl->statements ) {
646 std::list<Type*> rtns = from_decls( decl->type->returnVals );
647 Type* rtn = nullptr;
648 if ( rtns.size() == 1 ) {
649 if ( ! dynamic_cast<VoidType*>(rtns.front()) ) rtn = rtns.front()->clone();
650 } else if ( rtns.size() > 1 ) {
651 rtn = new TupleType{ Type::Qualifiers{}, rtns };
652 }
653 PassVisitor<ProtoDump> body{ this, rtn };
654
655 for ( TypeDecl* tyvar : decl->type->forall ) {
656 // add set of "closed" types to body so that it can print them as NamedType
657 body.pass.closed.insert( tyvar->name );
658
659 // add assertions to local scope as declarations as well
660 for ( DeclarationWithType* assn : tyvar->assertions ) {
661 assn->accept( body );
662 }
663 }
664
665 // add named parameters and returns to local scope
666 body.pass.addAll( decl->type->returnVals );
667 body.pass.addAll( decl->type->parameters );
668
669 // add contents of function to new scope
670 decl->statements->accept( body );
671
672 // store sub-scope
673 addSub( std::move(body) );
674 }
675
676 visit_children = false;
677 }
678
679 void previsit( StructDecl* sd ) { addAggregateFields(sd); }
680 void previsit( UnionDecl* ud ) { addAggregateFields(ud); }
681
682 void previsit( EnumDecl* ed ) {
683 std::unique_ptr<Type> eType =
684 std::make_unique<BasicType>( Type::Qualifiers{}, BasicType::SignedInt );
685
686 // add field names directly to enclosing scope
687 for ( Declaration* member : ed->members ) {
688 if ( ObjectDecl* obj = dynamic_cast< ObjectDecl* >(member) ) {
689 previsit(obj);
690 }
691 }
692
693 visit_children = false;
694 }
695
696 void previsit( ReturnStmt* stmt ) {
697 // do nothing for void-returning functions or statements returning nothing
698 if ( ! rtnType || ! stmt->expr ) return;
699
700 // otherwise construct the return type from the expression
701 std::stringstream ss;
702 build( rtnType.get(), stmt->expr, ss );
703 addExpr( ss.str() );
704 visit_children = false;
705 }
706
707 void previsit( AsmStmt* ) {
708 // skip asm statements
709 visit_children = false;
710 }
711
712 void previsit( Expression* expr ) {
713 std::stringstream ss;
714 PassVisitor<ExprPrinter> exPrinter{ closed, ss };
715 expr->accept( exPrinter );
716 addExpr( ss.str() );
717 visit_children = false;
718 }
719
720 /// Print non-prelude global declarations for resolv proto
721 void printGlobals() const {
722 std::cout << "#$ptr<T> $addr T" << std::endl; // &?
723 int i = (int)BasicType::SignedInt;
724 std::cout << i << " $and " << i << ' ' << i << std::endl; // ?&&?
725 std::cout << i << " $or " << i << ' ' << i << std::endl; // ?||?
726 std::cout << "T $if " << i << " T T" << std::endl; // ternary operator
727 std::cout << "T $seq X T" << std::endl; // ?,?
728 }
729
730 public:
731 /// Prints this ProtoDump instance
732 void print(unsigned indent = 0) const {
733 // print globals at root level
734 if ( ! parent ) printGlobals();
735 // print decls
736 std::string tab( indent, '\t' );
737 for ( const std::string& d : decls ) {
738 std::cout << tab << d << std::endl;
739 }
740 // print divider
741 std::cout << '\n' << tab << "%%\n" << std::endl;
742 // print top-level expressions
743 for ( const std::string& e : exprs ) {
744 std::cout << tab << e << std::endl;
745 }
746 // print child scopes
747 ++indent;
748 for ( const ProtoDump & s : subs ) {
749 std::cout << tab << '{' << std::endl;
750 s.print( indent );
751 std::cout << tab << '}' << std::endl;
752 }
753 }
754 };
755
756 void dumpAsResolvProto( std::list< Declaration * > &translationUnit ) {
757 PassVisitor<ProtoDump> dump;
758 acceptAll( translationUnit, dump );
759 dump.pass.print();
760 }
761
762} // namespace CodeTools
763
764// Local Variables: //
765// tab-width: 4 //
766// mode: c++ //
767// compile-command: "make install" //
768// End: //
Note: See TracBrowser for help on using the repository browser.