From a649c9a62408f63ca16e897bcc9c690af317a0ad Mon Sep 17 00:00:00 2001 From: kabra1110 Date: Mon, 31 Jul 2023 10:17:16 +0530 Subject: [PATCH 1/3] add list reserve --- integration_tests/CMakeLists.txt | 1 + integration_tests/test_list_reserve.py | 30 +++++++++++ src/libasr/codegen/asr_to_llvm.cpp | 18 +++++++ src/libasr/codegen/llvm_utils.cpp | 27 ++++++++++ src/libasr/codegen/llvm_utils.h | 3 ++ src/libasr/pass/intrinsic_function_registry.h | 53 +++++++++++++++++++ src/lpython/semantics/python_attribute_eval.h | 18 ++++++- 7 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 integration_tests/test_list_reserve.py diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index aac3e60aed..4cddefd933 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -517,6 +517,7 @@ RUN(NAME test_list_pop2 LABELS cpython llvm NOFAST) # TODO: Remove NOFAST RUN(NAME test_list_pop3 LABELS cpython llvm) RUN(NAME test_list_compare LABELS cpython llvm) RUN(NAME test_list_concat LABELS cpython llvm c NOFAST) +RUN(NAME test_list_reserve LABELS cpython llvm) RUN(NAME test_tuple_01 LABELS cpython llvm c) RUN(NAME test_tuple_02 LABELS cpython llvm c NOFAST) RUN(NAME test_tuple_03 LABELS cpython llvm c) diff --git a/integration_tests/test_list_reserve.py b/integration_tests/test_list_reserve.py new file mode 100644 index 0000000000..9cbfafa3ab --- /dev/null +++ b/integration_tests/test_list_reserve.py @@ -0,0 +1,30 @@ +from lpython import i32, f64 + +def test_list_reserve(): + l1: list[i32] = [] + l2: list[list[tuple[f64, str, tuple[i32, f64]]]] = [] + i: i32 + + l1.reserve(100) + for i in range(50): + l1.append(i) + assert len(l1) == i + 1 + + l1.reserve(150) + + for i in range(50): + l1.pop(0) + assert len(l1) == 49 - i + + l2.reserve(100) + for i in range(50): + l2.append([(f64(i * i), str(i), (i, f64(i + 1))), (f64(i), str(i), (i, f64(i)))]) + assert len(l2) == i + 1 + + l2.reserve(150) + + for i in range(50): + l2.pop(0) + assert len(l2) == 49 - i + +test_list_reserve() diff --git a/src/libasr/codegen/asr_to_llvm.cpp b/src/libasr/codegen/asr_to_llvm.cpp index 17a6705dde..e8b8e77813 100644 --- a/src/libasr/codegen/asr_to_llvm.cpp +++ b/src/libasr/codegen/asr_to_llvm.cpp @@ -1680,6 +1680,20 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor tmp = list_api->pop_position(plist, pos, asr_el_type, module.get(), name2memidx); } + void generate_ListReserve(ASR::expr_t* m_arg, ASR::expr_t* m_ele) { + ASR::ttype_t* asr_el_type = ASRUtils::get_contained_type(ASRUtils::expr_type(m_arg)); + int64_t ptr_loads_copy = ptr_loads; + ptr_loads = 0; + this->visit_expr(*m_arg); + llvm::Value* plist = tmp; + + ptr_loads = 2; + this->visit_expr_wrapper(m_ele, true); + ptr_loads = ptr_loads_copy; + llvm::Value* n = tmp; + list_api->reserve(plist, n, asr_el_type, module.get()); + } + void generate_DictElems(ASR::expr_t* m_arg, bool key_or_value) { ASR::Dict_t* dict_type = ASR::down_cast( ASRUtils::expr_type(m_arg)); @@ -1794,6 +1808,10 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } break; } + case ASRUtils::IntrinsicFunctions::ListReserve: { + generate_ListReserve(x.m_args[0], x.m_args[1]); + break; + } case ASRUtils::IntrinsicFunctions::DictKeys: { generate_DictElems(x.m_args[0], 0); break; diff --git a/src/libasr/codegen/llvm_utils.cpp b/src/libasr/codegen/llvm_utils.cpp index 076f9594c7..14e5c41d56 100644 --- a/src/libasr/codegen/llvm_utils.cpp +++ b/src/libasr/codegen/llvm_utils.cpp @@ -4105,6 +4105,33 @@ namespace LCompilers { shift_end_point_by_one(list); } + void LLVMList::reserve(llvm::Value* list, llvm::Value* n, + ASR::ttype_t* asr_type, llvm::Module* module) { + /** + * C++ equivalent + * + * if( n > current_capacity ) { + * list_data = realloc(list_data, sizeof(el_type) * n); + * } + * + */ + llvm::Value* capacity = LLVM::CreateLoad(*builder, get_pointer_to_current_capacity(list)); + std::string type_code = ASRUtils::get_type_code(asr_type); + int type_size = std::get<1>(typecode2listtype[type_code]); + llvm::Type* el_type = std::get<2>(typecode2listtype[type_code]); + llvm_utils->create_if_else(builder->CreateICmpSGT(n, capacity), [&]() { + llvm::Value* arg_size = builder->CreateMul(llvm::ConstantInt::get(context, + llvm::APInt(32, type_size)), n); + llvm::Value* copy_data_ptr = get_pointer_to_list_data(list); + llvm::Value* copy_data = LLVM::CreateLoad(*builder, copy_data_ptr); + copy_data = LLVM::lfortran_realloc(context, *module, *builder, + copy_data, arg_size); + copy_data = builder->CreateBitCast(copy_data, el_type->getPointerTo()); + builder->CreateStore(copy_data, copy_data_ptr); + builder->CreateStore(n, get_pointer_to_current_capacity(list)); + }, []() {}); + } + void LLVMList::reverse(llvm::Value* list, llvm::Module& module) { /* Equivalent in C++: diff --git a/src/libasr/codegen/llvm_utils.h b/src/libasr/codegen/llvm_utils.h index 866cd05b68..147872f62c 100644 --- a/src/libasr/codegen/llvm_utils.h +++ b/src/libasr/codegen/llvm_utils.h @@ -403,6 +403,9 @@ namespace LCompilers { llvm::Module* module, std::map>& name2memidx); + void reserve(llvm::Value* list, llvm::Value* n, + ASR::ttype_t* asr_type, llvm::Module* module); + void remove(llvm::Value* list, llvm::Value* item, ASR::ttype_t* item_type, llvm::Module& module); diff --git a/src/libasr/pass/intrinsic_function_registry.h b/src/libasr/pass/intrinsic_function_registry.h index 4d6b2b1691..d708a0a771 100644 --- a/src/libasr/pass/intrinsic_function_registry.h +++ b/src/libasr/pass/intrinsic_function_registry.h @@ -46,6 +46,7 @@ enum class IntrinsicFunctions : int64_t { Partition, ListReverse, ListPop, + ListReserve, DictKeys, DictValues, SetAdd, @@ -102,6 +103,7 @@ inline std::string get_intrinsic_name(int x) { INTRINSIC_NAME_CASE(Partition) INTRINSIC_NAME_CASE(ListReverse) INTRINSIC_NAME_CASE(ListPop) + INTRINSIC_NAME_CASE(ListReserve) INTRINSIC_NAME_CASE(DictKeys) INTRINSIC_NAME_CASE(DictValues) INTRINSIC_NAME_CASE(SetAdd) @@ -1262,6 +1264,52 @@ static inline ASR::asr_t* create_ListPop(Allocator& al, const Location& loc, } // namespace ListPop +namespace ListReserve { + +static inline void verify_args(const ASR::IntrinsicFunction_t& x, diag::Diagnostics& diagnostics) { + ASRUtils::require_impl(x.n_args == 2, "Call to list.reserve must have exactly one argument", + x.base.base.loc, diagnostics); + ASRUtils::require_impl(ASR::is_a(*ASRUtils::expr_type(x.m_args[0])), + "Argument to list.reserve must be of list type", + x.base.base.loc, diagnostics); + ASRUtils::require_impl(ASR::is_a(*ASRUtils::expr_type(x.m_args[1])), + "Argument to list.reserve must be an integer", + x.base.base.loc, diagnostics); + ASRUtils::require_impl(x.m_type == nullptr, + "Return type of list.reserve must be empty", + x.base.base.loc, diagnostics); +} + +static inline ASR::expr_t *eval_list_reserve(Allocator &/*al*/, + const Location &/*loc*/, Vec& /*args*/) { + // TODO: To be implemented for ListConstant expression + return nullptr; +} + +static inline ASR::asr_t* create_ListReserve(Allocator& al, const Location& loc, + Vec& args, + const std::function err) { + if (args.size() != 2) { + err("Call to list.reserve must have exactly one argument", loc); + } + if (!ASR::is_a(*ASRUtils::expr_type(args[1]))) { + err("Argument to list.reserve must be an integer", loc); + } + + Vec arg_values; + arg_values.reserve(al, args.size()); + for( size_t i = 0; i < args.size(); i++ ) { + arg_values.push_back(al, ASRUtils::expr_value(args[i])); + } + ASR::expr_t* compile_time_value = eval_list_reserve(al, loc, arg_values); + return ASR::make_Expr_t(al, loc, + ASRUtils::EXPR(ASRUtils::make_IntrinsicFunction_t_util(al, loc, + static_cast(ASRUtils::IntrinsicFunctions::ListReserve), + args.p, args.size(), 0, nullptr, compile_time_value))); +} + +} // namespace ListReserve + namespace DictKeys { static inline void verify_args(const ASR::IntrinsicFunction_t& x, diag::Diagnostics& diagnostics) { @@ -3124,6 +3172,8 @@ namespace IntrinsicFunctionRegistry { {nullptr, &DictValues::verify_args}}, {static_cast(ASRUtils::IntrinsicFunctions::ListPop), {nullptr, &ListPop::verify_args}}, + {static_cast(ASRUtils::IntrinsicFunctions::ListReserve), + {nullptr, &ListReserve::verify_args}}, {static_cast(ASRUtils::IntrinsicFunctions::SetAdd), {nullptr, &SetAdd::verify_args}}, {static_cast(ASRUtils::IntrinsicFunctions::SetRemove), @@ -3206,6 +3256,8 @@ namespace IntrinsicFunctionRegistry { "list.reverse"}, {static_cast(ASRUtils::IntrinsicFunctions::ListPop), "list.pop"}, + {static_cast(ASRUtils::IntrinsicFunctions::ListReserve), + "list.reserve"}, {static_cast(ASRUtils::IntrinsicFunctions::DictKeys), "dict.keys"}, {static_cast(ASRUtils::IntrinsicFunctions::DictValues), @@ -3290,6 +3342,7 @@ namespace IntrinsicFunctionRegistry { {"list.index", {&ListIndex::create_ListIndex, &ListIndex::eval_list_index}}, {"list.reverse", {&ListReverse::create_ListReverse, &ListReverse::eval_list_reverse}}, {"list.pop", {&ListPop::create_ListPop, &ListPop::eval_list_pop}}, + {"list.reserve", {&ListReserve::create_ListReserve, &ListReserve::eval_list_reserve}}, {"dict.keys", {&DictKeys::create_DictKeys, &DictKeys::eval_dict_keys}}, {"dict.values", {&DictValues::create_DictValues, &DictValues::eval_dict_values}}, {"set.add", {&SetAdd::create_SetAdd, &SetAdd::eval_set_add}}, diff --git a/src/lpython/semantics/python_attribute_eval.h b/src/lpython/semantics/python_attribute_eval.h index 6355db3b5f..a048e53d1e 100644 --- a/src/lpython/semantics/python_attribute_eval.h +++ b/src/lpython/semantics/python_attribute_eval.h @@ -30,6 +30,7 @@ struct AttributeHandler { {"list@pop", &eval_list_pop}, {"list@clear", &eval_list_clear}, {"list@insert", &eval_list_insert}, + {"list@reserve", &eval_list_reserve}, {"set@pop", &eval_set_pop}, {"set@add", &eval_set_add}, {"set@remove", &eval_set_remove}, @@ -41,7 +42,8 @@ struct AttributeHandler { modify_attr_set = {"list@append", "list@remove", "list@reverse", "list@clear", "list@insert", "list@pop", - "set@pop", "set@add", "set@remove", "dict@pop"}; + "list@reserve", "set@pop", "set@add", "set@remove", + "dict@pop"}; symbolic_attribute_map = { {"diff", &eval_symbolic_diff}, @@ -284,6 +286,20 @@ struct AttributeHandler { return make_ListClear_t(al, loc, s); } + static ASR::asr_t* eval_list_reserve(ASR::expr_t *s, Allocator &al, const Location &loc, + Vec &args, diag::Diagnostics &/*diag*/) { + Vec args_with_list; + args_with_list.reserve(al, args.size() + 1); + args_with_list.push_back(al, s); + for(size_t i = 0; i < args.size(); i++) { + args_with_list.push_back(al, args[i]); + } + ASRUtils::create_intrinsic_function create_function = + ASRUtils::IntrinsicFunctionRegistry::get_create_function("list.reserve"); + return create_function(al, loc, args_with_list, [&](const std::string &msg, const Location &loc) + { throw SemanticError(msg, loc); }); + } + static ASR::asr_t* eval_set_pop(ASR::expr_t *s, Allocator &al, const Location &loc, Vec &args, diag::Diagnostics &/*diag*/) { if (args.size() != 0) { From 196151b872c3883447657905f3dfb17da44ef0cd Mon Sep 17 00:00:00 2001 From: kabra1110 Date: Tue, 1 Aug 2023 09:17:10 +0530 Subject: [PATCH 2/3] list.reserve to reserve --- integration_tests/test_list_reserve.py | 10 ++--- src/libasr/codegen/asr_to_llvm.cpp | 7 ++-- src/libasr/pass/intrinsic_function_registry.h | 41 ++++++++++--------- src/lpython/semantics/python_attribute_eval.h | 18 +------- src/runtime/lpython/lpython.py | 5 +++ 5 files changed, 37 insertions(+), 44 deletions(-) diff --git a/integration_tests/test_list_reserve.py b/integration_tests/test_list_reserve.py index 9cbfafa3ab..9c074c351d 100644 --- a/integration_tests/test_list_reserve.py +++ b/integration_tests/test_list_reserve.py @@ -1,27 +1,27 @@ -from lpython import i32, f64 +from lpython import i32, f64, reserve def test_list_reserve(): l1: list[i32] = [] l2: list[list[tuple[f64, str, tuple[i32, f64]]]] = [] i: i32 - l1.reserve(100) + reserve(l1, 100) for i in range(50): l1.append(i) assert len(l1) == i + 1 - l1.reserve(150) + reserve(l1, 150) for i in range(50): l1.pop(0) assert len(l1) == 49 - i - l2.reserve(100) + reserve(l2, 100) for i in range(50): l2.append([(f64(i * i), str(i), (i, f64(i + 1))), (f64(i), str(i), (i, f64(i)))]) assert len(l2) == i + 1 - l2.reserve(150) + reserve(l2, 150) for i in range(50): l2.pop(0) diff --git a/src/libasr/codegen/asr_to_llvm.cpp b/src/libasr/codegen/asr_to_llvm.cpp index e8b8e77813..76c8579b3a 100644 --- a/src/libasr/codegen/asr_to_llvm.cpp +++ b/src/libasr/codegen/asr_to_llvm.cpp @@ -1680,7 +1680,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor tmp = list_api->pop_position(plist, pos, asr_el_type, module.get(), name2memidx); } - void generate_ListReserve(ASR::expr_t* m_arg, ASR::expr_t* m_ele) { + void generate_Reserve(ASR::expr_t* m_arg, ASR::expr_t* m_ele) { + // For now, this only handles lists ASR::ttype_t* asr_el_type = ASRUtils::get_contained_type(ASRUtils::expr_type(m_arg)); int64_t ptr_loads_copy = ptr_loads; ptr_loads = 0; @@ -1808,8 +1809,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor } break; } - case ASRUtils::IntrinsicFunctions::ListReserve: { - generate_ListReserve(x.m_args[0], x.m_args[1]); + case ASRUtils::IntrinsicFunctions::Reserve: { + generate_Reserve(x.m_args[0], x.m_args[1]); break; } case ASRUtils::IntrinsicFunctions::DictKeys: { diff --git a/src/libasr/pass/intrinsic_function_registry.h b/src/libasr/pass/intrinsic_function_registry.h index d708a0a771..d8fe1d173f 100644 --- a/src/libasr/pass/intrinsic_function_registry.h +++ b/src/libasr/pass/intrinsic_function_registry.h @@ -46,7 +46,7 @@ enum class IntrinsicFunctions : int64_t { Partition, ListReverse, ListPop, - ListReserve, + Reserve, DictKeys, DictValues, SetAdd, @@ -103,7 +103,7 @@ inline std::string get_intrinsic_name(int x) { INTRINSIC_NAME_CASE(Partition) INTRINSIC_NAME_CASE(ListReverse) INTRINSIC_NAME_CASE(ListPop) - INTRINSIC_NAME_CASE(ListReserve) + INTRINSIC_NAME_CASE(Reserve) INTRINSIC_NAME_CASE(DictKeys) INTRINSIC_NAME_CASE(DictValues) INTRINSIC_NAME_CASE(SetAdd) @@ -1264,36 +1264,39 @@ static inline ASR::asr_t* create_ListPop(Allocator& al, const Location& loc, } // namespace ListPop -namespace ListReserve { +namespace Reserve { static inline void verify_args(const ASR::IntrinsicFunction_t& x, diag::Diagnostics& diagnostics) { - ASRUtils::require_impl(x.n_args == 2, "Call to list.reserve must have exactly one argument", + ASRUtils::require_impl(x.n_args == 2, "Call to reserve must have exactly one argument", x.base.base.loc, diagnostics); ASRUtils::require_impl(ASR::is_a(*ASRUtils::expr_type(x.m_args[0])), - "Argument to list.reserve must be of list type", + "First argument to reserve must be of list type", x.base.base.loc, diagnostics); ASRUtils::require_impl(ASR::is_a(*ASRUtils::expr_type(x.m_args[1])), - "Argument to list.reserve must be an integer", + "Second argument to reserve must be an integer", x.base.base.loc, diagnostics); ASRUtils::require_impl(x.m_type == nullptr, - "Return type of list.reserve must be empty", + "Return type of reserve must be empty", x.base.base.loc, diagnostics); } -static inline ASR::expr_t *eval_list_reserve(Allocator &/*al*/, +static inline ASR::expr_t *eval_reserve(Allocator &/*al*/, const Location &/*loc*/, Vec& /*args*/) { // TODO: To be implemented for ListConstant expression return nullptr; } -static inline ASR::asr_t* create_ListReserve(Allocator& al, const Location& loc, +static inline ASR::asr_t* create_Reserve(Allocator& al, const Location& loc, Vec& args, const std::function err) { if (args.size() != 2) { - err("Call to list.reserve must have exactly one argument", loc); + err("Call to reserve must have exactly two argument", loc); + } + if (!ASR::is_a(*ASRUtils::expr_type(args[0]))) { + err("First argument to reserve must be of list type", loc); } if (!ASR::is_a(*ASRUtils::expr_type(args[1]))) { - err("Argument to list.reserve must be an integer", loc); + err("Second argument to reserve must be an integer", loc); } Vec arg_values; @@ -1301,14 +1304,14 @@ static inline ASR::asr_t* create_ListReserve(Allocator& al, const Location& loc, for( size_t i = 0; i < args.size(); i++ ) { arg_values.push_back(al, ASRUtils::expr_value(args[i])); } - ASR::expr_t* compile_time_value = eval_list_reserve(al, loc, arg_values); + ASR::expr_t* compile_time_value = eval_reserve(al, loc, arg_values); return ASR::make_Expr_t(al, loc, ASRUtils::EXPR(ASRUtils::make_IntrinsicFunction_t_util(al, loc, - static_cast(ASRUtils::IntrinsicFunctions::ListReserve), + static_cast(ASRUtils::IntrinsicFunctions::Reserve), args.p, args.size(), 0, nullptr, compile_time_value))); } -} // namespace ListReserve +} // namespace Reserve namespace DictKeys { @@ -3172,8 +3175,8 @@ namespace IntrinsicFunctionRegistry { {nullptr, &DictValues::verify_args}}, {static_cast(ASRUtils::IntrinsicFunctions::ListPop), {nullptr, &ListPop::verify_args}}, - {static_cast(ASRUtils::IntrinsicFunctions::ListReserve), - {nullptr, &ListReserve::verify_args}}, + {static_cast(ASRUtils::IntrinsicFunctions::Reserve), + {nullptr, &Reserve::verify_args}}, {static_cast(ASRUtils::IntrinsicFunctions::SetAdd), {nullptr, &SetAdd::verify_args}}, {static_cast(ASRUtils::IntrinsicFunctions::SetRemove), @@ -3256,8 +3259,8 @@ namespace IntrinsicFunctionRegistry { "list.reverse"}, {static_cast(ASRUtils::IntrinsicFunctions::ListPop), "list.pop"}, - {static_cast(ASRUtils::IntrinsicFunctions::ListReserve), - "list.reserve"}, + {static_cast(ASRUtils::IntrinsicFunctions::Reserve), + "reserve"}, {static_cast(ASRUtils::IntrinsicFunctions::DictKeys), "dict.keys"}, {static_cast(ASRUtils::IntrinsicFunctions::DictValues), @@ -3342,7 +3345,7 @@ namespace IntrinsicFunctionRegistry { {"list.index", {&ListIndex::create_ListIndex, &ListIndex::eval_list_index}}, {"list.reverse", {&ListReverse::create_ListReverse, &ListReverse::eval_list_reverse}}, {"list.pop", {&ListPop::create_ListPop, &ListPop::eval_list_pop}}, - {"list.reserve", {&ListReserve::create_ListReserve, &ListReserve::eval_list_reserve}}, + {"reserve", {&Reserve::create_Reserve, &Reserve::eval_reserve}}, {"dict.keys", {&DictKeys::create_DictKeys, &DictKeys::eval_dict_keys}}, {"dict.values", {&DictValues::create_DictValues, &DictValues::eval_dict_values}}, {"set.add", {&SetAdd::create_SetAdd, &SetAdd::eval_set_add}}, diff --git a/src/lpython/semantics/python_attribute_eval.h b/src/lpython/semantics/python_attribute_eval.h index a048e53d1e..6355db3b5f 100644 --- a/src/lpython/semantics/python_attribute_eval.h +++ b/src/lpython/semantics/python_attribute_eval.h @@ -30,7 +30,6 @@ struct AttributeHandler { {"list@pop", &eval_list_pop}, {"list@clear", &eval_list_clear}, {"list@insert", &eval_list_insert}, - {"list@reserve", &eval_list_reserve}, {"set@pop", &eval_set_pop}, {"set@add", &eval_set_add}, {"set@remove", &eval_set_remove}, @@ -42,8 +41,7 @@ struct AttributeHandler { modify_attr_set = {"list@append", "list@remove", "list@reverse", "list@clear", "list@insert", "list@pop", - "list@reserve", "set@pop", "set@add", "set@remove", - "dict@pop"}; + "set@pop", "set@add", "set@remove", "dict@pop"}; symbolic_attribute_map = { {"diff", &eval_symbolic_diff}, @@ -286,20 +284,6 @@ struct AttributeHandler { return make_ListClear_t(al, loc, s); } - static ASR::asr_t* eval_list_reserve(ASR::expr_t *s, Allocator &al, const Location &loc, - Vec &args, diag::Diagnostics &/*diag*/) { - Vec args_with_list; - args_with_list.reserve(al, args.size() + 1); - args_with_list.push_back(al, s); - for(size_t i = 0; i < args.size(); i++) { - args_with_list.push_back(al, args[i]); - } - ASRUtils::create_intrinsic_function create_function = - ASRUtils::IntrinsicFunctionRegistry::get_create_function("list.reserve"); - return create_function(al, loc, args_with_list, [&](const std::string &msg, const Location &loc) - { throw SemanticError(msg, loc); }); - } - static ASR::asr_t* eval_set_pop(ASR::expr_t *s, Allocator &al, const Location &loc, Vec &args, diag::Diagnostics &/*diag*/) { if (args.size() != 0) { diff --git a/src/runtime/lpython/lpython.py b/src/runtime/lpython/lpython.py index 63bcc98c19..3ac9811c8c 100644 --- a/src/runtime/lpython/lpython.py +++ b/src/runtime/lpython/lpython.py @@ -760,6 +760,11 @@ def __lpython(*args, **kwargs): def bitnot(x, bitsize): return (~x) % (2 ** bitsize) +def reserve(data_structure, n): + if isinstance(data_structure, list): + data_structure = [None] * n + # no-op + bitnot_u8 = lambda x: bitnot(x, 8) bitnot_u16 = lambda x: bitnot(x, 16) bitnot_u32 = lambda x: bitnot(x, 32) From 415a3d3ed4bcb9cadc052ca20002e28aa24f49d3 Mon Sep 17 00:00:00 2001 From: Gagandeep Singh Date: Tue, 1 Aug 2023 22:04:30 +0530 Subject: [PATCH 3/3] Add reserve in AST->ASR --- src/lpython/semantics/python_ast_to_asr.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 987900e57d..7004177bf1 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -6510,6 +6510,9 @@ class BodyVisitor : public CommonVisitor { // Keyword arguments to be handled in make_call_helper args.reserve(al, c->n_args); visit_expr_list(c->m_args, c->n_args, args); + // TODO: Avoid overriding of user defined functions with same name as + // intrinsics like print, quit and reserve. Right now, user defined + // functions will never be considered. if (call_name == "print") { ASR::expr_t *fmt = nullptr; Vec args_expr = ASRUtils::call_arg2expr(al, args); @@ -6569,6 +6572,17 @@ class BodyVisitor : public CommonVisitor { } tmp = ASR::make_Stop_t(al, x.base.base.loc, code); return; + } else if( call_name == "reserve" ) { + ASRUtils::create_intrinsic_function create_func = + ASRUtils::IntrinsicFunctionRegistry::get_create_function("reserve"); + Vec args_exprs; args_exprs.reserve(al, args.size()); + for( size_t i = 0; i < args.size(); i++ ) { + args_exprs.push_back(al, args[i].m_value); + } + tmp = create_func(al, x.base.base.loc, args_exprs, + [&](const std::string &msg, const Location &loc) { + throw SemanticError(msg, loc); }); + return ; } ASR::symbol_t *s = current_scope->resolve_symbol(call_name); if (!s) {