Skip to content

Commit bf16a3d

Browse files
authored
Implementing for-else and while-else loops (#2555)
* Added for-else functionality * Added support for nested loops
1 parent 6d56882 commit bf16a3d

File tree

57 files changed

+429
-48
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+429
-48
lines changed

integration_tests/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,8 @@ RUN(NAME loop_05 LABELS cpython llvm c)
518518
RUN(NAME loop_06 LABELS cpython llvm c NOFAST)
519519
RUN(NAME loop_07 LABELS cpython llvm c)
520520
RUN(NAME loop_08 LABELS cpython llvm c)
521+
RUN(NAME loop_09 LABELS cpython llvm)
522+
RUN(NAME loop_10 LABELS cpython llvm)
521523
RUN(NAME if_01 LABELS cpython llvm c wasm wasm_x86 wasm_x64)
522524
RUN(NAME if_02 LABELS cpython llvm c wasm wasm_x86 wasm_x64)
523525
RUN(NAME if_03 FAIL LABELS cpython llvm c NOFAST)

integration_tests/loop_09.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
def with_break_for():
2+
i: i32
3+
s: i32 = 0
4+
for i in range(4):
5+
s += i
6+
break
7+
else:
8+
s += 10
9+
assert s == 0
10+
11+
def with_break_while():
12+
i: i32 = 0
13+
s: i32 = 0
14+
while i < 4:
15+
s += i
16+
break
17+
else:
18+
s += 10
19+
assert s == 0
20+
21+
def no_break_for():
22+
i: i32
23+
s: i32 = 0
24+
for i in range(2):
25+
s += i
26+
else:
27+
s += 10
28+
assert s == 11
29+
30+
def no_break_while():
31+
i: i32 = 0
32+
s: i32 = 0
33+
while i < 2:
34+
s += i
35+
i += 1
36+
else:
37+
s += 10
38+
assert s == 11
39+
40+
no_break_for()
41+
no_break_while()
42+
43+
with_break_for()
44+
with_break_while()
45+

integration_tests/loop_10.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
def with_break_for():
2+
i: i32
3+
for i in range(4):
4+
print(i)
5+
break
6+
else:
7+
assert False
8+
9+
10+
def with_break_while():
11+
i: i32 = 0
12+
while i < 4:
13+
print(i)
14+
break
15+
else:
16+
print(10)
17+
assert False
18+
19+
20+
def no_break_for():
21+
i: i32
22+
for i in range(2):
23+
print(i)
24+
else:
25+
print(10)
26+
return
27+
assert False
28+
29+
def break_in_if_for():
30+
i: i32
31+
for i in range(2):
32+
print(i)
33+
if i == 1:
34+
break
35+
else:
36+
print(10)
37+
assert False
38+
39+
def nested_loop_for_for():
40+
i: i32
41+
j: i32
42+
for i in range(2):
43+
print("outer: " + str(i))
44+
for j in range(10, 20):
45+
print(" inner: " + str(j))
46+
break
47+
else:
48+
print("no break in outer loop")
49+
return
50+
assert False
51+
52+
53+
with_break_for()
54+
with_break_while()
55+
no_break_for()
56+
break_in_if_for()
57+
nested_loop_for_for()

run_tests.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def is_included(backend):
3939
"dead_code_removal", "loop_vectorise", "print_list_tuple",
4040
"class_constructor"]
4141

42-
if pass_ and (pass_ not in ["do_loops", "global_stmts"] and
42+
if pass_ and (pass_ not in ["do_loops", "global_stmts", "while_else"] and
4343
pass_ not in optimization_passes):
4444
raise Exception(f"Unknown pass: {pass_}")
4545
if no_color:

src/libasr/ASR.asdl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ stmt
185185
-- deallocates if allocated otherwise does nothing
186186
| ImplicitDeallocate(expr* vars)
187187
| DoConcurrentLoop(do_loop_head head, stmt* body)
188-
| DoLoop(identifier? name, do_loop_head head, stmt* body)
188+
| DoLoop(identifier? name, do_loop_head head, stmt* body, stmt* orelse)
189189
| ErrorStop(expr? code)
190190
| Exit(identifier? stmt_name)
191191
| ForAllSingle(do_loop_head head, stmt assign_stmt)
@@ -219,7 +219,7 @@ stmt
219219
| Assert(expr test, expr? msg)
220220
| SubroutineCall(symbol name, symbol? original_name, call_arg* args, expr? dt)
221221
| Where(expr test, stmt* body, stmt* orelse)
222-
| WhileLoop(identifier? name, expr test, stmt* body)
222+
| WhileLoop(identifier? name, expr test, stmt* body, stmt* orelse)
223223
| Nullify(symbol* vars)
224224
| Flush(int label, expr unit, expr? err, expr? iomsg, expr? iostat)
225225
| ListAppend(expr a, expr ele)

src/libasr/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ set(SRC
3434
pass/param_to_const.cpp
3535
pass/do_loops.cpp
3636
pass/for_all.cpp
37+
pass/while_else.cpp
3738
pass/global_stmts.cpp
3839
pass/select_case.cpp
3940
pass/init_expr.cpp

src/libasr/codegen/asr_to_julia.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1237,7 +1237,7 @@ class ASRToJuliaVisitor : public ASR::BaseVisitor<ASRToJuliaVisitor>
12371237

12381238
void visit_DoConcurrentLoop(const ASR::DoConcurrentLoop_t& x)
12391239
{
1240-
const ASR::DoLoop_t do_loop = ASR::DoLoop_t{ x.base, nullptr, x.m_head, x.m_body, x.n_body };
1240+
const ASR::DoLoop_t do_loop = ASR::DoLoop_t{ x.base, nullptr, x.m_head, x.m_body, x.n_body , nullptr, 0};
12411241
visit_DoLoop(do_loop, true);
12421242
}
12431243

src/libasr/gen_pass.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"replace_flip_sign",
99
"replace_fma",
1010
"replace_for_all",
11+
"while_else",
1112
"wrap_global_stmts",
1213
"replace_implied_do_loops",
1314
"replace_init_expr",

src/libasr/pass/arr_slice.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ class ReplaceArraySection: public ASR::BaseExprReplacer<ReplaceArraySection> {
155155
const_1, int_type, nullptr));
156156
ASR::stmt_t* assign_stmt = ASRUtils::STMT(ASR::make_Assignment_t(al, x->base.base.loc, idx_vars_target[i], inc_expr, nullptr));
157157
doloop_body.push_back(al, assign_stmt);
158-
doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, x->base.base.loc, nullptr, head, doloop_body.p, doloop_body.size()));
158+
doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, x->base.base.loc, nullptr, head, doloop_body.p, doloop_body.size(), nullptr, 0));
159159
}
160160
int a_kind = ASRUtils::extract_kind_from_ttype_t(ASRUtils::expr_type(idx_vars_target[0]));
161161
ASR::ttype_t* int_type = ASRUtils::TYPE(ASR::make_Integer_t(al, x->base.base.loc, a_kind));

src/libasr/pass/array_op.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer<ReplaceArrayOp> {
171171
doloop_body.push_back(al, assign_stmt2);
172172
}
173173
}
174-
doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, head, doloop_body.p, doloop_body.size()));
174+
doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, head, doloop_body.p, doloop_body.size(), nullptr, 0));
175175
}
176176
if( var_rank > 0 ) {
177177
ASR::expr_t* idx_lb = PassUtils::get_bound(op_expr1, 1, "lbound", al);
@@ -207,7 +207,7 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer<ReplaceArrayOp> {
207207
} else {
208208
doloop_body.push_back(al, doloop);
209209
}
210-
doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, head, doloop_body.p, doloop_body.size()));
210+
doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, head, doloop_body.p, doloop_body.size(), nullptr, 0));
211211
}
212212
pass_result.push_back(al, doloop);
213213
}
@@ -460,7 +460,7 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer<ReplaceArrayOp> {
460460
al, loc, idx_vars_value[i], inc_expr, nullptr));
461461
doloop_body.push_back(al, assign_stmt);
462462
}
463-
doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, head, doloop_body.p, doloop_body.size()));
463+
doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, head, doloop_body.p, doloop_body.size(), nullptr, 0));
464464
}
465465
if( ASRUtils::is_array(ASRUtils::expr_type(op_expr)) ) {
466466
ASR::expr_t* idx_lb = PassUtils::get_bound(op_expr, 1, "lbound", al);
@@ -505,7 +505,7 @@ class ReplaceArrayOp: public ASR::BaseExprReplacer<ReplaceArrayOp> {
505505
} else {
506506
doloop_body.push_back(al, doloop);
507507
}
508-
doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, head, doloop_body.p, doloop_body.size()));
508+
doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, head, doloop_body.p, doloop_body.size(), nullptr, 0));
509509
}
510510
pass_result.push_back(al, doloop);
511511
}
@@ -1780,7 +1780,7 @@ class ArrayOpVisitor : public ASR::CallReplacerOnExpressionsVisitor<ArrayOpVisit
17801780
al, loc, idx_vars_value[i], inc_expr, nullptr));
17811781
doloop_body.push_back(al, assign_stmt);
17821782
}
1783-
doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, head, doloop_body.p, doloop_body.size()));
1783+
doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, head, doloop_body.p, doloop_body.size(), nullptr, 0));
17841784
}
17851785
if( var_rank > 0 ) {
17861786
ASR::expr_t* idx_lb = PassUtils::get_bound(op_expr, 1, "lbound", al);
@@ -1810,7 +1810,7 @@ class ArrayOpVisitor : public ASR::CallReplacerOnExpressionsVisitor<ArrayOpVisit
18101810
} else {
18111811
doloop_body.push_back(al, doloop);
18121812
}
1813-
doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, head, doloop_body.p, doloop_body.size()));
1813+
doloop = ASRUtils::STMT(ASR::make_DoLoop_t(al, loc, nullptr, head, doloop_body.p, doloop_body.size(), nullptr, 0));
18141814
}
18151815
pass_result.push_back(al, doloop);
18161816
}

0 commit comments

Comments
 (0)