Skip to content

Commit

Permalink
Merge branch 'main' into fix-symblic-pass-for-printing-intrinsic-elem…
Browse files Browse the repository at this point in the history
…ental-function
  • Loading branch information
kmr-srbh authored Apr 26, 2024
2 parents de3728b + 4921160 commit 658e561
Show file tree
Hide file tree
Showing 61 changed files with 1,389 additions and 1,234 deletions.
32 changes: 23 additions & 9 deletions integration_tests/test_gruntz.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from lpython import S
from sympy import Symbol, log, E, Pow
from sympy import Symbol, log, E, Pow, exp

def mmrv(e: S, x: S) -> list[S]:
empty_list : list[S] = []
Expand All @@ -13,22 +13,29 @@ def mmrv(e: S, x: S) -> list[S]:
list2: list[S] = mmrv(arg0, x)
return list2
elif e.func == Pow:
if e.args[0] != E:
e1: S = S(1)
base: S = e.args[0]
exponent: S = e.args[1]
one: S = S(1)
if base != E:
newe_exponent: S = S(1)
newe: S = e
while newe.func == Pow:
b1: S = newe.args[0]
e1 = e1 * newe.args[1]
newe = b1
if b1 == S(1):
newe_base: S = newe.args[0]
newe_args1: S = newe.args[1]
newe_exponent = newe_exponent * newe_args1
newe = newe_base
if newe_base == one:
return empty_list
if not e1.has(x):
list3: list[S] = mmrv(b1, x)
if not newe_exponent.has(x):
list3: list[S] = mmrv(newe_base, x)
return list3
else:
# TODO as noted in #2526
pass
else:
if exponent.func == log:
list4: list[S] = mmrv(exponent.args[0], x)
return list4
# TODO
pass
else:
Expand Down Expand Up @@ -63,4 +70,11 @@ def test_mrv():
assert ele3 == x
assert len(ans4) == 1

# Case 5
ans5: list[S] = mmrv(exp(log(x)), x)
ele4: S = ans5[0]
print(ele4)
assert ele4 == x
assert len(ans5) == 1

test_mrv()
27 changes: 27 additions & 0 deletions integration_tests/test_str_attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,31 @@ def is_numeric():
assert "".isnumeric() == False
assert "ab2%3".isnumeric() == False

def center():
s: str = "test"
assert s.center(8,'*') == "**test**"
assert s.center(11) == " test "
assert s.center(2) == "test"
assert s.center(4) == "test"
assert s.center(9,'/') == "///test//"

def expandtabs():
s: str = '01\t012\t0123\t01234'
assert s.expandtabs() == "01 012 0123 01234"
assert s.expandtabs(4) == "01 012 0123 01234"
assert s.expandtabs(-1) == "01012012301234"
s = '\t'
assert s.expandtabs() == " "
s = ''
assert s.expandtabs() == ""
s = '\tThis\ris\na\ttest'
assert s.expandtabs(4) == " This\ris\na test"
s = '\t\t\t'
assert s.expandtabs(2) == " "
s = 'test\ttest'
assert s.expandtabs(0) == "testtest"
assert s.expandtabs(-5) == "testtest"

def check():
capitalize()
lower()
Expand All @@ -492,6 +517,8 @@ def check():
is_space()
is_alnum()
is_numeric()
center()
expandtabs()


check()
53 changes: 53 additions & 0 deletions src/lpython/semantics/python_ast_to_asr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6880,6 +6880,59 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
value.m_value = args[2].m_value;
fn_args.push_back(al, value);
}
} else if(attr_name == "center") {
if (args.size() != 1 && args.size() != 2) {
throw SemanticError("str.center() takes one or two argument",
loc);
}
ASR::expr_t *arg_value = args[0].m_value;
ASR::ttype_t *arg_value_type = ASRUtils::expr_type(arg_value);
if (!ASRUtils::is_integer(*arg_value_type)) {
throw SemanticError("str.center() argument 1 must be integer", loc);
}

fn_call_name = "_lpython_str_center";
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;
fn_args.push_back(al, str);
fn_args.push_back(al, value);

if(args.size() == 2){
ASR::expr_t *arg_value = args[1].m_value;
ASR::ttype_t *arg_value_type = ASRUtils::expr_type(arg_value);
if (!ASRUtils::is_character(*arg_value_type)) {
throw SemanticError("str.center() argument 2 must be str", loc);
}
value.m_value = args[1].m_value;
fn_args.push_back(al, value);
}
} else if(attr_name == "expandtabs") {
if(args.size() > 1) {
throw SemanticError("str.expandtabs() takes at most one argument.", loc);
}
fn_call_name = "_lpython_str_expandtabs";
ASR::call_arg_t str;
str.loc = loc;
str.m_value = s_var;
fn_args.push_back(al, str);

if(args.size() == 1){
ASR::expr_t *arg_value = args[0].m_value;
ASR::ttype_t *arg_value_type = ASRUtils::expr_type(arg_value);
if (!ASRUtils::is_integer(*arg_value_type)) {
throw SemanticError("str.expandtabs() argument must be integer", loc);
}

ASR::call_arg_t value;
value.loc = loc;
value.m_value = args[0].m_value;
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
4 changes: 3 additions & 1 deletion src/lpython/semantics/python_comptime_eval.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ struct PythonIntrinsicProcedures {
{"_lpython_str_isupper", {m_builtin, &not_implemented}},
{"_lpython_str_isdecimal", {m_builtin, &not_implemented}},
{"_lpython_str_isascii", {m_builtin, &not_implemented}},
{"_lpython_str_isspace", {m_builtin, &not_implemented}}
{"_lpython_str_isspace", {m_builtin, &not_implemented}},
{"_lpython_str_center", {m_builtin, &not_implemented}},
{"_lpython_str_expandtabs", {m_builtin, &not_implemented}}
};
}

Expand Down
59 changes: 59 additions & 0 deletions src/runtime/lpython_builtin.py
Original file line number Diff line number Diff line change
Expand Up @@ -1085,6 +1085,65 @@ def _lpython_str_isspace(s: str) -> bool:
return False
return True

@overload
def _lpython_str_center(s: str, width: i32, fillchar: str) -> str:
"""
Return centered in a string of length width.
Padding is done using the specified fillchar (default is an ASCII space).
The original string is returned if width is less than or equal to len(s).
"""
if(len(fillchar) != 1):
raise TypeError("The fill character must be exactly one character long")
str_len: i32 = len(s)
if width <= str_len:
return s
width -= str_len
result: str = ""
left_padding: i32 = i32(width/2) + _mod(width,2)
i: i32
for i in range(left_padding):
result += fillchar
right_padding: i32 = width - left_padding
result += s
for i in range(right_padding):
result += fillchar
return result

@overload
def _lpython_str_center(s: str, width: i32) -> str:
return _lpython_str_center(s, width, ' ')

@overload
def _lpython_str_expandtabs(s: str, tabsize: i32) -> str:
"""
Return a copy of the string where all tab characters are replaced
by one or more spaces, depending on the current column and the given tab size.
"""
if len(s) == 0:
return s
col: i32 = 0
result: str = ""
c: str
for c in s:
if c == '\t':
if tabsize > 0:
i: i32
iterations: i32 = tabsize - _mod(col,tabsize)
for i in range(iterations):
result += ' '
col = 0
elif c == '\n' or c == '\r':
result += c
col = 0
else:
result += c
col += 1
return result

@overload
def _lpython_str_expandtabs(s: str) -> str:
return _lpython_str_expandtabs(s, 8)

def list(s: str) -> list[str]:
l: list[str] = []
i: i32
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": "34c5f9983e43e6b5c65f021792e415f0c2e4fe5135c6435eb5322719",
"stdout_hash": "292194a8fe4110a90c90bbcbf94f66b70f82978e14108ded75104711",
"stderr": null,
"stderr_hash": null,
"returncode": 0
Expand Down
Loading

0 comments on commit 658e561

Please sign in to comment.