Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/TranslateEnumRange.cpp

    r9739c56f r5f210c0  
    66namespace ControlStruct {
    77
    8 namespace {
    9 
    10 struct TranslateEnumRangeCore {
    11         const ast::Stmt * postvisit( const ast::ForStmt * stmt );
     8struct addInit {
     9    const ast::Stmt * postvisit( const ast::ForStmt * stmt );
    1210};
    1311
    14 const ast::Stmt * TranslateEnumRangeCore::postvisit( const ast::ForStmt * stmt ) {
    15         if ( !stmt->range_over ) return stmt;
    16         auto mutStmt = ast::mutate( stmt );
    17         auto & location = mutStmt->location;
     12struct translateEnumRangeCore {
     13    const ast::Stmt * postvisit( const ast::ForStmt * stmt );
     14};
    1815
    19         if ( auto declStmt = mutStmt->inits.front().as<ast::DeclStmt>() ) {
    20                 if ( auto objDecl = declStmt->decl.as<ast::ObjectDecl>() ) {
    21                         if ( !objDecl->init ) {
    22                                 ast::SingleInit * newInit = new ast::SingleInit( location,
    23                                         ast::UntypedExpr::createCall( location,
    24                                                 mutStmt->is_inc ? "lowerBound" : "upperBound", {} ),
    25                                         ast::ConstructFlag::MaybeConstruct
    26                                 );
    27                                 auto objDeclWithInit = ast::mutate_field( objDecl, &ast::ObjectDecl::init, newInit );
    28                                 auto declWithInit = ast::mutate_field( declStmt, &ast::DeclStmt::decl, objDeclWithInit );
    29                                 mutStmt->inits[0] = declWithInit;
    30                         }
    31                 }
    32         }
     16const ast::Stmt* addInit::postvisit( const ast::ForStmt * stmt ) {
     17    if ( stmt->range_over ) {
     18        auto inits = stmt->inits;
     19        auto init = stmt->inits.front();
    3320
    34         auto declStmt = mutStmt->inits.front().strict_as<ast::DeclStmt>();
    35         auto initDecl = declStmt->decl.strict_as<ast::ObjectDecl>();
    36         auto indexName = initDecl->name;
    37 
    38         // Both inc and dec check if the current posn less than the number of enumerator
    39         // for dec, it keeps call pred until it passes 0 (the first enumerator) and underflow,
    40         // it wraps around and become unsigned max
    41         ast::UntypedExpr * condition = ast::UntypedExpr::createCall( location,
    42                 mutStmt->is_inc ? "?<=?" : "?>=?",
    43                 {
    44                         new ast::NameExpr( location, indexName ),
    45                         ast::UntypedExpr::createCall( location,
    46                                 mutStmt->is_inc ? "upperBound" : "lowerBound", {} )
    47                 } );
    48         auto increment = ast::UntypedExpr::createCall( location,
    49                 mutStmt->is_inc ? "succ_unsafe" : "pred_unsafe",
    50                 { new ast::NameExpr( location, indexName ) } );
    51         auto assig = ast::UntypedExpr::createAssign( location,
    52                 new ast::NameExpr( location, indexName ), increment );
    53         mutStmt->cond = condition;
    54         mutStmt->inc = assig;
    55         return mutStmt;
     21        if (auto declStmt = init.as<ast::DeclStmt>()) {
     22            auto decl = declStmt->decl;
     23            if ( auto objDecl = decl.as<ast::ObjectDecl>()) {
     24                if ( !objDecl->init ) {
     25                    auto location = stmt->location;
     26                    ast::SingleInit * newInit = new ast::SingleInit( location,
     27                        stmt->is_inc?
     28                        ast::UntypedExpr::createCall( location, "lowerBound", {} ):
     29                        ast::UntypedExpr::createCall( location, "upperBound", {} ),
     30                        ast::ConstructFlag::MaybeConstruct
     31                    );
     32                    auto objDeclWithInit = ast::mutate_field( objDecl, &ast::ObjectDecl::init, newInit );
     33                    auto declWithInit = ast::mutate_field( declStmt, &ast::DeclStmt::decl, objDeclWithInit );
     34                    stmt = ast::mutate_field_index( stmt, &ast::ForStmt::inits, 0, declWithInit );
     35                }
     36            }
     37        }
     38    }
     39    return stmt;
    5640}
    5741
    58 } // namespace
     42const ast::Stmt* translateEnumRangeCore::postvisit( const ast::ForStmt * stmt ) {
     43    if ( !stmt->range_over ) return stmt;
     44    auto location = stmt->location;
     45    auto declStmt = stmt->inits.front().strict_as<ast::DeclStmt>();
     46    auto initDecl = declStmt->decl.strict_as<ast::ObjectDecl>();
     47    auto indexName = initDecl->name;
     48
     49    // Both inc and dec check if the current posn less than the number of enumerator
     50    // for dec, it keeps call pred until it passes 0 (the first enumerator) and underflow,
     51    // it wraps around and become unsigned max
     52    ast::UntypedExpr * condition = ast::UntypedExpr::createCall( location,
     53        stmt->is_inc? "?<=?": "?>=?",
     54        {   new ast::NameExpr( location, indexName ),
     55            stmt->is_inc?
     56                ast::UntypedExpr::createCall( location, "upperBound", {} ):
     57                ast::UntypedExpr::createCall( location, "lowerBound", {} )
     58        });
     59    auto increment = ast::UntypedExpr::createCall( location,
     60        stmt->is_inc? "succ_unsafe": "pred_unsafe",
     61        { new ast::NameExpr( location, indexName ) });
     62    auto assig = ast::UntypedExpr::createAssign( location, new ast::NameExpr( location, indexName ), increment );
     63    auto mut = ast::mutate_field( stmt, &ast::ForStmt::cond, condition );
     64    mut = ast::mutate_field(stmt, &ast::ForStmt::inc, assig );
     65    return mut;
     66
    5967
    6068void translateEnumRange( ast::TranslationUnit & translationUnit ) {
    61         ast::Pass<TranslateEnumRangeCore>::run( translationUnit );
     69    ast::Pass<addInit>::run( translationUnit );
     70    ast::Pass<translateEnumRangeCore>::run( translationUnit );
    6271}
    63 
    64 } // namespace ControlStruct
     72}
Note: See TracChangeset for help on using the changeset viewer.