Ignore:
Timestamp:
Dec 20, 2023, 12:04:33 PM (10 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
master
Children:
523e300
Parents:
9fba8e6
Message:

You can how use local control flow out of 'catch' clauses. Added a test to show that it works.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/ExceptTranslate.cpp

    r9fba8e6 r0a6d2045  
    151151                const ast::DeclWithType * except_obj, ast::CatchClause * modded_handler );
    152152        ast::FunctionDecl * create_terminate_match( CatchList &handlers );
    153         ast::CompoundStmt * create_terminate_caller( CodeLocation loc, ast::FunctionDecl * try_wrapper,
    154                 ast::FunctionDecl * terminate_catch, ast::FunctionDecl * terminate_match );
     153        ast::CompoundStmt * create_terminate_caller( const CodeLocation & location,
     154                ast::FunctionDecl * try_wrapper, ast::FunctionDecl * terminate_match,
     155                CatchList & terminate_handlers );
    155156        ast::FunctionDecl * create_resume_handler( CatchList &handlers );
    156157        ast::CompoundStmt * create_resume_wrapper(
     
    264265        //     `handler.body`;
    265266        // }
    266         // return;
     267        // break;
    267268        const CodeLocation & location = clause->location;
    268269
     
    295296                                body,
    296297                        } ),
    297                         new ast::ReturnStmt( location, nullptr ),
     298                        new ast::BranchStmt( location, ast::BranchStmt::Break,
     299                                ast::Label( location ) ),
    298300                }
    299301        );
     
    391393        // Index 1..{number of handlers}
    392394        int index = 0;
    393         CatchList::iterator it;
    394         for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
     395        for ( ast::CatchClause * handler : handlers ) {
    395396                ++index;
    396                 ast::CatchClause * handler = *it;
    397 
    398                 // Body should have been taken by create_terminate_catch.
    399                 // xxx - just ignore it?
    400                 // assert( nullptr == handler->get_body() );
    401 
    402                 // Create new body.
    403                 handler->body = new ast::ReturnStmt( handler->location,
     397
     398                ast::ptr<ast::Stmt> other_body = new ast::ReturnStmt( handler->location,
    404399                        ast::ConstantExpr::from_int( handler->location, index ) );
    405 
    406                 // Create the handler.
     400                handler->body.swap( other_body );
     401
    407402                body->push_back( create_single_matcher( except_obj, handler ) );
    408                 *it = nullptr;
     403
     404                handler->body.swap( other_body );
    409405        }
    410406
     
    425421
    426422ast::CompoundStmt * TryMutatorCore::create_terminate_caller(
    427                 CodeLocation loc,
     423                const CodeLocation & loc,
    428424                ast::FunctionDecl * try_wrapper,
    429                 ast::FunctionDecl * terminate_catch,
    430                 ast::FunctionDecl * terminate_match ) {
     425                ast::FunctionDecl * terminate_match,
     426                CatchList & terminate_handlers ) {
    431427        // {
    432428        //     int __handler_index = __cfaehm_try_terminate(`try`, `match`);
     
    447443        );
    448444
     445        ast::ObjectDecl * except = make_exception_object( loc );
     446        except->init = new ast::SingleInit( loc,
     447                new ast::UntypedExpr( loc,
     448                        new ast::NameExpr( loc, "__cfaehm_get_current_termination" )
     449                )
     450        );
     451
     452        std::vector<ast::ptr<ast::CaseClause>> cases;
     453        for ( auto const & [index, handler] : enumerate( terminate_handlers ) ) {
     454                cases.emplace_back(
     455                        create_terminate_catch_case( except, index + 1, handler ) );
     456        }
     457        auto switch_stmt = new ast::SwitchStmt( loc,
     458                new ast::VariableExpr( loc, index ), std::move( cases ) );
     459
    449460        return new ast::CompoundStmt( loc, {
    450461                new ast::DeclStmt( loc, index ),
    451462                new ast::IfStmt( loc,
    452463                        new ast::VariableExpr( loc, index ),
    453                         new ast::ExprStmt( loc,
    454                                 new ast::UntypedExpr( loc,
    455                                         new ast::VariableExpr( loc, terminate_catch ),
    456                                         {
    457                                                 new ast::VariableExpr( loc, index ),
    458                                                 new ast::UntypedExpr( loc,
    459                                                         new ast::NameExpr( loc, "__cfaehm_get_current_termination" )
    460                                                 ),
    461                                         }
    462                                 )
    463                         )
     464                        new ast::CompoundStmt( loc, {
     465                                new ast::DeclStmt( loc, except ),
     466                                switch_stmt,
     467                        } )
    464468                ),
    465469        } );
     
    663667
    664668        if ( termination_handlers.size() ) {
    665                 // Define the three helper functions.
     669                // Define the two helper functions.
    666670                ast::FunctionDecl * try_wrapper = create_try_wrapper( inner );
    667671                appendDeclStmt( block, try_wrapper );
    668                 ast::FunctionDecl * terminate_catch =
    669                         create_terminate_catch( termination_handlers );
    670                 appendDeclStmt( block, terminate_catch );
    671672                ast::FunctionDecl * terminate_match =
    672673                        create_terminate_match( termination_handlers );
     
    674675                // Build the call to the try wrapper.
    675676                inner = create_terminate_caller(inner->location,
    676                         try_wrapper, terminate_catch, terminate_match );
     677                        try_wrapper, terminate_match, termination_handlers );
    677678        }
    678679
Note: See TracChangeset for help on using the changeset viewer.