diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index 1389b32d14..2b6e9063b2 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -277,6 +277,7 @@ RUN(NAME test_list_10 LABELS cpython llvm c) RUN(NAME test_list_section LABELS cpython llvm c) RUN(NAME test_tuple_01 LABELS cpython llvm c) RUN(NAME test_tuple_02 LABELS cpython llvm c) +RUN(NAME test_tuple_03 LABELS cpython llvm) RUN(NAME test_dict_01 LABELS cpython llvm) RUN(NAME test_dict_02 LABELS cpython llvm) RUN(NAME test_dict_03 LABELS cpython llvm) diff --git a/integration_tests/test_tuple_03.py b/integration_tests/test_tuple_03.py new file mode 100644 index 0000000000..a2ba5f9543 --- /dev/null +++ b/integration_tests/test_tuple_03.py @@ -0,0 +1,10 @@ +from ltypes import i32, f64 + +def f(): + t1: tuple[i32, f64, str] = (1, 2.0, "3") + + assert t1[-1] == "3" + assert t1[-2] == 2.0 + assert t1[-3] == 1 + +f() \ No newline at end of file diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 305642f876..c15a65e28f 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -3125,8 +3125,30 @@ class CommonVisitor : public AST::BaseVisitor { ASR::down_cast(type)->m_type, nullptr); return false; } else if (ASR::is_a(*type)) { + int i = 0; index = ASRUtils::EXPR(tmp); - int i = ASR::down_cast(ASRUtils::EXPR(tmp))->m_n; + ASR::expr_t* val = ASRUtils::expr_value(index); + if (!val) { + throw SemanticError("Runtime Indexing with " + ASRUtils::type_to_str_python(type) + + " is not possible.", loc); + } + + if (ASR::is_a(*val)) { + i = ASR::down_cast(val)->m_n; + int tuple_size = ASR::down_cast(type)->n_type; + if (i < 0) { + i = tuple_size + i; + ASR::ttype_t *int_type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, + 4, nullptr, 0)); + index = ASRUtils::EXPR(ASR::make_IntegerConstant_t( + al, loc, i, int_type)); + } + if (i >= tuple_size || i < 0) { + throw SemanticError("Tuple index out of bounds", loc); + } + } else { + throw SemanticError("Tuple indices must be constant integers", loc); + } tmp = make_TupleItem_t(al, loc, value, index, ASR::down_cast(type)->m_type[i], nullptr); return false; diff --git a/tests/errors/test_tuple2.py b/tests/errors/test_tuple2.py new file mode 100644 index 0000000000..65f9f0d5e2 --- /dev/null +++ b/tests/errors/test_tuple2.py @@ -0,0 +1,6 @@ +def main0(): + t: tuple[i32, i32, i32] = (1, 2, 3) + x: i32 = -1 + print(t[x]) + +main0() \ No newline at end of file diff --git a/tests/errors/test_tuple3.py b/tests/errors/test_tuple3.py new file mode 100644 index 0000000000..5bfebee337 --- /dev/null +++ b/tests/errors/test_tuple3.py @@ -0,0 +1,5 @@ +def main0(): + t: tuple[i32, i32, i32] = (1, 2, 3) + print(t[-4]) + +main0() \ No newline at end of file diff --git a/tests/reference/asr-test_tuple2-b046610.json b/tests/reference/asr-test_tuple2-b046610.json new file mode 100644 index 0000000000..051ed20bfb --- /dev/null +++ b/tests/reference/asr-test_tuple2-b046610.json @@ -0,0 +1,13 @@ +{ + "basename": "asr-test_tuple2-b046610", + "cmd": "lpython --show-asr --no-color {infile} -o {outfile}", + "infile": "tests/errors/test_tuple2.py", + "infile_hash": "84aa4ecdd21f5d633975d08f6927a7d336c47a31c2fd2bc42cae1c7b", + "outfile": null, + "outfile_hash": null, + "stdout": null, + "stdout_hash": null, + "stderr": "asr-test_tuple2-b046610.stderr", + "stderr_hash": "1e22bbde9c9fdc171314f1158dcac6bf6373d94e00c9878f66d7b667", + "returncode": 2 +} \ No newline at end of file diff --git a/tests/reference/asr-test_tuple2-b046610.stderr b/tests/reference/asr-test_tuple2-b046610.stderr new file mode 100644 index 0000000000..e99518093e --- /dev/null +++ b/tests/reference/asr-test_tuple2-b046610.stderr @@ -0,0 +1,5 @@ +semantic error: Runtime Indexing with tuple[i32, i32, i32] is not possible. + --> tests/errors/test_tuple2.py:4:11 + | +4 | print(t[x]) + | ^^^^ diff --git a/tests/reference/asr-test_tuple3-19fa47f.json b/tests/reference/asr-test_tuple3-19fa47f.json new file mode 100644 index 0000000000..0a703f17d4 --- /dev/null +++ b/tests/reference/asr-test_tuple3-19fa47f.json @@ -0,0 +1,13 @@ +{ + "basename": "asr-test_tuple3-19fa47f", + "cmd": "lpython --show-asr --no-color {infile} -o {outfile}", + "infile": "tests/errors/test_tuple3.py", + "infile_hash": "cfa12cc4d8456bfd45e77cc49c5e8d2417181a1443cdaaf8b15c0528", + "outfile": null, + "outfile_hash": null, + "stdout": null, + "stdout_hash": null, + "stderr": "asr-test_tuple3-19fa47f.stderr", + "stderr_hash": "780d951c4bfa3476ee84d16d9a89c5a9255691b270bfb312d974608e", + "returncode": 2 +} \ No newline at end of file diff --git a/tests/reference/asr-test_tuple3-19fa47f.stderr b/tests/reference/asr-test_tuple3-19fa47f.stderr new file mode 100644 index 0000000000..fe438fb382 --- /dev/null +++ b/tests/reference/asr-test_tuple3-19fa47f.stderr @@ -0,0 +1,5 @@ +semantic error: Tuple index out of bounds + --> tests/errors/test_tuple3.py:3:11 + | +3 | print(t[-4]) + | ^^^^^ diff --git a/tests/tests.toml b/tests/tests.toml index 0a33623faa..04ac61869f 100644 --- a/tests/tests.toml +++ b/tests/tests.toml @@ -896,6 +896,14 @@ asr = true filename = "errors/test_tuple1.py" asr = true +[[test]] +filename = "errors/test_tuple2.py" +asr = true + +[[test]] +filename = "errors/test_tuple3.py" +asr = true + [[test]] filename = "errors/test_for2.py" asr = true