source: src/ControlStruct/TranslateEnumRange.cpp @ 94aa202

Last change on this file since 94aa202 was fca78f1, checked in by Andrew Beach <ajbeach@…>, 3 months ago

Added ForeachStmt? (felt better than ForEachStmt?). This new node is a bit optimistic in that currently it is covering a very narrow case, but with improvements to it and RangeExpr?, it could handle many more kind of loops.

  • Property mode set to 100644
File size: 2.0 KB
Line 
1#include "TranslateEnumRange.hpp"
2
3#include "AST/Pass.hpp"
4#include "AST/TranslationUnit.hpp"
5
6namespace ControlStruct {
7
8namespace {
9
10struct TranslateEnumRangeCore {
11        const ast::Stmt * postvisit( const ast::ForeachStmt * stmt );
12};
13
14const 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
62void translateEnumRange( ast::TranslationUnit & translationUnit ) {
63        ast::Pass<TranslateEnumRangeCore>::run( translationUnit );
64}
65
66} // namespace ControlStruct
Note: See TracBrowser for help on using the repository browser.