Skip to content

Commit db6ed14

Browse files
kmr-srbhubaidsk
andauthored
Add support for list methods with Const (#2570)
* Implement `append`, `remove`, `reverse`, `pop`, `clear` and `insert` * Implement `count` and `index` * Improve checking for `Const` type * Simplify type checking for `Const` * Update test references * Add tests * Update test * Update error test references * Update error test references * Update tests/tests.toml Co-authored-by: Shaikh Ubaid <[email protected]> * Tests: Update tests and test references * LLVM: Fix const list declaration * Fix type for type checking * Add print statements in test * TEST: Update reference tests * TEST: Remove C flag as ListCount() yet to be supported * Remove list, str import * Fix formatting changes --------- Co-authored-by: Shaikh Ubaid <[email protected]>
1 parent 7aa7084 commit db6ed14

24 files changed

+242
-10
lines changed

integration_tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,7 @@ RUN(NAME test_list_pop3 LABELS cpython llvm)
551551
RUN(NAME test_list_compare LABELS cpython llvm)
552552
RUN(NAME test_list_concat LABELS cpython llvm c NOFAST)
553553
RUN(NAME test_list_reserve LABELS cpython llvm)
554+
RUN(NAME test_const_list LABELS cpython llvm)
554555
RUN(NAME test_tuple_01 LABELS cpython llvm c)
555556
RUN(NAME test_tuple_02 LABELS cpython llvm c NOFAST)
556557
RUN(NAME test_tuple_03 LABELS cpython llvm c)

integration_tests/test_const_list.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from lpython import i32, Const
2+
3+
4+
def test_const_list():
5+
CONST_INTEGER_LIST: Const[list[i32]] = [1, 2, 3, 4, 5, 1]
6+
7+
print(CONST_INTEGER_LIST.count(1))
8+
print(CONST_INTEGER_LIST.index(1))
9+
assert CONST_INTEGER_LIST.count(1) == 2
10+
assert CONST_INTEGER_LIST.index(1) == 0
11+
12+
CONST_STRING_LIST: Const[list[str]] = ["ALPHA", "BETA", "RELEASE"]
13+
print(CONST_STRING_LIST.count("ALPHA"))
14+
print(CONST_STRING_LIST.index("RELEASE"))
15+
assert CONST_STRING_LIST.count("ALPHA") == 1
16+
assert CONST_STRING_LIST.index("RELEASE") == 2
17+
18+
19+
test_const_list()

src/libasr/codegen/asr_to_llvm.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1729,7 +1729,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
17291729
}
17301730

17311731
void visit_ListCount(const ASR::ListCount_t& x) {
1732-
ASR::ttype_t* asr_el_type = ASRUtils::get_contained_type(ASRUtils::expr_type(x.m_arg));
1732+
ASR::ttype_t *asr_el_type = ASRUtils::get_contained_type(ASRUtils::type_get_past_const(ASRUtils::expr_type(x.m_arg)));
17331733
int64_t ptr_loads_copy = ptr_loads;
17341734
ptr_loads = 0;
17351735
this->visit_expr(*x.m_arg);
@@ -1744,7 +1744,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
17441744

17451745
void generate_ListIndex(ASR::expr_t* m_arg, ASR::expr_t* m_ele,
17461746
ASR::expr_t* m_start=nullptr, ASR::expr_t* m_end=nullptr) {
1747-
ASR::ttype_t* asr_el_type = ASRUtils::get_contained_type(ASRUtils::expr_type(m_arg));
1747+
ASR::ttype_t *asr_el_type = ASRUtils::get_contained_type(ASRUtils::type_get_past_const(ASRUtils::expr_type(m_arg)));
17481748
int64_t ptr_loads_copy = ptr_loads;
17491749
ptr_loads = 0;
17501750
this->visit_expr(*m_arg);
@@ -3514,7 +3514,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
35143514
}
35153515
}
35163516
if( init_expr != nullptr &&
3517-
!ASR::is_a<ASR::List_t>(*v->m_type)) {
3517+
!is_list) {
35183518
target_var = ptr;
35193519
tmp = nullptr;
35203520
if (v->m_value != nullptr) {
@@ -3590,7 +3590,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
35903590
throw CodeGenError("Unsupported len value in ASR");
35913591
}
35923592
} else if (is_list) {
3593-
ASR::List_t* asr_list = ASR::down_cast<ASR::List_t>(v->m_type);
3593+
ASR::List_t* asr_list = ASR::down_cast<ASR::List_t>(
3594+
ASRUtils::type_get_past_const(v->m_type));
35943595
std::string type_code = ASRUtils::get_type_code(asr_list->m_type);
35953596
list_api->list_init(type_code, ptr, *module);
35963597
}

src/libasr/pass/intrinsic_function_registry.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2520,12 +2520,13 @@ namespace ListIndex {
25202520
static inline void verify_args(const ASR::IntrinsicScalarFunction_t& x, diag::Diagnostics& diagnostics) {
25212521
ASRUtils::require_impl(x.n_args <= 4, "Call to list.index must have at most four arguments",
25222522
x.base.base.loc, diagnostics);
2523-
ASRUtils::require_impl(ASR::is_a<ASR::List_t>(*ASRUtils::expr_type(x.m_args[0])) &&
2523+
ASR::ttype_t *list_type = ASRUtils::type_get_past_const(ASRUtils::expr_type(x.m_args[0]));
2524+
ASRUtils::require_impl(ASR::is_a<ASR::List_t>(*list_type) &&
25242525
ASRUtils::check_equal_type(ASRUtils::expr_type(x.m_args[1]),
2525-
ASRUtils::get_contained_type(ASRUtils::expr_type(x.m_args[0]))),
2526+
ASRUtils::get_contained_type(list_type)),
25262527
"First argument to list.index must be of list type and "
25272528
"second argument must be of same type as list elemental type",
2528-
x.base.base.loc, diagnostics);
2529+
x.base.base.loc, diagnostics);
25292530
if(x.n_args >= 3) {
25302531
ASRUtils::require_impl(
25312532
ASR::is_a<ASR::Integer_t>(*ASRUtils::expr_type(x.m_args[2])),
@@ -2555,7 +2556,7 @@ static inline ASR::asr_t* create_ListIndex(Allocator& al, const Location& loc,
25552556
const std::function<void (const std::string &, const Location &)> err) {
25562557
int64_t overload_id = 0;
25572558
ASR::expr_t* list_expr = args[0];
2558-
ASR::ttype_t *type = ASRUtils::expr_type(list_expr);
2559+
ASR::ttype_t *type = ASRUtils::type_get_past_const(ASRUtils::expr_type(list_expr));
25592560
ASR::ttype_t *list_type = ASR::down_cast<ASR::List_t>(type)->m_type;
25602561
ASR::ttype_t *ele_type = ASRUtils::expr_type(args[1]);
25612562
if (!ASRUtils::check_equal_type(ele_type, list_type)) {

src/lpython/semantics/python_attribute_eval.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ struct AttributeHandler {
6767

6868
ASR::asr_t* get_attribute(ASR::expr_t *e, std::string attr_name,
6969
Allocator &al, const Location &loc, Vec<ASR::expr_t*> &args, diag::Diagnostics &diag) {
70-
ASR::ttype_t *type = ASRUtils::expr_type(e);
70+
ASR::ttype_t *type = ASRUtils::type_get_past_const(ASRUtils::expr_type(e));
7171
std::string class_name = get_type_name(type);
7272
if (class_name == "") {
7373
throw SemanticError("Type name is not implemented yet.", loc);
@@ -124,6 +124,9 @@ struct AttributeHandler {
124124

125125
static ASR::asr_t* eval_list_append(ASR::expr_t *s, Allocator &al, const Location &loc,
126126
Vec<ASR::expr_t*> &args, diag::Diagnostics &diag) {
127+
if (ASR::is_a<ASR::Const_t>(*ASRUtils::expr_type(s))) {
128+
throw SemanticError("cannot append element to a const list", loc);
129+
}
127130
if (args.size() != 1) {
128131
throw SemanticError("append() takes exactly one argument",
129132
loc);
@@ -148,6 +151,9 @@ struct AttributeHandler {
148151

149152
static ASR::asr_t* eval_list_remove(ASR::expr_t *s, Allocator &al, const Location &loc,
150153
Vec<ASR::expr_t*> &args, diag::Diagnostics &diag) {
154+
if (ASR::is_a<ASR::Const_t>(*ASRUtils::expr_type(s))) {
155+
throw SemanticError("cannot remove element from a const list", loc);
156+
}
151157
if (args.size() != 1) {
152158
throw SemanticError("remove() takes exactly one argument",
153159
loc);
@@ -176,7 +182,7 @@ struct AttributeHandler {
176182
throw SemanticError("count() takes exactly one argument",
177183
loc);
178184
}
179-
ASR::ttype_t *type = ASRUtils::expr_type(s);
185+
ASR::ttype_t *type = ASRUtils::type_get_past_const(ASRUtils::expr_type(s));
180186
ASR::ttype_t *list_type = ASR::down_cast<ASR::List_t>(type)->m_type;
181187
ASR::ttype_t *ele_type = ASRUtils::expr_type(args[0]);
182188
if (!ASRUtils::check_equal_type(ele_type, list_type)) {
@@ -211,6 +217,9 @@ struct AttributeHandler {
211217

212218
static ASR::asr_t* eval_list_reverse(ASR::expr_t *s, Allocator &al, const Location &loc,
213219
Vec<ASR::expr_t*> &args, diag::Diagnostics &/*diag*/) {
220+
if (ASR::is_a<ASR::Const_t>(*ASRUtils::expr_type(s))) {
221+
throw SemanticError("cannot reverse a const list", loc);
222+
}
214223
Vec<ASR::expr_t*> args_with_list;
215224
args_with_list.reserve(al, args.size() + 1);
216225
args_with_list.push_back(al, s);
@@ -225,6 +234,9 @@ struct AttributeHandler {
225234

226235
static ASR::asr_t* eval_list_pop(ASR::expr_t *s, Allocator &al, const Location &loc,
227236
Vec<ASR::expr_t*> &args, diag::Diagnostics &/*diag*/) {
237+
if (ASR::is_a<ASR::Const_t>(*ASRUtils::expr_type(s))) {
238+
throw SemanticError("cannot pop element from a const list", loc);
239+
}
228240
Vec<ASR::expr_t*> args_with_list;
229241
args_with_list.reserve(al, args.size() + 1);
230242
args_with_list.push_back(al, s);
@@ -239,6 +251,9 @@ struct AttributeHandler {
239251

240252
static ASR::asr_t* eval_list_insert(ASR::expr_t *s, Allocator &al, const Location &loc,
241253
Vec<ASR::expr_t*> &args, diag::Diagnostics &diag) {
254+
if (ASR::is_a<ASR::Const_t>(*ASRUtils::expr_type(s))) {
255+
throw SemanticError("cannot insert element in a const list", loc);
256+
}
242257
if (args.size() != 2) {
243258
throw SemanticError("insert() takes exactly two arguments",
244259
loc);
@@ -270,6 +285,9 @@ struct AttributeHandler {
270285

271286
static ASR::asr_t* eval_list_clear(ASR::expr_t *s, Allocator &al,
272287
const Location &loc, Vec<ASR::expr_t*> &args, diag::Diagnostics & diag) {
288+
if (ASR::is_a<ASR::Const_t>(*ASRUtils::expr_type(s))) {
289+
throw SemanticError("cannot clear elements from a const list", loc);
290+
}
273291
if (args.size() != 0) {
274292
diag.add(diag::Diagnostic(
275293
"Incorrect number of arguments in 'clear', it accepts no argument",
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from lpython import i32, list, Const
2+
3+
4+
def test_const_list_append():
5+
CONST_INTEGER_LIST: Const[list[i32]] = [1, 2, 3, 4, 5, 1]
6+
7+
CONST_INTEGER_LIST.append(6)
8+
9+
10+
test_const_list_append()

tests/errors/test_const_list_clear.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from lpython import i32, list, Const
2+
3+
4+
def test_const_list_clear():
5+
CONST_INTEGER_LIST: Const[list[i32]] = [1, 2, 3, 4, 5, 1]
6+
7+
CONST_INTEGER_LIST.clear()
8+
9+
10+
test_const_list_clear()
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from lpython import i32, list, Const
2+
3+
4+
def test_const_list_insert():
5+
CONST_INTEGER_LIST: Const[list[i32]] = [1, 2, 3, 4, 5, 1]
6+
7+
CONST_INTEGER_LIST.insert(3, 8)
8+
9+
10+
test_const_list_insert()

tests/errors/test_const_list_pop.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from lpython import i32, list, Const
2+
3+
4+
def test_const_list_pop():
5+
CONST_INTEGER_LIST: Const[list[i32]] = [1, 2, 3, 4, 5, 1]
6+
7+
CONST_INTEGER_LIST.pop()
8+
9+
10+
test_const_list_pop()
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from lpython import i32, list, Const
2+
3+
4+
def test_const_list_remove():
5+
CONST_INTEGER_LIST: Const[list[i32]] = [1, 2, 3, 4, 5, 1]
6+
7+
CONST_INTEGER_LIST.remove(1)
8+
9+
10+
test_const_list_remove()

0 commit comments

Comments
 (0)