From 8b2f66cd152a9c17769f611e1069356c630a2710 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Tue, 23 Apr 2024 19:41:03 +0530 Subject: [PATCH 01/10] Implement `list.pop` for `ListConstant` --- src/libasr/pass/intrinsic_functions.h | 15 ++++++++++++--- src/lpython/semantics/python_ast_to_asr.cpp | 14 ++++++++++++++ src/lpython/semantics/python_attribute_eval.h | 14 +++++++------- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/libasr/pass/intrinsic_functions.h b/src/libasr/pass/intrinsic_functions.h index a78175bd28..2770bff2ca 100644 --- a/src/libasr/pass/intrinsic_functions.h +++ b/src/libasr/pass/intrinsic_functions.h @@ -4672,9 +4672,18 @@ 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& /*args*/, diag::Diagnostics& /*diag*/) { - // TODO: To be implemented for ListConstant expression - return nullptr; + const Location &/*loc*/, ASR::ttype_t */*t*/, Vec& args, diag::Diagnostics& /*diag*/) { + if (args[0] == nullptr) { + return nullptr; + } + ASR::ListConstant_t* clist = ASR::down_cast(args[0]); + + if (args.n == 1) { + return clist->m_args[clist->n_args - 1]; + } else { + return clist->m_args[ASR::down_cast(ASRUtils::expr_value(args[1]))->m_n]; + } + } static inline ASR::asr_t* create_ListPop(Allocator& al, const Location& loc, diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index da49d33249..0c89993f49 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -7597,6 +7597,20 @@ we will have to use something else. } } } + } else if (AST::is_a(*at->m_value)) { + AST::List_t* clist = AST::down_cast(at->m_value); + visit_List(*clist); + if (!tmp) { + throw SemanticError("cannot call " + std::string(at->m_attr) + " on an empty list" , loc); + } + ASR::expr_t* list_expr = ASR::down_cast(tmp); + Vec eles; + eles.reserve(al, args.size()); + for (size_t i=0; im_attr, loc, eles); + return; } else { throw SemanticError("Only Name type and constant integers supported in Call", loc); } diff --git a/src/lpython/semantics/python_attribute_eval.h b/src/lpython/semantics/python_attribute_eval.h index d244c92d88..941d5e4f3f 100644 --- a/src/lpython/semantics/python_attribute_eval.h +++ b/src/lpython/semantics/python_attribute_eval.h @@ -74,13 +74,13 @@ struct AttributeHandler { throw SemanticError("Type name is not implemented yet.", loc); } 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 (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); + // } + // } auto search = attribute_map.find(key); if (search != attribute_map.end()) { attribute_eval_callback cb = search->second; From 9cdd47d51e9aeca3ff0b6abb5ea1b1d4bb103fb2 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Tue, 23 Apr 2024 20:07:50 +0530 Subject: [PATCH 02/10] Support non-constant argument to `list.pop` --- src/libasr/pass/intrinsic_functions.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libasr/pass/intrinsic_functions.h b/src/libasr/pass/intrinsic_functions.h index 2770bff2ca..56a71ccc52 100644 --- a/src/libasr/pass/intrinsic_functions.h +++ b/src/libasr/pass/intrinsic_functions.h @@ -4681,6 +4681,9 @@ static inline ASR::expr_t *eval_list_pop(Allocator &/*al*/, if (args.n == 1) { return clist->m_args[clist->n_args - 1]; } else { + if (args[1] == nullptr) { + return nullptr; + } return clist->m_args[ASR::down_cast(ASRUtils::expr_value(args[1]))->m_n]; } From a7e862b06bc51be676dc723cb8bae6f76e53e9cb Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Tue, 23 Apr 2024 20:12:04 +0530 Subject: [PATCH 03/10] Tests: Add tests and update references --- integration_tests/test_list_pop.py | 28 ++++++++ tests/reference/asr-func_04-eef2656.json | 10 +-- tests/reference/asr-func_04-eef2656.stdout | 82 ++++++++++++++++++++++ 3 files changed, 115 insertions(+), 5 deletions(-) create mode 100644 tests/reference/asr-func_04-eef2656.stdout diff --git a/integration_tests/test_list_pop.py b/integration_tests/test_list_pop.py index 51c9f02f45..dff3131b2b 100644 --- a/integration_tests/test_list_pop.py +++ b/integration_tests/test_list_pop.py @@ -65,4 +65,32 @@ def test_list_pop(): j += 1 assert len(l2) == 0 + # list.pop on list constant + assert [1, 2, 3, 4, 5].pop() == 5 + print([1, 2, 3, 4, 5].pop()) + + assert [1, 2, 3, 4, 5].pop(3) == 4 + print([1, 2, 3, 4, 5].pop(3)) + + index: i32 = 1 + assert [1, 2, 3, 4, 5].pop(index) == 2 + print([1, 2, 3, 4, 5].pop(index)) + + element_1: i32 = [1, 2, 3, 4, 5].pop() + assert element_1 == 5 + print(element_1) + + element_2: i32 = [1, 2, 3, 4, 5].pop(2) + assert element_2 == 3 + print(element_2) + + a: i32 = 5 + b: i32 = 3 + + assert [(1, 2), (3, 4), (5, 6)].pop(a//b) == (3, 4) + print([(1, 2), (3, 4), (5, 6)].pop(a//b)) + + assert [["a", "b"], ["c", "d"], ["e", "f"]].pop() == ["e", "f"] + print([["a", "b"], ["c", "d"], ["e", "f"]].pop()) + test_list_pop() \ No newline at end of file diff --git a/tests/reference/asr-func_04-eef2656.json b/tests/reference/asr-func_04-eef2656.json index 6fa82a6009..44e93610b4 100644 --- a/tests/reference/asr-func_04-eef2656.json +++ b/tests/reference/asr-func_04-eef2656.json @@ -5,9 +5,9 @@ "infile_hash": "f8a6eed44ebd1dee435e6db842a874c41b8ba2b13d88d16944a4d265", "outfile": null, "outfile_hash": null, - "stdout": null, - "stdout_hash": null, - "stderr": "asr-func_04-eef2656.stderr", - "stderr_hash": "d1e5bb4b5356e57124ff34eea9e5b96ecc44d3bc8a1da4b0a7db5b4a", - "returncode": 2 + "stdout": "asr-func_04-eef2656.stdout", + "stdout_hash": "c7979254dc7f5a638192ce932c137597f64bb20d490f293201837205", + "stderr": null, + "stderr_hash": null, + "returncode": 0 } \ No newline at end of file diff --git a/tests/reference/asr-func_04-eef2656.stdout b/tests/reference/asr-func_04-eef2656.stdout new file mode 100644 index 0000000000..6059b7dbf2 --- /dev/null +++ b/tests/reference/asr-func_04-eef2656.stdout @@ -0,0 +1,82 @@ +(TranslationUnit + (SymbolTable + 1 + { + __main__: + (Module + (SymbolTable + 2 + { + f: + (Function + (SymbolTable + 3 + { + l: + (Variable + 3 + l + [] + In + () + () + Default + (List + (Integer 4) + ) + () + Source + Public + Required + .false. + ) + }) + f + (FunctionType + [(List + (Integer 4) + )] + () + Source + Implementation + () + .false. + .false. + .false. + .false. + .false. + [] + .false. + ) + [] + [(Var 3 l)] + [(ListAppend + (Var 3 l) + (IntegerConstant 5 (Integer 4)) + )] + () + Public + .false. + .false. + () + ) + }) + __main__ + [] + .false. + .false. + ), + main_program: + (Program + (SymbolTable + 4 + { + + }) + main_program + [] + [] + ) + }) + [] +) From 00b9b19565e6f6dc923554a377d51b2fe1b0210f Mon Sep 17 00:00:00 2001 From: Saurabh Kumar <151380951+kmr-srbh@users.noreply.github.com> Date: Fri, 26 Apr 2024 07:37:34 +0530 Subject: [PATCH 04/10] Be more verbose with handling `nullptr` Co-authored-by: Shaikh Ubaid --- src/lpython/semantics/python_ast_to_asr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 0c89993f49..4d7ec29fd6 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -7600,7 +7600,7 @@ we will have to use something else. } else if (AST::is_a(*at->m_value)) { AST::List_t* clist = AST::down_cast(at->m_value); visit_List(*clist); - if (!tmp) { + 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(tmp); From d2f51d6e771ba07d8c5eb3d415e552b42c230268 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar <151380951+kmr-srbh@users.noreply.github.com> Date: Fri, 26 Apr 2024 20:44:45 +0530 Subject: [PATCH 05/10] Check for no arguments Co-authored-by: Shaikh Ubaid --- src/libasr/pass/intrinsic_functions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libasr/pass/intrinsic_functions.h b/src/libasr/pass/intrinsic_functions.h index 56a71ccc52..707d8ec5df 100644 --- a/src/libasr/pass/intrinsic_functions.h +++ b/src/libasr/pass/intrinsic_functions.h @@ -4673,7 +4673,7 @@ 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& args, diag::Diagnostics& /*diag*/) { - if (args[0] == nullptr) { + if (args.n == 0 || args[0] == nullptr) { return nullptr; } ASR::ListConstant_t* clist = ASR::down_cast(args[0]); From e5153819938d75d85fcd9794f1c4bdc10deffa26 Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Fri, 26 Apr 2024 20:54:23 +0530 Subject: [PATCH 06/10] Simplify compile-time evaluation logic --- src/libasr/pass/intrinsic_functions.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libasr/pass/intrinsic_functions.h b/src/libasr/pass/intrinsic_functions.h index 707d8ec5df..01616a2f5a 100644 --- a/src/libasr/pass/intrinsic_functions.h +++ b/src/libasr/pass/intrinsic_functions.h @@ -4677,14 +4677,17 @@ static inline ASR::expr_t *eval_list_pop(Allocator &/*al*/, return nullptr; } ASR::ListConstant_t* clist = ASR::down_cast(args[0]); + int64_t index; if (args.n == 1) { - return clist->m_args[clist->n_args - 1]; + index = clist->n_args - 1; + return clist->m_args[index]; } else { if (args[1] == nullptr) { return nullptr; } - return clist->m_args[ASR::down_cast(ASRUtils::expr_value(args[1]))->m_n]; + index = ASR::down_cast(ASRUtils::expr_value(args[1]))->m_n; + return clist->m_args[index]; } } From 94062cc007f429af41c4f1b292c396f1f076995c Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Wed, 1 May 2024 08:50:21 +0530 Subject: [PATCH 07/10] Handle modifying attribute on a compile time value --- src/lpython/semantics/python_attribute_eval.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/lpython/semantics/python_attribute_eval.h b/src/lpython/semantics/python_attribute_eval.h index 941d5e4f3f..aa0d37f42d 100644 --- a/src/lpython/semantics/python_attribute_eval.h +++ b/src/lpython/semantics/python_attribute_eval.h @@ -74,13 +74,15 @@ struct AttributeHandler { throw SemanticError("Type name is not implemented yet.", loc); } 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 (modify_attr_set.find(key) != modify_attr_set.end()) { + if (ASR::is_a(*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); if (search != attribute_map.end()) { attribute_eval_callback cb = search->second; From b880171590c893cd7432b37925dab2863e9d4d2a Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Wed, 1 May 2024 08:50:37 +0530 Subject: [PATCH 08/10] Tests: Update references --- tests/reference/asr-func_04-eef2656.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/reference/asr-func_04-eef2656.json b/tests/reference/asr-func_04-eef2656.json index 44e93610b4..6fa82a6009 100644 --- a/tests/reference/asr-func_04-eef2656.json +++ b/tests/reference/asr-func_04-eef2656.json @@ -5,9 +5,9 @@ "infile_hash": "f8a6eed44ebd1dee435e6db842a874c41b8ba2b13d88d16944a4d265", "outfile": null, "outfile_hash": null, - "stdout": "asr-func_04-eef2656.stdout", - "stdout_hash": "c7979254dc7f5a638192ce932c137597f64bb20d490f293201837205", - "stderr": null, - "stderr_hash": null, - "returncode": 0 + "stdout": null, + "stdout_hash": null, + "stderr": "asr-func_04-eef2656.stderr", + "stderr_hash": "d1e5bb4b5356e57124ff34eea9e5b96ecc44d3bc8a1da4b0a7db5b4a", + "returncode": 2 } \ No newline at end of file From a27e46ce7316333134d820f49f4fd1709ce0920e Mon Sep 17 00:00:00 2001 From: Saurabh Kumar Date: Wed, 1 May 2024 16:00:55 +0530 Subject: [PATCH 09/10] Tests: Print before asserts --- integration_tests/test_list_pop.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/integration_tests/test_list_pop.py b/integration_tests/test_list_pop.py index dff3131b2b..da2db3e5fd 100644 --- a/integration_tests/test_list_pop.py +++ b/integration_tests/test_list_pop.py @@ -66,31 +66,31 @@ def test_list_pop(): assert len(l2) == 0 # list.pop on list constant - assert [1, 2, 3, 4, 5].pop() == 5 print([1, 2, 3, 4, 5].pop()) + assert [1, 2, 3, 4, 5].pop() == 5 - assert [1, 2, 3, 4, 5].pop(3) == 4 print([1, 2, 3, 4, 5].pop(3)) + assert [1, 2, 3, 4, 5].pop(3) == 4 index: i32 = 1 - assert [1, 2, 3, 4, 5].pop(index) == 2 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() - assert element_1 == 5 print(element_1) + assert element_1 == 5 element_2: i32 = [1, 2, 3, 4, 5].pop(2) - assert element_2 == 3 print(element_2) + assert element_2 == 3 a: i32 = 5 b: i32 = 3 - assert [(1, 2), (3, 4), (5, 6)].pop(a//b) == (3, 4) print([(1, 2), (3, 4), (5, 6)].pop(a//b)) + assert [(1, 2), (3, 4), (5, 6)].pop(a//b) == (3, 4) - assert [["a", "b"], ["c", "d"], ["e", "f"]].pop() == ["e", "f"] print([["a", "b"], ["c", "d"], ["e", "f"]].pop()) + assert [["a", "b"], ["c", "d"], ["e", "f"]].pop() == ["e", "f"] test_list_pop() \ No newline at end of file From 134f10408a81571024eb48ffbd2ec9408ff21c3a Mon Sep 17 00:00:00 2001 From: Saurabh Kumar <151380951+kmr-srbh@users.noreply.github.com> Date: Wed, 1 May 2024 16:01:27 +0530 Subject: [PATCH 10/10] Delete tests/reference/asr-func_04-eef2656.stdout --- tests/reference/asr-func_04-eef2656.stdout | 82 ---------------------- 1 file changed, 82 deletions(-) delete mode 100644 tests/reference/asr-func_04-eef2656.stdout diff --git a/tests/reference/asr-func_04-eef2656.stdout b/tests/reference/asr-func_04-eef2656.stdout deleted file mode 100644 index 6059b7dbf2..0000000000 --- a/tests/reference/asr-func_04-eef2656.stdout +++ /dev/null @@ -1,82 +0,0 @@ -(TranslationUnit - (SymbolTable - 1 - { - __main__: - (Module - (SymbolTable - 2 - { - f: - (Function - (SymbolTable - 3 - { - l: - (Variable - 3 - l - [] - In - () - () - Default - (List - (Integer 4) - ) - () - Source - Public - Required - .false. - ) - }) - f - (FunctionType - [(List - (Integer 4) - )] - () - Source - Implementation - () - .false. - .false. - .false. - .false. - .false. - [] - .false. - ) - [] - [(Var 3 l)] - [(ListAppend - (Var 3 l) - (IntegerConstant 5 (Integer 4)) - )] - () - Public - .false. - .false. - () - ) - }) - __main__ - [] - .false. - .false. - ), - main_program: - (Program - (SymbolTable - 4 - { - - }) - main_program - [] - [] - ) - }) - [] -)