- Timestamp:
- Jul 29, 2022, 12:15:29 PM (2 years ago)
- Branches:
- ADT, ast-experimental, master, pthread-emulation
- Children:
- ce1d721
- Parents:
- d0fcc82
- Location:
- src
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Tuples/TupleExpansionNew.cpp
rd0fcc82 rb507dcd 15 15 16 16 #include "Tuples.h" 17 18 #include "AST/Pass.hpp" 19 #include "Common/ScopedMap.h" 17 20 18 21 namespace Tuples { … … 111 114 } 112 115 } // namespace 116 117 namespace { 118 119 struct TupleAssignExpander { 120 ast::Expr const * postvisit( ast::TupleAssignExpr const * expr ) { 121 // Just move the env on the new top level expression. 122 return ast::mutate_field( expr->stmtExpr.get(), 123 &ast::TupleAssignExpr::env, expr->env.get() ); 124 } 125 }; 126 127 struct TupleTypeReplacer : 128 public ast::WithGuards, 129 public ast::WithVisitorRef<TupleTypeReplacer>, 130 public ast::WithDeclsToAdd<> { 131 void previsit( ast::ParseNode const * node ) { 132 GuardValue( location ) = &node->location; 133 } 134 135 void previsit( ast::CompoundStmt const * stmt ) { 136 previsit( (ast::ParseNode const *)stmt ); 137 GuardScope( typeMap ); 138 } 139 140 ast::Expr const * postvisit( ast::Expr const * expr ) { 141 if ( nullptr == expr->env ) { 142 return expr; 143 } 144 // TypeSubstitutions are never visited in the new Pass template, 145 // so it is done manually here, where all types have to be replaced. 146 return ast::mutate_field( expr, &ast::Expr::env, 147 expr->env->accept( *visitor ) ); 148 } 149 150 ast::Type const * postvisit( ast::TupleType const * type ) { 151 assert( location ); 152 unsigned tupleSize = type->size(); 153 if ( !typeMap.count( tupleSize ) ) { 154 ast::StructDecl * decl = new ast::StructDecl( *location, 155 toString( "_tuple", tupleSize, "_" ) 156 ); 157 decl->body = true; 158 159 for ( size_t i = 0 ; i < tupleSize ; ++i ) { 160 ast::TypeDecl * typeParam = new ast::TypeDecl( *location, 161 toString( "tuple_param_", tupleSize, "_", i ), 162 ast::Storage::Classes(), 163 nullptr, 164 ast::TypeDecl::Dtype, 165 true 166 ); 167 ast::ObjectDecl * member = new ast::ObjectDecl( *location, 168 toString( "field_", i ), 169 new ast::TypeInstType( typeParam ) 170 ); 171 decl->params.push_back( typeParam ); 172 decl->members.push_back( member ); 173 } 174 175 // Empty structures are not standard C. Add a dummy field to 176 // empty tuples to silence warnings when a compound literal 177 // `_tuple0_` is created. 178 if ( tupleSize == 0 ) { 179 decl->members.push_back( 180 new ast::ObjectDecl( *location, 181 "dummy", 182 new ast::BasicType( ast::BasicType::SignedInt ), 183 nullptr, 184 ast::Storage::Classes(), 185 // Does this have to be a C linkage? 186 ast::Linkage::C 187 ) 188 ); 189 } 190 typeMap[tupleSize] = decl; 191 declsToAddBefore.push_back( decl ); 192 } 193 194 ast::StructDecl const * decl = typeMap[ tupleSize ]; 195 ast::StructInstType * newType = 196 new ast::StructInstType( decl, type->qualifiers ); 197 for ( auto pair : group_iterate( type->types, decl->params ) ) { 198 ast::Type const * t = std::get<0>( pair ); 199 newType->params.push_back( 200 new ast::TypeExpr( *location, ast::deepCopy( t ) ) ); 201 } 202 return newType; 203 } 204 private: 205 ScopedMap< int, ast::StructDecl const * > typeMap; 206 CodeLocation const * location = nullptr; 207 }; 208 209 struct TupleIndexExpander { 210 ast::Expr const * postvisit( 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 } 240 }; 241 242 ast::Expr const * replaceTupleExpr( 243 CodeLocation const & location, 244 ast::Type const * result, 245 std::vector<ast::ptr<ast::Expr>> const & exprs, 246 ast::TypeSubstitution const * env ) { 247 assert( result ); 248 // A void result: It doesn't need to produce a value for cascading, 249 // just output a chain of comma exprs. 250 if ( result->isVoid() ) { 251 assert( !exprs.empty() ); 252 std::vector<ast::ptr<ast::Expr>>::const_iterator iter = exprs.begin(); 253 ast::Expr * expr = new ast::CastExpr( *iter++ ); 254 for ( ; iter != exprs.end() ; ++iter ) { 255 expr = new ast::CommaExpr( location, 256 expr, new ast::CastExpr( *iter ) ); 257 } 258 expr->env = env; 259 return expr; 260 // Typed tuple expression: Produce a compound literal which performs 261 // each of the expressions as a distinct part of its initializer. The 262 // produced compound literal may be used as part of another expression. 263 } else { 264 auto inits = map_range<std::vector<ast::ptr<ast::Init>>>( exprs, 265 []( ast::Expr const * expr ) { 266 return new ast::SingleInit( expr->location, expr ); 267 } 268 ); 269 ast::Expr * expr = new ast::CompoundLiteralExpr( location, 270 result, new ast::ListInit( location, std::move( inits ) ) ); 271 expr->env = env; 272 return expr; 273 } 274 } 275 276 struct TupleExprExpander { 277 ast::Expr const * postvisit( ast::TupleExpr const * expr ) { 278 return replaceTupleExpr( expr->location, 279 expr->result, expr->exprs, expr->env ); 280 } 281 }; 282 283 } // namespace 284 285 void expandTuples( ast::TranslationUnit & translationUnit ) { 286 // These may not have to be seperate passes. 287 ast::Pass<TupleAssignExpander>::run( translationUnit ); 288 ast::Pass<TupleTypeReplacer>::run( translationUnit ); 289 ast::Pass<TupleIndexExpander>::run( translationUnit ); 290 ast::Pass<TupleExprExpander>::run( translationUnit ); 291 } 292 113 293 } // namespace Tuples -
src/Tuples/Tuples.h
rd0fcc82 rb507dcd 32 32 void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * assign, 33 33 std::vector< ResolvExpr::AlternativeFinder >& args ); 34 void handleTupleAssignment( 35 ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign, 34 void handleTupleAssignment( 35 ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign, 36 36 std::vector< ResolvExpr::CandidateFinder > & args ); 37 37 … … 43 43 /// replaces tuple-related elements, such as TupleType, TupleExpr, TupleAssignExpr, etc. 44 44 void expandTuples( std::list< Declaration * > & translationUnit ); 45 void expandTuples( ast::TranslationUnit & translaionUnit ); 45 46 46 47 /// replaces UniqueExprs with a temporary variable and one call -
src/main.cc
rd0fcc82 rb507dcd 443 443 PASS( "Convert Specializations", GenPoly::convertSpecializations( transUnit ) ); 444 444 445 PASS( "Expand Tuples", Tuples::expandTuples( transUnit ) ); 446 445 447 translationUnit = convert( move( transUnit ) ); 446 448 } else { … … 517 519 PASS( "Gen Waitfor", Concurrency::generateWaitFor( translationUnit ) ); 518 520 PASS( "Convert Specializations", GenPoly::convertSpecializations( translationUnit ) ); // needs to happen before tuple types are expanded 521 PASS( "Expand Tuples", Tuples::expandTuples( translationUnit ) ); // xxx - is this the right place for this? 519 522 } 520 521 PASS( "Expand Tuples", Tuples::expandTuples( translationUnit ) ); // xxx - is this the right place for this?522 523 523 524 if ( tuplep ) {
Note: See TracChangeset
for help on using the changeset viewer.