Skip to content

Commit 33a4fde

Browse files
authored
Merge pull request #106 from czgdp1807/while_loop_01
Ported ``integration_tests/loop_02.py`` from LPython and improve LC to compile it
2 parents 2222724 + 467fed5 commit 33a4fde

File tree

3 files changed

+204
-1
lines changed

3 files changed

+204
-1
lines changed

integration_tests/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -234,3 +234,5 @@ RUN(NAME union_01.cpp LABELS gcc llvm NOFAST)
234234
RUN(NAME union_02.cpp LABELS gcc llvm NOFAST)
235235

236236
RUN(NAME vector_01.cpp LABELS gcc llvm NOFAST)
237+
238+
RUN(NAME loop_01.cpp LABELS gcc llvm NOFAST)

integration_tests/loop_01.cpp

+142
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
#include <iostream>
2+
3+
#define assert(cond) if( !(cond) ) { \
4+
exit(2); \
5+
} \
6+
7+
void test_loop_01() {
8+
int32_t i = 0;
9+
int32_t j = 0;
10+
11+
while( false ) {
12+
assert( false );
13+
}
14+
15+
while( i < 0 ) {
16+
assert( false );
17+
}
18+
19+
while( i < 10 ) {
20+
i += 1;
21+
}
22+
std::cout<<i<<std::endl;
23+
assert( i == 10 );
24+
25+
while( i < 20 ) {
26+
while( i < 15 ) {
27+
i += 1;
28+
}
29+
i += 1;
30+
}
31+
std::cout<<i<<std::endl;
32+
assert( i == 20 );
33+
34+
for( i = 0; i < 5; i++ ) {
35+
std::cout<<i<<" "<<j<<std::endl;
36+
assert( i == j );
37+
j += 1;
38+
}
39+
}
40+
41+
void test_loop_02() {
42+
int32_t i = 0;
43+
int32_t j = 0;
44+
45+
j = 0;
46+
for( i = 10; i > 0; i-- ) {
47+
j = j + i;
48+
}
49+
std::cout<<j<<std::endl;
50+
assert( j == 55 );
51+
52+
for( i = 0; i < 5; i++ ) {
53+
if( i == 3 ) {
54+
break;
55+
}
56+
}
57+
std::cout<<i<<std::endl;
58+
assert( i == 3 );
59+
60+
j = 0;
61+
for( i = 0; i < 5; i++ ) {
62+
if( i == 3 ) {
63+
continue;
64+
}
65+
j += 1;
66+
}
67+
std::cout<<j<<std::endl;
68+
assert( j == 4 );
69+
}
70+
71+
void test_loop_03() {
72+
int32_t i = 0;
73+
int32_t j = 0;
74+
int32_t k = 0;
75+
while( i < 10 ) {
76+
j = 0;
77+
while( j < 10 ) {
78+
k += 1;
79+
if( i == 0 ) {
80+
if( j == 3 ) {
81+
continue;
82+
} else {
83+
j += 1;
84+
}
85+
}
86+
j += 1;
87+
}
88+
i += 1;
89+
}
90+
std::cout<<k<<std::endl;
91+
assert( k == 95 );
92+
93+
i = 0; j = 0; k = 0;
94+
while( i < 10 ) {
95+
j = 0;
96+
while( j < 10 ) {
97+
k += i + j;
98+
if( i == 5 ) {
99+
if( j == 4 ) {
100+
break;
101+
} else {
102+
j += 1;
103+
}
104+
}
105+
j += 1;
106+
}
107+
i += 1;
108+
}
109+
std::cout<<k<<std::endl;
110+
assert( k == 826 );
111+
112+
i = 0;
113+
if( i == 0 ) {
114+
while( i < 10 ) {
115+
j = 0;
116+
if( j == 0 ) {
117+
while( j < 10 ) {
118+
k += 1;
119+
if( i == 9 ) {
120+
break;
121+
}
122+
j += 1;
123+
}
124+
i += 1;
125+
}
126+
}
127+
}
128+
std::cout<<k<<std::endl;
129+
assert( k == 917 );
130+
}
131+
132+
void verify() {
133+
test_loop_01();
134+
test_loop_02();
135+
test_loop_03();
136+
}
137+
138+
int main() {
139+
140+
verify();
141+
142+
}

src/lc/clang_ast_to_asr.cpp

+60-1
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
165165
bool enable_fall_through;
166166
std::map<ASR::symbol_t*, std::map<std::string, ASR::expr_t*>> struct2member_inits;
167167
std::map<SymbolTable*, std::vector<ASR::symbol_t*>> scope2enums;
168+
clang::ForStmt* for_loop;
169+
bool inside_loop;
168170

169171
explicit ClangASTtoASRVisitor(clang::ASTContext *Context_,
170172
Allocator& al_, ASR::asr_t*& tu_):
@@ -173,7 +175,8 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
173175
assignment_target{nullptr}, print_args{nullptr},
174176
is_all_called{false}, is_range_called{false},
175177
current_switch_case{nullptr}, default_stmt{nullptr},
176-
interpret_init_list_expr_as_list{false}, enable_fall_through{false} {}
178+
interpret_init_list_expr_as_list{false}, enable_fall_through{false},
179+
for_loop{nullptr}, inside_loop{false} {}
177180

178181
template <typename T>
179182
Location Lloc(T *x) {
@@ -2290,10 +2293,26 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
22902293

22912294
bool TraverseBreakStmt(clang::BreakStmt* x) {
22922295
clang::RecursiveASTVisitor<ClangASTtoASRVisitor>::TraverseBreakStmt(x);
2296+
if( inside_loop ) {
2297+
tmp = ASR::make_Exit_t(al, Lloc(x), nullptr);
2298+
is_stmt_created = true;
2299+
}
22932300
is_break_stmt_present.set(true);
22942301
return true;
22952302
}
22962303

2304+
bool TraverseContinueStmt(clang::ContinueStmt* x) {
2305+
if( for_loop != nullptr ) {
2306+
clang::Stmt* inc_stmt = for_loop->getInc();
2307+
TraverseStmt(inc_stmt);
2308+
LCOMPILERS_ASSERT(tmp != nullptr && is_stmt_created);
2309+
current_body->push_back(al, ASRUtils::STMT(tmp.get()));
2310+
}
2311+
tmp = ASR::make_Cycle_t(al, Lloc(x), nullptr);
2312+
is_stmt_created = true;
2313+
return true;
2314+
}
2315+
22972316
bool TraverseCaseStmt(clang::CaseStmt* x) {
22982317
if ( x->caseStmtIsGNURange() ) {
22992318
throw std::runtime_error("Ranges not supported in case.");
@@ -2437,6 +2456,16 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
24372456
is_stmt_created = true;
24382457
break;
24392458
}
2459+
case clang::UnaryOperatorKind::UO_PostDec: {
2460+
ASR::expr_t* decbyone = ASRUtils::EXPR(ASR::make_IntegerBinOp_t(
2461+
al, Lloc(x), var, ASR::binopType::Sub,
2462+
ASRUtils::EXPR(ASR::make_IntegerConstant_t(
2463+
al, Lloc(x), 1, ASRUtils::expr_type(var))),
2464+
ASRUtils::expr_type(var), nullptr));
2465+
tmp = ASR::make_Assignment_t(al, Lloc(x), var, decbyone, nullptr);
2466+
is_stmt_created = true;
2467+
break;
2468+
}
24402469
case clang::UnaryOperatorKind::UO_Minus: {
24412470
CreateUnaryMinus(var, Lloc(x));
24422471
break;
@@ -2452,7 +2481,35 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
24522481
return true;
24532482
}
24542483

2484+
bool TraverseWhileStmt(clang::WhileStmt* x) {
2485+
bool inside_loop_copy = inside_loop;
2486+
inside_loop = true;
2487+
std::map<std::string, std::string> alias;
2488+
scopes.push_back(alias);
2489+
2490+
clang::Expr* loop_cond = x->getCond();
2491+
TraverseStmt(loop_cond);
2492+
ASR::expr_t* test = ASRUtils::EXPR(tmp.get());
2493+
2494+
Vec<ASR::stmt_t*> body; body.reserve(al, 1);
2495+
Vec<ASR::stmt_t*>*current_body_copy = current_body;
2496+
current_body = &body;
2497+
clang::Stmt* loop_body = x->getBody();
2498+
TraverseStmt(loop_body);
2499+
current_body = current_body_copy;
2500+
2501+
tmp = ASR::make_WhileLoop_t(al, Lloc(x), nullptr, test, body.p, body.size());
2502+
is_stmt_created = true;
2503+
scopes.pop_back();
2504+
inside_loop = inside_loop_copy;
2505+
return true;
2506+
}
2507+
24552508
bool TraverseForStmt(clang::ForStmt* x) {
2509+
bool inside_loop_copy = inside_loop;
2510+
inside_loop = true;
2511+
clang::ForStmt* for_loop_copy = for_loop;
2512+
for_loop = x;
24562513
std::map<std::string, std::string> alias;
24572514
scopes.push_back(alias);
24582515
clang::Stmt* init_stmt = x->getInit();
@@ -2478,6 +2535,8 @@ class ClangASTtoASRVisitor: public clang::RecursiveASTVisitor<ClangASTtoASRVisit
24782535
tmp = ASR::make_WhileLoop_t(al, Lloc(x), nullptr, test, body.p, body.size());
24792536
is_stmt_created = true;
24802537
scopes.pop_back();
2538+
for_loop = for_loop_copy;
2539+
inside_loop = inside_loop_copy;
24812540
return true;
24822541
}
24832542

0 commit comments

Comments
 (0)