| 1 | #include "TranslateEnumRange.hpp"
 | 
|---|
| 2 | 
 | 
|---|
| 3 | #include "AST/Pass.hpp"
 | 
|---|
| 4 | #include "AST/TranslationUnit.hpp"
 | 
|---|
| 5 | 
 | 
|---|
| 6 | namespace ControlStruct {
 | 
|---|
| 7 | 
 | 
|---|
| 8 | namespace {
 | 
|---|
| 9 | 
 | 
|---|
| 10 | struct TranslateEnumRangeCore {
 | 
|---|
| 11 |         const ast::Stmt * postvisit( const ast::ForeachStmt * stmt );
 | 
|---|
| 12 | };
 | 
|---|
| 13 | 
 | 
|---|
| 14 | const ast::Stmt * TranslateEnumRangeCore::postvisit( const ast::ForeachStmt * stmt ) {
 | 
|---|
| 15 |         auto & location = stmt->location;
 | 
|---|
| 16 | 
 | 
|---|
| 17 |         assert( stmt->inits.size() == 1 );
 | 
|---|
| 18 |         ast::DeclStmt const * initialize = stmt->inits.front().strict_as<ast::DeclStmt>();
 | 
|---|
| 19 | 
 | 
|---|
| 20 |         auto objDecl = initialize->decl.strict_as<ast::ObjectDecl>();
 | 
|---|
| 21 |         if ( !objDecl->init ) {
 | 
|---|
| 22 |                 ast::SingleInit * init = new ast::SingleInit( location,
 | 
|---|
| 23 |                         ast::UntypedExpr::createCall( location,
 | 
|---|
| 24 |                                 stmt->isIncreasing ? "lowerBound" : "upperBound", {} ),
 | 
|---|
| 25 |                         ast::ConstructFlag::MaybeConstruct
 | 
|---|
| 26 |                 );
 | 
|---|
| 27 |                 objDecl = ast::mutate_field( objDecl, &ast::ObjectDecl::init, init );
 | 
|---|
| 28 |                 initialize = ast::mutate_field( initialize, &ast::DeclStmt::decl, objDecl );
 | 
|---|
| 29 |         }
 | 
|---|
| 30 | 
 | 
|---|
| 31 |         auto indexName = objDecl->name;
 | 
|---|
| 32 | 
 | 
|---|
| 33 |         // Both inc and dec check if the current posn less than the number of enumerator
 | 
|---|
| 34 |         // for dec, it keeps call pred until it passes 0 (the first enumerator) and underflow,
 | 
|---|
| 35 |         // it wraps around and become unsigned max
 | 
|---|
| 36 |         ast::UntypedExpr * condition = ast::UntypedExpr::createCall( location,
 | 
|---|
| 37 |                 stmt->isIncreasing ? "?<=?" : "?>=?",
 | 
|---|
| 38 |                 {
 | 
|---|
| 39 |                         new ast::NameExpr( location, indexName ),
 | 
|---|
| 40 |                         ast::UntypedExpr::createCall( location,
 | 
|---|
| 41 |                                 stmt->isIncreasing ? "upperBound" : "lowerBound", {} )
 | 
|---|
| 42 |                 } );
 | 
|---|
| 43 |         ast::UntypedExpr * increment = ast::UntypedExpr::createAssign( location,
 | 
|---|
| 44 |                 new ast::NameExpr( location, indexName ),
 | 
|---|
| 45 |                 ast::UntypedExpr::createCall( location,
 | 
|---|
| 46 |                         stmt->isIncreasing ? "succ_unsafe" : "pred_unsafe",
 | 
|---|
| 47 |                         { new ast::NameExpr( location, indexName ) } ) );
 | 
|---|
| 48 | 
 | 
|---|
| 49 |         return new ast::ForStmt(
 | 
|---|
| 50 |                 stmt->location,
 | 
|---|
| 51 |                 { initialize },
 | 
|---|
| 52 |                 condition,
 | 
|---|
| 53 |                 increment,
 | 
|---|
| 54 |                 stmt->body,
 | 
|---|
| 55 |                 stmt->else_,
 | 
|---|
| 56 |                 copy( stmt->labels )
 | 
|---|
| 57 |         );
 | 
|---|
| 58 | }
 | 
|---|
| 59 | 
 | 
|---|
| 60 | } // namespace
 | 
|---|
| 61 | 
 | 
|---|
| 62 | void translateEnumRange( ast::TranslationUnit & translationUnit ) {
 | 
|---|
| 63 |         ast::Pass<TranslateEnumRangeCore>::run( translationUnit );
 | 
|---|
| 64 | }
 | 
|---|
| 65 | 
 | 
|---|
| 66 | } // namespace ControlStruct
 | 
|---|