Skip to content
Merged
28 changes: 28 additions & 0 deletions integration_tests/test_list_pop.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,32 @@ def test_list_pop():
j += 1
assert len(l2) == 0

# list.pop on list constant
print([1, 2, 3, 4, 5].pop())
assert [1, 2, 3, 4, 5].pop() == 5

print([1, 2, 3, 4, 5].pop(3))
assert [1, 2, 3, 4, 5].pop(3) == 4

index: i32 = 1
print([1, 2, 3, 4, 5].pop(index))
assert [1, 2, 3, 4, 5].pop(index) == 2

element_1: i32 = [1, 2, 3, 4, 5].pop()
print(element_1)
assert element_1 == 5

element_2: i32 = [1, 2, 3, 4, 5].pop(2)
print(element_2)
assert element_2 == 3

a: i32 = 5
b: i32 = 3

print([(1, 2), (3, 4), (5, 6)].pop(a//b))
assert [(1, 2), (3, 4), (5, 6)].pop(a//b) == (3, 4)

print([["a", "b"], ["c", "d"], ["e", "f"]].pop())
assert [["a", "b"], ["c", "d"], ["e", "f"]].pop() == ["e", "f"]

test_list_pop()
21 changes: 18 additions & 3 deletions src/libasr/pass/intrinsic_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -4672,9 +4672,24 @@ static inline void verify_args(const ASR::IntrinsicElementalFunction_t& x, diag:
}

static inline ASR::expr_t *eval_list_pop(Allocator &/*al*/,
const Location &/*loc*/, ASR::ttype_t */*t*/, Vec<ASR::expr_t*>& /*args*/, diag::Diagnostics& /*diag*/) {
// TODO: To be implemented for ListConstant expression
return nullptr;
const Location &/*loc*/, ASR::ttype_t */*t*/, Vec<ASR::expr_t*>& args, diag::Diagnostics& /*diag*/) {
if (args.n == 0 || args[0] == nullptr) {
return nullptr;
}
ASR::ListConstant_t* clist = ASR::down_cast<ASR::ListConstant_t>(args[0]);
int64_t index;

if (args.n == 1) {
index = clist->n_args - 1;
return clist->m_args[index];
} else {
if (args[1] == nullptr) {
return nullptr;
}
index = ASR::down_cast<ASR::IntegerConstant_t>(ASRUtils::expr_value(args[1]))->m_n;
return clist->m_args[index];
}

}

static inline ASR::asr_t* create_ListPop(Allocator& al, const Location& loc,
Expand Down
14 changes: 14 additions & 0 deletions src/lpython/semantics/python_ast_to_asr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7653,6 +7653,20 @@ we will have to use something else.
}
}
}
} else if (AST::is_a<AST::List_t>(*at->m_value)) {
AST::List_t* clist = AST::down_cast<AST::List_t>(at->m_value);
visit_List(*clist);
if (tmp == nullptr) {
throw SemanticError("cannot call " + std::string(at->m_attr) + " on an empty list" , loc);
}
ASR::expr_t* list_expr = ASR::down_cast<ASR::expr_t>(tmp);
Vec<ASR::expr_t*> eles;
eles.reserve(al, args.size());
for (size_t i=0; i<args.size(); i++) {
eles.push_back(al, args[i].m_value);
}
handle_builtin_attribute(list_expr, at->m_attr, loc, eles);
return;
} else if (AST::is_a<AST::Dict_t>(*at->m_value)) {
AST::Dict_t* cdict = AST::down_cast<AST::Dict_t>(at->m_value);
visit_Dict(*cdict);
Expand Down
10 changes: 6 additions & 4 deletions src/lpython/semantics/python_attribute_eval.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,12 @@ struct AttributeHandler {
}
std::string key = class_name + "@" + attr_name;
if (modify_attr_set.find(key) != modify_attr_set.end()) {
ASR::Variable_t* v = ASRUtils::EXPR2VAR(e);
if (v->m_intent == ASRUtils::intent_in) {
throw SemanticError("Modifying input function parameter `"
+ std::string(v->m_name) + "` is not allowed", loc);
if (ASR::is_a<ASR::Var_t>(*e)) {
ASR::Variable_t* v = ASRUtils::EXPR2VAR(e);
if (v->m_intent == ASRUtils::intent_in) {
throw SemanticError("Modifying input function parameter `"
+ std::string(v->m_name) + "` is not allowed", loc);
}
}
}
auto search = attribute_map.find(key);
Expand Down