- Timestamp:
- Jun 12, 2023, 12:05:58 PM (2 years ago)
- Branches:
- master
- Children:
- fec8bd1
- Parents:
- 2b78949 (diff), 38e266ca (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- src
- Files:
-
- 43 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/DeclReplacer.hpp
r2b78949 r8a930c03 18 18 #include <unordered_map> 19 19 20 #include "Node.hpp" 20 namespace ast { 21 class DeclWithType; 22 class Expr; 23 class Node; 24 class TypeDecl; 25 } 21 26 22 27 namespace ast { 23 class DeclWithType;24 class TypeDecl;25 class Expr;26 28 27 namespace DeclReplacer { 28 using DeclMap = std::unordered_map< const DeclWithType *, const DeclWithType * >; 29 using TypeMap = std::unordered_map< const TypeDecl *, const TypeDecl * >; 30 using ExprMap = std::unordered_map< const DeclWithType *, const Expr * >; 29 namespace DeclReplacer { 31 30 32 const Node * replace( const Node * node, const DeclMap & declMap, bool debug = false ); 33 const Node * replace( const Node * node, const TypeMap & typeMap, bool debug = false ); 34 const Node * replace( const Node * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug = false ); 35 const Node * replace( const Node * node, const ExprMap & exprMap); 36 } 31 using DeclMap = std::unordered_map< const DeclWithType *, const DeclWithType * >; 32 using TypeMap = std::unordered_map< const TypeDecl *, const TypeDecl * >; 33 using ExprMap = std::unordered_map< const DeclWithType *, const Expr * >; 34 35 const Node * replace( const Node * node, const DeclMap & declMap, bool debug = false ); 36 const Node * replace( const Node * node, const TypeMap & typeMap, bool debug = false ); 37 const Node * replace( const Node * node, const DeclMap & declMap, const TypeMap & typeMap, bool debug = false ); 38 const Node * replace( const Node * node, const ExprMap & exprMap); 39 40 } 41 37 42 } 38 43 -
src/AST/Pass.hpp
r2b78949 r8a930c03 414 414 }; 415 415 416 /// Use when the templated visitor should update the symbol table 416 /// Use when the templated visitor should update the symbol table, 417 /// that is, when your pass core needs to query the symbol table. 418 /// Expected setups: 419 /// - For master passes that kick off at the compilation unit 420 /// - before resolver: extend WithSymbolTableX<IgnoreErrors> 421 /// - after resolver: extend WithSymbolTable and use defaults 422 /// - (FYI, for completeness, the resolver's main pass uses ValidateOnAdd when it kicks off) 423 /// - For helper passes that kick off at arbitrary points in the AST: 424 /// - take an existing symbol table as a parameter, extend WithSymbolTable, 425 /// and construct with WithSymbolTable(const SymbolTable &) 417 426 struct WithSymbolTable { 418 SymbolTable symtab; 427 WithSymbolTable(const ast::SymbolTable & from) : symtab(from) {} 428 WithSymbolTable(ast::SymbolTable::ErrorDetection errorMode = ast::SymbolTable::ErrorDetection::AssertClean) : symtab(errorMode) {} 429 ast::SymbolTable symtab; 430 }; 431 template <ast::SymbolTable::ErrorDetection errorMode> 432 struct WithSymbolTableX : WithSymbolTable { 433 WithSymbolTableX() : WithSymbolTable(errorMode) {} 419 434 }; 420 435 -
src/AST/Pass.impl.hpp
r2b78949 r8a930c03 20 20 #include <unordered_map> 21 21 22 #include "AST/Copy.hpp" 22 23 #include "AST/TranslationUnit.hpp" 23 24 #include "AST/TypeSubstitution.hpp" … … 45 46 46 47 #ifdef PEDANTIC_PASS_ASSERT 47 #define __pedantic_pass_assert(...) assert 48 #define __pedantic_pass_assert(...) assert(__VA_ARGS__) 48 49 #define __pedantic_pass_assertf(...) assertf(__VA_ARGS__) 49 50 #else … … 71 72 template<typename it_t, template <class...> class container_t> 72 73 static inline void take_all( it_t it, container_t<ast::ptr<ast::Decl>> * decls, bool * mutated = nullptr ) { 73 if (empty(decls)) return;74 if ( empty( decls ) ) return; 74 75 75 76 std::transform(decls->begin(), decls->end(), it, [](const ast::Decl * decl) -> auto { … … 77 78 }); 78 79 decls->clear(); 79 if (mutated) *mutated = true;80 if ( mutated ) *mutated = true; 80 81 } 81 82 82 83 template<typename it_t, template <class...> class container_t> 83 84 static inline void take_all( it_t it, container_t<ast::ptr<ast::Stmt>> * stmts, bool * mutated = nullptr ) { 84 if (empty(stmts)) return;85 if ( empty( stmts ) ) return; 85 86 86 87 std::move(stmts->begin(), stmts->end(), it); 87 88 stmts->clear(); 88 if (mutated) *mutated = true;89 if ( mutated ) *mutated = true; 89 90 } 90 91 … … 92 93 /// Check if should be skipped, different for pointers and containers 93 94 template<typename node_t> 94 bool skip( const ast::ptr<node_t> & val ) {95 bool skip( const ast::ptr<node_t> & val ) { 95 96 return !val; 96 97 } … … 109 110 110 111 template<typename node_t> 111 const node_t & get( const node_t & val, long ) {112 const node_t & get( const node_t & val, long ) { 112 113 return val; 113 114 } … … 125 126 } 126 127 } 127 128 template< typename core_t > 129 template< typename node_t > 130 auto ast::Pass< core_t >::call_accept( const node_t * node ) 131 -> typename ast::Pass< core_t >::template generic_call_accept_result<node_t>::type 132 { 133 __pedantic_pass_assert( __visit_children() ); 134 __pedantic_pass_assert( node ); 135 136 static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR"); 137 static_assert( !std::is_base_of<ast::Stmt, node_t>::value, "ERROR"); 138 139 auto nval = node->accept( *this ); 140 __pass::result1< 141 typename std::remove_pointer< decltype( node->accept(*this) ) >::type 142 > res; 143 res.differs = nval != node; 144 res.value = nval; 145 return res; 146 } 147 148 template< typename core_t > 149 __pass::template result1<ast::Expr> ast::Pass< core_t >::call_accept( const ast::Expr * expr ) { 150 __pedantic_pass_assert( __visit_children() ); 151 __pedantic_pass_assert( expr ); 152 153 auto nval = expr->accept( *this ); 154 return { nval != expr, nval }; 155 } 156 157 template< typename core_t > 158 __pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) { 159 __pedantic_pass_assert( __visit_children() ); 160 __pedantic_pass_assert( stmt ); 161 162 const ast::Stmt * nval = stmt->accept( *this ); 163 return { nval != stmt, nval }; 164 } 165 166 template< typename core_t > 167 __pass::template result1<ast::Expr> ast::Pass< core_t >::call_accept_top( const ast::Expr * expr ) { 168 __pedantic_pass_assert( __visit_children() ); 169 __pedantic_pass_assert( expr ); 170 171 const ast::TypeSubstitution ** typeSubs_ptr = __pass::typeSubs( core, 0 ); 172 if ( typeSubs_ptr && expr->env ) { 173 *typeSubs_ptr = expr->env; 174 } 175 176 auto nval = expr->accept( *this ); 177 return { nval != expr, nval }; 178 } 179 180 template< typename core_t > 181 __pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) { 182 __pedantic_pass_assert( __visit_children() ); 183 __pedantic_pass_assert( stmt ); 184 185 // add a few useful symbols to the scope 186 using __pass::empty; 187 188 // get the stmts/decls that will need to be spliced in 189 auto stmts_before = __pass::stmtsToAddBefore( core, 0 ); 190 auto stmts_after = __pass::stmtsToAddAfter ( core, 0 ); 191 auto decls_before = __pass::declsToAddBefore( core, 0 ); 192 auto decls_after = __pass::declsToAddAfter ( core, 0 ); 193 194 // These may be modified by subnode but most be restored once we exit this statemnet. 195 ValueGuardPtr< const ast::TypeSubstitution * > __old_env ( __pass::typeSubs( core, 0 ) ); 196 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before ); 197 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after ); 198 ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) >::type > __old_stmts_before( decls_before ); 199 ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) >::type > __old_stmts_after ( decls_after ); 200 201 // Now is the time to actually visit the node 202 const ast::Stmt * nstmt = stmt->accept( *this ); 203 204 // If the pass doesn't want to add anything then we are done 205 if( empty(stmts_before) && empty(stmts_after) && empty(decls_before) && empty(decls_after) ) { 206 return { nstmt != stmt, nstmt }; 207 } 208 209 // Make sure that it is either adding statements or declartions but not both 210 // this is because otherwise the order would be awkward to predict 211 assert(( empty( stmts_before ) && empty( stmts_after )) 212 || ( empty( decls_before ) && empty( decls_after )) ); 213 214 // Create a new Compound Statement to hold the new decls/stmts 215 ast::CompoundStmt * compound = new ast::CompoundStmt( stmt->location ); 216 217 // Take all the declarations that go before 218 __pass::take_all( std::back_inserter( compound->kids ), decls_before ); 219 __pass::take_all( std::back_inserter( compound->kids ), stmts_before ); 220 221 // Insert the original declaration 222 compound->kids.emplace_back( nstmt ); 223 224 // Insert all the declarations that go before 225 __pass::take_all( std::back_inserter( compound->kids ), decls_after ); 226 __pass::take_all( std::back_inserter( compound->kids ), stmts_after ); 227 228 return {true, compound}; 229 } 230 231 template< typename core_t > 232 template< template <class...> class container_t > 233 __pass::template resultNstmt<container_t> ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) { 234 __pedantic_pass_assert( __visit_children() ); 235 if( statements.empty() ) return {}; 236 237 // We are going to aggregate errors for all these statements 238 SemanticErrorException errors; 239 240 // add a few useful symbols to the scope 241 using __pass::empty; 242 243 // get the stmts/decls that will need to be spliced in 244 auto stmts_before = __pass::stmtsToAddBefore( core, 0 ); 245 auto stmts_after = __pass::stmtsToAddAfter ( core, 0 ); 246 auto decls_before = __pass::declsToAddBefore( core, 0 ); 247 auto decls_after = __pass::declsToAddAfter ( core, 0 ); 248 249 // These may be modified by subnode but most be restored once we exit this statemnet. 250 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before ); 251 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after ); 252 ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) >::type > __old_stmts_before( decls_before ); 253 ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) >::type > __old_stmts_after ( decls_after ); 254 255 // update pass statitistics 256 pass_visitor_stats.depth++; 257 pass_visitor_stats.max->push(pass_visitor_stats.depth); 258 pass_visitor_stats.avg->push(pass_visitor_stats.depth); 259 260 __pass::resultNstmt<container_t> new_kids; 261 for( auto value : enumerate( statements ) ) { 262 try { 263 size_t i = value.idx; 264 const Stmt * stmt = value.val; 265 __pedantic_pass_assert( stmt ); 266 const ast::Stmt * new_stmt = stmt->accept( *this ); 267 assert( new_stmt ); 268 if(new_stmt != stmt ) { new_kids.differs = true; } 269 270 // Make sure that it is either adding statements or declartions but not both 271 // this is because otherwise the order would be awkward to predict 272 assert(( empty( stmts_before ) && empty( stmts_after )) 273 || ( empty( decls_before ) && empty( decls_after )) ); 274 275 // Take all the statements which should have gone after, N/A for first iteration 276 new_kids.take_all( decls_before ); 277 new_kids.take_all( stmts_before ); 278 279 // Now add the statement if there is one 280 if(new_stmt != stmt) { 281 new_kids.values.emplace_back( new_stmt, i, false ); 282 } else { 283 new_kids.values.emplace_back( nullptr, i, true ); 284 } 285 286 // Take all the declarations that go before 287 new_kids.take_all( decls_after ); 288 new_kids.take_all( stmts_after ); 128 } 129 130 template< typename core_t > 131 template< typename node_t > 132 auto ast::Pass< core_t >::call_accept( const node_t * node ) -> 133 typename ast::Pass< core_t >::template generic_call_accept_result<node_t>::type 134 { 135 __pedantic_pass_assert( __visit_children() ); 136 __pedantic_pass_assert( node ); 137 138 static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR" ); 139 static_assert( !std::is_base_of<ast::Stmt, node_t>::value, "ERROR" ); 140 141 auto nval = node->accept( *this ); 142 __pass::result1< 143 typename std::remove_pointer< decltype( node->accept(*this) ) >::type 144 > res; 145 res.differs = nval != node; 146 res.value = nval; 147 return res; 148 } 149 150 template< typename core_t > 151 ast::__pass::template result1<ast::Expr> ast::Pass< core_t >::call_accept( const ast::Expr * expr ) { 152 __pedantic_pass_assert( __visit_children() ); 153 __pedantic_pass_assert( expr ); 154 155 auto nval = expr->accept( *this ); 156 return { nval != expr, nval }; 157 } 158 159 template< typename core_t > 160 ast::__pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) { 161 __pedantic_pass_assert( __visit_children() ); 162 __pedantic_pass_assert( stmt ); 163 164 const ast::Stmt * nval = stmt->accept( *this ); 165 return { nval != stmt, nval }; 166 } 167 168 template< typename core_t > 169 ast::__pass::template result1<ast::Expr> ast::Pass< core_t >::call_accept_top( const ast::Expr * expr ) { 170 __pedantic_pass_assert( __visit_children() ); 171 __pedantic_pass_assert( expr ); 172 173 const ast::TypeSubstitution ** typeSubs_ptr = __pass::typeSubs( core, 0 ); 174 if ( typeSubs_ptr && expr->env ) { 175 *typeSubs_ptr = expr->env; 176 } 177 178 auto nval = expr->accept( *this ); 179 return { nval != expr, nval }; 180 } 181 182 template< typename core_t > 183 ast::__pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept_as_compound( const ast::Stmt * stmt ) { 184 __pedantic_pass_assert( __visit_children() ); 185 __pedantic_pass_assert( stmt ); 186 187 // add a few useful symbols to the scope 188 using __pass::empty; 189 190 // get the stmts/decls that will need to be spliced in 191 auto stmts_before = __pass::stmtsToAddBefore( core, 0 ); 192 auto stmts_after = __pass::stmtsToAddAfter ( core, 0 ); 193 auto decls_before = __pass::declsToAddBefore( core, 0 ); 194 auto decls_after = __pass::declsToAddAfter ( core, 0 ); 195 196 // These may be modified by subnode but most be restored once we exit this statemnet. 197 ValueGuardPtr< const ast::TypeSubstitution * > __old_env ( __pass::typeSubs( core, 0 ) ); 198 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before ); 199 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after ); 200 ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) >::type > __old_stmts_before( decls_before ); 201 ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) >::type > __old_stmts_after ( decls_after ); 202 203 // Now is the time to actually visit the node 204 const ast::Stmt * nstmt = stmt->accept( *this ); 205 206 // If the pass doesn't want to add anything then we are done 207 if ( empty(stmts_before) && empty(stmts_after) && empty(decls_before) && empty(decls_after) ) { 208 return { nstmt != stmt, nstmt }; 209 } 210 211 // Make sure that it is either adding statements or declartions but not both 212 // this is because otherwise the order would be awkward to predict 213 assert(( empty( stmts_before ) && empty( stmts_after )) 214 || ( empty( decls_before ) && empty( decls_after )) ); 215 216 // Create a new Compound Statement to hold the new decls/stmts 217 ast::CompoundStmt * compound = new ast::CompoundStmt( stmt->location ); 218 219 // Take all the declarations that go before 220 __pass::take_all( std::back_inserter( compound->kids ), decls_before ); 221 __pass::take_all( std::back_inserter( compound->kids ), stmts_before ); 222 223 // Insert the original declaration 224 compound->kids.emplace_back( nstmt ); 225 226 // Insert all the declarations that go before 227 __pass::take_all( std::back_inserter( compound->kids ), decls_after ); 228 __pass::take_all( std::back_inserter( compound->kids ), stmts_after ); 229 230 return { true, compound }; 231 } 232 233 template< typename core_t > 234 template< template <class...> class container_t > 235 ast::__pass::template resultNstmt<container_t> ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) { 236 __pedantic_pass_assert( __visit_children() ); 237 if ( statements.empty() ) return {}; 238 239 // We are going to aggregate errors for all these statements 240 SemanticErrorException errors; 241 242 // add a few useful symbols to the scope 243 using __pass::empty; 244 245 // get the stmts/decls that will need to be spliced in 246 auto stmts_before = __pass::stmtsToAddBefore( core, 0 ); 247 auto stmts_after = __pass::stmtsToAddAfter ( core, 0 ); 248 auto decls_before = __pass::declsToAddBefore( core, 0 ); 249 auto decls_after = __pass::declsToAddAfter ( core, 0 ); 250 251 // These may be modified by subnode but most be restored once we exit this statemnet. 252 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) >::type > __old_decls_before( stmts_before ); 253 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) >::type > __old_decls_after ( stmts_after ); 254 ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) >::type > __old_stmts_before( decls_before ); 255 ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) >::type > __old_stmts_after ( decls_after ); 256 257 // update pass statitistics 258 pass_visitor_stats.depth++; 259 pass_visitor_stats.max->push(pass_visitor_stats.depth); 260 pass_visitor_stats.avg->push(pass_visitor_stats.depth); 261 262 __pass::resultNstmt<container_t> new_kids; 263 for ( auto value : enumerate( statements ) ) { 264 try { 265 size_t i = value.idx; 266 const Stmt * stmt = value.val; 267 __pedantic_pass_assert( stmt ); 268 const ast::Stmt * new_stmt = stmt->accept( *this ); 269 assert( new_stmt ); 270 if ( new_stmt != stmt ) { new_kids.differs = true; } 271 272 // Make sure that it is either adding statements or declartions but not both 273 // this is because otherwise the order would be awkward to predict 274 assert(( empty( stmts_before ) && empty( stmts_after )) 275 || ( empty( decls_before ) && empty( decls_after )) ); 276 277 // Take all the statements which should have gone after, N/A for first iteration 278 new_kids.take_all( decls_before ); 279 new_kids.take_all( stmts_before ); 280 281 // Now add the statement if there is one 282 if ( new_stmt != stmt ) { 283 new_kids.values.emplace_back( new_stmt, i, false ); 284 } else { 285 new_kids.values.emplace_back( nullptr, i, true ); 289 286 } 290 catch ( SemanticErrorException &e ) { 291 errors.append( e ); 287 288 // Take all the declarations that go before 289 new_kids.take_all( decls_after ); 290 new_kids.take_all( stmts_after ); 291 } catch ( SemanticErrorException &e ) { 292 errors.append( e ); 293 } 294 } 295 pass_visitor_stats.depth--; 296 if ( !errors.isEmpty() ) { throw errors; } 297 298 return new_kids; 299 } 300 301 template< typename core_t > 302 template< template <class...> class container_t, typename node_t > 303 ast::__pass::template resultN<container_t, node_t> ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) { 304 __pedantic_pass_assert( __visit_children() ); 305 if ( container.empty() ) return {}; 306 SemanticErrorException errors; 307 308 pass_visitor_stats.depth++; 309 pass_visitor_stats.max->push(pass_visitor_stats.depth); 310 pass_visitor_stats.avg->push(pass_visitor_stats.depth); 311 312 bool mutated = false; 313 container_t<ptr<node_t>> new_kids; 314 for ( const node_t * node : container ) { 315 try { 316 __pedantic_pass_assert( node ); 317 const node_t * new_stmt = strict_dynamic_cast< const node_t * >( node->accept( *this ) ); 318 if ( new_stmt != node ) { 319 mutated = true; 320 new_kids.emplace_back( new_stmt ); 321 } else { 322 new_kids.emplace_back( nullptr ); 292 323 } 293 } 294 pass_visitor_stats.depth--; 295 if ( !errors.isEmpty() ) { throw errors; } 296 297 return new_kids; 298 } 299 300 template< typename core_t > 301 template< template <class...> class container_t, typename node_t > 302 __pass::template resultN<container_t, node_t> ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) { 303 __pedantic_pass_assert( __visit_children() ); 304 if( container.empty() ) return {}; 305 SemanticErrorException errors; 306 307 pass_visitor_stats.depth++; 308 pass_visitor_stats.max->push(pass_visitor_stats.depth); 309 pass_visitor_stats.avg->push(pass_visitor_stats.depth); 310 311 bool mutated = false; 312 container_t<ptr<node_t>> new_kids; 313 for ( const node_t * node : container ) { 314 try { 315 __pedantic_pass_assert( node ); 316 const node_t * new_stmt = strict_dynamic_cast< const node_t * >( node->accept( *this ) ); 317 if(new_stmt != node ) { 318 mutated = true; 319 new_kids.emplace_back( new_stmt ); 320 } else { 321 new_kids.emplace_back( nullptr ); 322 } 323 324 } 325 catch( SemanticErrorException &e ) { 326 errors.append( e ); 327 } 328 } 329 330 __pedantic_pass_assert( new_kids.size() == container.size() ); 331 pass_visitor_stats.depth--; 332 if ( ! errors.isEmpty() ) { throw errors; } 333 334 return ast::__pass::resultN<container_t, node_t>{ mutated, new_kids }; 335 } 336 337 template< typename core_t > 338 template<typename node_t, typename super_t, typename field_t> 339 void ast::Pass< core_t >::maybe_accept( 340 const node_t * & parent, 341 field_t super_t::*field 342 ) { 343 static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" ); 344 345 if(__pass::skip(parent->*field)) return; 346 const auto & old_val = __pass::get(parent->*field, 0); 347 348 static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR"); 349 350 auto new_val = call_accept( old_val ); 351 352 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR"); 353 354 if( new_val.differs ) { 355 auto new_parent = __pass::mutate<core_t>(parent); 356 new_val.apply(new_parent, field); 357 parent = new_parent; 358 } 359 } 360 361 template< typename core_t > 362 template<typename node_t, typename super_t, typename field_t> 363 void ast::Pass< core_t >::maybe_accept_top( 364 const node_t * & parent, 365 field_t super_t::*field 366 ) { 367 static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" ); 368 369 if(__pass::skip(parent->*field)) return; 370 const auto & old_val = __pass::get(parent->*field, 0); 371 372 static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR"); 373 374 auto new_val = call_accept_top( old_val ); 375 376 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR"); 377 378 if( new_val.differs ) { 379 auto new_parent = __pass::mutate<core_t>(parent); 380 new_val.apply(new_parent, field); 381 parent = new_parent; 382 } 383 } 384 385 template< typename core_t > 386 template<typename node_t, typename super_t, typename field_t> 387 void ast::Pass< core_t >::maybe_accept_as_compound( 388 const node_t * & parent, 389 field_t super_t::*child 390 ) { 391 static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" ); 392 393 if(__pass::skip(parent->*child)) return; 394 const auto & old_val = __pass::get(parent->*child, 0); 395 396 static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR"); 397 398 auto new_val = call_accept_as_compound( old_val ); 399 400 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR"); 401 402 if( new_val.differs ) { 403 auto new_parent = __pass::mutate<core_t>(parent); 404 new_val.apply( new_parent, child ); 405 parent = new_parent; 406 } 407 } 408 324 } catch ( SemanticErrorException &e ) { 325 errors.append( e ); 326 } 327 } 328 329 __pedantic_pass_assert( new_kids.size() == container.size() ); 330 pass_visitor_stats.depth--; 331 if ( !errors.isEmpty() ) { throw errors; } 332 333 return ast::__pass::resultN<container_t, node_t>{ mutated, new_kids }; 334 } 335 336 template< typename core_t > 337 template<typename node_t, typename super_t, typename field_t> 338 void ast::Pass< core_t >::maybe_accept( 339 const node_t * & parent, 340 field_t super_t::*field 341 ) { 342 static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" ); 343 344 if ( __pass::skip( parent->*field ) ) return; 345 const auto & old_val = __pass::get(parent->*field, 0); 346 347 static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR" ); 348 349 auto new_val = call_accept( old_val ); 350 351 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR" ); 352 353 if ( new_val.differs ) { 354 auto new_parent = __pass::mutate<core_t>(parent); 355 new_val.apply(new_parent, field); 356 parent = new_parent; 357 } 358 } 359 360 template< typename core_t > 361 template<typename node_t, typename super_t, typename field_t> 362 void ast::Pass< core_t >::maybe_accept_top( 363 const node_t * & parent, 364 field_t super_t::*field 365 ) { 366 static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" ); 367 368 if ( __pass::skip( parent->*field ) ) return; 369 const auto & old_val = __pass::get(parent->*field, 0); 370 371 static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR" ); 372 373 auto new_val = call_accept_top( old_val ); 374 375 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR" ); 376 377 if ( new_val.differs ) { 378 auto new_parent = __pass::mutate<core_t>(parent); 379 new_val.apply(new_parent, field); 380 parent = new_parent; 381 } 382 } 383 384 template< typename core_t > 385 template<typename node_t, typename super_t, typename field_t> 386 void ast::Pass< core_t >::maybe_accept_as_compound( 387 const node_t * & parent, 388 field_t super_t::*child 389 ) { 390 static_assert( std::is_base_of<super_t, node_t>::value, "Error deducing member object" ); 391 392 if ( __pass::skip( parent->*child ) ) return; 393 const auto & old_val = __pass::get(parent->*child, 0); 394 395 static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR" ); 396 397 auto new_val = call_accept_as_compound( old_val ); 398 399 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR" ); 400 401 if ( new_val.differs ) { 402 auto new_parent = __pass::mutate<core_t>(parent); 403 new_val.apply( new_parent, child ); 404 parent = new_parent; 405 } 409 406 } 410 407 … … 760 757 761 758 if ( __visit_children() ) { 762 // Do not enter (or leave) a new scope if atFunctionTop. Remember to save the result. 763 auto guard1 = makeFuncGuard( [this, enterScope = !this->atFunctionTop]() { 764 if ( enterScope ) { 765 __pass::symtab::enter(core, 0); 766 } 767 }, [this, leaveScope = !this->atFunctionTop]() { 768 if ( leaveScope ) { 769 __pass::symtab::leave(core, 0); 770 } 771 }); 772 ValueGuard< bool > guard2( atFunctionTop ); 773 atFunctionTop = false; 774 guard_scope guard3 { *this }; 775 maybe_accept( node, &CompoundStmt::kids ); 759 // Do not enter (or leave) a new symbol table scope if atFunctionTop. 760 // But always enter (and leave) a new general scope. 761 if ( atFunctionTop ) { 762 ValueGuard< bool > guard1( atFunctionTop ); 763 atFunctionTop = false; 764 guard_scope guard2( *this ); 765 maybe_accept( node, &CompoundStmt::kids ); 766 } else { 767 guard_symtab guard1( *this ); 768 guard_scope guard2( *this ); 769 maybe_accept( node, &CompoundStmt::kids ); 770 } 776 771 } 777 772 -
src/AST/Pass.proto.hpp
r2b78949 r8a930c03 27 27 28 28 #ifdef PEDANTIC_PASS_ASSERT 29 #define __pedantic_pass_assert(...) assert 29 #define __pedantic_pass_assert(...) assert(__VA_ARGS__) 30 30 #define __pedantic_pass_assertf(...) assertf(__VA_ARGS__) 31 31 #else -
src/AST/Print.cpp
r2b78949 r8a930c03 16 16 #include "Print.hpp" 17 17 18 #include "Attribute.hpp" 18 19 #include "Decl.hpp" 19 20 #include "Expr.hpp" 21 #include "Init.hpp" 20 22 #include "Stmt.hpp" 21 23 #include "Type.hpp" 22 24 #include "TypeSubstitution.hpp" 23 25 #include "CompilationState.h" 24 25 #include "Common/utility.h" // for group_iterate 26 #include "Common/Iterate.hpp" 26 27 27 28 using namespace std; -
src/AST/SymbolTable.cpp
r2b78949 r8a930c03 18 18 #include <cassert> 19 19 20 #include "Copy.hpp" 20 21 #include "Decl.hpp" 21 22 #include "Expr.hpp" … … 87 88 } 88 89 89 SymbolTable::SymbolTable( )90 SymbolTable::SymbolTable( ErrorDetection errorMode ) 90 91 : idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable(), 91 prevScope(), scope( 0 ), repScope( 0 ) { ++*stats().count; }92 prevScope(), scope( 0 ), repScope( 0 ), errorMode(errorMode) { ++*stats().count; } 92 93 93 94 SymbolTable::~SymbolTable() { stats().size->push( idTable ? idTable->size() : 0 ); } 95 96 void SymbolTable::OnFindError( CodeLocation location, std::string error ) const { 97 assertf( errorMode != AssertClean, "Name collision/redefinition, found during a compilation phase where none should be possible. Detail: %s", error.c_str() ); 98 if (errorMode == ValidateOnAdd) { 99 SemanticError(location, error); 100 } 101 assertf( errorMode == IgnoreErrors, "Unrecognized symbol-table error mode %d", errorMode ); 102 } 94 103 95 104 void SymbolTable::enterScope() { … … 268 277 } 269 278 270 namespace { 271 /// true if redeclaration conflict between two types 272 bool addedTypeConflicts( const NamedTypeDecl * existing, const NamedTypeDecl * added ) { 273 if ( existing->base == nullptr ) { 274 return false; 275 } else if ( added->base == nullptr ) { 276 return true; 277 } else { 278 // typedef redeclarations are errors only if types are different 279 if ( ! ResolvExpr::typesCompatible( existing->base, added->base, SymbolTable{} ) ) { 280 SemanticError( added->location, "redeclaration of " + added->name ); 281 } 282 } 283 // does not need to be added to the table if both existing and added have a base that are 284 // the same 279 bool SymbolTable::addedTypeConflicts( 280 const NamedTypeDecl * existing, const NamedTypeDecl * added ) const { 281 if ( existing->base == nullptr ) { 282 return false; 283 } else if ( added->base == nullptr ) { 285 284 return true; 286 } 287 288 /// true if redeclaration conflict between two aggregate declarations 289 bool addedDeclConflicts( const AggregateDecl * existing, const AggregateDecl * added ) { 290 if ( ! existing->body ) { 291 return false; 292 } else if ( added->body ) { 293 SemanticError( added, "redeclaration of " ); 294 } 295 return true; 296 } 285 } else { 286 // typedef redeclarations are errors only if types are different 287 if ( ! ResolvExpr::typesCompatible( existing->base, added->base ) ) { 288 OnFindError( added->location, "redeclaration of " + added->name ); 289 } 290 } 291 // does not need to be added to the table if both existing and added have a base that are 292 // the same 293 return true; 294 } 295 296 bool SymbolTable::addedDeclConflicts( 297 const AggregateDecl * existing, const AggregateDecl * added ) const { 298 if ( ! existing->body ) { 299 return false; 300 } else if ( added->body ) { 301 OnFindError( added, "redeclaration of " ); 302 } 303 return true; 297 304 } 298 305 … … 642 649 } else if ( existing.id->linkage.is_mangled 643 650 || ResolvExpr::typesCompatible( 644 added->get_type(), existing.id->get_type() , SymbolTable{}) ) {651 added->get_type(), existing.id->get_type() ) ) { 645 652 646 653 // it is a conflict if one declaration is deleted and the other is not 647 654 if ( deleter && ! existing.deleter ) { 648 655 if ( handleConflicts.mode == OnConflict::Error ) { 649 SemanticError( added, "deletion of defined identifier " );656 OnFindError( added, "deletion of defined identifier " ); 650 657 } 651 658 return true; 652 659 } else if ( ! deleter && existing.deleter ) { 653 660 if ( handleConflicts.mode == OnConflict::Error ) { 654 SemanticError( added, "definition of deleted identifier " );661 OnFindError( added, "definition of deleted identifier " ); 655 662 } 656 663 return true; … … 660 667 if ( isDefinition( added ) && isDefinition( existing.id ) ) { 661 668 if ( handleConflicts.mode == OnConflict::Error ) { 662 SemanticError( added,669 OnFindError( added, 663 670 isFunction( added ) ? 664 671 "duplicate function definition for " : … … 669 676 } else { 670 677 if ( handleConflicts.mode == OnConflict::Error ) { 671 SemanticError( added, "duplicate definition for " );678 OnFindError( added, "duplicate definition for " ); 672 679 } 673 680 return true; … … 721 728 // Check that a Cforall declaration doesn't override any C declaration 722 729 if ( hasCompatibleCDecl( name, mangleName ) ) { 723 SemanticError( decl, "Cforall declaration hides C function " );730 OnFindError( decl, "Cforall declaration hides C function " ); 724 731 } 725 732 } else { … … 727 734 // type-compatibility, which it may not be. 728 735 if ( hasIncompatibleCDecl( name, mangleName ) ) { 729 SemanticError( decl, "conflicting overload of C function " );736 OnFindError( decl, "conflicting overload of C function " ); 730 737 } 731 738 } -
src/AST/SymbolTable.hpp
r2b78949 r8a930c03 93 93 94 94 public: 95 SymbolTable(); 95 96 /// Mode to control when (during which pass) user-caused name-declaration errors get reported. 97 /// The default setting `AssertClean` supports, "I expect all user-caused errors to have been 98 /// reported by now," or, "I wouldn't know what to do with an error; are there even any here?" 99 enum ErrorDetection { 100 AssertClean, ///< invalid user decls => assert fails during addFoo (default) 101 ValidateOnAdd, ///< invalid user decls => calls SemanticError during addFoo 102 IgnoreErrors ///< acts as if unspecified decls were removed, forcing validity 103 }; 104 105 explicit SymbolTable( 106 ErrorDetection ///< mode for the lifetime of the symbol table (whole pass) 107 ); 108 SymbolTable() : SymbolTable(AssertClean) {} 96 109 ~SymbolTable(); 110 111 ErrorDetection getErrorMode() const { 112 return errorMode; 113 } 97 114 98 115 // when using an indexer manually (e.g., within a mutator traversal), it is necessary to … … 158 175 159 176 private: 177 void OnFindError( CodeLocation location, std::string error ) const; 178 179 template< typename T > 180 void OnFindError( const T * obj, const std::string & error ) const { 181 OnFindError( obj->location, toString( error, obj ) ); 182 } 183 184 template< typename T > 185 void OnFindError( CodeLocation location, const T * obj, const std::string & error ) const { 186 OnFindError( location, toString( error, obj ) ); 187 } 188 160 189 /// Ensures that a proper backtracking scope exists before a mutation 161 190 void lazyInitScope(); … … 168 197 bool removeSpecialOverrides( IdData & decl, MangleTable::Ptr & mangleTable ); 169 198 170 /// Options for handling identifier conflicts 199 /// Error detection mode given at construction (pass-specific). 200 /// Logically const, except that the symbol table's push-pop is achieved by autogenerated 201 /// assignment onto self. The feield is left motuable to keep this code-gen simple. 202 /// Conceptual constness is preserved by all SymbolTable in a stack sharing the same mode. 203 ErrorDetection errorMode; 204 205 /// Options for handling identifier conflicts. 206 /// Varies according to AST location during traversal: captures semantics of the construct 207 /// being visited as "would shadow" vs "must not collide." 208 /// At a given AST location, is the same for every pass. 171 209 struct OnConflict { 172 210 enum { 173 Error, ///< Throw a semantic error211 Error, ///< Follow the current pass's ErrorDetection mode (may throw a semantic error) 174 212 Delete ///< Delete the earlier version with the delete statement 175 213 } mode; … … 191 229 const Decl * deleter ); 192 230 231 /// true if redeclaration conflict between two types 232 bool addedTypeConflicts( const NamedTypeDecl * existing, const NamedTypeDecl * added ) const; 233 234 /// true if redeclaration conflict between two aggregate declarations 235 bool addedDeclConflicts( const AggregateDecl * existing, const AggregateDecl * added ) const; 236 193 237 /// common code for addId, addDeletedId, etc. 194 238 void addIdCommon( … … 213 257 } 214 258 259 215 260 // Local Variables: // 216 261 // tab-width: 4 // -
src/AST/TypeEnvironment.cpp
r2b78949 r8a930c03 178 178 179 179 bool TypeEnvironment::combine( 180 const TypeEnvironment & o, OpenVarSet & open , const SymbolTable & symtab) {180 const TypeEnvironment & o, OpenVarSet & open ) { 181 181 // short-circuit easy cases 182 182 if ( o.empty() ) return true; … … 201 201 EqvClass & r = *rt; 202 202 // merge bindings 203 if ( ! mergeBound( r, c, open , symtab) ) return false;203 if ( ! mergeBound( r, c, open ) ) return false; 204 204 // merge previous unbound variables into this class, checking occurs if needed 205 205 if ( r.bound ) for ( const auto & u : c.vars ) { … … 216 216 } else if ( st != rt ) { 217 217 // bound, but not to the same class 218 if ( ! mergeClasses( rt, st, open , symtab) ) return false;218 if ( ! mergeClasses( rt, st, open ) ) return false; 219 219 } // ignore bound into the same class 220 220 } … … 280 280 bool TypeEnvironment::bindVar( 281 281 const TypeInstType * typeInst, const Type * bindTo, const TypeData & data, 282 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, WidenMode widen, 283 const SymbolTable & symtab 282 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, WidenMode widen 284 283 ) { 285 284 // remove references from bound type, so that type variables can only bind to value types … … 300 299 if ( unifyInexact( 301 300 newType, target, *this, need, have, open, 302 widen & WidenMode{ it->allowWidening, true }, symtab,common ) ) {301 widen & WidenMode{ it->allowWidening, true }, common ) ) { 303 302 if ( common ) { 304 303 it->bound = std::move(common); … … 321 320 const TypeInstType * var1, const TypeInstType * var2, TypeData && data, 322 321 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, 323 WidenMode widen , const SymbolTable & symtab322 WidenMode widen 324 323 ) { 325 324 auto c1 = internal_lookup( *var1 ); … … 358 357 359 358 if ( unifyInexact( 360 newType1, newType2, *this, need, have, open, newWidenMode, symtab,common ) ) {359 newType1, newType2, *this, need, have, open, newWidenMode, common ) ) { 361 360 c1->vars.insert( c2->vars.begin(), c2->vars.end() ); 362 361 c1->allowWidening = widen1 && widen2; … … 409 408 410 409 bool TypeEnvironment::mergeBound( 411 EqvClass & to, const EqvClass & from, OpenVarSet & open , const SymbolTable & symtab) {410 EqvClass & to, const EqvClass & from, OpenVarSet & open ) { 412 411 if ( from.bound ) { 413 412 if ( to.bound ) { … … 419 418 420 419 if ( unifyInexact( 421 toType, fromType, *this, need, have, open, widen, symtab,common ) ) {420 toType, fromType, *this, need, have, open, widen, common ) ) { 422 421 // unifies, set common type if necessary 423 422 if ( common ) { … … 437 436 438 437 bool TypeEnvironment::mergeClasses( 439 ClassList::iterator to, ClassList::iterator from, OpenVarSet & open , const SymbolTable & symtab438 ClassList::iterator to, ClassList::iterator from, OpenVarSet & open 440 439 ) { 441 440 EqvClass & r = *to, & s = *from; 442 441 443 442 // ensure bounds match 444 if ( ! mergeBound( r, s, open , symtab) ) return false;443 if ( ! mergeBound( r, s, open ) ) return false; 445 444 446 445 // check safely bindable -
src/AST/TypeEnvironment.hpp
r2b78949 r8a930c03 169 169 /// Merge environment with this one, checking compatibility. 170 170 /// Returns false if fails, but does NOT roll back partial changes. 171 bool combine( const TypeEnvironment & o, OpenVarSet & openVars , const SymbolTable & symtab);171 bool combine( const TypeEnvironment & o, OpenVarSet & openVars ); 172 172 173 173 /// Add all type variables in environment to open var list … … 183 183 const TypeInstType * typeInst, const Type * bindTo, const TypeData & data, 184 184 AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 185 ResolvExpr::WidenMode widen , const SymbolTable & symtab);185 ResolvExpr::WidenMode widen ); 186 186 187 187 /// Binds the type classes represented by `var1` and `var2` together; will add one or both … … 190 190 const TypeInstType * var1, const TypeInstType * var2, TypeData && data, 191 191 AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 192 ResolvExpr::WidenMode widen , const SymbolTable & symtab);192 ResolvExpr::WidenMode widen ); 193 193 194 194 /// Disallows widening for all bindings in the environment … … 205 205 /// Unifies the type bound of `to` with the type bound of `from`, returning false if fails 206 206 bool mergeBound( 207 EqvClass & to, const EqvClass & from, OpenVarSet & openVars , const SymbolTable & symtab);207 EqvClass & to, const EqvClass & from, OpenVarSet & openVars ); 208 208 209 209 /// Merges two type classes from local environment, returning false if fails 210 210 bool mergeClasses( 211 ClassList::iterator to, ClassList::iterator from, OpenVarSet & openVars, 212 const SymbolTable & symtab ); 211 ClassList::iterator to, ClassList::iterator from, OpenVarSet & openVars); 213 212 214 213 /// Private lookup API; returns array index of string, or env.size() for not found -
src/AST/TypeSubstitution.cpp
r2b78949 r8a930c03 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Jun 3 13:26:00 2017 13 // Update Count : 5 14 // 12 // Last Modified On : Thr May 25 11:24:00 2023 13 // Update Count : 6 14 // 15 16 #include "TypeSubstitution.hpp" 15 17 16 18 #include "Type.hpp" // for TypeInstType, Type, StructInstType, UnionInstType 17 #include " TypeSubstitution.hpp"19 #include "Pass.hpp" // for Pass, PureVisitor, WithGuards, WithVisitorRef 18 20 19 21 namespace ast { 20 21 22 // size_t TypeSubstitution::Substituter::traceId = Stats::Heap::new_stacktrace_id("TypeSubstitution");23 22 24 23 TypeSubstitution::TypeSubstitution() { … … 119 118 } 120 119 120 // definitition must happen after PassVisitor is included so that WithGuards can be used 121 struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter>, public PureVisitor { 122 //static size_t traceId; 123 124 Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {} 125 126 const Type * postvisit( const TypeInstType * aggregateUseType ); 127 128 /// Records type variable bindings from forall-statements 129 void previsit( const FunctionType * type ); 130 /// Records type variable bindings from forall-statements and instantiations of generic types 131 // void handleAggregateType( const BaseInstType * type ); 132 133 // void previsit( const StructInstType * aggregateUseType ); 134 // void previsit( const UnionInstType * aggregateUseType ); 135 136 const TypeSubstitution & sub; 137 int subCount = 0; 138 bool freeOnly; 139 typedef std::unordered_set< TypeEnvKey > BoundVarsType; 140 BoundVarsType boundVars; 141 }; 142 143 // size_t TypeSubstitution::Substituter::traceId = Stats::Heap::new_stacktrace_id("TypeSubstitution"); 144 121 145 void TypeSubstitution::normalize() { 122 146 Pass<Substituter> sub( *this, true ); … … 128 152 } 129 153 } while ( sub.core.subCount ); 154 } 155 156 TypeSubstitution::ApplyResult<Node> TypeSubstitution::applyBase( 157 const Node * input, bool isFree ) const { 158 assert( input ); 159 Pass<Substituter> sub( *this, isFree ); 160 const Node * output = input->accept( sub ); 161 return { output, sub.core.subCount }; 130 162 } 131 163 -
src/AST/TypeSubstitution.hpp
r2b78949 r8a930c03 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : T ue Apr 30 22:52:47 201913 // Update Count : 911 // Last Modified By : Andrew Beach 12 // Last Modified On : Thr May 25 12:31:00 2023 13 // Update Count : 10 14 14 // 15 15 … … 46 46 TypeSubstitution &operator=( const TypeSubstitution &other ); 47 47 48 template< typename SynTreeClass>48 template< typename node_t > 49 49 struct ApplyResult { 50 ast::ptr< SynTreeClass> node;50 ast::ptr<node_t> node; 51 51 int count; 52 52 }; 53 53 54 template< typename SynTreeClass > ApplyResult<SynTreeClass> apply( const SynTreeClass * input ) const; 55 template< typename SynTreeClass > ApplyResult<SynTreeClass> applyFree( const SynTreeClass * input ) const; 54 template< typename node_t > 55 ApplyResult<node_t> apply( const node_t * input ) const { 56 ApplyResult<Node> ret = applyBase( input, false ); 57 return { ret.node.strict_as<node_t>(), ret.count }; 58 } 56 59 57 60 template< typename node_t, enum Node::ref_type ref_t > 58 61 int apply( ptr_base< node_t, ref_t > & input ) const { 59 const node_t * p = input.get(); 60 auto ret = apply(p); 61 input = ret.node; 62 ApplyResult<Node> ret = applyBase( input.get(), false ); 63 input = ret.node.strict_as<node_t>(); 62 64 return ret.count; 65 } 66 67 template< typename node_t > 68 ApplyResult<node_t> applyFree( const node_t * input ) const { 69 ApplyResult<Node> ret = applyBase( input, true ); 70 return { ret.node.strict_as<node_t>(), ret.count }; 63 71 } 64 72 65 73 template< typename node_t, enum Node::ref_type ref_t > 66 74 int applyFree( ptr_base< node_t, ref_t > & input ) const { 67 const node_t * p = input.get(); 68 auto ret = applyFree(p); 69 input = ret.node; 75 ApplyResult<Node> ret = applyBase( input.get(), true ); 76 input = ret.node.strict_as<node_t>(); 70 77 return ret.count; 71 78 } … … 97 104 // Mutator that performs the substitution 98 105 struct Substituter; 106 ApplyResult<Node> applyBase( const Node * input, bool isFree ) const; 99 107 100 108 // TODO: worry about traversing into a forall-qualified function type or type decl with assertions … … 158 166 } // namespace ast 159 167 160 // include needs to happen after TypeSubstitution is defined so that both TypeSubstitution and161 // PassVisitor are defined before PassVisitor implementation accesses TypeSubstitution internals.162 #include "Pass.hpp"163 #include "Copy.hpp"164 165 namespace ast {166 167 // definitition must happen after PassVisitor is included so that WithGuards can be used168 struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter>, public PureVisitor {169 static size_t traceId;170 171 Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}172 173 const Type * postvisit( const TypeInstType * aggregateUseType );174 175 /// Records type variable bindings from forall-statements176 void previsit( const FunctionType * type );177 /// Records type variable bindings from forall-statements and instantiations of generic types178 // void handleAggregateType( const BaseInstType * type );179 180 // void previsit( const StructInstType * aggregateUseType );181 // void previsit( const UnionInstType * aggregateUseType );182 183 const TypeSubstitution & sub;184 int subCount = 0;185 bool freeOnly;186 typedef std::unordered_set< TypeEnvKey > BoundVarsType;187 BoundVarsType boundVars;188 189 };190 191 template< typename SynTreeClass >192 TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::apply( const SynTreeClass * input ) const {193 assert( input );194 Pass<Substituter> sub( *this, false );195 input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );196 return { input, sub.core.subCount };197 }198 199 template< typename SynTreeClass >200 TypeSubstitution::ApplyResult<SynTreeClass> TypeSubstitution::applyFree( const SynTreeClass * input ) const {201 assert( input );202 Pass<Substituter> sub( *this, true );203 input = strict_dynamic_cast< const SynTreeClass * >( input->accept( sub ) );204 return { input, sub.core.subCount };205 }206 207 } // namespace ast208 209 168 // Local Variables: // 210 169 // tab-width: 4 // -
src/AST/Util.cpp
r2b78949 r8a930c03 83 83 } 84 84 85 /// Check that the MemberExpr has an aggregate type and matching member. 86 void memberMatchesAggregate( const MemberExpr * expr ) { 87 const Type * aggrType = expr->aggregate->result->stripReferences(); 88 const AggregateDecl * decl = nullptr; 89 if ( auto inst = dynamic_cast<const StructInstType *>( aggrType ) ) { 90 decl = inst->base; 91 } else if ( auto inst = dynamic_cast<const UnionInstType *>( aggrType ) ) { 92 decl = inst->base; 93 } 94 assertf( decl, "Aggregate of member not correct type." ); 95 96 for ( auto aggrMember : decl->members ) { 97 if ( expr->member == aggrMember ) { 98 return; 99 } 100 } 101 assertf( false, "Member not found." ); 102 } 103 85 104 struct InvariantCore { 86 105 // To save on the number of visits: this is a kind of composed core. … … 108 127 } 109 128 129 void previsit( const MemberExpr * node ) { 130 previsit( (const ParseNode *)node ); 131 memberMatchesAggregate( node ); 132 } 133 110 134 void postvisit( const Node * node ) { 111 135 no_strong_cycles.postvisit( node ); -
src/Concurrency/Actors.cpp
r2b78949 r8a930c03 38 38 bool namedDecl = false; 39 39 40 // finds and sets a ptr to the Allocation enum, which is needed in the next pass40 // finds and sets a ptr to the allocation enum, which is needed in the next pass 41 41 void previsit( const EnumDecl * decl ) { 42 if( decl->name == " Allocation" ) *allocationDecl = decl;42 if( decl->name == "allocation" ) *allocationDecl = decl; 43 43 } 44 44 … … 227 227 static inline derived_actor & ?|?( derived_actor & receiver, derived_msg & msg ) { 228 228 request new_req; 229 Allocation (*my_work_fn)( derived_actor &, derived_msg & ) = receive;229 allocation (*my_work_fn)( derived_actor &, derived_msg & ) = receive; 230 230 __receive_fn fn = (__receive_fn)my_work_fn; 231 231 new_req{ &receiver, &msg, fn }; … … 246 246 )); 247 247 248 // Function type is: Allocation (*)( derived_actor &, derived_msg & )248 // Function type is: allocation (*)( derived_actor &, derived_msg & ) 249 249 FunctionType * derivedReceive = new FunctionType(); 250 250 derivedReceive->params.push_back( ast::deepCopy( derivedActorRef ) ); … … 252 252 derivedReceive->returns.push_back( new EnumInstType( *allocationDecl ) ); 253 253 254 // Generates: Allocation (*my_work_fn)( derived_actor &, derived_msg & ) = receive;254 // Generates: allocation (*my_work_fn)( derived_actor &, derived_msg & ) = receive; 255 255 sendBody->push_back( new DeclStmt( 256 256 decl->location, … … 263 263 )); 264 264 265 // Function type is: Allocation (*)( actor &, message & )265 // Function type is: allocation (*)( actor &, message & ) 266 266 FunctionType * genericReceive = new FunctionType(); 267 267 genericReceive->params.push_back( new ReferenceType( new StructInstType( *actorDecl ) ) ); … … 269 269 genericReceive->returns.push_back( new EnumInstType( *allocationDecl ) ); 270 270 271 // Generates: Allocation (*fn)( actor &, message & ) = (Allocation (*)( actor &, message & ))my_work_fn;271 // Generates: allocation (*fn)( actor &, message & ) = (allocation (*)( actor &, message & ))my_work_fn; 272 272 // More readable synonymous code: 273 // typedef Allocation (*__receive_fn)(actor &, message &);273 // typedef allocation (*__receive_fn)(actor &, message &); 274 274 // __receive_fn fn = (__receive_fn)my_work_fn; 275 275 sendBody->push_back( new DeclStmt( … … 422 422 const StructDecl ** msgDecl = &msgDeclPtr; 423 423 424 // first pass collects ptrs to Allocation enum, request type, and generic receive fn typedef424 // first pass collects ptrs to allocation enum, request type, and generic receive fn typedef 425 425 // also populates maps of all derived actors and messages 426 426 Pass<CollectactorStructDecls>::run( translationUnit, actorStructDecls, messageStructDecls, requestDecl, -
src/Concurrency/Waituntil.cpp
r2b78949 r8a930c03 14 14 // 15 15 16 #include "Waituntil.hpp" 17 16 18 #include <string> 17 19 18 #include " Waituntil.hpp"20 #include "AST/Copy.hpp" 19 21 #include "AST/Expr.hpp" 20 22 #include "AST/Pass.hpp" … … 93 95 case 0: 94 96 try { 95 if (on_selected( A, clause1 ))97 on_selected( A, clause1 ); 96 98 doA(); 97 99 } … … 120 122 // the unregister and on_selected calls are needed to support primitives where the acquire has side effects 121 123 // so the corresponding block MUST be run for those primitives to not lose state (example is channels) 122 if ( ! has_run(clause_statuses[0]) && whenA && unregister_select(A, clause1) && on_selected( A, clause1 ) ) 124 if ( !has_run(clause_statuses[0]) && whenA && unregister_select(A, clause1) ) 125 on_selected( A, clause1 ) 123 126 doA(); 124 127 ... repeat if above for B and C ... … … 617 620 618 621 // Generates: 619 /* if ( on_selected( target_1, node_1 ))... corresponding body of target_1 ...622 /* on_selected( target_1, node_1 ); ... corresponding body of target_1 ... 620 623 */ 621 624 CompoundStmt * GenerateWaitUntilCore::genStmtBlock( const WhenClause * clause, const ClauseData * data ) { … … 623 626 return new CompoundStmt( cLoc, 624 627 { 625 new IfStmt( cLoc, 626 genSelectTraitCall( clause, data, "on_selected" ), 627 new CompoundStmt( cLoc, 628 { 629 ast::deepCopy( clause->stmt ) 630 } 631 ) 632 ) 628 new ExprStmt( cLoc, 629 genSelectTraitCall( clause, data, "on_selected" ) 630 ), 631 ast::deepCopy( clause->stmt ) 633 632 } 634 633 ); … … 642 641 case 0: 643 642 try { 644 if (on_selected( target1, clause1 ))645 643 on_selected( target1, clause1 ); 644 dotarget1stmt(); 646 645 } 647 646 finally { clause_statuses[i] = __SELECT_RUN; unregister_select(target1, clause1); } … … 662 661 case 0: 663 662 try { 664 if (on_selected( target1, clause1 ))665 663 on_selected( target1, clause1 ); 664 dotarget1stmt(); 666 665 } 667 666 finally { clause_statuses[i] = __SELECT_RUN; unregister_select(target1, clause1); } … … 938 937 } 939 938 940 // C_TODO: will remove this commented code later. Currently it isn't needed but may switch to a modified version of this later if it has better performance941 // std::vector<ptr<CaseClause>> switchCases;942 943 // int idx = 0;944 // for ( const auto & clause: stmt->clauses ) {945 // const CodeLocation & cLoc = clause->location;946 // switchCases.push_back(947 // new CaseClause( cLoc,948 // new CastExpr( cLoc,949 // new AddressExpr( cLoc, new NameExpr( cLoc, data.at(idx)->targetName ) ),950 // new BasicType( BasicType::Kind::LongUnsignedInt ), GeneratedFlag::ExplicitCast951 // ),952 // {953 // new CompoundStmt( cLoc,954 // {955 // ast::deepCopy( clause->stmt ),956 // new BranchStmt( cLoc, BranchStmt::Kind::Break, Label( cLoc ) )957 // }958 // )959 // }960 // )961 // );962 // idx++;963 // }964 965 939 return new CompoundStmt( loc, 966 940 { 967 941 new ExprStmt( loc, new UntypedExpr( loc, new NameExpr( loc, "park" ) ) ), 968 942 outerIf 969 // new SwitchStmt( loc,970 // new NameExpr( loc, statusName ),971 // std::move( switchCases )972 // )973 943 } 974 944 ); … … 1013 983 const CodeLocation & cLoc = stmt->clauses.at(idx)->location; 1014 984 985 Expr * baseCond = genSelectTraitCall( stmt->clauses.at(idx), data.at(idx), "register_select" ); 1015 986 Expr * ifCond; 1016 987 … … 1023 994 ), 1024 995 new CastExpr( cLoc, 1025 genSelectTraitCall( stmt->clauses.at(idx), data.at(idx), "register_select" ),996 baseCond, 1026 997 new BasicType( BasicType::Kind::Bool ), GeneratedFlag::ExplicitCast 1027 998 ), 1028 999 LogicalFlag::AndExpr 1029 1000 ); 1030 } else ifCond = genSelectTraitCall( stmt->clauses.at(idx), data.at(idx), "register_select" );1001 } else ifCond = baseCond; 1031 1002 1032 1003 return new CompoundStmt( cLoc, … … 1046 1017 ifCond, 1047 1018 genStmtBlock( stmt->clauses.at(idx), data.at(idx) ), 1048 // ast::deepCopy( stmt->clauses.at(idx)->stmt ),1049 1019 recursiveOrIfGen( stmt, data, idx + 1, elseWhenName ) 1050 1020 ) -
src/ControlStruct/ExceptDeclNew.cpp
r2b78949 r8a930c03 18 18 #include <sstream> 19 19 20 #include "AST/Copy.hpp" 20 21 #include "AST/Decl.hpp" 21 22 #include "AST/Pass.hpp" -
src/GenPoly/InstantiateGenericNew.cpp
r2b78949 r8a930c03 362 362 ResolvExpr::typesCompatible( 363 363 memberExpr->result, 364 memberExpr->member->get_type() , ast::SymbolTable()) ) {364 memberExpr->member->get_type() ) ) { 365 365 return memberExpr; 366 366 } -
src/GenPoly/LvalueNew.cpp
r2b78949 r8a930c03 359 359 !ResolvExpr::typesCompatible( 360 360 srcType, 361 strict_dynamic_cast<ast::ReferenceType const *>( dstType )->base, 362 ast::SymbolTable() ) ) { 361 strict_dynamic_cast<ast::ReferenceType const *>( dstType )->base ) ) { 363 362 // Must keep cast if cast-to type is different from the actual type. 364 363 return ast::mutate_field( expr, &ast::CastExpr::arg, ret ); … … 377 376 if ( !ResolvExpr::typesCompatibleIgnoreQualifiers( 378 377 dstType->stripReferences(), 379 srcType->stripReferences(), 380 ast::SymbolTable() ) ) { 378 srcType->stripReferences() ) ) { 381 379 return ast::mutate_field( expr, &ast::CastExpr::arg, ret ); 382 380 } … … 393 391 ResolvExpr::typesCompatible( 394 392 expr->result, 395 expr->arg->result , ast::SymbolTable()) ) {393 expr->arg->result ) ) { 396 394 PRINT( 397 395 std::cerr << "types are compatible, removing cast: " << expr << '\n'; … … 590 588 ast::OpenVarSet openVars; 591 589 ResolvExpr::unify( ret->arg2->result, ret->arg3->result, newEnv, 592 needAssertions, haveAssertions, openVars, 593 ast::SymbolTable(), common ); 590 needAssertions, haveAssertions, openVars, common ); 594 591 ret->result = common ? common : ast::deepCopy( ret->arg2->result ); 595 592 return ret; -
src/GenPoly/SpecializeNew.cpp
r2b78949 r8a930c03 16 16 #include "Specialize.h" 17 17 18 #include "AST/Copy.hpp" // for deepCopy 18 19 #include "AST/Inspect.hpp" // for isIntrinsicCallExpr 19 20 #include "AST/Pass.hpp" // for Pass -
src/InitTweak/InitTweak.cc
r2b78949 r8a930c03 1066 1066 const ast::Type * t2 = ftype->params.back(); 1067 1067 1068 return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2 , ast::SymbolTable());1068 return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2 ); 1069 1069 } 1070 1070 -
src/MakeLibCfaNew.cpp
r2b78949 r8a930c03 16 16 #include "MakeLibCfa.h" 17 17 18 #include "AST/Copy.hpp" 18 19 #include "AST/Fwd.hpp" 19 20 #include "AST/Pass.hpp" -
src/Parser/lex.ll
r2b78949 r8a930c03 10 10 * Created On : Sat Sep 22 08:58:10 2001 11 11 * Last Modified By : Peter A. Buhr 12 * Last Modified On : Tue May 2 08:45:21202313 * Update Count : 7 6912 * Last Modified On : Fri Jun 9 10:04:00 2023 13 * Update Count : 770 14 14 */ 15 15 … … 319 319 static { KEYWORD_RETURN(STATIC); } 320 320 _Static_assert { KEYWORD_RETURN(STATICASSERT); } // C11 321 _static_assert { KEYWORD_RETURN(STATICASSERT); } // C23 321 322 struct { KEYWORD_RETURN(STRUCT); } 322 323 suspend { KEYWORD_RETURN(SUSPEND); } // CFA -
src/Parser/parser.yy
r2b78949 r8a930c03 10 10 // Created On : Sat Sep 1 20:22:55 2001 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Apr 26 16:45:37202313 // Update Count : 63 3012 // Last Modified On : Wed Jun 7 14:32:28 2023 13 // Update Count : 6341 14 14 // 15 15 … … 108 108 assert( declList ); 109 109 // printf( "distAttr1 typeSpec %p\n", typeSpec ); typeSpec->print( std::cout ); 110 DeclarationNode * c ur = declList, * cl = (new DeclarationNode)->addType( typeSpec );110 DeclarationNode * cl = (new DeclarationNode)->addType( typeSpec ); 111 111 // printf( "distAttr2 cl %p\n", cl ); cl->type->print( std::cout ); 112 112 // cl->type->aggregate.name = cl->type->aggInst.aggregate->aggregate.name; 113 113 114 for ( cur = dynamic_cast<DeclarationNode *>( cur->get_next() ); cur != nullptr; cur = dynamic_cast<DeclarationNode *>( cur->get_next() ) ) {114 for ( DeclarationNode * cur = dynamic_cast<DeclarationNode *>( declList->get_next() ); cur != nullptr; cur = dynamic_cast<DeclarationNode *>( cur->get_next() ) ) { 115 115 cl->cloneBaseType( cur ); 116 116 } // for … … 206 206 #define NEW_ONE new ExpressionNode( build_constantInteger( yylloc, *new string( "1" ) ) ) 207 207 #define UPDOWN( compop, left, right ) (compop == OperKinds::LThan || compop == OperKinds::LEThan ? left : right) 208 #define MISSING_ANON_FIELD " Missing loop fields with an anonymous loop index is meaningless as loop index is unavailable in loop body."209 #define MISSING_LOW " Missing low value for up-to range so index is uninitialized."210 #define MISSING_HIGH " Missing high value for down-to range so index is uninitialized."208 #define MISSING_ANON_FIELD "syntax error, missing loop fields with an anonymous loop index is meaningless as loop index is unavailable in loop body." 209 #define MISSING_LOW "syntax error, missing low value for up-to range so index is uninitialized." 210 #define MISSING_HIGH "syntax error, missing high value for down-to range so index is uninitialized." 211 211 212 212 static ForCtrl * makeForCtrl( … … 232 232 ForCtrl * forCtrl( const CodeLocation & location, DeclarationNode * index, ExpressionNode * start, enum OperKinds compop, ExpressionNode * comp, ExpressionNode * inc ) { 233 233 if ( index->initializer ) { 234 SemanticError( yylloc, " Direct initialization disallowed. Use instead: type var; initialization ~ comparison ~ increment." );234 SemanticError( yylloc, "syntax error, direct initialization disallowed. Use instead: type var; initialization ~ comparison ~ increment." ); 235 235 } // if 236 236 if ( index->next ) { 237 SemanticError( yylloc, " Multiple loop indexes disallowed in for-loop declaration." );237 SemanticError( yylloc, "syntax error, multiple loop indexes disallowed in for-loop declaration." ); 238 238 } // if 239 239 DeclarationNode * initDecl = index->addInitializer( new InitializerNode( start ) ); … … 260 260 return forCtrl( location, type, new string( identifier->name ), start, compop, comp, inc ); 261 261 } else { 262 SemanticError( yylloc, " Expression disallowed. Only loop-index nameallowed." ); return nullptr;262 SemanticError( yylloc, "syntax error, loop-index name missing. Expression disallowed." ); return nullptr; 263 263 } // if 264 264 } else { 265 SemanticError( yylloc, " Expression disallowed. Only loop-index name allowed." ); return nullptr;265 SemanticError( yylloc, "syntax error, loop-index name missing. Expression disallowed. ." ); return nullptr; 266 266 } // if 267 267 } // forCtrl 268 268 269 269 static void IdentifierBeforeIdentifier( string & identifier1, string & identifier2, const char * kind ) { 270 SemanticError( yylloc, ::toString( " Adjacent identifiers \"", identifier1, "\" and \"", identifier2, "\" are not meaningful in a", kind, ".\n"270 SemanticError( yylloc, ::toString( "syntax error, adjacent identifiers \"", identifier1, "\" and \"", identifier2, "\" are not meaningful in a", kind, ".\n" 271 271 "Possible cause is misspelled type name or missing generic parameter." ) ); 272 272 } // IdentifierBeforeIdentifier 273 273 274 274 static void IdentifierBeforeType( string & identifier, const char * kind ) { 275 SemanticError( yylloc, ::toString( " Identifier \"", identifier, "\" cannot appear before a ", kind, ".\n"275 SemanticError( yylloc, ::toString( "syntax error, identifier \"", identifier, "\" cannot appear before a ", kind, ".\n" 276 276 "Possible cause is misspelled storage/CV qualifier, misspelled typename, or missing generic parameter." ) ); 277 277 } // IdentifierBeforeType … … 689 689 // | RESUME '(' comma_expression ')' compound_statement 690 690 // { SemanticError( yylloc, "Resume expression is currently unimplemented." ); $$ = nullptr; } 691 | IDENTIFIER IDENTIFIER // syntax error691 | IDENTIFIER IDENTIFIER // invalid syntax rules 692 692 { IdentifierBeforeIdentifier( *$1.str, *$2.str, "n expression" ); $$ = nullptr; } 693 | IDENTIFIER type_qualifier // syntax error693 | IDENTIFIER type_qualifier // invalid syntax rules 694 694 { IdentifierBeforeType( *$1.str, "type qualifier" ); $$ = nullptr; } 695 | IDENTIFIER storage_class // syntax error695 | IDENTIFIER storage_class // invalid syntax rules 696 696 { IdentifierBeforeType( *$1.str, "storage class" ); $$ = nullptr; } 697 | IDENTIFIER basic_type_name // syntax error697 | IDENTIFIER basic_type_name // invalid syntax rules 698 698 { IdentifierBeforeType( *$1.str, "type" ); $$ = nullptr; } 699 | IDENTIFIER TYPEDEFname // syntax error699 | IDENTIFIER TYPEDEFname // invalid syntax rules 700 700 { IdentifierBeforeType( *$1.str, "type" ); $$ = nullptr; } 701 | IDENTIFIER TYPEGENname // syntax error701 | IDENTIFIER TYPEGENname // invalid syntax rules 702 702 { IdentifierBeforeType( *$1.str, "type" ); $$ = nullptr; } 703 703 ; … … 1152 1152 identifier_or_type_name ':' attribute_list_opt statement 1153 1153 { $$ = $4->add_label( yylloc, $1, $3 ); } 1154 | identifier_or_type_name ':' attribute_list_opt error // syntax error1155 { 1156 SemanticError( yylloc, ::toString( " Label \"", *$1.str, "\" must be associated with a statement, "1154 | identifier_or_type_name ':' attribute_list_opt error // invalid syntax rule 1155 { 1156 SemanticError( yylloc, ::toString( "syntx error, label \"", *$1.str, "\" must be associated with a statement, " 1157 1157 "where a declaration, case, or default is not a statement. " 1158 1158 "Move the label or terminate with a semi-colon." ) ); … … 1193 1193 | statement_list_nodecl statement 1194 1194 { assert( $1 ); $1->set_last( $2 ); $$ = $1; } 1195 | statement_list_nodecl error // syntax error1196 { SemanticError( yylloc, " Declarations only allowed at the start of the switch body, i.e., after the '{'." ); $$ = nullptr; }1195 | statement_list_nodecl error // invalid syntax rule 1196 { SemanticError( yylloc, "syntax error, declarations only allowed at the start of the switch body, i.e., after the '{'." ); $$ = nullptr; } 1197 1197 ; 1198 1198 … … 1219 1219 $$ = $7 ? new StatementNode( build_compound( yylloc, (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw; 1220 1220 } 1221 | SWITCH '(' comma_expression ')' '{' error '}' // CFA, syntaxerror1222 { SemanticError( yylloc, " Only declarations canappear before the list of case clauses." ); $$ = nullptr; }1221 | SWITCH '(' comma_expression ')' '{' error '}' // CFA, invalid syntax rule error 1222 { SemanticError( yylloc, "synatx error, declarations can only appear before the list of case clauses." ); $$ = nullptr; } 1223 1223 | CHOOSE '(' comma_expression ')' case_clause // CFA 1224 1224 { $$ = new StatementNode( build_switch( yylloc, false, $3, $5 ) ); } … … 1228 1228 $$ = $7 ? new StatementNode( build_compound( yylloc, (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw; 1229 1229 } 1230 | CHOOSE '(' comma_expression ')' '{' error '}' // CFA, syntax error1231 { SemanticError( yylloc, " Only declarations canappear before the list of case clauses." ); $$ = nullptr; }1230 | CHOOSE '(' comma_expression ')' '{' error '}' // CFA, invalid syntax rule 1231 { SemanticError( yylloc, "syntax error, declarations can only appear before the list of case clauses." ); $$ = nullptr; } 1232 1232 ; 1233 1233 … … 1268 1268 1269 1269 case_label: // CFA 1270 CASE error // syntax error1271 { SemanticError( yylloc, " Missing case listafter case." ); $$ = nullptr; }1270 CASE error // invalid syntax rule 1271 { SemanticError( yylloc, "syntax error, case list missing after case." ); $$ = nullptr; } 1272 1272 | CASE case_value_list ':' { $$ = $2; } 1273 | CASE case_value_list error // syntax error1274 { SemanticError( yylloc, " Missing colonafter case list." ); $$ = nullptr; }1273 | CASE case_value_list error // invalid syntax rule 1274 { SemanticError( yylloc, "syntax error, colon missing after case list." ); $$ = nullptr; } 1275 1275 | DEFAULT ':' { $$ = new ClauseNode( build_default( yylloc ) ); } 1276 1276 // A semantic check is required to ensure only one default clause per switch/choose statement. 1277 | DEFAULT error // syntax error1278 { SemanticError( yylloc, " Missing colonafter default." ); $$ = nullptr; }1277 | DEFAULT error // invalid syntax rules 1278 { SemanticError( yylloc, "syntax error, colon missing after default." ); $$ = nullptr; } 1279 1279 ; 1280 1280 … … 1405 1405 else { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1406 1406 } 1407 | comma_expression updowneq comma_expression '~' '@' // CFA, error1407 | comma_expression updowneq comma_expression '~' '@' // CFA, invalid syntax rules 1408 1408 { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; } 1409 | '@' updowneq '@' // CFA, error1409 | '@' updowneq '@' // CFA, invalid syntax rules 1410 1410 { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; } 1411 | '@' updowneq comma_expression '~' '@' // CFA, error1411 | '@' updowneq comma_expression '~' '@' // CFA, invalid syntax rules 1412 1412 { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; } 1413 | comma_expression updowneq '@' '~' '@' // CFA, error1413 | comma_expression updowneq '@' '~' '@' // CFA, invalid syntax rules 1414 1414 { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; } 1415 | '@' updowneq '@' '~' '@' // CFA, error1415 | '@' updowneq '@' '~' '@' // CFA, invalid syntax rules 1416 1416 { SemanticError( yylloc, MISSING_ANON_FIELD ); $$ = nullptr; } 1417 1417 … … 1431 1431 { 1432 1432 if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1433 else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, " Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }1433 else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "syntax error, equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1434 1434 else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, NEW_ONE ); 1435 1435 } 1436 | comma_expression ';' '@' updowneq '@' // CFA, error1437 { SemanticError( yylloc, " Missing low/high value for up/down-to range so index is uninitialized." ); $$ = nullptr; }1436 | comma_expression ';' '@' updowneq '@' // CFA, invalid syntax rules 1437 { SemanticError( yylloc, "syntax error, missing low/high value for up/down-to range so index is uninitialized." ); $$ = nullptr; } 1438 1438 1439 1439 | comma_expression ';' comma_expression updowneq comma_expression '~' comma_expression // CFA 1440 1440 { $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), $7 ); } 1441 | comma_expression ';' '@' updowneq comma_expression '~' comma_expression // CFA, error1441 | comma_expression ';' '@' updowneq comma_expression '~' comma_expression // CFA, invalid syntax rules 1442 1442 { 1443 1443 if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } … … 1447 1447 { 1448 1448 if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1449 else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, " Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }1449 else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "syntax error, equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1450 1450 else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, $7 ); 1451 1451 } 1452 1452 | comma_expression ';' comma_expression updowneq comma_expression '~' '@' // CFA 1453 1453 { $$ = forCtrl( yylloc, $3, $1, UPDOWN( $4, $3->clone(), $5 ), $4, UPDOWN( $4, $5->clone(), $3->clone() ), nullptr ); } 1454 | comma_expression ';' '@' updowneq comma_expression '~' '@' // CFA, error1454 | comma_expression ';' '@' updowneq comma_expression '~' '@' // CFA, invalid syntax rules 1455 1455 { 1456 1456 if ( $4 == OperKinds::LThan || $4 == OperKinds::LEThan ) { SemanticError( yylloc, MISSING_LOW ); $$ = nullptr; } … … 1460 1460 { 1461 1461 if ( $4 == OperKinds::GThan || $4 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1462 else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, " Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }1462 else if ( $4 == OperKinds::LEThan ) { SemanticError( yylloc, "syntax error, equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1463 1463 else $$ = forCtrl( yylloc, $3, $1, $3->clone(), $4, nullptr, nullptr ); 1464 1464 } 1465 1465 | comma_expression ';' '@' updowneq '@' '~' '@' // CFA 1466 { SemanticError( yylloc, " Missing low/high value for up/down-to range so index is uninitialized." ); $$ = nullptr; }1466 { SemanticError( yylloc, "syntax error, missing low/high value for up/down-to range so index is uninitialized." ); $$ = nullptr; } 1467 1467 1468 1468 | declaration comma_expression // CFA … … 1481 1481 { 1482 1482 if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1483 else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, " Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }1483 else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "syntax error, equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1484 1484 else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, NEW_ONE ); 1485 1485 } … … 1495 1495 { 1496 1496 if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1497 else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, " Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }1497 else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "syntax error, equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1498 1498 else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, $6 ); 1499 1499 } … … 1508 1508 { 1509 1509 if ( $3 == OperKinds::GThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, MISSING_HIGH ); $$ = nullptr; } 1510 else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, " Equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; }1510 else if ( $3 == OperKinds::LEThan ) { SemanticError( yylloc, "syntax error, equality with missing high value is meaningless. Use \"~\"." ); $$ = nullptr; } 1511 1511 else $$ = forCtrl( yylloc, $1, $2, $3, nullptr, nullptr ); 1512 1512 } 1513 | declaration '@' updowneq '@' '~' '@' // CFA, error1514 { SemanticError( yylloc, " Missing low/high value for up/down-to range so index is uninitialized." ); $$ = nullptr; }1513 | declaration '@' updowneq '@' '~' '@' // CFA, invalid syntax rules 1514 { SemanticError( yylloc, "syntax error, missing low/high value for up/down-to range so index is uninitialized." ); $$ = nullptr; } 1515 1515 1516 1516 | comma_expression ';' TYPEDEFname // CFA, array type … … 1521 1521 | comma_expression ';' downupdowneq TYPEDEFname // CFA, array type 1522 1522 { 1523 if ( $3 == OperKinds::LEThan || $3 == OperKinds::GEThan ) { SemanticError( yylloc, "All enumation ranges are equal (all values). Remove \"=~\"." ); $$ = nullptr; } 1523 if ( $3 == OperKinds::LEThan || $3 == OperKinds::GEThan ) { 1524 SemanticError( yylloc, "syntax error, all enumeration ranges are equal (all values). Remove \"=~\"." ); $$ = nullptr; 1525 } 1524 1526 SemanticError( yylloc, "Type iterator is currently unimplemented." ); $$ = nullptr; 1525 1527 } … … 1616 1618 MUTEX '(' argument_expression_list_opt ')' statement 1617 1619 { 1618 if ( ! $3 ) { SemanticError( yylloc, " mutex argument list cannot be empty." ); $$ = nullptr; }1620 if ( ! $3 ) { SemanticError( yylloc, "syntax error, mutex argument list cannot be empty." ); $$ = nullptr; } 1619 1621 $$ = new StatementNode( build_mutex( yylloc, $3, $5 ) ); 1620 1622 } … … 1664 1666 { $$ = build_waitfor_timeout( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ); } 1665 1667 // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless) 1666 | wor_waitfor_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error1667 { SemanticError( yylloc, " else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }1668 | wor_waitfor_clause wor when_clause_opt timeout statement wor ELSE statement // invalid syntax rules 1669 { SemanticError( yylloc, "syntax error, else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; } 1668 1670 | wor_waitfor_clause wor when_clause_opt timeout statement wor when_clause ELSE statement 1669 1671 { $$ = build_waitfor_else( yylloc, build_waitfor_timeout( yylloc, $1, $3, $4, maybe_build_compound( yylloc, $5 ) ), $7, maybe_build_compound( yylloc, $9 ) ); } … … 1709 1711 { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1, build_waituntil_timeout( yylloc, $3, $4, maybe_build_compound( yylloc, $5 ) ) ); } 1710 1712 // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless) 1711 | wor_waituntil_clause wor when_clause_opt timeout statement wor ELSE statement // syntax error1712 { SemanticError( yylloc, " else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }1713 | wor_waituntil_clause wor when_clause_opt timeout statement wor ELSE statement // invalid syntax rules 1714 { SemanticError( yylloc, "syntax error, else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; } 1713 1715 | wor_waituntil_clause wor when_clause_opt timeout statement wor when_clause ELSE statement 1714 1716 { $$ = new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::LEFT_OR, $1, … … 2065 2067 assert( $1->type ); 2066 2068 if ( $1->type->qualifiers.any() ) { // CV qualifiers ? 2067 SemanticError( yylloc, " Useless type qualifier(s) in empty declaration." ); $$ = nullptr;2069 SemanticError( yylloc, "syntax error, useless type qualifier(s) in empty declaration." ); $$ = nullptr; 2068 2070 } 2069 2071 // enums are never empty declarations because there must have at least one enumeration. 2070 2072 if ( $1->type->kind == TypeData::AggregateInst && $1->storageClasses.any() ) { // storage class ? 2071 SemanticError( yylloc, " Useless storage qualifier(s) in empty aggregate declaration." ); $$ = nullptr;2073 SemanticError( yylloc, "syntax error, useless storage qualifier(s) in empty aggregate declaration." ); $$ = nullptr; 2072 2074 } 2073 2075 } … … 2100 2102 | type_declaration_specifier 2101 2103 | sue_declaration_specifier 2102 | sue_declaration_specifier invalid_types 2103 { 2104 SemanticError( yylloc, ::toString( " Missing ';' afterend of ",2104 | sue_declaration_specifier invalid_types // invalid syntax rule 2105 { 2106 SemanticError( yylloc, ::toString( "syntax error, expecting ';' at end of ", 2105 2107 $1->type->enumeration.name ? "enum" : ast::AggregateDecl::aggrString( $1->type->aggregate.kind ), 2106 " declaration " ) );2108 " declaration." ) ); 2107 2109 $$ = nullptr; 2108 2110 } … … 2584 2586 // } // for 2585 2587 } 2588 | type_specifier field_declaring_list_opt '}' // invalid syntax rule 2589 { 2590 SemanticError( yylloc, ::toString( "syntax error, expecting ';' at end of previous declaration." ) ); 2591 $$ = nullptr; 2592 } 2586 2593 | EXTENSION type_specifier field_declaring_list_opt ';' // GCC 2587 2594 { $$ = fieldDecl( $2, $3 ); distExt( $$ ); } … … 2682 2689 | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt '{' enumerator_list comma_opt '}' 2683 2690 { 2684 if ( $3->storageClasses.val != 0 || $3->type->qualifiers.any() ) 2685 { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); }2686 2691 if ( $3->storageClasses.val != 0 || $3->type->qualifiers.any() ) { 2692 SemanticError( yylloc, "syntax error, storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); 2693 } 2687 2694 $$ = DeclarationNode::newEnum( nullptr, $7, true, true, $3 )->addQualifiers( $5 ); 2688 2695 } 2689 2696 | ENUM '(' cfa_abstract_parameter_declaration ')' attribute_list_opt identifier attribute_list_opt 2690 2697 { 2691 if ( $3->storageClasses.any() || $3->type->qualifiers.val != 0 ) { SemanticError( yylloc, "storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); } 2698 if ( $3->storageClasses.any() || $3->type->qualifiers.val != 0 ) { 2699 SemanticError( yylloc, "syntax error, storage-class and CV qualifiers are not meaningful for enumeration constants, which are const." ); 2700 } 2692 2701 typedefTable.makeTypedef( *$6 ); 2693 2702 } … … 3154 3163 | IDENTIFIER IDENTIFIER 3155 3164 { IdentifierBeforeIdentifier( *$1.str, *$2.str, " declaration" ); $$ = nullptr; } 3156 | IDENTIFIER type_qualifier // syntax error3165 | IDENTIFIER type_qualifier // invalid syntax rules 3157 3166 { IdentifierBeforeType( *$1.str, "type qualifier" ); $$ = nullptr; } 3158 | IDENTIFIER storage_class // syntax error3167 | IDENTIFIER storage_class // invalid syntax rules 3159 3168 { IdentifierBeforeType( *$1.str, "storage class" ); $$ = nullptr; } 3160 | IDENTIFIER basic_type_name // syntax error3169 | IDENTIFIER basic_type_name // invalid syntax rules 3161 3170 { IdentifierBeforeType( *$1.str, "type" ); $$ = nullptr; } 3162 | IDENTIFIER TYPEDEFname // syntax error3171 | IDENTIFIER TYPEDEFname // invalid syntax rules 3163 3172 { IdentifierBeforeType( *$1.str, "type" ); $$ = nullptr; } 3164 | IDENTIFIER TYPEGENname // syntax error3173 | IDENTIFIER TYPEGENname // invalid syntax rules 3165 3174 { IdentifierBeforeType( *$1.str, "type" ); $$ = nullptr; } 3166 3175 | external_function_definition … … 3197 3206 | type_qualifier_list 3198 3207 { 3199 if ( $1->type->qualifiers.any() ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); } 3208 if ( $1->type->qualifiers.any() ) { 3209 SemanticError( yylloc, "syntax error, CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); 3210 } 3200 3211 if ( $1->type->forall ) forall = true; // remember generic type 3201 3212 } … … 3208 3219 | declaration_qualifier_list 3209 3220 { 3210 if ( $1->type && $1->type->qualifiers.any() ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); } 3221 if ( $1->type && $1->type->qualifiers.any() ) { 3222 SemanticError( yylloc, "syntax error, CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); 3223 } 3211 3224 if ( $1->type && $1->type->forall ) forall = true; // remember generic type 3212 3225 } … … 3219 3232 | declaration_qualifier_list type_qualifier_list 3220 3233 { 3221 if ( ($1->type && $1->type->qualifiers.any()) || ($2->type && $2->type->qualifiers.any()) ) { SemanticError( yylloc, "CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); } 3234 if ( ($1->type && $1->type->qualifiers.any()) || ($2->type && $2->type->qualifiers.any()) ) { 3235 SemanticError( yylloc, "syntax error, CV qualifiers cannot be distributed; only storage-class and forall qualifiers." ); 3236 } 3222 3237 if ( ($1->type && $1->type->forall) || ($2->type && $2->type->forall) ) forall = true; // remember generic type 3223 3238 } … … 3250 3265 $$ = $3; forall = false; 3251 3266 if ( $5 ) { 3252 SemanticError( yylloc, " Attributes cannot be associated with function body. Move attribute(s) before \"with\" clause." );3267 SemanticError( yylloc, "syntax error, attributes cannot be associated with function body. Move attribute(s) before \"with\" clause." ); 3253 3268 $$ = nullptr; 3254 3269 } // if -
src/ResolvExpr/CandidateFinder.cpp
r2b78949 r8a930c03 373 373 unify( 374 374 ttype, argType, newResult.env, newResult.need, newResult.have, 375 newResult.open , symtab)375 newResult.open ) 376 376 ) { 377 377 finalResults.emplace_back( std::move( newResult ) ); … … 444 444 ) 445 445 446 if ( unify( paramType, argType, env, need, have, open , symtab) ) {446 if ( unify( paramType, argType, env, need, have, open ) ) { 447 447 unsigned nextExpl = results[i].nextExpl + 1; 448 448 if ( nextExpl == expl.exprs.size() ) { nextExpl = 0; } … … 463 463 ast::OpenVarSet open = results[i].open; 464 464 465 if ( unify( paramType, cnst->result, env, need, have, open , symtab) ) {465 if ( unify( paramType, cnst->result, env, need, have, open ) ) { 466 466 results.emplace_back( 467 467 i, new ast::DefaultArgExpr{ cnst->location, cnst }, std::move( env ), … … 506 506 507 507 // attempt to unify types 508 if ( unify( paramType, argType, env, need, have, open , symtab) ) {508 if ( unify( paramType, argType, env, need, have, open ) ) { 509 509 // add new result 510 510 results.emplace_back( … … 750 750 const ast::Type * returnType = funcType->returns.front(); 751 751 if ( ! unify( 752 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen , symtab)752 returnType, targetType, funcEnv, funcNeed, funcHave, funcOpen ) 753 753 ) { 754 754 // unification failed, do not pursue this candidate … … 1159 1159 1160 1160 // unification run for side-effects 1161 unify( toType, cand->expr->result, cand->env, need, have, open , symtab);1161 unify( toType, cand->expr->result, cand->env, need, have, open ); 1162 1162 Cost thisCost = 1163 1163 (castExpr->isGenerated == ast::GeneratedFlag::GeneratedCast) … … 1483 1483 if ( 1484 1484 unify( 1485 r2->expr->result, r3->expr->result, env, need, have, open, symtab,1485 r2->expr->result, r3->expr->result, env, need, have, open, 1486 1486 common ) 1487 1487 ) { … … 1556 1556 if ( 1557 1557 unify( 1558 r1->expr->result, r2->expr->result, env, need, have, open, symtab,1558 r1->expr->result, r2->expr->result, env, need, have, open, 1559 1559 common ) 1560 1560 ) { … … 1659 1659 1660 1660 // unification run for side-effects 1661 bool canUnify = unify( toType, cand->expr->result, env, need, have, open , symtab);1661 bool canUnify = unify( toType, cand->expr->result, env, need, have, open ); 1662 1662 (void) canUnify; 1663 1663 Cost thisCost = computeConversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), -
src/ResolvExpr/CastCost.cc
r2b78949 r8a930c03 165 165 if ( 166 166 pointerType->qualifiers <= ptr->qualifiers 167 && typesCompatibleIgnoreQualifiers( pointerType->base, ptr->base, symtab,env )167 && typesCompatibleIgnoreQualifiers( pointerType->base, ptr->base, env ) 168 168 ) { 169 169 cost = Cost::safe; … … 232 232 ) 233 233 234 if ( typesCompatibleIgnoreQualifiers( src, dst, symtab,env ) ) {234 if ( typesCompatibleIgnoreQualifiers( src, dst, env ) ) { 235 235 PRINT( std::cerr << "compatible!" << std::endl; ) 236 236 return Cost::zero; -
src/ResolvExpr/CommonType.cc
r2b78949 r8a930c03 21 21 22 22 #include "AST/Decl.hpp" 23 #include "AST/Pass.hpp" 23 24 #include "AST/Type.hpp" 24 25 #include "Common/PassVisitor.h" … … 675 676 const ast::Type * type2; 676 677 WidenMode widen; 677 const ast::SymbolTable & symtab;678 678 ast::TypeEnvironment & tenv; 679 679 const ast::OpenVarSet & open; … … 685 685 686 686 CommonType_new( 687 const ast::Type * t2, WidenMode w, const ast::SymbolTable & st,687 const ast::Type * t2, WidenMode w, 688 688 ast::TypeEnvironment & env, const ast::OpenVarSet & o, 689 689 ast::AssertionSet & need, ast::AssertionSet & have ) 690 : type2( t2 ), widen( w ), symtab( st ),tenv( env ), open( o ), need (need), have (have) ,result() {}690 : type2( t2 ), widen( w ), tenv( env ), open( o ), need (need), have (have) ,result() {} 691 691 692 692 void previsit( const ast::Node * ) { visit_children = false; } … … 748 748 ast::AssertionSet need, have; 749 749 if ( ! tenv.bindVar( 750 var, voidPtr->base, entry->second, need, have, open, widen , symtab)750 var, voidPtr->base, entry->second, need, have, open, widen ) 751 751 ) return; 752 752 } … … 761 761 ast::OpenVarSet newOpen{ open }; 762 762 if (enumInst->base->base 763 && unifyExact(type1, enumInst->base->base, tenv, need, have, newOpen, widen , symtab)) {763 && unifyExact(type1, enumInst->base->base, tenv, need, have, newOpen, widen)) { 764 764 result = type1; 765 765 return true; … … 798 798 799 799 ast::OpenVarSet newOpen{ open }; 800 if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden() , symtab) ) {800 if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden() ) ) { 801 801 result = pointer; 802 802 if ( q1.val != q2.val ) { … … 841 841 if (unifyExact( 842 842 arg1, tupleFromTypes( crnt2, end2 ), tenv, need, have, open, 843 noWiden() , symtab)) {843 noWiden() )) { 844 844 break; 845 845 … … 850 850 if (unifyExact( 851 851 tupleFromTypes( crnt1, end1 ), arg2, tenv, need, have, open, 852 noWiden() , symtab)) {852 noWiden() )) { 853 853 break; 854 854 … … 874 874 875 875 if ( ! unifyExact( 876 base1, base2, tenv, need, have, open, noWiden() , symtab)876 base1, base2, tenv, need, have, open, noWiden() ) 877 877 ) return; 878 878 } … … 894 894 895 895 if ( ! unifyExact( 896 base1, base2, tenv, need, have, open, noWiden() , symtab)896 base1, base2, tenv, need, have, open, noWiden() ) 897 897 ) return; 898 898 } … … 902 902 } 903 903 else if (! unifyExact( 904 arg1, arg2, tenv, need, have, open, noWiden() , symtab)) return;904 arg1, arg2, tenv, need, have, open, noWiden() )) return; 905 905 906 906 ++crnt1; ++crnt2; … … 912 912 if (! unifyExact( 913 913 t1, tupleFromTypes( crnt2, end2 ), tenv, need, have, open, 914 noWiden() , symtab)) return;914 noWiden() )) return; 915 915 } else if ( crnt2 != end2 ) { 916 916 // try unifying empty tuple with ttype … … 919 919 if (! unifyExact( 920 920 tupleFromTypes( crnt1, end1 ), t2, tenv, need, have, open, 921 noWiden() , symtab)) return;921 noWiden() )) return; 922 922 } 923 923 if ((f1->returns.size() == 0 && f2->returns.size() == 0) 924 || (f1->returns.size() == 1 && f2->returns.size() == 1 && unifyExact(f1->returns[0], f2->returns[0], tenv, need, have, open, noWiden() , symtab))) {924 || (f1->returns.size() == 1 && f2->returns.size() == 1 && unifyExact(f1->returns[0], f2->returns[0], tenv, need, have, open, noWiden()))) { 925 925 result = pointer; 926 926 … … 979 979 980 980 ast::OpenVarSet newOpen{ open }; 981 if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden() , symtab) ) {981 if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden() ) ) { 982 982 result = ref; 983 983 if ( q1.val != q2.val ) { … … 994 994 } else { 995 995 if (!dynamic_cast<const ast::EnumInstType *>(type2)) 996 result = commonType( type2, ref, tenv, need, have, open, widen , symtab);996 result = commonType( type2, ref, tenv, need, have, open, widen ); 997 997 } 998 998 } … … 1012 1012 void postvisit( const ast::EnumInstType * enumInst ) { 1013 1013 if (!dynamic_cast<const ast::EnumInstType *>(type2)) 1014 result = commonType( type2, enumInst, tenv, need, have, open, widen , symtab);1014 result = commonType( type2, enumInst, tenv, need, have, open, widen); 1015 1015 } 1016 1016 1017 1017 void postvisit( const ast::TraitInstType * ) {} 1018 1018 1019 void postvisit( const ast::TypeInstType * inst ) { 1020 if ( ! widen.first ) return; 1021 if ( const ast::NamedTypeDecl * nt = symtab.lookupType( inst->name ) ) { 1022 if ( const ast::Type * base = 1023 strict_dynamic_cast< const ast::TypeDecl * >( nt )->base 1024 ) { 1025 ast::CV::Qualifiers q1 = inst->qualifiers, q2 = type2->qualifiers; 1026 1027 // force t{1,2} to be cloned if their qualifiers must be mutated 1028 ast::ptr< ast::Type > t1{ base }, t2{ type2 }; 1029 reset_qualifiers( t1, q1 ); 1030 reset_qualifiers( t2 ); 1031 1032 ast::OpenVarSet newOpen{ open }; 1033 if ( unifyExact( t1, t2, tenv, have, need, newOpen, noWiden(), symtab ) ) { 1034 result = type2; 1035 reset_qualifiers( result, q1 | q2 ); 1036 } else { 1037 tryResolveWithTypedEnum( t1 ); 1038 } 1039 } 1040 } 1041 } 1042 1043 void postvisit( const ast::TupleType * tuple) { 1019 void postvisit( const ast::TypeInstType * ) {} 1020 1021 void postvisit( const ast::TupleType * tuple ) { 1044 1022 tryResolveWithTypedEnum( tuple ); 1045 1023 } … … 1102 1080 ast::ptr< ast::Type > handleReference( 1103 1081 const ast::ptr< ast::Type > & t1, const ast::ptr< ast::Type > & t2, WidenMode widen, 1104 const ast::SymbolTable & symtab,ast::TypeEnvironment & env,1082 ast::TypeEnvironment & env, 1105 1083 const ast::OpenVarSet & open 1106 1084 ) { … … 1110 1088 1111 1089 // need unify to bind type variables 1112 if ( unify( t1, t2, env, have, need, newOpen, symtab,common ) ) {1090 if ( unify( t1, t2, env, have, need, newOpen, common ) ) { 1113 1091 ast::CV::Qualifiers q1 = t1->qualifiers, q2 = t2->qualifiers; 1114 1092 PRINT( … … 1134 1112 const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2, 1135 1113 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 1136 const ast::OpenVarSet & open, WidenMode widen , const ast::SymbolTable & symtab1114 const ast::OpenVarSet & open, WidenMode widen 1137 1115 ) { 1138 1116 unsigned depth1 = type1->referenceDepth(); … … 1149 1127 if ( depth1 > depth2 ) { 1150 1128 assert( ref1 ); 1151 result = handleReference( ref1->base, type2, widen, symtab,env, open );1129 result = handleReference( ref1->base, type2, widen, env, open ); 1152 1130 } else { // implies depth1 < depth2 1153 1131 assert( ref2 ); 1154 result = handleReference( type1, ref2->base, widen, symtab,env, open );1132 result = handleReference( type1, ref2->base, widen, env, open ); 1155 1133 } 1156 1134 … … 1170 1148 } 1171 1149 // otherwise both are reference types of the same depth and this is handled by the visitor 1172 ast::Pass<CommonType_new> visitor{ type2, widen, symtab,env, open, need, have };1150 ast::Pass<CommonType_new> visitor{ type2, widen, env, open, need, have }; 1173 1151 type1->accept( visitor ); 1174 ast::ptr< ast::Type > result = visitor.core.result; 1175 1176 // handling for opaque type declarations (?) 1177 if ( ! result && widen.second ) { 1178 if ( const ast::TypeInstType * inst = type2.as< ast::TypeInstType >() ) { 1179 if ( const ast::NamedTypeDecl * nt = symtab.lookupType( inst->name ) ) { 1180 auto type = strict_dynamic_cast< const ast::TypeDecl * >( nt ); 1181 if ( type->base ) { 1182 ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers; 1183 ast::OpenVarSet newOpen{ open }; 1184 1185 // force t{1,2} to be cloned if its qualifiers must be stripped, so that 1186 // type1 and type->base are left unchanged; calling convention forces 1187 // {type1,type->base}->strong_ref >= 1 1188 ast::ptr<ast::Type> t1{ type1 }, t2{ type->base }; 1189 reset_qualifiers( t1 ); 1190 reset_qualifiers( t2, q1 ); 1191 1192 if ( unifyExact( t1, t2, env, have, need, newOpen, noWiden(), symtab ) ) { 1193 result = t1; 1194 reset_qualifiers( result, q1 | q2 ); 1195 } 1196 } 1197 } 1198 } 1199 } 1200 1201 return result; 1152 // ast::ptr< ast::Type > result = visitor.core.result; 1153 1154 return visitor.core.result; 1202 1155 } 1203 1156 -
src/ResolvExpr/CommonType.hpp
r2b78949 r8a930c03 36 36 ast::TypeEnvironment & env, 37 37 ast::AssertionSet & need, ast::AssertionSet & have, 38 const ast::OpenVarSet & open, WidenMode widen, 39 const ast::SymbolTable & symtab ); 38 const ast::OpenVarSet & open, WidenMode widen); 40 39 41 40 } -
src/ResolvExpr/ConversionCost.cc
r2b78949 r8a930c03 532 532 } 533 533 } 534 if ( typesCompatibleIgnoreQualifiers( src, dst, symtab,env ) ) {534 if ( typesCompatibleIgnoreQualifiers( src, dst, env ) ) { 535 535 return Cost::zero; 536 536 } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) { … … 566 566 ast::CV::Qualifiers tq2 = dstAsRef->base->qualifiers; 567 567 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( 568 srcAsRef->base, dstAsRef->base, symtab,env ) ) {568 srcAsRef->base, dstAsRef->base, env ) ) { 569 569 if ( tq1 == tq2 ) { 570 570 return Cost::zero; … … 587 587 const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst ); 588 588 assert( dstAsRef ); 589 if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab,env ) ) {589 if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, env ) ) { 590 590 if ( srcIsLvalue ) { 591 591 if ( src->qualifiers == dstAsRef->base->qualifiers ) { … … 653 653 ast::CV::Qualifiers tq2 = dstAsPtr->base->qualifiers; 654 654 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( 655 pointerType->base, dstAsPtr->base, symtab,env ) ) {655 pointerType->base, dstAsPtr->base, env ) ) { 656 656 if ( tq1 == tq2 ) { 657 657 cost = Cost::zero; -
src/ResolvExpr/PolyCost.cc
r2b78949 r8a930c03 15 15 16 16 #include "AST/SymbolTable.hpp" 17 #include "AST/Pass.hpp" 17 18 #include "AST/Type.hpp" 18 19 #include "AST/TypeEnvironment.hpp" -
src/ResolvExpr/Resolver.cc
r2b78949 r8a930c03 1106 1106 1107 1107 /// Removes cast to type of argument (unlike StripCasts, also handles non-generated casts) 1108 void removeExtraneousCast( ast::ptr<ast::Expr> & expr , const ast::SymbolTable & symtab) {1108 void removeExtraneousCast( ast::ptr<ast::Expr> & expr ) { 1109 1109 if ( const ast::CastExpr * castExpr = expr.as< ast::CastExpr >() ) { 1110 if ( typesCompatible( castExpr->arg->result, castExpr->result , symtab) ) {1110 if ( typesCompatible( castExpr->arg->result, castExpr->result ) ) { 1111 1111 // cast is to the same type as its argument, remove it 1112 1112 swap_and_save_env( expr, castExpr->arg ); … … 1196 1196 ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type }; 1197 1197 ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, context ); 1198 removeExtraneousCast( newExpr , context.symtab);1198 removeExtraneousCast( newExpr ); 1199 1199 return newExpr; 1200 1200 } … … 1261 1261 static size_t traceId; 1262 1262 Resolver_new( const ast::TranslationGlobal & global ) : 1263 ast::WithSymbolTable(ast::SymbolTable::ErrorDetection::ValidateOnAdd), 1263 1264 context{ symtab, global } {} 1264 1265 Resolver_new( const ResolveContext & context ) : … … 1834 1835 if ( 1835 1836 ! unify( 1836 arg->expr->result, *param, resultEnv, need, have, open, 1837 symtab ) 1837 arg->expr->result, *param, resultEnv, need, have, open ) 1838 1838 ) { 1839 1839 // Type doesn't match … … 2041 2041 const ast::Type * initContext = currentObject.getCurrentType(); 2042 2042 2043 removeExtraneousCast( newExpr , symtab);2043 removeExtraneousCast( newExpr ); 2044 2044 2045 2045 // check if actual object's type is char[] -
src/ResolvExpr/SatisfyAssertions.cpp
r2b78949 r8a930c03 215 215 findOpenVars( adjType, newOpen, closed, newNeed, have, FirstOpen ); 216 216 if ( allowConversion ) { 217 if ( auto c = commonType( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true} , sat.symtab) ) {217 if ( auto c = commonType( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) { 218 218 // set up binding slot for recursive assertions 219 219 ast::UniqueId crntResnSlot = 0; … … 229 229 } 230 230 else { 231 if ( unifyExact( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true} , sat.symtab) ) {231 if ( unifyExact( toType, adjType, newEnv, newNeed, have, newOpen, WidenMode {true, true} ) ) { 232 232 // set up binding slot for recursive assertions 233 233 ast::UniqueId crntResnSlot = 0; … … 392 392 mergeOpenVars( open, i.match.open ); 393 393 394 if ( ! env.combine( i.match.env, open , symtab) ) return false;394 if ( ! env.combine( i.match.env, open ) ) return false; 395 395 396 396 crnt.emplace_back( i ); -
src/ResolvExpr/Unify.cc
r2b78949 r8a930c03 128 128 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env, 129 129 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 130 WidenMode widen , const ast::SymbolTable & symtab);130 WidenMode widen ); 131 131 132 132 bool typesCompatible( const Type * first, const Type * second, const SymTab::Indexer & indexer, const TypeEnvironment & env ) { … … 150 150 151 151 bool typesCompatible( 152 const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab,152 const ast::Type * first, const ast::Type * second, 153 153 const ast::TypeEnvironment & env ) { 154 154 ast::TypeEnvironment newEnv; … … 163 163 findOpenVars( newSecond, open, closed, need, have, FirstOpen ); 164 164 165 return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden() , symtab);165 return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden() ); 166 166 } 167 167 … … 183 183 184 184 bool typesCompatibleIgnoreQualifiers( 185 const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab,185 const ast::Type * first, const ast::Type * second, 186 186 const ast::TypeEnvironment & env ) { 187 187 ast::TypeEnvironment newEnv; … … 216 216 subFirst, 217 217 subSecond, 218 newEnv, need, have, open, noWiden() , symtab);218 newEnv, need, have, open, noWiden() ); 219 219 } 220 220 … … 786 786 const ast::OpenVarSet & open; 787 787 WidenMode widen; 788 const ast::SymbolTable & symtab;789 788 public: 790 789 static size_t traceId; … … 793 792 Unify_new( 794 793 const ast::Type * type2, ast::TypeEnvironment & env, ast::AssertionSet & need, 795 ast::AssertionSet & have, const ast::OpenVarSet & open, WidenMode widen, 796 const ast::SymbolTable & symtab ) 794 ast::AssertionSet & have, const ast::OpenVarSet & open, WidenMode widen ) 797 795 : type2(type2), tenv(env), need(need), have(have), open(open), widen(widen), 798 symtab(symtab),result(false) {}796 result(false) {} 799 797 800 798 void previsit( const ast::Node * ) { visit_children = false; } … … 814 812 result = unifyExact( 815 813 pointer->base, pointer2->base, tenv, need, have, open, 816 noWiden() , symtab);814 noWiden()); 817 815 } 818 816 } … … 837 835 838 836 result = unifyExact( 839 array->base, array2->base, tenv, need, have, open, noWiden(), 840 symtab ); 837 array->base, array2->base, tenv, need, have, open, noWiden()); 841 838 } 842 839 … … 844 841 if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) { 845 842 result = unifyExact( 846 ref->base, ref2->base, tenv, need, have, open, noWiden(), 847 symtab ); 843 ref->base, ref2->base, tenv, need, have, open, noWiden()); 848 844 } 849 845 } … … 854 850 static bool unifyTypeList( 855 851 Iter crnt1, Iter end1, Iter crnt2, Iter end2, ast::TypeEnvironment & env, 856 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 857 const ast::SymbolTable & symtab 852 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open 858 853 ) { 859 854 while ( crnt1 != end1 && crnt2 != end2 ) { … … 868 863 return unifyExact( 869 864 t1, tupleFromTypes( crnt2, end2 ), env, need, have, open, 870 noWiden() , symtab);865 noWiden() ); 871 866 } else if ( ! isTuple1 && isTuple2 ) { 872 867 // combine remainder of list1, then unify 873 868 return unifyExact( 874 869 tupleFromTypes( crnt1, end1 ), t2, env, need, have, open, 875 noWiden() , symtab);870 noWiden() ); 876 871 } 877 872 878 873 if ( ! unifyExact( 879 t1, t2, env, need, have, open, noWiden() , symtab)874 t1, t2, env, need, have, open, noWiden() ) 880 875 ) return false; 881 876 … … 891 886 return unifyExact( 892 887 t1, tupleFromTypes( crnt2, end2 ), env, need, have, open, 893 noWiden() , symtab);888 noWiden() ); 894 889 } else if ( crnt2 != end2 ) { 895 890 // try unifying empty tuple with ttype … … 898 893 return unifyExact( 899 894 tupleFromTypes( crnt1, end1 ), t2, env, need, have, open, 900 noWiden() , symtab);895 noWiden() ); 901 896 } 902 897 … … 908 903 const std::vector< ast::ptr< ast::Type > > & list2, 909 904 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 910 const ast::OpenVarSet & open , const ast::SymbolTable & symtab905 const ast::OpenVarSet & open 911 906 ) { 912 907 return unifyTypeList( 913 list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open, 914 symtab ); 908 list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open); 915 909 } 916 910 … … 953 947 ) return; 954 948 955 if ( ! unifyTypeList( params, params2, tenv, need, have, open , symtab) ) return;949 if ( ! unifyTypeList( params, params2, tenv, need, have, open ) ) return; 956 950 if ( ! unifyTypeList( 957 func->returns, func2->returns, tenv, need, have, open , symtab) ) return;951 func->returns, func2->returns, tenv, need, have, open ) ) return; 958 952 959 953 markAssertions( have, need, func ); … … 1026 1020 1027 1021 if ( ! unifyExact( 1028 pty, pty2, tenv, need, have, open, noWiden() , symtab) ) {1022 pty, pty2, tenv, need, have, open, noWiden() ) ) { 1029 1023 result = false; 1030 1024 return; … … 1065 1059 const std::vector< ast::ptr< ast::Type > > & list1, 1066 1060 const std::vector< ast::ptr< ast::Type > > & list2, ast::TypeEnvironment & env, 1067 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 1068 const ast::SymbolTable & symtab 1061 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open 1069 1062 ) { 1070 1063 auto crnt1 = list1.begin(); … … 1081 1074 return unifyExact( 1082 1075 t1, tupleFromTypes( list2 ), env, need, have, open, 1083 noWiden() , symtab);1076 noWiden() ); 1084 1077 } else if ( ! isTuple1 && isTuple2 ) { 1085 1078 // combine entirety of list1, then unify 1086 1079 return unifyExact( 1087 1080 tupleFromTypes( list1 ), t2, env, need, have, open, 1088 noWiden() , symtab);1081 noWiden() ); 1089 1082 } 1090 1083 1091 1084 if ( ! unifyExact( 1092 t1, t2, env, need, have, open, noWiden() , symtab)1085 t1, t2, env, need, have, open, noWiden() ) 1093 1086 ) return false; 1094 1087 … … 1104 1097 return unifyExact( 1105 1098 t1, tupleFromTypes( list2 ), env, need, have, open, 1106 noWiden() , symtab);1099 noWiden() ); 1107 1100 } else if ( crnt2 != list2.end() ) { 1108 1101 // try unifying empty tuple with ttype … … 1113 1106 return unifyExact( 1114 1107 tupleFromTypes( list1 ), t2, env, need, have, open, 1115 noWiden() , symtab);1108 noWiden() ); 1116 1109 } 1117 1110 … … 1132 1125 auto types2 = flatten( flat2 ); 1133 1126 1134 result = unifyList( types, types2, tenv, need, have, open , symtab);1127 result = unifyList( types, types2, tenv, need, have, open ); 1135 1128 } 1136 1129 … … 1156 1149 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 1157 1150 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 1158 ast::OpenVarSet & open , const ast::SymbolTable & symtab1151 ast::OpenVarSet & open 1159 1152 ) { 1160 1153 ast::ptr<ast::Type> common; 1161 return unify( type1, type2, env, need, have, open, symtab,common );1154 return unify( type1, type2, env, need, have, open, common ); 1162 1155 } 1163 1156 … … 1165 1158 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 1166 1159 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 1167 ast::OpenVarSet & open, const ast::SymbolTable & symtab,ast::ptr<ast::Type> & common1160 ast::OpenVarSet & open, ast::ptr<ast::Type> & common 1168 1161 ) { 1169 1162 ast::OpenVarSet closed; … … 1171 1164 findOpenVars( type2, open, closed, need, have, FirstOpen ); 1172 1165 return unifyInexact( 1173 type1, type2, env, need, have, open, WidenMode{ true, true }, symtab,common );1166 type1, type2, env, need, have, open, WidenMode{ true, true }, common ); 1174 1167 } 1175 1168 … … 1177 1170 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env, 1178 1171 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 1179 WidenMode widen , const ast::SymbolTable & symtab1172 WidenMode widen 1180 1173 ) { 1181 1174 if ( type1->qualifiers != type2->qualifiers ) return false; … … 1193 1186 return env.bindVarToVar( 1194 1187 var1, var2, ast::TypeData{ entry1->second, entry2->second }, need, have, 1195 open, widen , symtab);1188 open, widen ); 1196 1189 } else if ( isopen1 ) { 1197 return env.bindVar( var1, type2, entry1->second, need, have, open, widen , symtab);1190 return env.bindVar( var1, type2, entry1->second, need, have, open, widen ); 1198 1191 } else if ( isopen2 ) { 1199 return env.bindVar( var2, type1, entry2->second, need, have, open, widen , symtab);1192 return env.bindVar( var2, type1, entry2->second, need, have, open, widen ); 1200 1193 } else { 1201 1194 return ast::Pass<Unify_new>::read( 1202 type1, type2, env, need, have, open, widen , symtab);1195 type1, type2, env, need, have, open, widen ); 1203 1196 } 1204 1197 } … … 1207 1200 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 1208 1201 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 1209 const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab,1202 const ast::OpenVarSet & open, WidenMode widen, 1210 1203 ast::ptr<ast::Type> & common 1211 1204 ) { … … 1221 1214 ast::ptr< ast::Type > t2_(t2); 1222 1215 1223 if ( unifyExact( t1, t2, env, need, have, open, widen , symtab) ) {1216 if ( unifyExact( t1, t2, env, need, have, open, widen ) ) { 1224 1217 // if exact unification on unqualified types, try to merge qualifiers 1225 1218 if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) { … … 1231 1224 } 1232 1225 1233 } else if (( common = commonType( t1, t2, env, need, have, open, widen , symtab))) {1226 } else if (( common = commonType( t1, t2, env, need, have, open, widen ))) { 1234 1227 // no exact unification, but common type 1235 1228 auto c = shallowCopy(common.get()); -
src/ResolvExpr/Unify.h
r2b78949 r8a930c03 59 59 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 60 60 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 61 ast::OpenVarSet & open , const ast::SymbolTable & symtab);61 ast::OpenVarSet & open ); 62 62 63 63 bool unify( 64 64 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 65 65 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 66 ast::OpenVarSet & open, const ast::SymbolTable & symtab,ast::ptr<ast::Type> & common );66 ast::OpenVarSet & open, ast::ptr<ast::Type> & common ); 67 67 68 68 bool unifyExact( 69 69 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env, 70 70 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 71 WidenMode widen , const ast::SymbolTable & symtab);71 WidenMode widen ); 72 72 73 73 bool unifyInexact( 74 74 const ast::ptr<ast::Type> & type1, const ast::ptr<ast::Type> & type2, 75 75 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have, 76 const ast::OpenVarSet & open, WidenMode widen, const ast::SymbolTable & symtab,76 const ast::OpenVarSet & open, WidenMode widen, 77 77 ast::ptr<ast::Type> & common ); 78 78 79 79 bool typesCompatible( 80 const ast::Type *, const ast::Type *, const ast::SymbolTable & symtab = {},80 const ast::Type *, const ast::Type *, 81 81 const ast::TypeEnvironment & env = {} ); 82 82 83 83 bool typesCompatibleIgnoreQualifiers( 84 const ast::Type *, const ast::Type *, const ast::SymbolTable & symtab = {},84 const ast::Type *, const ast::Type *, 85 85 const ast::TypeEnvironment & env = {} ); 86 86 -
src/SymTab/Autogen.h
r2b78949 r8a930c03 20 20 #include <string> // for string 21 21 22 #include "AST/Decl.hpp"23 #include "AST/Expr.hpp"24 #include "AST/Init.hpp"25 #include "AST/Node.hpp"26 #include "AST/Stmt.hpp"27 #include "AST/Type.hpp"28 22 #include "CodeGen/OperatorTable.h" 29 23 #include "Common/UniqueName.h" // for UniqueName … … 57 51 /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic 58 52 FunctionType * genCopyType( Type * paramType, bool maybePolymorphic = true ); 59 60 /// Enum for loop direction61 enum LoopDirection { LoopBackward, LoopForward };62 53 63 54 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. -
src/SymTab/GenImplicitCall.cpp
r2b78949 r8a930c03 16 16 #include "GenImplicitCall.hpp" 17 17 18 #include "AST/Decl.hpp" // for ObjectDecl 19 #include "AST/Expr.hpp" // for ConstantExpr, UntypedExpr,... 20 #include "AST/Init.hpp" // for SingleInit 18 21 #include "AST/Inspect.hpp" // for isUnnamedBitfield 22 #include "AST/Stmt.hpp" // for ExprStmt 23 #include "AST/Type.hpp" // for ArrayType, BasicType, ... 19 24 #include "CodeGen/OperatorTable.h" // for isCtorDtor 20 25 #include "Common/UniqueName.h" // for UniqueName 21 26 22 27 namespace SymTab { 28 29 namespace { 23 30 24 31 template< typename OutIter > … … 173 180 } 174 181 182 } // namespace 183 175 184 ast::ptr< ast::Stmt > genImplicitCall( 176 185 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam, -
src/SymTab/GenImplicitCall.hpp
r2b78949 r8a930c03 17 17 18 18 #include "InitTweak/InitTweak.h" // for InitExpander 19 #include "SymTab/Autogen.h" // for LoopDirection20 19 21 20 namespace SymTab { 22 21 22 /// Enum for loop direction 23 enum LoopDirection { LoopBackward, LoopForward }; 24 25 /// Returns a generated call expression to function fname with srcParam and 26 /// dstParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. 23 27 ast::ptr<ast::Stmt> genImplicitCall( 24 28 InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam, … … 34 38 // compile-command: "make install" // 35 39 // End: // 36 -
src/Tuples/Explode.cc
r2b78949 r8a930c03 17 17 #include <list> // for list 18 18 19 #include "AST/Pass.hpp" // for Pass 19 20 #include "SynTree/Mutator.h" // for Mutator 20 21 #include "Common/PassVisitor.h" // for PassVisitor -
src/Validate/Autogen.cpp
r2b78949 r8a930c03 25 25 26 26 #include "AST/Attribute.hpp" 27 #include "AST/Copy.hpp" 27 28 #include "AST/Create.hpp" 28 29 #include "AST/Decl.hpp" … … 43 44 #include "CompilationState.h" 44 45 45 // TODO: The other new ast function should be moved over to this file.46 #include "SymTab/Autogen.h"47 48 46 namespace Validate { 49 47 … … 95 93 96 94 const CodeLocation& getLocation() const { return getDecl()->location; } 97 ast::FunctionDecl * genProto( const std::string& name,95 ast::FunctionDecl * genProto( std::string&& name, 98 96 std::vector<ast::ptr<ast::DeclWithType>>&& params, 99 97 std::vector<ast::ptr<ast::DeclWithType>>&& returns ) const; … … 336 334 } 337 335 336 void replaceAll( std::vector<ast::ptr<ast::DeclWithType>> & dwts, 337 const ast::DeclReplacer::TypeMap & map ) { 338 for ( auto & dwt : dwts ) { 339 dwt = strict_dynamic_cast<const ast::DeclWithType *>( 340 ast::DeclReplacer::replace( dwt, map ) ); 341 } 342 } 343 338 344 /// Generates a basic prototype function declaration. 339 ast::FunctionDecl * FuncGenerator::genProto( const std::string& name,345 ast::FunctionDecl * FuncGenerator::genProto( std::string&& name, 340 346 std::vector<ast::ptr<ast::DeclWithType>>&& params, 341 347 std::vector<ast::ptr<ast::DeclWithType>>&& returns ) const { … … 343 349 // Handle generic prameters and assertions, if any. 344 350 auto const & old_type_params = getGenericParams( type ); 351 ast::DeclReplacer::TypeMap oldToNew; 345 352 std::vector<ast::ptr<ast::TypeDecl>> type_params; 346 353 std::vector<ast::ptr<ast::DeclWithType>> assertions; 347 354 for ( auto & old_param : old_type_params ) { 348 355 ast::TypeDecl * decl = ast::deepCopy( old_param ); 349 for ( auto assertion : decl->assertions ) { 350 assertions.push_back( assertion ); 351 } 352 decl->assertions.clear(); 356 decl->init = nullptr; 357 splice( assertions, decl->assertions ); 358 oldToNew.emplace( std::make_pair( old_param, decl ) ); 353 359 type_params.push_back( decl ); 354 360 } 355 // TODO: The values in params and returns still may point at the old356 // generic params, that does not appear to be an issue but perhaps it357 // should be addressed.361 replaceAll( params, oldToNew ); 362 replaceAll( returns, oldToNew ); 363 replaceAll( assertions, oldToNew ); 358 364 359 365 ast::FunctionDecl * decl = new ast::FunctionDecl( 360 366 // Auto-generated routines use the type declaration's location. 361 367 getLocation(), 362 name,368 std::move( name ), 363 369 std::move( type_params ), 364 370 std::move( assertions ), -
src/Validate/FixQualifiedTypes.cpp
r2b78949 r8a930c03 16 16 #include "Validate/FixQualifiedTypes.hpp" 17 17 18 #include "AST/Copy.hpp" 18 19 #include "AST/LinkageSpec.hpp" // for Linkage 19 20 #include "AST/Pass.hpp" -
src/Validate/GenericParameter.cpp
r2b78949 r8a930c03 16 16 #include "GenericParameter.hpp" 17 17 18 #include "AST/Copy.hpp" 18 19 #include "AST/Decl.hpp" 19 20 #include "AST/Expr.hpp" -
src/Validate/HoistStruct.cpp
r2b78949 r8a930c03 18 18 #include <sstream> 19 19 20 #include "AST/DeclReplacer.hpp" 20 21 #include "AST/Pass.hpp" 21 22 #include "AST/TranslationUnit.hpp" 23 #include "AST/Vector.hpp" 22 24 23 25 namespace Validate { … … 51 53 template<typename AggrDecl> 52 54 AggrDecl const * postAggregate( AggrDecl const * ); 55 template<typename InstType> 56 InstType const * preCollectionInstType( InstType const * type ); 53 57 54 58 ast::AggregateDecl const * parent = nullptr; … … 66 70 qualifiedName( decl, ss ); 67 71 return ss.str(); 72 } 73 74 void extendParams( ast::vector<ast::TypeDecl> & dstParams, 75 ast::vector<ast::TypeDecl> const & srcParams ) { 76 if ( srcParams.empty() ) return; 77 78 ast::DeclReplacer::TypeMap newToOld; 79 ast::vector<ast::TypeDecl> params; 80 for ( ast::ptr<ast::TypeDecl> const & srcParam : srcParams ) { 81 ast::TypeDecl * dstParam = ast::deepCopy( srcParam.get() ); 82 dstParam->init = nullptr; 83 newToOld.emplace( srcParam, dstParam ); 84 for ( auto assertion : dstParam->assertions ) { 85 assertion = ast::DeclReplacer::replace( assertion, newToOld ); 86 } 87 params.emplace_back( dstParam ); 88 } 89 spliceBegin( dstParams, params ); 68 90 } 69 91 … … 74 96 mut->parent = parent; 75 97 mut->name = qualifiedName( mut ); 76 return mut;77 } else {78 GuardValue( parent ) = decl;79 returndecl;80 }98 extendParams( mut->params, parent->params ); 99 decl = mut; 100 } 101 GuardValue( parent ) = decl; 102 return decl; 81 103 } 82 104 … … 112 134 } 113 135 136 ast::AggregateDecl const * commonParent( 137 ast::AggregateDecl const * lhs, ast::AggregateDecl const * rhs ) { 138 for ( auto outer = lhs ; outer ; outer = outer->parent ) { 139 for ( auto inner = rhs ; inner ; inner = inner->parent ) { 140 if ( outer == inner ) { 141 return outer; 142 } 143 } 144 } 145 return nullptr; 146 } 147 148 template<typename InstType> 149 InstType const * HoistStructCore::preCollectionInstType( InstType const * type ) { 150 if ( !type->base->parent ) return type; 151 if ( type->base->params.empty() ) return type; 152 153 InstType * mut = ast::mutate( type ); 154 ast::AggregateDecl const * parent = 155 commonParent( this->parent, mut->base->parent ); 156 assert( parent ); 157 158 std::vector<ast::ptr<ast::Expr>> args; 159 for ( const ast::ptr<ast::TypeDecl> & param : parent->params ) { 160 args.emplace_back( new ast::TypeExpr( param->location, 161 new ast::TypeInstType( param ) 162 ) ); 163 } 164 spliceBegin( mut->params, args ); 165 return mut; 166 } 167 114 168 template<typename InstType> 115 169 InstType const * preInstType( InstType const * type ) { … … 121 175 122 176 ast::StructInstType const * HoistStructCore::previsit( ast::StructInstType const * type ) { 123 return preInstType( type);177 return preInstType( preCollectionInstType( type ) ); 124 178 } 125 179 126 180 ast::UnionInstType const * HoistStructCore::previsit( ast::UnionInstType const * type ) { 127 return preInstType( type);181 return preInstType( preCollectionInstType( type ) ); 128 182 } 129 183 -
src/Validate/ReplaceTypedef.cpp
r2b78949 r8a930c03 16 16 #include "ReplaceTypedef.hpp" 17 17 18 #include "AST/Copy.hpp" 18 19 #include "AST/Pass.hpp" 19 20 #include "Common/ScopedMap.h" … … 149 150 // constant/enumerator. The effort required to fix this corner case 150 151 // likely outweighs the utility of allowing it. 151 if ( !ResolvExpr::typesCompatible( t0, t1 , ast::SymbolTable())152 if ( !ResolvExpr::typesCompatible( t0, t1 ) 152 153 || ast::Pass<VarLenChecker>::read( t0 ) 153 154 || ast::Pass<VarLenChecker>::read( t1 ) ) { -
src/Virtual/ExpandCasts.cc
r2b78949 r8a930c03 20 20 #include <string> // for string, allocator, operator==, ope... 21 21 22 #include "AST/Copy.hpp" 22 23 #include "AST/Decl.hpp" 23 24 #include "AST/Expr.hpp" -
src/main.cc
r2b78949 r8a930c03 32 32 33 33 #include "AST/Convert.hpp" 34 #include "AST/Pass.hpp" // for pass_visitor_stats 35 #include "AST/TranslationUnit.hpp" // for TranslationUnit 34 36 #include "AST/Util.hpp" // for checkInvariants 35 37 #include "CompilationState.h"
Note:
See TracChangeset
for help on using the changeset viewer.