Skip to content

Commit 5452ed1

Browse files
authored
ASR -> CPython: Add list method visitors (#2694)
* Add visitors for `append`, `count`, `remove`, `clear` and `insert` * Tests: Add tests and create references * Fix codegen considering whether the method has a return value * Tests: Update test references * Tests: Update test references pertaining to fix related to `__main__global_stmts`
1 parent 9817f8a commit 5452ed1

5 files changed

Lines changed: 209 additions & 0 deletions

File tree

src/libasr/codegen/asr_to_python.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,56 @@ class ASRToLpythonVisitor : public ASR::BaseVisitor<ASRToLpythonVisitor>
636636
void visit_SetConstant(const ASR::SetConstant_t &x) {
637637
visit_AggregateConstant(x.n_elements, x.m_elements, "{", "}");
638638
}
639+
640+
// An aggregate visitor for list methods with 0 or 1 argument
641+
void visit_UnaryListMethods(ASR::expr_t* list, std::string method_name,
642+
ASR::expr_t* arg=nullptr, bool has_return_value=false) {
643+
std::string r = "";
644+
visit_expr(*list);
645+
r += s;
646+
r += "." + method_name + "(";
647+
if (arg != nullptr) {
648+
visit_expr(*arg);
649+
r += s;
650+
}
651+
r += ")";
652+
if (!has_return_value) {
653+
r = indent + r + "\n";
654+
}
655+
656+
s = r;
657+
}
658+
659+
void visit_ListAppend(const ASR::ListAppend_t &x) {
660+
visit_UnaryListMethods(x.m_a, "append", x.m_ele);
661+
}
662+
663+
void visit_ListCount(const ASR::ListCount_t &x) {
664+
visit_UnaryListMethods(x.m_arg, "count", x.m_ele, true);
665+
}
666+
667+
void visit_ListRemove(const ASR::ListRemove_t &x) {
668+
visit_UnaryListMethods(x.m_a, "remove", x.m_ele);
669+
}
670+
671+
void visit_ListClear(const ASR::ListClear_t &x) {
672+
visit_UnaryListMethods(x.m_a, "clear");
673+
}
674+
675+
void visit_ListInsert(const ASR::ListInsert_t &x) {
676+
std::string r = indent;
677+
visit_expr(*x.m_a);
678+
r += s;
679+
r += ".insert(";
680+
visit_expr(*x.m_pos);
681+
r += s + ", ";
682+
visit_expr(*x.m_ele);
683+
r += s;
684+
r += ")\n";
685+
686+
s = r;
687+
}
688+
639689
};
640690

641691
Result<std::string> asr_to_python(Allocator& al, ASR::TranslationUnit_t &asr,
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"basename": "python-test_list_methods-ceccf6b",
3+
"cmd": "lpython --no-color --show-python {infile}",
4+
"infile": "tests/test_list_methods.py",
5+
"infile_hash": "8fe6f0b490e63a1b86d4964ede9d5410d421e0251bd692d36a4b79c6",
6+
"outfile": null,
7+
"outfile_hash": null,
8+
"stdout": "python-test_list_methods-ceccf6b.stdout",
9+
"stdout_hash": "888c041c38f4a7c2ea49df884a2caae10cc223b746227de97f9abf25",
10+
"stderr": null,
11+
"stderr_hash": null,
12+
"returncode": 0
13+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
def __main__global_stmts():
2+
my_first_list = [1, 2, 3, 4, 5]
3+
print(my_first_list)
4+
my_first_list.append(4)
5+
my_first_list.remove(2)
6+
print(my_first_list.count(4))
7+
my_first_list.insert(0, 1)
8+
my_first_list.clear()
9+
my_second_list = [1.200000, 4.300000, 2.800000]
10+
print(my_second_list)
11+
my_second_list.append(4.300000)
12+
my_second_list.remove(2.800000)
13+
print(my_second_list.count(4.300000))
14+
my_second_list.insert(0, 3.300000)
15+
my_second_list.clear()
16+
my_third_list = ["hello", "world", "lpython"]
17+
print(my_third_list)
18+
my_third_list.append("hello")
19+
my_third_list.remove("world")
20+
print(my_third_list.count("hello"))
21+
my_third_list.insert(0, "hi")
22+
my_third_list.clear()
23+
my_fourth_list = [(1.200000, 4.300000), (2.800000, 3.300000)]
24+
print(my_fourth_list)
25+
my_fourth_list.append((1.600000, 2.200000))
26+
my_fourth_list.remove((1.200000, 4.300000))
27+
print(my_fourth_list.count((2.800000, 3.300000)))
28+
my_fourth_list.insert(0, (1.000000, 0.000000))
29+
my_fourth_list.clear()
30+
f()
31+
def f():
32+
my_first_list: list[i32]
33+
my_fourth_list: list[tuple[f64, f64]]
34+
my_second_list: list[f64]
35+
my_third_list: list[str]
36+
my_first_list = [1, 2, 3, 4, 5]
37+
print(my_first_list)
38+
my_first_list.append(4)
39+
my_first_list.remove(2)
40+
print(my_first_list.count(4))
41+
my_first_list.insert(0, 1)
42+
my_first_list.clear()
43+
my_second_list = [1.200000, 4.300000, 2.800000]
44+
print(my_second_list)
45+
my_second_list.append(4.300000)
46+
my_second_list.remove(2.800000)
47+
print(my_second_list.count(4.300000))
48+
my_second_list.insert(0, 3.300000)
49+
my_second_list.clear()
50+
my_third_list = ["hello", "world", "lpython"]
51+
print(my_third_list)
52+
my_third_list.append("hello")
53+
my_third_list.remove("world")
54+
print(my_third_list.count("hello"))
55+
my_third_list.insert(0, "hi")
56+
my_third_list.clear()
57+
my_fourth_list = [(1.200000, 4.300000), (2.800000, 3.300000)]
58+
print(my_fourth_list)
59+
my_fourth_list.append((1.600000, 2.200000))
60+
my_fourth_list.remove((1.200000, 4.300000))
61+
print(my_fourth_list.count((2.800000, 3.300000)))
62+
my_fourth_list.insert(0, (1.000000, 0.000000))
63+
my_fourth_list.clear()

tests/test_list_methods.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
from lpython import i32, f64
2+
3+
# Global scope
4+
my_first_list: list[i32] = [1, 2, 3, 4, 5]
5+
print(my_first_list)
6+
7+
my_first_list.append(4)
8+
my_first_list.remove(2)
9+
print(my_first_list.count(4))
10+
my_first_list.insert(0, 1)
11+
my_first_list.clear()
12+
13+
my_second_list: list[f64] = [1.2, 4.3, 2.8]
14+
print(my_second_list)
15+
16+
my_second_list.append(4.3)
17+
my_second_list.remove(2.8)
18+
print(my_second_list.count(4.3))
19+
my_second_list.insert(0, 3.3)
20+
my_second_list.clear()
21+
22+
my_third_list: list[str] = ["hello", "world", "lpython"]
23+
print(my_third_list)
24+
25+
my_third_list.append("hello")
26+
my_third_list.remove("world")
27+
print(my_third_list.count("hello"))
28+
my_third_list.insert(0, "hi")
29+
my_third_list.clear()
30+
31+
my_fourth_list: list[tuple[f64, f64]] = [(1.2, 4.3), (2.8, 3.3)]
32+
print(my_fourth_list)
33+
34+
my_fourth_list.append((1.6, 2.2))
35+
my_fourth_list.remove((1.2, 4.3))
36+
print(my_fourth_list.count((2.8, 3.3)))
37+
my_fourth_list.insert(0, (1.0, 0.0))
38+
my_fourth_list.clear()
39+
40+
# Local scope
41+
def f():
42+
my_first_list: list[i32] = [1, 2, 3, 4, 5]
43+
print(my_first_list)
44+
45+
my_first_list.append(4)
46+
my_first_list.remove(2)
47+
print(my_first_list.count(4))
48+
my_first_list.insert(0, 1)
49+
my_first_list.clear()
50+
51+
my_second_list: list[f64] = [1.2, 4.3, 2.8]
52+
print(my_second_list)
53+
54+
my_second_list.append(4.3)
55+
my_second_list.remove(2.8)
56+
print(my_second_list.count(4.3))
57+
my_second_list.insert(0, 3.3)
58+
my_second_list.clear()
59+
60+
my_third_list: list[str] = ["hello", "world", "lpython"]
61+
print(my_third_list)
62+
63+
my_third_list.append("hello")
64+
my_third_list.remove("world")
65+
print(my_third_list.count("hello"))
66+
my_third_list.insert(0, "hi")
67+
my_third_list.clear()
68+
69+
my_fourth_list: list[tuple[f64, f64]] = [(1.2, 4.3), (2.8, 3.3)]
70+
print(my_fourth_list)
71+
72+
my_fourth_list.append((1.6, 2.2))
73+
my_fourth_list.remove((1.2, 4.3))
74+
print(my_fourth_list.count((2.8, 3.3)))
75+
my_fourth_list.insert(0, (1.0, 0.0))
76+
my_fourth_list.clear()
77+
78+
79+
f()

tests/tests.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ asr = true
5555
filename = "test_aggregate_constants.py"
5656
python = true
5757

58+
[[test]]
59+
filename = "test_list_methods.py"
60+
python = true
61+
5862
[[test]]
5963
filename = "expr1.py"
6064
ast = true

0 commit comments

Comments
 (0)