From 6afeac0127b9a00f8ad4df927c95c2661bc0d1f1 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Tue, 30 Apr 2024 15:19:43 +0530 Subject: [PATCH 1/6] Support string repeat with non-constant integer --- src/lpython/semantics/python_ast_to_asr.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 571883a84e..ee8b2b33cf 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -2079,7 +2079,7 @@ class CommonVisitor : public AST::BaseVisitor { } else if ((right_is_int || left_is_int) && op == ASR::binopType::Mul) { // string repeat int64_t left_int = 0, right_int = 0, dest_len = 0; - if (right_is_int) { + if (right_is_int && ASRUtils::expr_value(right) != nullptr) { ASR::Character_t *left_type2 = ASR::down_cast( ASRUtils::type_get_past_array(left_type)); LCOMPILERS_ASSERT(ASRUtils::extract_n_dims_from_ttype(left_type) == 0); @@ -2090,7 +2090,7 @@ class CommonVisitor : public AST::BaseVisitor { dest_type = ASR::down_cast( ASR::make_Character_t(al, loc, left_type2->m_kind, dest_len, nullptr)); - } else if (left_is_int) { + } else if (left_is_int && ASRUtils::expr_value(left) != nullptr) { ASR::Character_t *right_type2 = ASR::down_cast( ASRUtils::type_get_past_array(right_type)); LCOMPILERS_ASSERT(ASRUtils::extract_n_dims_from_ttype(right_type) == 0); @@ -2101,6 +2101,10 @@ class CommonVisitor : public AST::BaseVisitor { dest_type = ASR::down_cast( ASR::make_Character_t(al, loc, right_type2->m_kind, dest_len, nullptr)); + } else if ((left_is_int && ASRUtils::expr_value(left) == nullptr) + || (right_is_int && ASRUtils::expr_value(right) == nullptr)) { + dest_type = ASRUtils::TYPE(ASR::make_Character_t(al, + loc, 1, 1, nullptr)); } if (ASRUtils::expr_value(left) != nullptr && ASRUtils::expr_value(right) != nullptr) { From ea7ce9c2c7f22a6ad04199eba25c2fa0c115b2ce Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Tue, 30 Apr 2024 15:46:24 +0530 Subject: [PATCH 2/6] Tests: Add tests --- integration_tests/test_str_01.py | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/integration_tests/test_str_01.py b/integration_tests/test_str_01.py index a889a85d83..56d9706ef3 100644 --- a/integration_tests/test_str_01.py +++ b/integration_tests/test_str_01.py @@ -1,3 +1,5 @@ +from lpython import i32 + def f(): x: str x = "ok" @@ -58,9 +60,37 @@ def test_str_repeat(): assert a*3 == "XyzXyzXyz" assert a*2*3 == "XyzXyzXyzXyzXyzXyz" assert 3*a*3 == "XyzXyzXyzXyzXyzXyzXyzXyzXyz" - assert a*-1 == "" + # assert a*-1 == "" assert len(a*(10**6)) == (3 * 10 ** 6) + # string repeat with a non-constant integer + s: str = "#" + n: i32 = 5 + + assert s * n == "#####" + assert n * s == "#####" + + assert "@" * n == "@@@@@" + assert "@#$%" * n == "@#$%@#$%@#$%@#$%@#$%" + + s = "@#$%" + assert n * s == "@#$%@#$%@#$%@#$%@#$%" + + n = 10 ** 6 + assert len(s * n) == (4 * 10 ** 6) + + s = "$" + m: i32 = 2 + n = 5 + t: str = s * m * n + assert t == "$$$$$$$$$$" + assert s * m * 2 == "$$$$" + assert 2 * (m + n) * s == "$$$$$$$$$$$$$$" + + t = 2 * (m + n) * "abc-" + assert t == "abc-abc-abc-abc-abc-abc-abc-abc-abc-abc-abc-abc-abc-abc-" + + def test_str_join(): a: str a = "," From 8c3675b8d2e003a874c4081ed127c534360b4b70 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar <151380951+kmr-srbh@users.noreply.github.com> Date: Wed, 1 May 2024 08:09:08 +0530 Subject: [PATCH 3/6] Set character `a_len` to -1 Co-authored-by: Shaikh Ubaid --- src/lpython/semantics/python_ast_to_asr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index ee8b2b33cf..d7ba25457a 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -2104,7 +2104,7 @@ class CommonVisitor : public AST::BaseVisitor { } else if ((left_is_int && ASRUtils::expr_value(left) == nullptr) || (right_is_int && ASRUtils::expr_value(right) == nullptr)) { dest_type = ASRUtils::TYPE(ASR::make_Character_t(al, - loc, 1, 1, nullptr)); + loc, 1, -1, nullptr)); } if (ASRUtils::expr_value(left) != nullptr && ASRUtils::expr_value(right) != nullptr) { From c30f865208fc27be31241045d3f1a3de037260e6 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Wed, 1 May 2024 08:17:35 +0530 Subject: [PATCH 4/6] Simplify conditional check to `else` --- src/lpython/semantics/python_ast_to_asr.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index d7ba25457a..06da016050 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -2101,8 +2101,7 @@ class CommonVisitor : public AST::BaseVisitor { dest_type = ASR::down_cast( ASR::make_Character_t(al, loc, right_type2->m_kind, dest_len, nullptr)); - } else if ((left_is_int && ASRUtils::expr_value(left) == nullptr) - || (right_is_int && ASRUtils::expr_value(right) == nullptr)) { + } else { dest_type = ASRUtils::TYPE(ASR::make_Character_t(al, loc, 1, -1, nullptr)); } From c3c20e943e42d1c1e5abd244a33fceda43fe9978 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Wed, 1 May 2024 08:32:37 +0530 Subject: [PATCH 5/6] Handle negative integers for string repeat --- src/libasr/runtime/lfortran_intrinsics.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libasr/runtime/lfortran_intrinsics.c b/src/libasr/runtime/lfortran_intrinsics.c index ce6c6901a4..d6ea899619 100644 --- a/src/libasr/runtime/lfortran_intrinsics.c +++ b/src/libasr/runtime/lfortran_intrinsics.c @@ -2140,7 +2140,7 @@ LFORTRAN_API void _lfortran_strrepeat(char** s, int32_t n, char** dest) char* dest_char = (char*)malloc(f_len+trmn_size); if (s_len == 1) { - memset(dest_char, *(*s), n); + memset(dest_char, *(*s), f_len); } else { memcpy(dest_char, *s, s_len); int chars_copied = s_len; From d1d1b68b713a9b16625e8461c7a18edbb59349e2 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Wed, 1 May 2024 08:32:58 +0530 Subject: [PATCH 6/6] Tests: Update test --- integration_tests/test_str_01.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/integration_tests/test_str_01.py b/integration_tests/test_str_01.py index 56d9706ef3..6be357aa3b 100644 --- a/integration_tests/test_str_01.py +++ b/integration_tests/test_str_01.py @@ -60,7 +60,8 @@ def test_str_repeat(): assert a*3 == "XyzXyzXyz" assert a*2*3 == "XyzXyzXyzXyzXyzXyz" assert 3*a*3 == "XyzXyzXyzXyzXyzXyzXyzXyzXyz" - # assert a*-1 == "" + b: str = a * -1 + assert b == "" assert len(a*(10**6)) == (3 * 10 ** 6) # string repeat with a non-constant integer