Skip to content

Commit

Permalink
Merge pull request lcompilers#1039 from Abdelrahman-Kh-Fouad/str@swap…
Browse files Browse the repository at this point in the history
…case

Strings methods: `swapcase()`
  • Loading branch information
czgdp1807 committed Sep 2, 2022
2 parents 13d3443 + 36b85d4 commit 2805b30
Show file tree
Hide file tree
Showing 52 changed files with 112 additions and 49 deletions.
7 changes: 7 additions & 0 deletions integration_tests/test_str_attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ def strip():
assert " AASAsaSas " .lstrip() == "AASAsaSas "
assert " AASAsaSas " .strip() == "AASAsaSas"

def swapcase():
s: str
s = "aaaaaabbbbbbbb!@12223bn"
assert s.swapcase() == "AAAAAABBBBBBBB!@12223BN"
assert "AASAsaSas" .swapcase() == "aasaSAsAS"

def find():
s: str
sub: str
Expand Down Expand Up @@ -65,5 +71,6 @@ def startswith():
capitalize()
lower()
strip()
swapcase()
find()
startswith()
33 changes: 33 additions & 0 deletions src/lpython/semantics/python_ast_to_asr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4195,6 +4195,20 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
args.push_back(al, arg);
tmp = make_call_helper(al, fn_div, current_scope, args, "_lpython_str_strip", x.base.base.loc);
return;
} else if (std::string(at->m_attr) == std::string("swapcase")) {
if(args.size() != 0) {
throw SemanticError("str.swapcase() takes no arguments",
x.base.base.loc);
}
ASR::symbol_t *fn_div = resolve_intrinsic_function(x.base.base.loc, "_lpython_str_swapcase");
Vec<ASR::call_arg_t> args;
args.reserve(al, 1);
ASR::call_arg_t arg;
arg.loc = x.base.base.loc;
arg.m_value = se;
args.push_back(al, arg);
tmp = make_call_helper(al, fn_div, current_scope, args, "_lpython_str_swapcase", x.base.base.loc);
return;
} else if (std::string(at->m_attr) == std::string("startswith")) {
if(args.size() != 1) {
throw SemanticError("str.startwith() takes one argument",
Expand Down Expand Up @@ -4407,6 +4421,25 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
1, 1, nullptr, nullptr , 0));
tmp = ASR::make_StringConstant_t(al, x.base.base.loc, s2c(al, res), str_type);
return;
} else if (std::string(at->m_attr) == std::string("swapcase")) {
if(args.size() != 0) {
throw SemanticError("str.swapcase() takes no arguments",
x.base.base.loc);
}
AST::ConstantStr_t *n = AST::down_cast<AST::ConstantStr_t>(at->m_value);
std::string res = n->m_value;
for (size_t i = 0; i < res.size(); i++) {
char &cur = res[i];
if(cur >= 'a' && cur <= 'z') {
cur = cur -'a' + 'A';
} else if(cur >= 'A' && cur <= 'Z') {
cur = cur - 'A' + 'a';
}
}
ASR::ttype_t *str_type = ASRUtils::TYPE(ASR::make_Character_t(al, x.base.base.loc,
1, 1, nullptr, nullptr , 0));
tmp = ASR::make_StringConstant_t(al, x.base.base.loc, s2c(al, res), str_type);
return;
} else if (std::string(at->m_attr) == std::string("startswith")) {
if (args.size() != 1) {
throw SemanticError("str.startswith() takes one arguments",
Expand Down
12 changes: 11 additions & 1 deletion src/lpython/semantics/python_comptime_eval.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ struct PythonIntrinsicProcedures {
{"_lpython_str_rstrip", {m_builtin, &eval__lpython_str_rstrip}},
{"_lpython_str_lstrip", {m_builtin, &eval__lpython_str_lstrip}},
{"_lpython_str_strip", {m_builtin, &eval__lpython_str_strip}},
{"_lpython_str_swapcase", {m_builtin, &eval__lpython_str_swapcase}},
{"_lpython_str_startswith", {m_builtin, &eval__lpython_str_startswith}}
};
}
Expand Down Expand Up @@ -742,7 +743,16 @@ struct PythonIntrinsicProcedures {
ASR::ttype_t *res_type = ASRUtils::TYPE(ASR::make_StringConstant_t(al, loc, s2c(al, ""), type));
return ASR::down_cast<ASR::expr_t>(ASR::make_StringConstant_t(al, loc, s2c(al, res), res_type));
}


static ASR::expr_t *eval__lpython_str_swapcase(Allocator &al, const Location &loc, Vec<ASR::expr_t *> &args) {
LFORTRAN_ASSERT(ASRUtils::all_args_evaluated(args));
std::string res = "";
ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_Character_t(al, loc,
1, 1, nullptr, nullptr, 0));
ASR::ttype_t *res_type = ASRUtils::TYPE(ASR::make_StringConstant_t(al, loc, s2c(al, ""), type));
return ASR::down_cast<ASR::expr_t>(ASR::make_StringConstant_t(al, loc, s2c(al, res), res_type));
}

static ASR::expr_t *eval_lpython_str_find(Allocator &al, const Location &loc, Vec<ASR::expr_t *> &/*args*/) {
// compile time action implemented on ast->asr
ASR::ttype_t *int_type = ASRUtils::TYPE(ASR::make_Integer_t(al, loc, 4, nullptr, 0));
Expand Down
13 changes: 13 additions & 0 deletions src/runtime/lpython_builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,19 @@ def _lpython_str_strip(x: str) -> str:
res = _lpython_str_rstrip(res)
return res

@overload
def _lpython_str_swapcase(s: str) -> str:
res :str = ""
cur: str
for cur in s:
if ord(cur) >= ord('a') and ord(cur) <= ord('z'):
res += chr(ord(cur) - ord('a') + ord('A'))
elif ord(cur) >= ord('A') and ord(cur) <= ord('Z'):
res += chr(ord(cur) - ord('A') + ord('a'))
else:
res += cur
return res

@overload
def _lpython_str_startswith(s: str ,sub: str) -> bool:
res :bool
Expand Down
2 changes: 1 addition & 1 deletion tests/reference/asr-complex1-f26c460.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"outfile": null,
"outfile_hash": null,
"stdout": "asr-complex1-f26c460.stdout",
"stdout_hash": "ec30511e10451c64a896595e1470c429df7ec2bb31dd60b299a15d2b",
"stdout_hash": "c741bb3cc0e4ba3e9076c989424b8eddb5ebdb9458b9fb894dc84044",
"stderr": null,
"stderr_hash": null,
"returncode": 0
Expand Down
Loading

0 comments on commit 2805b30

Please sign in to comment.