Skip to content

Commit

Permalink
Merge pull request lcompilers#2342 from SudhanshuJoshi09/str-count
Browse files Browse the repository at this point in the history
Implemented Str.Count() method
  • Loading branch information
certik committed Sep 27, 2023
2 parents a872c0b + ee5eeb0 commit 03a9cf1
Show file tree
Hide file tree
Showing 67 changed files with 1,313 additions and 1,260 deletions.
1 change: 1 addition & 0 deletions integration_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,7 @@ RUN(NAME test_str_01 LABELS cpython llvm c)
RUN(NAME test_str_02 LABELS cpython llvm c)
RUN(NAME test_str_03 LABELS cpython llvm c)
RUN(NAME test_str_04 LABELS cpython llvm c wasm)
RUN(NAME test_str_05 LABELS cpython llvm c)
RUN(NAME test_list_01 LABELS cpython llvm c)
RUN(NAME test_list_02 LABELS cpython llvm c)
RUN(NAME test_list_03 LABELS cpython llvm c NOFAST)
Expand Down
12 changes: 12 additions & 0 deletions integration_tests/test_str_05.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
def main0():
x: str
x = "Hello, World"
y: str
y = "o"
assert x.count(y) == 2
y = ""
assert x.count(y) == len(x) + 1
y = "Hello,"
assert x.count(y) == 1

main0()
22 changes: 22 additions & 0 deletions src/lpython/semantics/python_ast_to_asr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6791,6 +6791,28 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
[&](const std::string &msg, const Location &loc) {
throw SemanticError(msg, loc); });
return;
} else if(attr_name == "count") {
if(args.size() != 1) {
throw SemanticError("str.count() takes one argument for now.", loc);
}
ASR::expr_t *arg_value = args[0].m_value;
ASR::ttype_t *arg_value_type = ASRUtils::expr_type(arg_value);
if (!ASRUtils::is_character(*arg_value_type)) {
throw SemanticError("str.count() takes one argument of type: str", loc);
}

fn_call_name = "_lpython_str_count";
ASR::call_arg_t str;
str.loc = loc;
str.m_value = s_var;

ASR::call_arg_t value;
value.loc = loc;
value.m_value = args[0].m_value;

// Push string and substring argument on top of Vector (or Function Arguments Stack basically)
fn_args.push_back(al, str);
fn_args.push_back(al, value);
} else if(attr_name.size() > 2 && attr_name[0] == 'i' && attr_name[1] == 's') {
/*
String Validation Methods i.e all "is" based functions are handled here
Expand Down
1 change: 1 addition & 0 deletions src/lpython/semantics/python_comptime_eval.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ struct PythonIntrinsicProcedures {
// The following functions for string methods are not used
// for evaluation.
{"_lpython_str_capitalize", {m_builtin, &not_implemented}},
{"_lpython_str_count", {m_builtin, &not_implemented}},
{"_lpython_str_lower", {m_builtin, &not_implemented}},
{"_lpython_str_upper", {m_builtin, &not_implemented}},
{"_lpython_str_find", {m_builtin, &not_implemented}},
Expand Down
17 changes: 17 additions & 0 deletions src/runtime/lpython_builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,23 @@ def _lpython_str_capitalize(x: str) -> str:
res = chr(val) + res[1:]
return res


@overload
def _lpython_str_count(x: str, y: str) -> i32:
if(len(y) == 0): return len(x) + 1

count: i32 = 0
curr_char: str
i: i32

for i in range(len(x)):
curr_char = x[i]
if curr_char == y[0]:
count += i32(x[i:i+len(y)] == y)

return count


@overload
def _lpython_str_lower(x: str) -> str:
res: str
Expand Down
2 changes: 1 addition & 1 deletion tests/reference/asr-array_01_decl-39cf894.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"outfile": null,
"outfile_hash": null,
"stdout": "asr-array_01_decl-39cf894.stdout",
"stdout_hash": "b0dc16e057dc08b7ec8adac23b2d98fa29d536fca17934c2689425d8",
"stdout_hash": "960bc68922ceaabf957cbdc2cfc76c1f4a4758856072d6be3ae9ed18",
"stderr": null,
"stderr_hash": null,
"returncode": 0
Expand Down
Loading

0 comments on commit 03a9cf1

Please sign in to comment.