Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/MLEMutator.cc

    raf68f0a r8688ce1  
    5656                bool labeledBlock = !(cmpndStmt->get_labels().empty());
    5757                if ( labeledBlock ) {
    58                         Label brkLabel = generator->newLabel("blockBreak", cmpndStmt);
     58                        Label brkLabel = generator->newLabel("blockBreak");
    5959                        enclosingControlStructures.push_back( Entry( cmpndStmt, brkLabel ) );
    6060                } // if
     
    8080                // whether brkLabel and contLabel are used with branch statements and will recursively do the same to nested
    8181                // loops
    82                 Label brkLabel = generator->newLabel("loopBreak", loopStmt);
    83                 Label contLabel = generator->newLabel("loopContinue", loopStmt);
     82                Label brkLabel = generator->newLabel("loopBreak");
     83                Label contLabel = generator->newLabel("loopContinue");
    8484                enclosingControlStructures.push_back( Entry( loopStmt, brkLabel, contLabel ) );
    8585                loopStmt->set_body ( loopStmt->get_body()->acceptMutator( *this ) );
    8686
    87                 assert( ! enclosingControlStructures.empty() );
    8887                Entry &e = enclosingControlStructures.back();
    8988                // sanity check that the enclosing loops have been popped correctly
     
    109108                bool labeledBlock = !(ifStmt->get_labels().empty());
    110109                if ( labeledBlock ) {
    111                         Label brkLabel = generator->newLabel("blockBreak", ifStmt);
     110                        Label brkLabel = generator->newLabel("blockBreak");
    112111                        enclosingControlStructures.push_back( Entry( ifStmt, brkLabel ) );
    113112                } // if
    114113
    115114                Parent::mutate( ifStmt );
    116 
     115               
    117116                if ( labeledBlock ) {
    118117                        if ( ! enclosingControlStructures.back().useBreakExit().empty() ) {
     
    127126        Statement *MLEMutator::handleSwitchStmt( SwitchClass *switchStmt ) {
    128127                // generate a label for breaking out of a labeled switch
    129                 Label brkLabel = generator->newLabel("switchBreak", switchStmt);
     128                Label brkLabel = generator->newLabel("switchBreak");
    130129                enclosingControlStructures.push_back( Entry(switchStmt, brkLabel) );
    131130                mutateAll( switchStmt->get_statements(), *this );
     
    159158
    160159                std::list< Entry >::reverse_iterator targetEntry;
    161                 switch ( branchStmt->get_type() ) {
    162                         case BranchStmt::Goto:
    163                                 return branchStmt;
    164                         case BranchStmt::Continue:
    165                         case BranchStmt::Break: {
    166                                 bool isContinue = branchStmt->get_type() == BranchStmt::Continue;
    167                                 // unlabeled break/continue
    168                                 if ( branchStmt->get_target() == "" ) {
    169                                         if ( isContinue ) {
    170                                                 // continue target is outermost loop
    171                                                 targetEntry = std::find_if( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), [](Entry &e) { return isLoop( e.get_controlStructure() ); } );
    172                                         } else {
    173                                                 // break target is outmost control structure
    174                                                 if ( enclosingControlStructures.empty() ) throw SemanticError( "'break' outside a loop, switch, or labelled block" );
    175                                                 targetEntry = enclosingControlStructures.rbegin();
    176                                         } // if
    177                                 } else {
    178                                         // labeled break/continue - lookup label in table to find attached control structure
    179                                         targetEntry = std::find( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), (*targetTable)[branchStmt->get_target()] );
    180                                 } // if
    181                                 // ensure that selected target is valid
    182                                 if ( targetEntry == enclosingControlStructures.rend() || (isContinue && ! isLoop( targetEntry->get_controlStructure() ) ) ) {
    183                                         throw SemanticError( toString( (isContinue ? "'continue'" : "'break'"), " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "), originalTarget ) );
    184                                 } // if
    185                                 break;
    186                         }
    187                         default:
    188                                 assert( false );
    189                 } // switch
     160                if ( branchStmt->get_type() == BranchStmt::Goto ) {
     161                        return branchStmt;
     162                } else if ( branchStmt->get_type() == BranchStmt::Continue) {
     163                        // continue target must be a loop
     164                        if ( branchStmt->get_target() == "" ) {
     165                                targetEntry = std::find_if( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), [](Entry &e) { return isLoop( e.get_controlStructure() ); } );
     166                        } else {
     167                                // labelled continue - lookup label in table ot find attached control structure
     168                                targetEntry = std::find( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), (*targetTable)[branchStmt->get_target()] );
     169                        } // if
     170                        if ( targetEntry == enclosingControlStructures.rend() || ! isLoop( targetEntry->get_controlStructure() ) ) {
     171                                throw SemanticError( "'continue' target must be an enclosing loop: " + originalTarget );
     172                        } // if
     173                } else if ( branchStmt->get_type() == BranchStmt::Break ) {
     174                        if ( enclosingControlStructures.empty() ) throw SemanticError( "'break' outside a loop, switch, or labelled block" );
     175                        targetEntry = enclosingControlStructures.rbegin();
     176                } else {
     177                        assert( false );
     178                } // if
     179
     180                if ( branchStmt->get_target() != "" && targetTable->find( branchStmt->get_target() ) == targetTable->end() ) {
     181                        throw SemanticError("The label defined in the exit loop statement does not exist: " + originalTarget );  // shouldn't happen (since that's already checked)
     182                } // if
    190183
    191184                // branch error checks, get the appropriate label name and create a goto
     
    204197                } // switch
    205198
    206                 // transform break/continue statements into goto to simplify later handling of branches
    207                 delete branchStmt;
    208                 return new BranchStmt( std::list<Label>(), exitLabel, BranchStmt::Goto );
     199                if ( branchStmt->get_target() == "" && branchStmt->get_type() != BranchStmt::Continue ) {
     200                        // unlabelled break/continue - can keep branch as break/continue for extra semantic information, but add
     201                        // exitLabel as its destination so that label passes can easily determine where the break/continue goes to
     202                        branchStmt->set_target( exitLabel );
     203                        return branchStmt;
     204                } else {
     205                        // labelled break/continue - can't easily emulate this with break and continue, so transform into a goto
     206                        delete branchStmt;
     207                        return new BranchStmt( std::list<Label>(), exitLabel, BranchStmt::Goto );
     208                } // if
    209209        }
    210210
Note: See TracChangeset for help on using the changeset viewer.