[d66a43b] | 1 | #include "TranslateEnumRange.hpp"
|
---|
[567c775] | 2 |
|
---|
| 3 | #include "AST/Pass.hpp"
|
---|
| 4 | #include "AST/TranslationUnit.hpp"
|
---|
| 5 |
|
---|
| 6 | namespace ControlStruct {
|
---|
| 7 |
|
---|
[9739c56f] | 8 | namespace {
|
---|
[567c775] | 9 |
|
---|
[9739c56f] | 10 | struct TranslateEnumRangeCore {
|
---|
| 11 | const ast::Stmt * postvisit( const ast::ForStmt * stmt );
|
---|
[567c775] | 12 | };
|
---|
| 13 |
|
---|
[9739c56f] | 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;
|
---|
[567c775] | 18 |
|
---|
[9739c56f] | 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 | }
|
---|
| 33 |
|
---|
| 34 | auto declStmt = mutStmt->inits.front().strict_as<ast::DeclStmt>();
|
---|
| 35 | auto initDecl = declStmt->decl.strict_as<ast::ObjectDecl>();
|
---|
| 36 | auto indexName = initDecl->name;
|
---|
[567c775] | 37 |
|
---|
[9739c56f] | 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;
|
---|
| 56 | }
|
---|
[73d0e3f4] | 57 |
|
---|
[9739c56f] | 58 | } // namespace
|
---|
[567c775] | 59 |
|
---|
| 60 | void translateEnumRange( ast::TranslationUnit & translationUnit ) {
|
---|
[9739c56f] | 61 | ast::Pass<TranslateEnumRangeCore>::run( translationUnit );
|
---|
[d66a43b] | 62 | }
|
---|
[9739c56f] | 63 |
|
---|
| 64 | } // namespace ControlStruct
|
---|