source: src/CodeTools/ResolvProtoDump.cc @ 4c42a5f

aaron-thesisarm-ehcleanup-dtorsdeferred_resnjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprno_listpersistent-indexer
Last change on this file since 4c42a5f was 4c42a5f, checked in by Aaron Moss <a3moss@…>, 3 years ago

Add function pointer types and variable decls and expressions to RPDump

  • Property mode set to 100644
File size: 21.4 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 : Aaron Moss
12// Last Modified On : Tue Sep 11 09:04:00 2018
13// Update Count     : 1
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&&) = default;
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                        CodeGen::OperatorInfo info;
185                        if ( CodeGen::operatorLookup( name, info ) ) {
186                                ss << new_prefix(pre, "");
187                                op_name( info.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                        unsigned i = 0;
207                        while ( i < name.size() && name[i] == '_' ) { ++i; }
208                        if ( i == name.size() ) {
209                                ss << "Anon";
210                                return;
211                        }
212                        ss << (char)std::toupper( static_cast<unsigned char>(name[i]) )
213                           << (name.c_str() + i + 1);
214                }
215
216                /// Visitor for printing types
217                struct TypePrinter : public WithShortCircuiting, WithVisitorRef<TypePrinter>, WithGuards {
218                        std::stringstream& ss;                          ///< Output to print to
219                        const std::unordered_set<std::string>& closed;  ///< Closed type variables
220                        unsigned depth;                                 ///< Depth of nesting from root type
221
222                        TypePrinter( const std::unordered_set<std::string>& closed, std::stringstream& ss ) 
223                                : ss(ss), closed(closed), depth(0) {}
224
225                        // basic type represented as integer type
226                        // TODO maybe hard-code conversion graph and make named type
227                        void previsit( BasicType* bt ) { ss << (int)bt->get_kind(); }
228
229                        // pointers (except function pointers) represented as generic type
230                        void previsit( PointerType* pt ) {
231                                if ( ! dynamic_cast<FunctionType*>(pt->base) ) { ss << "#$ptr<"; ++depth; }
232                        }
233                        void postvisit( PointerType* pt ) {
234                                if ( ! dynamic_cast<FunctionType*>(pt->base) ) { --depth; ss << '>'; }
235                        }
236
237                        // arrays represented as generic pointers
238                        void previsit( ArrayType* at ) {
239                                ss << "#$ptr<";
240                                ++depth;
241                                at->base->accept( *visitor );
242                                --depth;
243                                ss << '>';
244                                visit_children = false;
245                        }
246
247                        // ignore top-level reference types, they're mostly transparent to resolution
248                        void previsit( ReferenceType* ) {
249                                if ( depth > 0 ) { ss << "#$ref<"; }
250                                ++depth;
251                        }
252                        void postvisit( ReferenceType* ) {
253                                --depth;
254                                if ( depth > 0 ) { ss << '>'; }
255                        }
256
257                        // print function types using prototype syntax
258                        void previsit( FunctionType* ft ) {
259                                ss << '[';
260                                ++depth;
261                                build( *visitor, from_decls( ft->returnVals ), ss, preceded );
262                                ss << " : ";
263                                build( *visitor, from_decls( ft->parameters ), ss, terminated );
264                                --depth;
265                                ss << ']';
266                                visit_children = false;
267                        }
268
269                private:
270                        // prints aggregate type name as NamedType with optional paramters
271                        void handleAggregate( ReferenceToType* at ) {
272                                ss << '#' << at->name;
273                                if ( ! at->parameters.empty() ) {
274                                        ss << '<';
275                                        ++depth;
276                                        build( *visitor, from_exprs( at->parameters ), ss );
277                                        --depth;
278                                        ss << '>';
279                                }
280                                visit_children = false;
281                        }
282
283                public:
284                        // handle aggregate types using NamedType
285                        void previsit( StructInstType* st ) { handleAggregate( st ); }
286                        void previsit( UnionInstType* ut ) { handleAggregate( ut ); }
287
288                        // replace enums with int
289                        void previsit( EnumInstType* ) { ss << (int)BasicType::SignedInt; }
290
291                        void previsit( TypeInstType* vt ) {
292                                // print closed variables as named types
293                                if ( closed.count( vt->name ) ) { ss << '#' << vt->name; }
294                                // otherwise make sure first letter is capitalized
295                                else { ti_name( vt->name, ss ); }
296                        }
297
298                        // flattens empty and singleton tuples
299                        void previsit( TupleType* tt ) {
300                                ++depth;
301                                buildAsTuple( *visitor, tt->types, ss );
302                                --depth;
303                                visit_children = false;
304                        }
305
306                        // TODO support VarArgsType
307
308                        // replace 0 and 1 with int
309                        // TODO support 0 and 1 with their proper type names and conversions
310                        void previsit( ZeroType* ) { ss << (int)BasicType::SignedInt; }
311                        void previsit( OneType* ) { ss << (int)BasicType::SignedInt; }
312
313                        // only print void type if not at top level
314                        void previsit( VoidType* ) {
315                                if ( depth > 0 ) { ss << "#void"; }
316                        }
317                };
318       
319                /// builds description of function
320                void build( const std::string& name, FunctionType* fnTy, std::stringstream& ss ) {
321                        PassVisitor<TypePrinter> printTy{ closed, ss };
322                        // print return values
323                        build( printTy, from_decls( fnTy->returnVals ), ss, terminated );
324                        // print name
325                        rp_name( name, ss );
326                        // print parameters
327                        build( printTy, from_decls( fnTy->parameters ), ss, preceded );
328                        // print assertions
329                        for ( TypeDecl* tyvar : fnTy->forall ) {
330                                for ( DeclarationWithType* assn : tyvar->assertions ) {
331                                        ss << " | "; 
332                                        build( assn->name, assn->get_type(), ss );
333                                }
334                        }
335                }
336
337                /// builds description of a variable (falls back to function if function type)
338                void build( const std::string& name, Type* ty, std::stringstream& ss ) {
339                        // ignore top-level references
340                        Type *norefs = ty->stripReferences();
341                       
342                        // fall back to function declaration if function type
343                        if ( PointerType* pTy = dynamic_cast< PointerType* >(norefs) ) {
344                                if ( FunctionType* fnTy = dynamic_cast< FunctionType* >(pTy->base) ) {
345                                        build( name, fnTy, ss );
346                                        return;
347                                }
348                        } else if ( FunctionType* fnTy = dynamic_cast< FunctionType* >(norefs) ) {
349                                build( name, fnTy, ss );
350                                return;
351                        }
352
353                        // print variable declaration in prototype syntax
354                        PassVisitor<TypePrinter> printTy{ closed, ss };
355                        norefs->accept( printTy );
356                        ss << " &";
357                        rp_name( name, ss );
358                }
359
360                /// builds description of a field access
361                void build( const std::string& name, AggregateDecl* agg, Type* ty, std::stringstream& ss ) {
362                        // ignore top-level references
363                        Type *norefs = ty->stripReferences();
364
365                        // print access as new field name
366                        PassVisitor<TypePrinter> printTy{ closed, ss };
367                        norefs->accept( printTy );
368                        ss << ' ';
369                        rp_name( name, ss, "$field_" );
370                        ss << " #" << agg->name;
371                        // handle type parameters
372                        if ( ! agg->parameters.empty() ) {
373                                ss << '<';
374                                auto it = agg->parameters.begin();
375                                while (true) {
376                                        ti_name( (*it)->name, ss );
377                                        if ( ++it == agg->parameters.end() ) break;
378                                        ss << ' ';
379                                }
380                                ss << '>';
381                        }
382                }
383
384                /// Visitor for printing expressions
385                struct ExprPrinter : WithShortCircuiting, WithVisitorRef<ExprPrinter> {
386                        // TODO change interface to generate multiple expression candidates
387                        const std::unordered_set<std::string>& closed;  ///< set of closed type vars
388                        std::stringstream& ss;                          ///< Output to print to
389
390                        ExprPrinter( const std::unordered_set<std::string>& closed, std::stringstream& ss ) 
391                                : closed(closed), ss(ss) {}
392
393                        /// Names handled as name expressions
394                        void previsit( NameExpr* expr ) {
395                                ss << '&';
396                                rp_name( expr->name, ss );
397                        }
398
399                        /// Calls handled as calls
400                        void previsit( UntypedExpr* expr ) {
401                                // TODO handle name extraction more generally
402                                NameExpr* name = dynamic_cast<NameExpr*>(expr->function);
403
404                                // fall back on just resolving call to function name
405                                // TODO incorporate function type into resolv-proto
406                                if ( ! name ) {
407                                        expr->function->accept( *visitor );
408                                        visit_children = false;
409                                        return;
410                                }
411
412                                rp_name( name->name, ss );
413                                if ( expr->args.empty() ) {
414                                        ss << "()";
415                                } else {
416                                        ss << "( ";
417                                        auto it = expr->args.begin();
418                                        while (true) {
419                                                (*it)->accept( *visitor );
420                                                if ( ++it == expr->args.end() ) break;
421                                                ss << ' ';
422                                        }
423                                        ss << " )";
424                                }
425                                visit_children = false;
426                        }
427
428                        /// Already-resolved calls skipped
429                        void previsit( ApplicationExpr* ) {
430                                visit_children = false;
431                        }
432
433                        /// Address-of handled as operator
434                        void previsit( AddressExpr* expr ) {
435                                ss << "$addr( ";
436                                expr->arg->accept( *visitor );
437                                ss << " )";
438                                visit_children = false;
439                        }
440
441                        /// Casts replaced with result type
442                        /// TODO put cast target functions in, and add second expression for target
443                        void previsit( CastExpr* cast ) {
444                                PassVisitor<TypePrinter> tyPrinter{ closed, ss };
445                                cast->result->accept( tyPrinter );
446                                visit_children = false;
447                        }
448                       
449                        /// Member access handled as function from aggregate to member
450                        void previsit( UntypedMemberExpr* expr ) {
451                                // TODO handle name extraction more generally
452                                NameExpr* name = dynamic_cast<NameExpr*>(expr->member);
453
454                                // fall back on just resolving call to member name
455                                // TODO incorporate function type into resolv-proto
456                                if ( ! name ) {
457                                        expr->member->accept( *visitor );
458                                        visit_children = false;
459                                        return;
460                                }
461
462                                rp_name( name->name, ss, "$field_" );
463                                ss << "( ";
464                                expr->aggregate->accept( *visitor );
465                                ss << " )";
466                                visit_children = false;
467                        }
468
469                        /// Constant expression replaced by its type
470                        void previsit( ConstantExpr* expr ) {
471                                PassVisitor<TypePrinter> tyPrinter{ closed, ss };
472                                expr->constant.get_type()->accept( tyPrinter );
473                                visit_children = false;
474                        }
475
476                        /// sizeof( ... ), alignof( ... ), offsetof( ... ) replaced by unsigned long constant
477                        /// TODO extra expression to resolve argument
478                        void previsit( SizeofExpr* ) {
479                                ss << (int)BasicType::LongUnsignedInt;
480                                visit_children = false;
481                        }
482                        void previsit( AlignofExpr* ) {
483                                ss << (int)BasicType::LongUnsignedInt;
484                                visit_children = false;
485                        }
486                        void previsit( UntypedOffsetofExpr* ) {
487                                ss << (int)BasicType::LongUnsignedInt;
488                                visit_children = false;
489                        }
490
491                        /// Logical expressions represented as operators
492                        void previsit( LogicalExpr* expr ) {
493                                ss << '$' << ( expr->get_isAnd() ? "and" : "or" ) << "( ";
494                                expr->arg1->accept( *visitor );
495                                ss << ' ';
496                                expr->arg2->accept( *visitor );
497                                ss << " )";
498                                visit_children = false;
499                        }
500
501                        /// Conditional expression represented as operator
502                        void previsit( ConditionalExpr* expr ) {
503                                ss << "$if( ";
504                                expr->arg1->accept( *visitor );
505                                ss << ' ';
506                                expr->arg2->accept( *visitor );
507                                ss << ' ';
508                                expr->arg3->accept( *visitor );
509                                ss << " )";
510                                visit_children = false;
511                        }
512
513                        /// Comma expression represented as operator
514                        void previsit( CommaExpr* expr ) {
515                                ss << "$seq( ";
516                                expr->arg1->accept( *visitor );
517                                ss << ' ';
518                                expr->arg2->accept( *visitor );
519                                ss << " )";
520                                visit_children = false;
521                        }
522
523                        // TODO handle ignored ImplicitCopyCtorExpr and below
524                };
525
526                void build( Initializer* init, std::stringstream& ss ) {
527                        if ( SingleInit* si = dynamic_cast<SingleInit*>(init) ) {
528                                PassVisitor<ExprPrinter> exprPrinter{ closed, ss };
529                                si->value->accept( exprPrinter );
530                                ss << ' ';
531                        } else if ( ListInit* li = dynamic_cast<ListInit*>(init) ) {
532                                for ( Initializer* it : li->initializers ) {
533                                        build( it, ss );
534                                        ss << ' ';
535                                }
536                        }
537                }
538
539                /// Adds an object initializer to the list of expressions
540                void build( const std::string& name, Initializer* init, std::stringstream& ss ) {
541                        ss << "$constructor( ";
542                        rp_name( name, ss );
543                        ss << "() ";
544                        build( init, ss );
545                        ss << ')';
546                }
547
548                /// Adds a return expression to the list of expressions
549                void build( Type* rtnType, Expression* expr, std::stringstream& ss ) {
550                        ss << "$constructor( ";
551                        PassVisitor<TypePrinter> tyPrinter{ closed, ss };
552                        rtnType->accept( tyPrinter );
553                        ss << ' ';
554                        PassVisitor<ExprPrinter> exprPrinter{ closed, ss };
555                        expr->accept( exprPrinter );
556                        ss << " )";
557                }
558
559                /// Adds all named declarations in a list to the local scope
560                void addAll( const std::list<DeclarationWithType*>& decls ) {
561                        for ( auto decl : decls ) {
562                                // skip anonymous decls
563                                if ( decl->name.empty() ) continue;
564
565                                // handle objects
566                                if ( ObjectDecl* obj = dynamic_cast< ObjectDecl* >( decl ) ) {
567                                        previsit( obj );
568                                }
569                        }
570                }
571
572                /// encode field access as function
573                void addAggregateFields( AggregateDecl* agg ) {
574                        // make field names functions
575                        for ( Declaration* member : agg->members ) {
576                                if ( ObjectDecl* obj = dynamic_cast< ObjectDecl* >(member) ) {
577                                        std::stringstream ss;
578                                        build( obj->name, agg, obj->type, ss );
579                                        addDecl( ss.str() );
580                                }
581                        }
582
583                        visit_children = false;
584                }
585
586        public:
587                void previsit( ObjectDecl *obj ) {
588                        // add variable as declaration
589                        std::stringstream ss;
590                        build( obj->name, obj->type, ss );
591                        addDecl( ss.str() );
592
593                        // add initializer as expression if applicable
594                        if ( obj->init ) {
595                                std::stringstream ss;
596                                build( obj->name, obj->init, ss );
597                                addExpr( ss.str() );
598                        }
599                }
600
601                void previsit( FunctionDecl *decl ) {
602                        // skip decls with ftype parameters
603                        for ( TypeDecl* tyvar : decl->type->forall ) {
604                                if ( tyvar->get_kind() == TypeDecl::Ftype ) {
605                                        visit_children = false;
606                                        return;
607                                }
608                        }
609
610                        // add function as declaration
611                        std::stringstream ss;
612                        build( decl->name, decl->type, ss );
613                        addDecl( ss.str() );
614
615                        // add body if available
616                        if ( decl->statements ) {
617                                std::list<Type*> rtns = from_decls( decl->type->returnVals );
618                                Type* rtn = nullptr;
619                                if ( rtns.size() == 1 ) {
620                                        if ( ! dynamic_cast<VoidType*>(rtns.front()) ) rtn = rtns.front()->clone();
621                                } else if ( rtns.size() > 1 ) {
622                                        rtn = new TupleType{ Type::Qualifiers{}, rtns };
623                                }
624                                PassVisitor<ProtoDump> body{ this, rtn };
625
626                                for ( TypeDecl* tyvar : decl->type->forall ) {
627                                        // add set of "closed" types to body so that it can print them as NamedType
628                                        body.pass.closed.insert( tyvar->name );
629
630                                        // add assertions to local scope as declarations as well
631                                        for ( DeclarationWithType* assn : tyvar->assertions ) {
632                                                assn->accept( body );
633                                        }
634                                }
635                               
636                                // add named parameters and returns to local scope
637                                body.pass.addAll( decl->type->returnVals );
638                                body.pass.addAll( decl->type->parameters );
639
640                                // add contents of function to new scope
641                                decl->statements->accept( body );
642
643                                // store sub-scope
644                                addSub( std::move(body) );
645                        }
646
647                        visit_children = false;
648                }
649
650                void previsit( StructDecl* sd ) { addAggregateFields(sd); }
651                void previsit( UnionDecl* ud ) { addAggregateFields(ud); }
652               
653                void previsit( EnumDecl* ed ) {
654                        std::unique_ptr<Type> eType = 
655                                std::make_unique<BasicType>( Type::Qualifiers{}, BasicType::SignedInt );
656                       
657                        // add field names directly to enclosing scope
658                        for ( Declaration* member : ed->members ) {
659                                if ( ObjectDecl* obj = dynamic_cast< ObjectDecl* >(member) ) {
660                                        previsit(obj);
661                                }
662                        }
663
664                        visit_children = false;
665                }
666
667                void previsit( ReturnStmt* stmt ) {
668                        // do nothing for void-returning functions or statements returning nothing
669                        if ( ! rtnType || ! stmt->expr ) return;
670
671                        // otherwise construct the return type from the expression
672                        std::stringstream ss;
673                        build( rtnType.get(), stmt->expr, ss );
674                        addExpr( ss.str() );
675                        visit_children = false;
676                }
677
678                void previsit( Expression* expr ) {
679                        std::stringstream ss;
680                        PassVisitor<ExprPrinter> exPrinter{ closed, ss };
681                        expr->accept( exPrinter );
682                        addExpr( ss.str() );
683                        visit_children = false;
684                }
685
686                /// Print non-prelude global declarations for resolv proto
687                void printGlobals() const {
688                        std::cout << "#ptr<T> $addr T" << std::endl;  // &?
689                        int i = (int)BasicType::SignedInt;
690                        std::cout << i << " $and " << i << ' ' << i << std::endl;  // ?&&?
691                        std::cout << i << " $or " << i << ' ' << i << std::endl;  // ?||?
692                        std::cout << "T $if " << i << " T T" << std::endl; // ternary operator
693                        std::cout << "T $seq X T" << std::endl;  // ?,?
694                }
695
696        public:
697                /// Prints this ProtoDump instance
698                void print(unsigned indent = 0) const {
699                        // print globals at root level
700                        if ( ! parent ) printGlobals();
701                        // print decls
702                        std::string tab( indent, '\t' );
703                        for ( const std::string& d : decls ) {
704                                std::cout << tab << d << std::endl;
705                        }
706                        // print divider
707                        std::cout << '\n' << tab << "%%\n" << std::endl;
708                        // print top-level expressions
709                        for ( const std::string& e : exprs ) {
710                                std::cout << tab << e << std::endl;
711                        }
712                        // print child scopes
713                        ++indent;
714                        for ( const PassVisitor<ProtoDump>& s : subs ) {
715                                std::cout << tab << '{' << std::endl;
716                                s.pass.print( indent );
717                                std::cout << tab << '}' << std::endl;
718                        }
719                }
720        };
721
722        void dumpAsResolvProto( std::list< Declaration * > &translationUnit ) {
723                PassVisitor<ProtoDump> dump;
724                acceptAll( translationUnit, dump );
725                dump.pass.print();
726        }
727
728}  // namespace CodeTools
729
730// Local Variables: //
731// tab-width: 4 //
732// mode: c++ //
733// compile-command: "make install" //
734// End: //
Note: See TracBrowser for help on using the repository browser.