From 6b882f3702b788d4e1e86ce5439b4c5e21627a96 Mon Sep 17 00:00:00 2001 From: Wolf Vollprecht Date: Thu, 25 Jul 2024 10:25:44 +0200 Subject: [PATCH 1/5] implement StringContains --- integration_tests/CMakeLists.txt | 1 + src/libasr/codegen/asr_to_llvm.cpp | 31 ++++++++++++++++++++++++ src/libasr/runtime/lfortran_intrinsics.c | 6 +++++ 3 files changed, 38 insertions(+) diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index ea416e764b..41e21b5101 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -532,6 +532,7 @@ RUN(NAME test_str_02 LABELS cpython llvm llvm_jit c) RUN(NAME test_str_03 LABELS cpython llvm llvm_jit c) RUN(NAME test_str_04 LABELS cpython llvm llvm_jit c wasm) RUN(NAME test_str_05 LABELS cpython llvm llvm_jit c) +RUN(NAME test_str_06 LABELS cpython llvm llvm_jit c) RUN(NAME test_list_01 LABELS cpython llvm llvm_jit c) RUN(NAME test_list_02 LABELS cpython llvm llvm_jit c) RUN(NAME test_list_03 LABELS cpython llvm llvm_jit c NOFAST) diff --git a/src/libasr/codegen/asr_to_llvm.cpp b/src/libasr/codegen/asr_to_llvm.cpp index 4921c46f75..c2a5ac1b5a 100644 --- a/src/libasr/codegen/asr_to_llvm.cpp +++ b/src/libasr/codegen/asr_to_llvm.cpp @@ -716,6 +716,21 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor return builder->CreateCall(fn, {str, idx1}); } + llvm::Value* lfortran_str_contains(llvm::Value* str, llvm::Value* substr) + { + std::string runtime_func_name = "_lfortran_str_contains"; + llvm::Function *fn = module->getFunction(runtime_func_name); + if (!fn) { + llvm::FunctionType *function_type = llvm::FunctionType::get( + llvm::Type::getInt1Ty(context), { + character_type, character_type + }, false); + fn = llvm::Function::Create(function_type, + llvm::Function::ExternalLinkage, runtime_func_name, *module); + } + return builder->CreateCall(fn, {str, substr}); + } + llvm::Value* lfortran_str_copy(llvm::Value* str, llvm::Value* idx1, llvm::Value* idx2) { std::string runtime_func_name = "_lfortran_str_copy"; @@ -6066,6 +6081,22 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } } + void visit_StringContains(const ASR::StringContains_t& x) { + if (x.m_value) { + this->visit_expr_wrapper(x.m_value, true); + return; + } + + this->visit_expr_wrapper(x.m_left, true); + llvm::Value *substr = tmp; + + this->visit_expr_wrapper(x.m_right, true); + llvm::Value *right = tmp; + + tmp = lfortran_str_contains(right, substr); + strings_to_be_deallocated.push_back(al, tmp); + } + void visit_StringSection(const ASR::StringSection_t& x) { if (x.m_value) { this->visit_expr_wrapper(x.m_value, true); diff --git a/src/libasr/runtime/lfortran_intrinsics.c b/src/libasr/runtime/lfortran_intrinsics.c index 7c09965c09..8bcbe893cb 100644 --- a/src/libasr/runtime/lfortran_intrinsics.c +++ b/src/libasr/runtime/lfortran_intrinsics.c @@ -2197,6 +2197,12 @@ LFORTRAN_API char* _lfortran_str_item(char* s, int32_t idx) { return res; } +/// Find a substring in a string +LFORTRAN_API bool _lfortran_str_contains(char* str, char* substr) { + char* res = strstr(str, substr); + return res != NULL; +} + // idx1 and idx2 both start from 1 LFORTRAN_API char* _lfortran_str_copy(char* s, int32_t idx1, int32_t idx2) { From f269a72e6122a9909ba410917e3254801e360178 Mon Sep 17 00:00:00 2001 From: Wolf Vollprecht Date: Thu, 25 Jul 2024 10:28:02 +0200 Subject: [PATCH 2/5] add missing file --- integration_tests/test_str_06.py | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 integration_tests/test_str_06.py diff --git a/integration_tests/test_str_06.py b/integration_tests/test_str_06.py new file mode 100644 index 0000000000..8df130521d --- /dev/null +++ b/integration_tests/test_str_06.py @@ -0,0 +1,11 @@ +def main0(): + x: str + x = "Hello, World" + + assert "Hello" in x + assert "," in x + assert "rld" in x + + assert "Hello" not in "World" + +main0() From 379873192107d552f2111f23564ba0cedbcc482f Mon Sep 17 00:00:00 2001 From: Wolf Vollprecht Date: Thu, 25 Jul 2024 10:34:31 +0200 Subject: [PATCH 3/5] implement string contains for c --- src/libasr/codegen/asr_to_c_cpp.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/libasr/codegen/asr_to_c_cpp.h b/src/libasr/codegen/asr_to_c_cpp.h index c0404b70f9..7dadf848fb 100644 --- a/src/libasr/codegen/asr_to_c_cpp.h +++ b/src/libasr/codegen/asr_to_c_cpp.h @@ -1244,6 +1244,15 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { src = "_lfortran_strrepeat_c(" + s + ", " + n + ")"; } + void visit_StringContains(const ASR::StringRepeat_t &x) { + CHECK_FAST_C_CPP(compiler_options, x) + self().visit_expr(*x.m_left); + std::string substr = src; + self().visit_expr(*x.m_right); + std::string str = src; + src = "_lfortran_str_contains(" + str + ", " + substr + ")"; + } + void visit_Assignment(const ASR::Assignment_t &x) { std::string target; ASR::ttype_t* m_target_type = ASRUtils::expr_type(x.m_target); From a39e7e21af4e8024700aa32ac3b08516f543d380 Mon Sep 17 00:00:00 2001 From: Wolf Vollprecht Date: Thu, 25 Jul 2024 10:42:20 +0200 Subject: [PATCH 4/5] fix --- src/libasr/codegen/asr_to_c_cpp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libasr/codegen/asr_to_c_cpp.h b/src/libasr/codegen/asr_to_c_cpp.h index 7dadf848fb..22762b9c27 100644 --- a/src/libasr/codegen/asr_to_c_cpp.h +++ b/src/libasr/codegen/asr_to_c_cpp.h @@ -1244,7 +1244,7 @@ PyMODINIT_FUNC PyInit_lpython_module_)" + fn_name + R"((void) { src = "_lfortran_strrepeat_c(" + s + ", " + n + ")"; } - void visit_StringContains(const ASR::StringRepeat_t &x) { + void visit_StringContains(const ASR::StringContains_t &x) { CHECK_FAST_C_CPP(compiler_options, x) self().visit_expr(*x.m_left); std::string substr = src; From 1325bd8aa9ee355f8a60d7e8ae02b3e42bdfacdd Mon Sep 17 00:00:00 2001 From: Wolf Vollprecht Date: Thu, 25 Jul 2024 12:00:37 +0200 Subject: [PATCH 5/5] add header --- src/libasr/runtime/lfortran_intrinsics.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libasr/runtime/lfortran_intrinsics.h b/src/libasr/runtime/lfortran_intrinsics.h index 7215573fde..e857171da5 100644 --- a/src/libasr/runtime/lfortran_intrinsics.h +++ b/src/libasr/runtime/lfortran_intrinsics.h @@ -209,6 +209,7 @@ LFORTRAN_API void _lfortran_free(char* ptr); LFORTRAN_API void _lfortran_alloc(char** ptr, int32_t len); LFORTRAN_API void _lfortran_string_init(int size_plus_one, char *s); LFORTRAN_API char* _lfortran_str_item(char* s, int32_t idx); +LFORTRAN_API bool _lfortran_str_contains(char* str, char* substr); LFORTRAN_API char* _lfortran_str_copy(char* s, int32_t idx1, int32_t idx2); // idx1 and idx2 both start from 1 LFORTRAN_API char* _lfortran_str_slice(char* s, int32_t idx1, int32_t idx2, int32_t step, bool idx1_present, bool idx2_present);