Skip to content

Commit 8451ad2

Browse files
kmr-srbhubaidsk
andauthored
Add compile-time support for list.pop (#2659)
* Implement `list.pop` for `ListConstant` * Support non-constant argument to `list.pop` * Tests: Add tests and update references * Be more verbose with handling `nullptr` Co-authored-by: Shaikh Ubaid <shaikhubaid769@gmail.com> * Check for no arguments Co-authored-by: Shaikh Ubaid <shaikhubaid769@gmail.com> * Simplify compile-time evaluation logic * Handle modifying attribute on a compile time value * Tests: Update references * Tests: Print before asserts * Delete tests/reference/asr-func_04-eef2656.stdout --------- Co-authored-by: Shaikh Ubaid <shaikhubaid769@gmail.com>
1 parent d7121dd commit 8451ad2

File tree

4 files changed

+66
-7
lines changed

4 files changed

+66
-7
lines changed

integration_tests/test_list_pop.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,32 @@ def test_list_pop():
6565
j += 1
6666
assert len(l2) == 0
6767

68+
# list.pop on list constant
69+
print([1, 2, 3, 4, 5].pop())
70+
assert [1, 2, 3, 4, 5].pop() == 5
71+
72+
print([1, 2, 3, 4, 5].pop(3))
73+
assert [1, 2, 3, 4, 5].pop(3) == 4
74+
75+
index: i32 = 1
76+
print([1, 2, 3, 4, 5].pop(index))
77+
assert [1, 2, 3, 4, 5].pop(index) == 2
78+
79+
element_1: i32 = [1, 2, 3, 4, 5].pop()
80+
print(element_1)
81+
assert element_1 == 5
82+
83+
element_2: i32 = [1, 2, 3, 4, 5].pop(2)
84+
print(element_2)
85+
assert element_2 == 3
86+
87+
a: i32 = 5
88+
b: i32 = 3
89+
90+
print([(1, 2), (3, 4), (5, 6)].pop(a//b))
91+
assert [(1, 2), (3, 4), (5, 6)].pop(a//b) == (3, 4)
92+
93+
print([["a", "b"], ["c", "d"], ["e", "f"]].pop())
94+
assert [["a", "b"], ["c", "d"], ["e", "f"]].pop() == ["e", "f"]
95+
6896
test_list_pop()

src/libasr/pass/intrinsic_functions.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4672,9 +4672,24 @@ static inline void verify_args(const ASR::IntrinsicElementalFunction_t& x, diag:
46724672
}
46734673

46744674
static inline ASR::expr_t *eval_list_pop(Allocator &/*al*/,
4675-
const Location &/*loc*/, ASR::ttype_t */*t*/, Vec<ASR::expr_t*>& /*args*/, diag::Diagnostics& /*diag*/) {
4676-
// TODO: To be implemented for ListConstant expression
4677-
return nullptr;
4675+
const Location &/*loc*/, ASR::ttype_t */*t*/, Vec<ASR::expr_t*>& args, diag::Diagnostics& /*diag*/) {
4676+
if (args.n == 0 || args[0] == nullptr) {
4677+
return nullptr;
4678+
}
4679+
ASR::ListConstant_t* clist = ASR::down_cast<ASR::ListConstant_t>(args[0]);
4680+
int64_t index;
4681+
4682+
if (args.n == 1) {
4683+
index = clist->n_args - 1;
4684+
return clist->m_args[index];
4685+
} else {
4686+
if (args[1] == nullptr) {
4687+
return nullptr;
4688+
}
4689+
index = ASR::down_cast<ASR::IntegerConstant_t>(ASRUtils::expr_value(args[1]))->m_n;
4690+
return clist->m_args[index];
4691+
}
4692+
46784693
}
46794694

46804695
static inline ASR::asr_t* create_ListPop(Allocator& al, const Location& loc,

src/lpython/semantics/python_ast_to_asr.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7659,6 +7659,20 @@ we will have to use something else.
76597659
}
76607660
}
76617661
}
7662+
} else if (AST::is_a<AST::List_t>(*at->m_value)) {
7663+
AST::List_t* clist = AST::down_cast<AST::List_t>(at->m_value);
7664+
visit_List(*clist);
7665+
if (tmp == nullptr) {
7666+
throw SemanticError("cannot call " + std::string(at->m_attr) + " on an empty list" , loc);
7667+
}
7668+
ASR::expr_t* list_expr = ASR::down_cast<ASR::expr_t>(tmp);
7669+
Vec<ASR::expr_t*> eles;
7670+
eles.reserve(al, args.size());
7671+
for (size_t i=0; i<args.size(); i++) {
7672+
eles.push_back(al, args[i].m_value);
7673+
}
7674+
handle_builtin_attribute(list_expr, at->m_attr, loc, eles);
7675+
return;
76627676
} else if (AST::is_a<AST::Dict_t>(*at->m_value)) {
76637677
AST::Dict_t* cdict = AST::down_cast<AST::Dict_t>(at->m_value);
76647678
visit_Dict(*cdict);

src/lpython/semantics/python_attribute_eval.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,12 @@ struct AttributeHandler {
7575
}
7676
std::string key = class_name + "@" + attr_name;
7777
if (modify_attr_set.find(key) != modify_attr_set.end()) {
78-
ASR::Variable_t* v = ASRUtils::EXPR2VAR(e);
79-
if (v->m_intent == ASRUtils::intent_in) {
80-
throw SemanticError("Modifying input function parameter `"
81-
+ std::string(v->m_name) + "` is not allowed", loc);
78+
if (ASR::is_a<ASR::Var_t>(*e)) {
79+
ASR::Variable_t* v = ASRUtils::EXPR2VAR(e);
80+
if (v->m_intent == ASRUtils::intent_in) {
81+
throw SemanticError("Modifying input function parameter `"
82+
+ std::string(v->m_name) + "` is not allowed", loc);
83+
}
8284
}
8385
}
8486
auto search = attribute_map.find(key);

0 commit comments

Comments
 (0)