Skip to content

Commit d66b71f

Browse files
authored
Added support for negative constant indexing in tuples (#1534)
* Added integration test * Added tests to check for errors being thrown
1 parent bc09e3f commit d66b71f

10 files changed

+89
-1
lines changed

integration_tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ RUN(NAME test_list_10 LABELS cpython llvm c)
277277
RUN(NAME test_list_section LABELS cpython llvm c)
278278
RUN(NAME test_tuple_01 LABELS cpython llvm c)
279279
RUN(NAME test_tuple_02 LABELS cpython llvm c)
280+
RUN(NAME test_tuple_03 LABELS cpython llvm)
280281
RUN(NAME test_dict_01 LABELS cpython llvm)
281282
RUN(NAME test_dict_02 LABELS cpython llvm)
282283
RUN(NAME test_dict_03 LABELS cpython llvm)

integration_tests/test_tuple_03.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from ltypes import i32, f64
2+
3+
def f():
4+
t1: tuple[i32, f64, str] = (1, 2.0, "3")
5+
6+
assert t1[-1] == "3"
7+
assert t1[-2] == 2.0
8+
assert t1[-3] == 1
9+
10+
f()

src/lpython/semantics/python_ast_to_asr.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3125,8 +3125,30 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
31253125
ASR::down_cast<ASR::List_t>(type)->m_type, nullptr);
31263126
return false;
31273127
} else if (ASR::is_a<ASR::Tuple_t>(*type)) {
3128+
int i = 0;
31283129
index = ASRUtils::EXPR(tmp);
3129-
int i = ASR::down_cast<ASR::IntegerConstant_t>(ASRUtils::EXPR(tmp))->m_n;
3130+
ASR::expr_t* val = ASRUtils::expr_value(index);
3131+
if (!val) {
3132+
throw SemanticError("Runtime Indexing with " + ASRUtils::type_to_str_python(type) +
3133+
" is not possible.", loc);
3134+
}
3135+
3136+
if (ASR::is_a<ASR::IntegerConstant_t>(*val)) {
3137+
i = ASR::down_cast<ASR::IntegerConstant_t>(val)->m_n;
3138+
int tuple_size = ASR::down_cast<ASR::Tuple_t>(type)->n_type;
3139+
if (i < 0) {
3140+
i = tuple_size + i;
3141+
ASR::ttype_t *int_type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc,
3142+
4, nullptr, 0));
3143+
index = ASRUtils::EXPR(ASR::make_IntegerConstant_t(
3144+
al, loc, i, int_type));
3145+
}
3146+
if (i >= tuple_size || i < 0) {
3147+
throw SemanticError("Tuple index out of bounds", loc);
3148+
}
3149+
} else {
3150+
throw SemanticError("Tuple indices must be constant integers", loc);
3151+
}
31303152
tmp = make_TupleItem_t(al, loc, value, index,
31313153
ASR::down_cast<ASR::Tuple_t>(type)->m_type[i], nullptr);
31323154
return false;

tests/errors/test_tuple2.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
def main0():
2+
t: tuple[i32, i32, i32] = (1, 2, 3)
3+
x: i32 = -1
4+
print(t[x])
5+
6+
main0()

tests/errors/test_tuple3.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
def main0():
2+
t: tuple[i32, i32, i32] = (1, 2, 3)
3+
print(t[-4])
4+
5+
main0()
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"basename": "asr-test_tuple2-b046610",
3+
"cmd": "lpython --show-asr --no-color {infile} -o {outfile}",
4+
"infile": "tests/errors/test_tuple2.py",
5+
"infile_hash": "84aa4ecdd21f5d633975d08f6927a7d336c47a31c2fd2bc42cae1c7b",
6+
"outfile": null,
7+
"outfile_hash": null,
8+
"stdout": null,
9+
"stdout_hash": null,
10+
"stderr": "asr-test_tuple2-b046610.stderr",
11+
"stderr_hash": "1e22bbde9c9fdc171314f1158dcac6bf6373d94e00c9878f66d7b667",
12+
"returncode": 2
13+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
semantic error: Runtime Indexing with tuple[i32, i32, i32] is not possible.
2+
--> tests/errors/test_tuple2.py:4:11
3+
|
4+
4 | print(t[x])
5+
| ^^^^
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"basename": "asr-test_tuple3-19fa47f",
3+
"cmd": "lpython --show-asr --no-color {infile} -o {outfile}",
4+
"infile": "tests/errors/test_tuple3.py",
5+
"infile_hash": "cfa12cc4d8456bfd45e77cc49c5e8d2417181a1443cdaaf8b15c0528",
6+
"outfile": null,
7+
"outfile_hash": null,
8+
"stdout": null,
9+
"stdout_hash": null,
10+
"stderr": "asr-test_tuple3-19fa47f.stderr",
11+
"stderr_hash": "780d951c4bfa3476ee84d16d9a89c5a9255691b270bfb312d974608e",
12+
"returncode": 2
13+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
semantic error: Tuple index out of bounds
2+
--> tests/errors/test_tuple3.py:3:11
3+
|
4+
3 | print(t[-4])
5+
| ^^^^^

tests/tests.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,14 @@ asr = true
896896
filename = "errors/test_tuple1.py"
897897
asr = true
898898

899+
[[test]]
900+
filename = "errors/test_tuple2.py"
901+
asr = true
902+
903+
[[test]]
904+
filename = "errors/test_tuple3.py"
905+
asr = true
906+
899907
[[test]]
900908
filename = "errors/test_for2.py"
901909
asr = true

0 commit comments

Comments
 (0)