source: src/ResolvExpr/RenameVars.cc @ 329487c

Last change on this file since 329487c was f76dd1a, checked in by Andrew Beach <ajbeach@…>, 22 months ago

Some cleanup in RenameVars?.cc.

  • Property mode set to 100644
File size: 5.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// RenameVars.cc --
8//
9// Author           : Richard C. Bilson
10// Created On       : Sun May 17 12:05:18 2015
11// Last Modified By : Andrew Beach
12// Last Modified On : Thr Jun 20 17:39:00 2019
13// Update Count     : 8
14//
15
16#include <ext/alloc_traits.h>      // for __alloc_traits<>::value_type
17#include <memory>                  // for allocator_traits<>::value_type
18#include <sstream>                 // for operator<<, basic_ostream, ostring...
19#include <utility>                 // for pair
20
21#include "AST/Pass.hpp"
22#include "AST/Type.hpp"
23#include "Common/PassVisitor.h"
24#include "Common/ScopedMap.h"
25#include "Common/SemanticError.h"  // for SemanticError
26#include "RenameVars.h"
27#include "SynTree/Declaration.h"   // for DeclarationWithType, TypeDecl, Dec...
28#include "SynTree/Expression.h"    // for Expression
29#include "SynTree/Type.h"          // for Type, TypeInstType, TraitInstType
30#include "SynTree/Visitor.h"       // for acceptAll, maybeAccept
31
32#include "AST/Copy.hpp"
33
34namespace ResolvExpr {
35
36namespace {
37        class RenamingData {
38                int level = 0;
39                int resetCount = 0;
40
41                int next_expr_id = 1;
42                int next_usage_id = 1;
43                ScopedMap< std::string, std::string > nameMap;
44                ScopedMap< std::string, ast::TypeEnvKey > idMap;
45        public:
46                void reset() {
47                        level = 0;
48                        ++resetCount;
49                }
50
51                void rename( TypeInstType * type ) {
52                        auto it = nameMap.find( type->name );
53                        if ( it != nameMap.end() ) {
54                                type->name = it->second;
55                        }
56                }
57
58                void nextUsage() {
59                        ++next_usage_id;
60                }
61
62                void openLevel( Type * type ) {
63                        if ( ! type->forall.empty() ) {
64                                nameMap.beginScope();
65                                // renames all "forall" type names to `_${level}_${name}'
66                                for ( auto td : type->forall ) {
67                                        std::ostringstream output;
68                                        output << "_" << resetCount << "_" << level << "_" << td->name;
69                                        std::string newname( output.str() );
70                                        nameMap[ td->get_name() ] = newname;
71                                        td->name = newname;
72                                        // ditto for assertion names, the next level in
73                                        level++;
74                                }
75                        }
76                }
77
78                void closeLevel( Type * type ) {
79                        if ( !type->forall.empty() ) {
80                                nameMap.endScope();
81                        }
82                }
83
84                const ast::TypeInstType * rename( const ast::TypeInstType * type ) {
85                        auto it = idMap.find( type->name );
86                        if ( it == idMap.end() ) return type;
87
88                        // Unconditionally mutate because map will *always* have different name.
89                        ast::TypeInstType * mut = ast::shallowCopy( type );
90                        // Reconcile base node since some copies might have been made.
91                        mut->base = it->second.base;
92                        mut->formal_usage = it->second.formal_usage;
93                        mut->expr_id = it->second.expr_id;
94                        return mut;
95                }
96
97                const ast::FunctionType * openLevel( const ast::FunctionType * type, RenameMode mode ) {
98                        if ( type->forall.empty() ) return type;
99                        idMap.beginScope();
100
101                        // Load new names from this forall clause and perform renaming.
102                        auto mutType = ast::shallowCopy( type );
103                        // assert( type == mutType && "mutated type must be unique from ForallSubstitutor" );
104                        for ( auto & td : mutType->forall ) {
105                                auto mut = ast::shallowCopy( td.get() );
106                                // assert( td == mutDecl && "mutated decl must be unique from ForallSubstitutor" );
107
108                                if (mode == GEN_EXPR_ID) {
109                                        mut->expr_id = next_expr_id;
110                                        mut->formal_usage = -1;
111                                        ++next_expr_id;
112                                }
113                                else if (mode == GEN_USAGE) {
114                                        assertf(mut->expr_id, "unfilled expression id in generating candidate type");
115                                        mut->formal_usage = next_usage_id;
116                                }
117                                else {
118                                        assert(false);
119                                }
120                                idMap[ td->name ] = ast::TypeEnvKey( *mut );
121
122                                td = mut;
123                        }
124
125                        return mutType;
126                }
127
128                void closeLevel( const ast::FunctionType * type ) {
129                        if ( type->forall.empty() ) return;
130                        idMap.endScope();
131                }
132        };
133
134        // Global State:
135        RenamingData renaming;
136
137        struct RenameVars_old {
138                void previsit( TypeInstType * instType ) {
139                        renaming.openLevel( (Type*)instType );
140                        renaming.rename( instType );
141                }
142                void previsit( Type * type ) {
143                        renaming.openLevel( type );
144                }
145                void postvisit( Type * type ) {
146                        renaming.closeLevel( type );
147                }
148        };
149
150        struct RenameVars_new : public ast::PureVisitor /*: public ast::WithForallSubstitutor*/ {
151                RenameMode mode;
152
153                const ast::FunctionType * previsit( const ast::FunctionType * type ) {
154                        return renaming.openLevel( type, mode );
155                }
156
157                /*
158                const ast::StructInstType * previsit( const ast::StructInstType * type ) {
159                        return renaming.openLevel( type );
160                }
161                const ast::UnionInstType * previsit( const ast::UnionInstType * type ) {
162                        return renaming.openLevel( type );
163                }
164                const ast::TraitInstType * previsit( const ast::TraitInstType * type ) {
165                        return renaming.openLevel( type );
166                }
167                */
168
169                const ast::TypeInstType * previsit( const ast::TypeInstType * type ) {
170                        if (mode == GEN_USAGE && !type->formal_usage) return type; // do not rename an actual type
171                        return renaming.rename( type );
172                }
173                void postvisit( const ast::FunctionType * type ) {
174                        renaming.closeLevel( type );
175                }
176        };
177
178} // namespace
179
180void renameTyVars( Type * t ) {
181        PassVisitor<RenameVars_old> renamer;
182        t->accept( renamer );
183}
184
185const ast::Type * renameTyVars( const ast::Type * t, RenameMode mode, bool reset ) {
186        ast::Pass<RenameVars_new> renamer;
187        renamer.core.mode = mode;
188        if (mode == GEN_USAGE && reset) {
189                renaming.nextUsage();
190        }
191        return t->accept( renamer );
192}
193
194void resetTyVarRenaming() {
195        renaming.reset();
196        renaming.nextUsage();
197}
198
199} // namespace ResolvExpr
200
201// Local Variables: //
202// tab-width: 4 //
203// mode: c++ //
204// compile-command: "make install" //
205// End: //
Note: See TracBrowser for help on using the repository browser.