- Timestamp:
- Apr 15, 2024, 12:24:36 PM (18 months ago)
- Branches:
- master
- Children:
- fb2e916
- Parents:
- af746cc (diff), 7a36848 (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:
-
- 1 deleted
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Pass.hpp
raf746cc rdc58e5d 252 252 private: 253 253 254 __pass::result1<ast::Stmt> call_accept( const ast::Stmt * ); 255 __pass::result1<ast::Expr> call_accept( const ast::Expr * ); 256 257 /// This has a `type` member that is the return type for the 258 /// generic call_accept if the generic call_accept is defined. 254 /// The return type of the general call_accept function. 259 255 template< typename node_t > 260 using generic_call_accept_result = 261 std::enable_if< 262 !std::is_base_of<ast::Expr, node_t>::value && 263 !std::is_base_of<ast::Stmt, node_t>::value 264 , __pass::result1< 265 typename std::remove_pointer< typename std::result_of< 266 decltype(&node_t::accept)(node_t*, type&) >::type >::type 267 > 256 using call_accept_result_t = __pass::result1< 257 typename std::remove_pointer< typename std::result_of< 258 decltype(&node_t::accept)(node_t*, type&) >::type >::type 268 259 >; 269 260 270 261 template< typename node_t > 271 auto call_accept( const node_t * node ) 272 -> typename generic_call_accept_result<node_t>::type; 262 auto call_accept( const node_t * node ) -> call_accept_result_t<node_t>; 273 263 274 264 // requests WithStmtsToAdd directly add to this statement, as if it is a compound. -
src/AST/Pass.impl.hpp
raf746cc rdc58e5d 109 109 return val; 110 110 } 111 112 //------------------------------113 /// Check if value was mutated, different for pointers and containers114 template<typename lhs_t, typename rhs_t>115 bool differs( const lhs_t * old_val, const rhs_t * new_val ) {116 return old_val != new_val;117 }118 119 template< template <class...> class container_t, typename node_t >120 bool differs( const container_t<ast::ptr< node_t >> &, const container_t<ast::ptr< node_t >> & new_val ) {121 return !new_val.empty();122 }123 111 } 124 112 … … 126 114 template< typename node_t > 127 115 auto ast::Pass< core_t >::call_accept( const node_t * node ) -> 128 typename ast::Pass< core_t >::template generic_call_accept_result<node_t>::type 129 { 116 ast::Pass< core_t >::call_accept_result_t<node_t> { 130 117 __pedantic_pass_assert( __visit_children() ); 131 118 __pedantic_pass_assert( node ); 132 119 133 static_assert( !std::is_base_of<ast::Expr, node_t>::value, "ERROR" );134 static_assert( !std::is_base_of<ast::Stmt, node_t>::value, "ERROR" );135 136 120 auto nval = node->accept( *this ); 137 __pass::result1< 138 typename std::remove_pointer< decltype( node->accept(*this) ) >::type 139 > res; 140 res.differs = nval != node; 141 res.value = nval; 142 return res; 143 } 144 145 template< typename core_t > 146 ast::__pass::template result1<ast::Expr> ast::Pass< core_t >::call_accept( const ast::Expr * expr ) { 147 __pedantic_pass_assert( __visit_children() ); 148 __pedantic_pass_assert( expr ); 149 150 auto nval = expr->accept( *this ); 151 return { nval != expr, nval }; 152 } 153 154 template< typename core_t > 155 ast::__pass::template result1<ast::Stmt> ast::Pass< core_t >::call_accept( const ast::Stmt * stmt ) { 156 __pedantic_pass_assert( __visit_children() ); 157 __pedantic_pass_assert( stmt ); 158 159 const ast::Stmt * nval = stmt->accept( *this ); 160 return { nval != stmt, nval }; 121 return { nval != node, nval }; 161 122 } 162 123 … … 230 191 ast::__pass::template resultNstmt<container_t> ast::Pass< core_t >::call_accept( const container_t< ptr<Stmt> > & statements ) { 231 192 __pedantic_pass_assert( __visit_children() ); 232 if ( statements.empty() ) return {};193 __pedantic_pass_assert( !statements.empty() ); 233 194 234 195 // We are going to aggregate errors for all these statements … … 263 224 const ast::Stmt * new_stmt = stmt->accept( *this ); 264 225 assert( new_stmt ); 265 if ( new_stmt != stmt ) { new_kids.differs = true; }266 226 267 227 // Make sure that it is either adding statements or declartions but not both … … 276 236 // Now add the statement if there is one 277 237 if ( new_stmt != stmt ) { 278 new_kids.values.emplace_back( new_stmt, i, false ); 238 new_kids.differs = true; 239 new_kids.values.emplace_back( new_stmt ); 279 240 } else { 280 new_kids.values.emplace_back( nullptr, i, true);241 new_kids.values.emplace_back( i ); 281 242 } 282 243 … … 298 259 ast::__pass::template resultN<container_t, node_t> ast::Pass< core_t >::call_accept( const container_t< ast::ptr<node_t> > & container ) { 299 260 __pedantic_pass_assert( __visit_children() ); 300 if ( container.empty() ) return {}; 261 __pedantic_pass_assert( !container.empty() ); 262 263 // Collect errors from processing all these nodes. 301 264 SemanticErrorException errors; 302 265 … … 342 305 static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR" ); 343 306 344 auto new_val = call_accept( old_val ); 345 346 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR" ); 347 348 if ( new_val.differs ) { 307 auto result = call_accept( old_val ); 308 if ( result.differs ) { 349 309 auto new_parent = __pass::mutate<core_t>(parent); 350 new_val.apply(new_parent, field);310 result.apply( new_parent, field ); 351 311 parent = new_parent; 352 312 } … … 366 326 static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR" ); 367 327 368 auto new_val = call_accept_top( old_val ); 369 370 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value /* || std::is_same<int, decltype(old_val)>::value */, "ERROR" ); 371 372 if ( new_val.differs ) { 328 auto result = call_accept_top( old_val ); 329 if ( result.differs ) { 373 330 auto new_parent = __pass::mutate<core_t>(parent); 374 new_val.apply(new_parent, field);331 result.apply( new_parent, field ); 375 332 parent = new_parent; 376 333 } … … 390 347 static_assert( !std::is_same<const ast::Node * &, decltype(old_val)>::value, "ERROR" ); 391 348 392 auto new_val = call_accept_as_compound( old_val ); 393 394 static_assert( !std::is_same<const ast::Node *, decltype(new_val)>::value || std::is_same<int, decltype(old_val)>::value, "ERROR" ); 395 396 if ( new_val.differs ) { 349 auto result = call_accept_as_compound( old_val ); 350 if ( result.differs ) { 397 351 auto new_parent = __pass::mutate<core_t>(parent); 398 new_val.apply( new_parent, child );352 result.apply( new_parent, child ); 399 353 parent = new_parent; 400 354 } … … 452 406 template< typename core_t > 453 407 inline void ast::accept_all( ast::TranslationUnit & unit, ast::Pass< core_t > & visitor ) { 454 if ( auto ptr = __pass::translation _unit::get_cptr( visitor.core, 0 ) ) {408 if ( auto ptr = __pass::translationUnit( visitor.core, 0 ) ) { 455 409 ValueGuard<const TranslationUnit *> guard( *ptr ); 456 410 *ptr = &unit; -
src/AST/Pass.proto.hpp
raf746cc rdc58e5d 154 154 bool is_old; 155 155 156 delta(const Stmt * s, ssize_t i, bool old) :157 new_val(s), old_idx(i), is_old(old) {}156 explicit delta(const Stmt * s) : new_val(s), old_idx(-1), is_old(false) {} 157 explicit delta(ssize_t i) : new_val(nullptr), old_idx(i), is_old(true) {} 158 158 }; 159 159 … … 188 188 std::transform( stmts->begin(), stmts->end(), std::back_inserter( values ), 189 189 [](ast::ptr<ast::Stmt>& stmt) -> delta { 190 return delta( stmt.release() , -1, false);190 return delta( stmt.release() ); 191 191 }); 192 192 stmts->clear(); … … 201 201 [](ast::ptr<ast::Decl>& decl) -> delta { 202 202 ast::Decl const * d = decl.release(); 203 return delta( new DeclStmt( d->location, d ) , -1, false);203 return delta( new DeclStmt( d->location, d ) ); 204 204 }); 205 205 decls->clear(); … … 226 226 // Now the original containers should still have the unchanged values 227 227 // but also contain the new values. 228 }229 };230 231 /// Used by previsit implementation232 /// We need to reassign the result to 'node', unless the function233 /// returns void, then we just leave 'node' unchanged234 template<bool is_void>235 struct __assign;236 237 template<>238 struct __assign<true> {239 template<typename core_t, typename node_t>240 static inline void result( core_t & core, const node_t * & node ) {241 core.previsit( node );242 }243 };244 245 template<>246 struct __assign<false> {247 template<typename core_t, typename node_t>248 static inline void result( core_t & core, const node_t * & node ) {249 node = core.previsit( node );250 assertf(node, "Previsit must not return NULL");251 }252 };253 254 /// Used by postvisit implementation255 /// We need to return the result unless the function256 /// returns void, then we just return the original node257 template<bool is_void>258 struct __return;259 260 template<>261 struct __return<true> {262 template<typename core_t, typename node_t>263 static inline const node_t * result( core_t & core, const node_t * & node ) {264 core.postvisit( node );265 return node;266 }267 };268 269 template<>270 struct __return<false> {271 template<typename core_t, typename node_t>272 static inline auto result( core_t & core, const node_t * & node ) {273 return core.postvisit( node );274 228 } 275 229 }; … … 297 251 ); 298 252 299 __assign< 300 std::is_void< 301 decltype( core.previsit( node ) ) 302 >::value 303 >::result( core, node ); 253 // We need to reassign the result to 'node', unless the function 254 // returns void, then we just leave 'node' unchanged 255 if constexpr ( std::is_void_v<decltype( core.previsit( node ) )> ) { 256 core.previsit( node ); 257 } else { 258 node = core.previsit( node ); 259 assertf( node, "Previsit must not return nullptr." ); 260 } 304 261 } 305 262 … … 312 269 decltype( core.postvisit( node ), node->accept( *(Visitor*)nullptr ) ) 313 270 { 314 return __return< 315 std::is_void< 316 decltype( core.postvisit( node ) ) 317 >::value 318 >::result( core, node ); 271 // We need to return the result unless the function 272 // returns void, then we just return the original node 273 if constexpr ( std::is_void_v<decltype( core.postvisit( node ) )> ) { 274 core.postvisit( node ); 275 return node; 276 } else { 277 return core.postvisit( node ); 278 } 319 279 } 320 280 … … 350 310 FIELD_PTR( at_cleanup, __pass::at_cleanup_t ) 351 311 FIELD_PTR( visitor, ast::Pass<core_t> * const ) 312 FIELD_PTR( translationUnit, const TranslationUnit * ) 352 313 353 314 // Remove the macro to make sure we don't clash … … 546 507 } // namespace forall 547 508 548 // For passes that need access to the global context. Searches `translationUnit`549 namespace translation_unit {550 template<typename core_t>551 static inline auto get_cptr( core_t & core, int )552 -> decltype( &core.translationUnit ) {553 return &core.translationUnit;554 }555 556 template<typename core_t>557 static inline const TranslationUnit ** get_cptr( core_t &, long ) {558 return nullptr;559 }560 }561 562 509 // For passes, usually utility passes, that have a result. 563 510 namespace result { -
src/Parser/StatementNode.cc
raf746cc rdc58e5d 122 122 ast::Expr * cond = nullptr; 123 123 if ( ctl->condition ) { 124 // compare the provided condition against 0 125 cond = notZeroExpr( maybeMoveBuild( ctl->condition ) ); 124 cond = maybeMoveBuild( ctl->condition ); 126 125 } else { 127 126 for ( ast::ptr<ast::Stmt> & stmt : inits ) { … … 129 128 auto declStmt = stmt.strict_as<ast::DeclStmt>(); 130 129 auto dwt = declStmt->decl.strict_as<ast::DeclWithType>(); 131 ast::Expr * nze = n otZeroExpr( new ast::VariableExpr( dwt->location, dwt ));130 ast::Expr * nze = new ast::VariableExpr( dwt->location, dwt ); 132 131 cond = cond ? new ast::LogicalExpr( dwt->location, cond, nze, ast::AndExpr ) : nze; 133 132 } … … 200 199 // do-while cannot have declarations in the contitional, so init is always empty 201 200 return new ast::WhileDoStmt( location, 202 notZeroExpr( maybeMoveBuild( ctl )),201 maybeMoveBuild( ctl ), 203 202 buildMoveSingle( stmt ), 204 203 buildMoveOptional( else_ ), … … 213 212 214 213 ast::Expr * astcond = nullptr; // maybe empty 215 astcond = notZeroExpr( maybeMoveBuild( forctl->condition ));214 astcond = maybeMoveBuild( forctl->condition ); 216 215 217 216 ast::Expr * astincr = nullptr; // maybe empty … … 330 329 clause->target = maybeBuild( targetExpr ); 331 330 clause->stmt = maybeMoveBuild( stmt ); 332 clause->when_cond = notZeroExpr( maybeMoveBuild( when ));331 clause->when_cond = maybeMoveBuild( when ); 333 332 334 333 ExpressionNode * next = targetExpr->next; … … 345 344 ast::WaitForStmt * build_waitfor_else( const CodeLocation & location, ast::WaitForStmt * existing, ExpressionNode * when, StatementNode * stmt ) { 346 345 existing->else_stmt = maybeMoveBuild( stmt ); 347 existing->else_cond = notZeroExpr( maybeMoveBuild( when ));346 existing->else_cond = maybeMoveBuild( when ); 348 347 349 348 (void)location; … … 354 353 existing->timeout_time = maybeMoveBuild( timeout ); 355 354 existing->timeout_stmt = maybeMoveBuild( stmt ); 356 existing->timeout_cond = notZeroExpr( maybeMoveBuild( when ));355 existing->timeout_cond = maybeMoveBuild( when ); 357 356 358 357 (void)location; … … 362 361 ast::WaitUntilStmt::ClauseNode * build_waituntil_clause( const CodeLocation & loc, ExpressionNode * when, ExpressionNode * targetExpr, StatementNode * stmt ) { 363 362 ast::WhenClause * clause = new ast::WhenClause( loc ); 364 clause->when_cond = notZeroExpr( maybeMoveBuild( when ));363 clause->when_cond = maybeMoveBuild( when ); 365 364 clause->stmt = maybeMoveBuild( stmt ); 366 365 clause->target = maybeMoveBuild( targetExpr ); … … 369 368 ast::WaitUntilStmt::ClauseNode * build_waituntil_else( const CodeLocation & loc, ExpressionNode * when, StatementNode * stmt ) { 370 369 ast::WhenClause * clause = new ast::WhenClause( loc ); 371 clause->when_cond = notZeroExpr( maybeMoveBuild( when ));370 clause->when_cond = maybeMoveBuild( when ); 372 371 clause->stmt = maybeMoveBuild( stmt ); 373 372 return new ast::WaitUntilStmt::ClauseNode( ast::WaitUntilStmt::ClauseNode::Op::ELSE, clause ); … … 508 507 509 508 ast::Expr * astcond = nullptr; // maybe empty 510 astcond = notZeroExpr( maybeMoveBuild( forctl->condition ));509 astcond = maybeMoveBuild( forctl->condition ); 511 510 512 511 ast::Expr * astincr = nullptr; // maybe empty -
src/Parser/module.mk
raf746cc rdc58e5d 31 31 Parser/parser.yy \ 32 32 Parser/ParserTypes.h \ 33 Parser/parserutility.cc \34 33 Parser/parserutility.h \ 35 34 Parser/RunParser.cpp \ -
src/Parser/parserutility.h
raf746cc rdc58e5d 17 17 18 18 #include "AST/Copy.hpp" // for shallowCopy 19 namespace ast {20 class Expr;21 }22 23 ast::Expr * notZeroExpr( const ast::Expr *orig );24 19 25 20 template< typename T > -
src/ResolvExpr/CandidateFinder.cpp
raf746cc rdc58e5d 46 46 #include "AST/Type.hpp" 47 47 #include "Common/utility.h" // for move, copy 48 #include "Parser/parserutility.h" // for notZeroExpr49 48 #include "SymTab/Mangler.h" 50 49 #include "Tuples/Tuples.h" // for handleTupleAssignment … … 1514 1513 void Finder::postvisit( const ast::LogicalExpr * logicalExpr ) { 1515 1514 CandidateFinder finder1( context, tenv ); 1516 ast::ptr<ast::Expr> arg1 = notZeroExpr( logicalExpr->arg1 );1515 ast::ptr<ast::Expr> arg1 = createCondExpr( logicalExpr->arg1 ); 1517 1516 finder1.find( arg1, ResolveMode::withAdjustment() ); 1518 1517 if ( finder1.candidates.empty() ) return; 1519 1518 1520 1519 CandidateFinder finder2( context, tenv ); 1521 ast::ptr<ast::Expr> arg2 = notZeroExpr( logicalExpr->arg2 );1520 ast::ptr<ast::Expr> arg2 = createCondExpr( logicalExpr->arg2 ); 1522 1521 finder2.find( arg2, ResolveMode::withAdjustment() ); 1523 1522 if ( finder2.candidates.empty() ) return; … … 1545 1544 void Finder::postvisit( const ast::ConditionalExpr * conditionalExpr ) { 1546 1545 // candidates for condition 1547 ast::ptr<ast::Expr> arg1 = notZeroExpr( conditionalExpr->arg1 );1546 ast::ptr<ast::Expr> arg1 = createCondExpr( conditionalExpr->arg1 ); 1548 1547 CandidateFinder finder1( context, tenv ); 1549 1548 finder1.find( arg1, ResolveMode::withAdjustment() ); … … 2166 2165 CandidateRef & choice = winners.front(); 2167 2166 return choice->expr; 2168 // return std::move( choice->expr.get() ); 2167 } 2168 2169 const ast::Expr * createCondExpr( const ast::Expr * expr ) { 2170 assert( expr ); 2171 return new ast::CastExpr( expr->location, 2172 ast::UntypedExpr::createCall( expr->location, 2173 "?!=?", 2174 { 2175 expr, 2176 new ast::ConstantExpr( expr->location, 2177 new ast::ZeroType(), "0", std::make_optional( 0ull ) 2178 ), 2179 } 2180 ), 2181 new ast::BasicType( ast::BasicType::SignedInt ) 2182 ); 2169 2183 } 2170 2184 -
src/ResolvExpr/CandidateFinder.hpp
raf746cc rdc58e5d 72 72 const ast::Expr * getValueEnumCall(const ast::Expr * expr, 73 73 const ResolvExpr::ResolveContext & context, const ast::TypeEnvironment & env ); 74 /// Wrap an expression to convert the result to a conditional result. 75 const ast::Expr * createCondExpr( const ast::Expr * expr ); 74 76 75 77 } // namespace ResolvExpr -
src/ResolvExpr/Resolver.cc
raf746cc rdc58e5d 340 340 } 341 341 342 ast::ptr< ast::Expr > findCondExpression( 343 const ast::Expr * untyped, const ResolveContext & context 344 ) { 345 if ( nullptr == untyped ) return untyped; 346 ast::ptr<ast::Expr> condExpr = createCondExpr( untyped ); 347 return findIntegralExpression( condExpr, context ); 348 } 349 342 350 /// check if a type is a character type 343 351 bool isCharType( const ast::Type * t ) { … … 356 364 return it != end; 357 365 } 358 } 366 } // anonymous namespace 359 367 360 368 class Resolver final … … 729 737 const ast::IfStmt * Resolver::previsit( const ast::IfStmt * ifStmt ) { 730 738 return ast::mutate_field( 731 ifStmt, &ast::IfStmt::cond, find IntegralExpression( ifStmt->cond, context ) );739 ifStmt, &ast::IfStmt::cond, findCondExpression( ifStmt->cond, context ) ); 732 740 } 733 741 734 742 const ast::WhileDoStmt * Resolver::previsit( const ast::WhileDoStmt * whileDoStmt ) { 735 743 return ast::mutate_field( 736 whileDoStmt, &ast::WhileDoStmt::cond, find IntegralExpression( whileDoStmt->cond, context ) );744 whileDoStmt, &ast::WhileDoStmt::cond, findCondExpression( whileDoStmt->cond, context ) ); 737 745 } 738 746 … … 740 748 if ( forStmt->cond ) { 741 749 forStmt = ast::mutate_field( 742 forStmt, &ast::ForStmt::cond, find IntegralExpression( forStmt->cond, context ) );750 forStmt, &ast::ForStmt::cond, findCondExpression( forStmt->cond, context ) ); 743 751 } 744 752 … … 1075 1083 1076 1084 // Resolve the conditions as if it were an IfStmt, statements normally 1077 clause2->when_cond = find SingleExpression( clause.when_cond, context );1085 clause2->when_cond = findCondExpression( clause.when_cond, context ); 1078 1086 clause2->stmt = clause.stmt->accept( *visitor ); 1079 1087 … … 1089 1097 new ast::BasicType{ ast::BasicType::LongLongUnsignedInt }; 1090 1098 auto timeout_time = findSingleExpression( stmt->timeout_time, target, context ); 1091 auto timeout_cond = find SingleExpression( stmt->timeout_cond, context );1099 auto timeout_cond = findCondExpression( stmt->timeout_cond, context ); 1092 1100 auto timeout_stmt = stmt->timeout_stmt->accept( *visitor ); 1093 1101 … … 1102 1110 if ( stmt->else_stmt ) { 1103 1111 // resolve the condition like IfStmt, stmts normally 1104 auto else_cond = find SingleExpression( stmt->else_cond, context );1112 auto else_cond = findCondExpression( stmt->else_cond, context ); 1105 1113 auto else_stmt = stmt->else_stmt->accept( *visitor ); 1106 1114 -
src/Validate/ImplementEnumFunc.cpp
raf746cc rdc58e5d 516 516 ast::EnumInstType enumInst(enumDecl->name); 517 517 enumInst.base = enumDecl; 518 // ast::EnumAttrType attr = ast::EnumAttrType(&enumInst); 519 // EnumAttrFuncGenerator gen(enumDecl, &enumInst functionNesting); 518 520 519 EnumAttrFuncGenerator gen(enumDecl, &enumInst, functionNesting); 521 520 gen.generateAndAppendFunctions(declsToAddAfter);
Note:
See TracChangeset
for help on using the changeset viewer.