Changeset 36cb4d9
- Timestamp:
- Sep 26, 2022, 10:32:56 AM (2 years ago)
- Branches:
- ADT, ast-experimental, master
- Children:
- d3af505
- Parents:
- 996c8ed
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Tuples/TupleExpansionNew.cpp
r996c8ed r36cb4d9 10 10 // Created On : Mon Aug 23 15:36:09 2021 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Tue Sep 20 16:17:00 202213 // Update Count : 412 // Last Modified On : Mon Sep 26 10:25:00 2022 13 // Update Count : 5 14 14 // 15 15 … … 30 30 struct UniqueExprExpander final : public ast::WithDeclsToAdd<> { 31 31 const ast::Expr * postvisit( const ast::UniqueExpr * unqExpr ); 32 std::map< int, ast::ptr<ast::Expr> > decls; // not vector, because order added may not be increasing order 32 // Not a vector, because they may not be adding in increasing order. 33 std::map< int, ast::ptr<ast::Expr> > decls; 34 }; 35 36 /// Replaces Tuple Assign & Index Expressions, and Tuple Types. 37 struct TupleMainExpander final : 38 public ast::WithCodeLocation, 39 public ast::WithDeclsToAdd<>, 40 public ast::WithGuards, 41 public ast::WithVisitorRef<TupleMainExpander> { 42 ast::Expr const * postvisit( ast::TupleAssignExpr const * expr ); 43 44 void previsit( ast::CompoundStmt const * ); 45 ast::Expr const * postvisit( ast::Expr const * expr ); 46 ast::Type const * postvisit( ast::TupleType const * type ); 47 48 ast::Expr const * postvisit( ast::TupleIndexExpr const * expr ); 49 private: 50 ScopedMap< int, ast::StructDecl const * > typeMap; 51 }; 52 53 struct TupleExprExpander final { 54 ast::Expr const * postvisit( ast::TupleExpr const * expr ); 33 55 }; 34 56 … … 100 122 } 101 123 102 /// Replaces Tuple Assign & Index Expressions, and Tuple Types. 103 struct TupleMainExpander final : 104 public ast::WithCodeLocation, 105 public ast::WithDeclsToAdd<>, 106 public ast::WithGuards, 107 public ast::WithVisitorRef<TupleMainExpander> { 108 ast::Expr const * postvisit( ast::TupleAssignExpr const * expr ) { 109 // Just move the env on the new top level expression. 110 return ast::mutate_field( expr->stmtExpr.get(), 111 &ast::TupleAssignExpr::env, expr->env.get() ); 112 } 113 114 void previsit( ast::CompoundStmt const * ) { 115 GuardScope( typeMap ); 116 } 117 118 ast::Expr const * postvisit( ast::Expr const * expr ) { 119 if ( nullptr == expr->env ) { 120 return expr; 121 } 122 // TypeSubstitutions are never visited in the new Pass template, 123 // so it is done manually here, where all types have to be replaced. 124 return ast::mutate_field( expr, &ast::Expr::env, 125 expr->env->accept( *visitor ) ); 126 } 127 128 ast::Type const * postvisit( ast::TupleType const * type ) { 129 assert( location ); 130 unsigned tupleSize = type->size(); 131 if ( !typeMap.count( tupleSize ) ) { 132 ast::StructDecl * decl = new ast::StructDecl( *location, 133 toString( "_tuple", tupleSize, "_" ) 124 // Handles expansion of tuple assignment. 125 ast::Expr const * TupleMainExpander::postvisit( 126 ast::TupleAssignExpr const * expr ) { 127 // Just move the env on the new top level expression. 128 return ast::mutate_field( expr->stmtExpr.get(), 129 &ast::TupleAssignExpr::env, expr->env.get() ); 130 } 131 132 // Context information for tuple type expansion. 133 void TupleMainExpander::previsit( ast::CompoundStmt const * ) { 134 GuardScope( typeMap ); 135 } 136 137 // Make sure types in a TypeSubstitution are expanded. 138 ast::Expr const * TupleMainExpander::postvisit( ast::Expr const * expr ) { 139 if ( nullptr == expr->env ) { 140 return expr; 141 } 142 return ast::mutate_field( expr, &ast::Expr::env, 143 expr->env->accept( *visitor ) ); 144 } 145 146 // Create a generic tuple structure of a given size. 147 ast::StructDecl * createTupleStruct( 148 unsigned int tupleSize, CodeLocation const & location ) { 149 ast::StructDecl * decl = new ast::StructDecl( location, 150 toString( "_tuple", tupleSize, "_" ) 151 ); 152 decl->body = true; 153 154 for ( size_t i = 0 ; i < tupleSize ; ++i ) { 155 ast::TypeDecl * typeParam = new ast::TypeDecl( location, 156 toString( "tuple_param_", tupleSize, "_", i ), 157 ast::Storage::Classes(), 158 nullptr, 159 ast::TypeDecl::Dtype, 160 true 134 161 ); 135 decl->body = true; 136 137 for ( size_t i = 0 ; i < tupleSize ; ++i ) { 138 ast::TypeDecl * typeParam = new ast::TypeDecl( *location, 139 toString( "tuple_param_", tupleSize, "_", i ), 140 ast::Storage::Classes(), 141 nullptr, 142 ast::TypeDecl::Dtype, 143 true 144 ); 145 ast::ObjectDecl * member = new ast::ObjectDecl( *location, 146 toString( "field_", i ), 147 new ast::TypeInstType( typeParam ) 148 ); 149 decl->params.push_back( typeParam ); 150 decl->members.push_back( member ); 151 } 152 153 // Empty structures are not standard C. Add a dummy field to 154 // empty tuples to silence warnings when a compound literal 155 // `_tuple0_` is created. 156 if ( tupleSize == 0 ) { 157 decl->members.push_back( 158 new ast::ObjectDecl( *location, 159 "dummy", 160 new ast::BasicType( ast::BasicType::SignedInt ), 161 nullptr, 162 ast::Storage::Classes(), 163 // Does this have to be a C linkage? 164 ast::Linkage::C 165 ) 166 ); 167 } 168 typeMap[tupleSize] = decl; 169 declsToAddBefore.push_back( decl ); 170 } 171 172 ast::StructDecl const * decl = typeMap[ tupleSize ]; 173 ast::StructInstType * newType = 174 new ast::StructInstType( decl, type->qualifiers ); 175 for ( auto pair : group_iterate( type->types, decl->params ) ) { 176 ast::Type const * t = std::get<0>( pair ); 177 newType->params.push_back( 178 new ast::TypeExpr( *location, ast::deepCopy( t ) ) ); 179 } 180 return newType; 181 } 182 183 ast::Expr const * postvisit( ast::TupleIndexExpr const * expr ) { 184 CodeLocation const & location = expr->location; 185 ast::Expr const * tuple = expr->tuple.get(); 186 assert( tuple ); 187 unsigned int index = expr->index; 188 ast::TypeSubstitution const * env = expr->env.get(); 189 190 if ( auto tupleExpr = dynamic_cast<ast::TupleExpr const *>( tuple ) ) { 191 // Optimization: If it is a definitely pure tuple expr, 192 // then it can reduce to the only relevant component. 193 if ( !maybeImpureIgnoreUnique( tupleExpr ) ) { 194 assert( index < tupleExpr->exprs.size() ); 195 ast::ptr<ast::Expr> const & expr = 196 *std::next( tupleExpr->exprs.begin(), index ); 197 ast::Expr * ret = ast::mutate( expr.get() ); 198 ret->env = env; 199 return ret; 200 } 201 } 202 203 auto type = tuple->result.strict_as<ast::StructInstType>(); 204 ast::StructDecl const * structDecl = type->base; 205 assert( index < structDecl->members.size() ); 206 ast::ptr<ast::Decl> const & member = 207 *std::next( structDecl->members.begin(), index ); 208 ast::MemberExpr * memberExpr = new ast::MemberExpr( location, 209 member.strict_as<ast::DeclWithType>(), tuple ); 210 memberExpr->env = env; 211 return memberExpr; 212 } 213 private: 214 ScopedMap< int, ast::StructDecl const * > typeMap; 215 }; 162 ast::ObjectDecl * member = new ast::ObjectDecl( location, 163 toString( "field_", i ), 164 new ast::TypeInstType( typeParam ) 165 ); 166 decl->params.push_back( typeParam ); 167 decl->members.push_back( member ); 168 } 169 170 // Empty structures are not standard C. Add a dummy field to 171 // empty tuples to silence warnings when a compound literal 172 // `_tuple0_` is created. 173 if ( tupleSize == 0 ) { 174 decl->members.push_back( 175 new ast::ObjectDecl( location, 176 "dummy", 177 new ast::BasicType( ast::BasicType::SignedInt ), 178 nullptr, 179 ast::Storage::Classes(), 180 // Does this have to be a C linkage? 181 ast::Linkage::C 182 ) 183 ); 184 } 185 return decl; 186 } 187 188 ast::Type const * TupleMainExpander::postvisit( ast::TupleType const * type ) { 189 assert( location ); 190 unsigned tupleSize = type->size(); 191 if ( !typeMap.count( tupleSize ) ) { 192 ast::StructDecl * decl = createTupleStruct( tupleSize, *location ); 193 typeMap[tupleSize] = decl; 194 declsToAddBefore.push_back( decl ); 195 } 196 197 ast::StructDecl const * decl = typeMap[ tupleSize ]; 198 ast::StructInstType * newType = 199 new ast::StructInstType( decl, type->qualifiers ); 200 for ( auto pair : group_iterate( type->types, decl->params ) ) { 201 ast::Type const * t = std::get<0>( pair ); 202 newType->params.push_back( 203 new ast::TypeExpr( *location, ast::deepCopy( t ) ) ); 204 } 205 return newType; 206 } 207 208 // Expand a tuple index into a field access in the underlying structure. 209 ast::Expr const * TupleMainExpander::postvisit( 210 ast::TupleIndexExpr const * expr ) { 211 CodeLocation const & location = expr->location; 212 ast::Expr const * tuple = expr->tuple.get(); 213 assert( tuple ); 214 unsigned int index = expr->index; 215 ast::TypeSubstitution const * env = expr->env.get(); 216 217 if ( auto tupleExpr = dynamic_cast<ast::TupleExpr const *>( tuple ) ) { 218 // Optimization: If it is a definitely pure tuple expr, 219 // then it can reduce to the only relevant component. 220 if ( !maybeImpureIgnoreUnique( tupleExpr ) ) { 221 assert( index < tupleExpr->exprs.size() ); 222 ast::ptr<ast::Expr> const & expr = 223 *std::next( tupleExpr->exprs.begin(), index ); 224 ast::Expr * ret = ast::mutate( expr.get() ); 225 ret->env = env; 226 return ret; 227 } 228 } 229 230 auto type = tuple->result.strict_as<ast::StructInstType>(); 231 ast::StructDecl const * structDecl = type->base; 232 assert( index < structDecl->members.size() ); 233 ast::ptr<ast::Decl> const & member = 234 *std::next( structDecl->members.begin(), index ); 235 ast::MemberExpr * memberExpr = new ast::MemberExpr( location, 236 member.strict_as<ast::DeclWithType>(), tuple ); 237 memberExpr->env = env; 238 return memberExpr; 239 } 216 240 217 241 ast::Expr const * replaceTupleExpr( … … 249 273 } 250 274 251 struct TupleExprExpander final { 252 ast::Expr const * postvisit( ast::TupleExpr const * expr ) { 253 return replaceTupleExpr( expr->location, 254 expr->result, expr->exprs, expr->env ); 255 } 256 }; 275 ast::Expr const * TupleExprExpander::postvisit( ast::TupleExpr const * expr ) { 276 return replaceTupleExpr( expr->location, 277 expr->result, expr->exprs, expr->env ); 278 } 257 279 258 280 } // namespace
Note: See TracChangeset
for help on using the changeset viewer.