diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index ddc335f7aa..fb862da002 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -666,6 +666,7 @@ RUN(NAME bindpy_02 LABELS cpython c_py EXTRA_ARGS --link-numpy COPY_TO RUN(NAME bindpy_03 LABELS cpython c_py EXTRA_ARGS --link-numpy NOFAST COPY_TO_BIN bindpy_03_module.py) RUN(NAME bindpy_04 LABELS cpython c_py EXTRA_ARGS --link-numpy NOFAST COPY_TO_BIN bindpy_04_module.py) RUN(NAME bindpy_05 LABELS llvm_py c_py EXTRA_ARGS --enable-cpython COPY_TO_BIN bindpy_05_module.py REQ_PY_VER 3.10) +RUN(NAME bindpy_06 LABELS cpython llvm_py EXTRA_ARGS --enable-cpython NOFAST COPY_TO_BIN bindpy_06_module.py REQ_PY_VER 3.10) RUN(NAME test_generics_01 LABELS cpython llvm llvm_jit c NOFAST) RUN(NAME test_cmath LABELS cpython llvm llvm_jit c NOFAST) RUN(NAME test_complex_01 LABELS cpython llvm llvm_jit c wasm wasm_x64) diff --git a/integration_tests/bindpy_06.py b/integration_tests/bindpy_06.py new file mode 100644 index 0000000000..9b077d2e46 --- /dev/null +++ b/integration_tests/bindpy_06.py @@ -0,0 +1,72 @@ +from lpython import i32, f64, pythoncall, Const +from numpy import empty, int32, float64 + + +@pythoncall(module = "bindpy_06_module") +def get_cpython_version() -> str: + pass + + +@pythoncall(module = "bindpy_06_module") +def get_modified_dict(d: dict[str, i32]) -> dict[str, i32]: + pass + + +@pythoncall(module = "bindpy_06_module") +def get_modified_list(d: list[str]) -> list[str]: + pass + +@pythoncall(module = "bindpy_06_module") +def get_modified_tuple(t: tuple[i32, i32]) -> tuple[i32, i32, i32]: + pass + + +@pythoncall(module = "bindpy_06_module") +def get_modified_set(s: set[i32]) -> set[i32]: + pass + + +def test_list(): + l: list[str] = ["LPython"] + lr: list[str] = get_modified_list(l) + assert len(lr) == 2 + assert lr[0] == "LPython" + assert lr[1] == "LFortran" + + +def test_tuple(): + t: tuple[i32, i32] = (2, 4) + tr: tuple[i32, i32, i32] = get_modified_tuple(t) + assert tr[0] == t[0] + assert tr[1] == t[1] + assert tr[2] == t[0] + t[1] + + +def test_set(): + s: set[i32] = {1, 2, 3} + sr: set[i32] = get_modified_set(s) + assert len(sr) == 4 + assert 1 in sr + assert 2 in sr + assert 3 in sr + assert 100 in sr + + +def test_dict(): + d: dict[str, i32] = { + "LPython": 50 + } + dr: dict[str, i32] = get_modified_dict(d) + assert len(dr) == 2 + assert dr["LPython"] == 50 + assert dr["LFortran"] == 100 + + +def main0(): + test_list() + test_tuple() + test_set() + test_dict() + + +main0() diff --git a/integration_tests/bindpy_06_module.py b/integration_tests/bindpy_06_module.py new file mode 100644 index 0000000000..a22386e1b7 --- /dev/null +++ b/integration_tests/bindpy_06_module.py @@ -0,0 +1,24 @@ +import platform + + +def get_cpython_version(): + return platform.python_version() + + +def get_modified_dict(d): + d["LFortran"] = 100 + return d + + +def get_modified_list(l): + l.append("LFortran") + return l + + +def get_modified_tuple(t): + return (t[0], t[1], t[0] + t[1]) + + +def get_modified_set(s): + s.add(100) + return s diff --git a/src/libasr/pass/python_bind.cpp b/src/libasr/pass/python_bind.cpp index 5a668a739e..598ea3cd1b 100644 --- a/src/libasr/pass/python_bind.cpp +++ b/src/libasr/pass/python_bind.cpp @@ -5,11 +5,18 @@ #include #include #include +#include namespace LCompilers { + +inline int get_random_number() { + static int x = 0; + return x++; +} + ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *type, const ASR::Function_t &f, - SymbolTable &parent_scope) { + Vec &body) { ASR::ttype_t *i1_type = ASRUtils::TYPE(ASR::make_Integer_t(al, f.base.base.loc, 1)); ASR::ttype_t *i1ptr_type = ASRUtils::TYPE(ASR::make_Pointer_t(al, f.base.base.loc, i1_type)); ASR::ttype_t *i4_type = ASRUtils::TYPE(ASR::make_Integer_t(al, f.base.base.loc, 4)); @@ -20,7 +27,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty ASR::expr_t *conv_result = nullptr; if (type->type == ASR::ttypeType::Integer) { - ASR::symbol_t *sym_PyLong_AsLongLong = parent_scope.resolve_symbol("PyLong_AsLongLong"); + ASR::symbol_t *sym_PyLong_AsLongLong = f.m_symtab->resolve_symbol("PyLong_AsLongLong"); Vec args_PyLong_AsLongLong; args_PyLong_AsLongLong.reserve(al, 1); args_PyLong_AsLongLong.push_back(al, {f.base.base.loc, exp}); @@ -30,7 +37,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty i8_type, nullptr, nullptr)), ASR::IntegerToInteger, type, nullptr)); } else if (type->type == ASR::ttypeType::UnsignedInteger) { - ASR::symbol_t *sym_PyLong_AsUnsignedLongLong = parent_scope.resolve_symbol("PyLong_AsUnsignedLongLong"); + ASR::symbol_t *sym_PyLong_AsUnsignedLongLong = f.m_symtab->resolve_symbol("PyLong_AsUnsignedLongLong"); Vec args_PyLong_AsUnsignedLongLong; args_PyLong_AsUnsignedLongLong.reserve(al, 1); args_PyLong_AsUnsignedLongLong.push_back(al, {f.base.base.loc, exp}); @@ -40,7 +47,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty args_PyLong_AsUnsignedLongLong.n, u8_type, nullptr, nullptr)), ASR::UnsignedIntegerToUnsignedInteger, type, nullptr)); } else if (type->type == ASR::ttypeType::Real) { - ASR::symbol_t *sym_PyFloat_AsDouble = parent_scope.resolve_symbol("PyFloat_AsDouble"); + ASR::symbol_t *sym_PyFloat_AsDouble = f.m_symtab->resolve_symbol("PyFloat_AsDouble"); Vec args_PyFloat_AsDouble; args_PyFloat_AsDouble.reserve(al, 1); args_PyFloat_AsDouble.push_back(al, {f.base.base.loc, exp}); @@ -50,7 +57,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty f8_type, nullptr, nullptr)), ASR::RealToReal, type, nullptr)); } else if (type->type == ASR::ttypeType::Logical) { - ASR::symbol_t *sym_PyObject_IsTrue = parent_scope.resolve_symbol("PyObject_IsTrue"); + ASR::symbol_t *sym_PyObject_IsTrue = f.m_symtab->resolve_symbol("PyObject_IsTrue"); Vec args_PyObject_IsTrue; args_PyObject_IsTrue.reserve(al, 1); args_PyObject_IsTrue.push_back(al, {f.base.base.loc, exp}); @@ -60,7 +67,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty i4_type, nullptr, nullptr)), ASR::IntegerToLogical, type, nullptr)); } else if (type->type == ASR::ttypeType::Character) { - ASR::symbol_t *sym_PyUnicode_AsUTF8AndSize = parent_scope.resolve_symbol("PyUnicode_AsUTF8AndSize"); + ASR::symbol_t *sym_PyUnicode_AsUTF8AndSize = f.m_symtab->resolve_symbol("PyUnicode_AsUTF8AndSize"); Vec args_PyUnicode_AsUTF8AndSize; args_PyUnicode_AsUTF8AndSize.reserve(al, 1); args_PyUnicode_AsUTF8AndSize.push_back(al, {f.base.base.loc, exp}); @@ -71,6 +78,335 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty sym_PyUnicode_AsUTF8AndSize, nullptr, args_PyUnicode_AsUTF8AndSize.p, args_PyUnicode_AsUTF8AndSize.n, i1ptr_type, nullptr, nullptr)), ASR::RealToReal, type, nullptr)); + + } else if (type->type == ASR::ttypeType::List) { + ASR::List_t *list = ASR::down_cast(type); + Str s; + + ASR::symbol_t *sym_PyList_Size = f.m_symtab->resolve_symbol("PyList_Size"); + Vec args_PyList_Size; + args_PyList_Size.reserve(al, 1); + args_PyList_Size.push_back(al, {f.base.base.loc, exp}); + std::string p = "_size" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pSize = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, i8_type, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pSize_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pSize))); + f.m_symtab->add_symbol(p, ASR::down_cast(pSize)); + body.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, pSize_ref, + ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, + sym_PyList_Size, nullptr, args_PyList_Size.p, + args_PyList_Size.n, i8_type, nullptr, nullptr)), nullptr))); + + p = "_i" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pI = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, i8_type, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pI_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pI))); + f.m_symtab->add_symbol(p, ASR::down_cast(pI)); + body.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, pI_ref, + ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, f.base.base.loc, 0, i8_type)), nullptr))); + + p = "_result" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pResult = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, type, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pResult_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pResult))); + f.m_symtab->add_symbol(p, ASR::down_cast(pResult)); + body.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, pResult_ref, + ASRUtils::EXPR(ASR::make_ListConstant_t(al, f.base.base.loc, nullptr, 0, type)), nullptr))); + + Vec while_body; + while_body.reserve(al, 2); + + ASR::symbol_t *sym_PyList_GetItem = f.m_symtab->resolve_symbol("PyList_GetItem"); + Vec args_PyList_GetItem; + args_PyList_GetItem.reserve(al, 2); + args_PyList_GetItem.push_back(al, {f.base.base.loc, exp}); + args_PyList_GetItem.push_back(al, {f.base.base.loc, pI_ref}); + + while_body.push_back(al, ASRUtils::STMT(ASR::make_ListAppend_t(al, f.base.base.loc, pResult_ref, + cpython_to_native(al, ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, + sym_PyList_GetItem, nullptr, args_PyList_GetItem.p, + args_PyList_GetItem.n, ptr_t, nullptr, nullptr)), list->m_type, f, while_body) + ))); + + while_body.push_back(al, ASRUtils::STMT( + ASR::make_Assignment_t(al, f.base.base.loc, + pI_ref, + ASRUtils::EXPR(ASR::make_IntegerBinOp_t(al, f.base.base.loc, pI_ref, ASR::binopType::Add, + ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, f.base.base.loc, 1, i8_type)), i8_type, nullptr)), + nullptr))); + + body.push_back(al, ASRUtils::STMT( + ASR::make_WhileLoop_t(al, f.base.base.loc, nullptr, + ASRUtils::EXPR(ASR::make_IntegerCompare_t(al, f.base.base.loc, pI_ref, ASR::cmpopType::Lt, pSize_ref, + i1_type, nullptr)), + while_body.p, while_body.n, nullptr, 0))); + + conv_result = pResult_ref; + + } else if (type->type == ASR::ttypeType::Tuple) { + ASR::Tuple_t *tuple = ASR::down_cast(type); + Str s; + + std::string p = "_result" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pResult = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, type, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pResult_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pResult))); + f.m_symtab->add_symbol(p, ASR::down_cast(pResult)); + + ASR::symbol_t *sym_PyTuple_GetItem = f.m_symtab->resolve_symbol("PyTuple_GetItem"); + Vec tuple_elements; + tuple_elements.reserve(al, tuple->n_type); + for (size_t i = 0; i < tuple->n_type; i++) { + Vec args_PyTuple_GetItem; + args_PyTuple_GetItem.reserve(al, 2); + args_PyTuple_GetItem.push_back(al, {f.base.base.loc, exp}); + args_PyTuple_GetItem.push_back(al, {f.base.base.loc, ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, + f.base.base.loc, i, i8_type))}); + tuple_elements.push_back(al, cpython_to_native(al, ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, + f.base.base.loc, sym_PyTuple_GetItem, nullptr, + args_PyTuple_GetItem.p, args_PyTuple_GetItem.n, + ptr_t, nullptr, nullptr)), + tuple->m_type[i], f, body)); + } + + body.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, pResult_ref, + ASRUtils::EXPR(ASR::make_TupleConstant_t(al, f.base.base.loc, tuple_elements.p, tuple_elements.n, type)), + nullptr))); + conv_result = pResult_ref; + + } else if (type->type == ASR::ttypeType::Set) { + ASR::Set_t *set = ASR::down_cast(type); + Str s; + + std::string p = "_result" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pResult = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, type, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pResult_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pResult))); + f.m_symtab->add_symbol(p, ASR::down_cast(pResult)); + + body.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, pResult_ref, + ASRUtils::EXPR(ASR::make_SetConstant_t(al, f.base.base.loc, nullptr, 0, type)), + nullptr))); + + ASR::symbol_t *sym_PySet_Size = f.m_symtab->resolve_symbol("PySet_Size"); + Vec args_PySet_Size; + args_PySet_Size.reserve(al, 1); + args_PySet_Size.push_back(al, {f.base.base.loc, exp}); + p = "_size" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pSize = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, i8_type, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pSize_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pSize))); + f.m_symtab->add_symbol(p, ASR::down_cast(pSize)); + body.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, pSize_ref, + ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, + sym_PySet_Size, nullptr, args_PySet_Size.p, + args_PySet_Size.n, i8_type, nullptr, nullptr)), nullptr))); + + p = "_i" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pI = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, i8_type, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pI_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pI))); + f.m_symtab->add_symbol(p, ASR::down_cast(pI)); + body.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, pI_ref, + ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, f.base.base.loc, 0, i8_type)), nullptr))); + + p = "_iterator" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pIterator = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, ptr_t, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pIterator_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pIterator))); + f.m_symtab->add_symbol(p, ASR::down_cast(pIterator)); + + ASR::symbol_t *sym_PyObject_GetIter = f.m_symtab->resolve_symbol("PyObject_GetIter"); // TODO: decrement + Vec args_PyObject_GetIter; + args_PyObject_GetIter.reserve(al, 1); + args_PyObject_GetIter.push_back(al, {f.base.base.loc, exp}); + body.push_back(al, + ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, pIterator_ref, + ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyObject_GetIter, nullptr, + args_PyObject_GetIter.p, args_PyObject_GetIter.n, ptr_t, nullptr, nullptr)), nullptr))); + + p = "_i" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pItem = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, ptr_t, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pItem_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pItem))); + f.m_symtab->add_symbol(p, ASR::down_cast(pItem)); + + Vec while_body; + while_body.reserve(al, 3); + + while_body.push_back(al, ASRUtils::STMT( + ASR::make_Assignment_t(al, f.base.base.loc, + pI_ref, + ASRUtils::EXPR(ASR::make_IntegerBinOp_t(al, f.base.base.loc, pI_ref, ASR::binopType::Add, + ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, f.base.base.loc, 1, i8_type)), i8_type, nullptr)), + nullptr))); + + ASR::symbol_t *sym_PyIter_Next = f.m_symtab->resolve_symbol("PyIter_Next"); // TODO: decrement + Vec args_PyIter_Next; + args_PyIter_Next.reserve(al, 1); + args_PyIter_Next.push_back(al, {f.base.base.loc, pIterator_ref}); + + Vec args_Set_add; + args_Set_add.reserve(al, 2); + args_Set_add.push_back(al, pResult_ref); + args_Set_add.push_back(al, cpython_to_native(al, pItem_ref, set->m_type, f, while_body)); + + while_body.push_back(al, + ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, pItem_ref, + ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyIter_Next, nullptr, + args_PyIter_Next.p, args_PyIter_Next.n, ptr_t, nullptr, nullptr)), nullptr))); + + while_body.push_back(al, ASRUtils::STMT(ASR::make_Expr_t(al, f.base.base.loc, + ASRUtils::EXPR(ASR::make_IntrinsicElementalFunction_t(al, f.base.base.loc, + static_cast(ASRUtils::IntrinsicElementalFunctions::SetAdd), + args_Set_add.p, args_Set_add.n, 0, nullptr, nullptr))))); + + body.push_back(al, ASRUtils::STMT(ASR::make_WhileLoop_t(al, f.base.base.loc, nullptr, + ASRUtils::EXPR(ASR::make_IntegerCompare_t(al, f.base.base.loc, pI_ref, ASR::cmpopType::Lt, pSize_ref, + i1_type, nullptr)), + while_body.p, while_body.n, nullptr, 0))); + + conv_result = pResult_ref; + + } else if (type->type == ASR::ttypeType::Dict) { + ASR::Dict_t *dict = ASR::down_cast(type); + Str s; + + std::string p = "_result" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pResult = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, type, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pResult_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pResult))); + f.m_symtab->add_symbol(p, ASR::down_cast(pResult)); + + body.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, pResult_ref, + ASRUtils::EXPR(ASR::make_DictConstant_t(al, f.base.base.loc, nullptr, 0, nullptr, 0, type)), + nullptr))); + + ASR::symbol_t *sym_PyDict_Size = f.m_symtab->resolve_symbol("PyDict_Size"); + Vec args_PyDict_Size; + args_PyDict_Size.reserve(al, 1); + args_PyDict_Size.push_back(al, {f.base.base.loc, exp}); + p = "_size" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pSize = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, i8_type, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pSize_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pSize))); + f.m_symtab->add_symbol(p, ASR::down_cast(pSize)); + body.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, pSize_ref, + ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, + sym_PyDict_Size, nullptr, args_PyDict_Size.p, + args_PyDict_Size.n, i8_type, nullptr, nullptr)), nullptr))); + + p = "_i" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pI = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, i8_type, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pI_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pI))); + f.m_symtab->add_symbol(p, ASR::down_cast(pI)); + body.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, pI_ref, + ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, f.base.base.loc, 0, i8_type)), nullptr))); + + p = "_iterator" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pIterator = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, ptr_t, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pIterator_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pIterator))); + f.m_symtab->add_symbol(p, ASR::down_cast(pIterator)); + + ASR::symbol_t *sym_PyObject_GetIter = f.m_symtab->resolve_symbol("PyObject_GetIter"); // TODO: decrement + Vec args_PyObject_GetIter; + args_PyObject_GetIter.reserve(al, 1); + args_PyObject_GetIter.push_back(al, {f.base.base.loc, exp}); + body.push_back(al, + ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, pIterator_ref, + ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyObject_GetIter, nullptr, + args_PyObject_GetIter.p, args_PyObject_GetIter.n, ptr_t, nullptr, nullptr)), nullptr))); + + p = "_k" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pKey = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, ptr_t, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pKey_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pKey))); + f.m_symtab->add_symbol(p, ASR::down_cast(pKey)); + + Vec while_body; + while_body.reserve(al, 3); + + while_body.push_back(al, ASRUtils::STMT( + ASR::make_Assignment_t(al, f.base.base.loc, + pI_ref, + ASRUtils::EXPR(ASR::make_IntegerBinOp_t(al, f.base.base.loc, pI_ref, ASR::binopType::Add, + ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, f.base.base.loc, 1, i8_type)), i8_type, nullptr)), + nullptr))); + + ASR::symbol_t *sym_PyIter_Next = f.m_symtab->resolve_symbol("PyIter_Next"); // TODO: decrement + Vec args_PyIter_Next; + args_PyIter_Next.reserve(al, 1); + args_PyIter_Next.push_back(al, {f.base.base.loc, pIterator_ref}); + + ASR::symbol_t *sym_PyDict_GetItem = f.m_symtab->resolve_symbol("PyDict_GetItem"); + Vec args_PyDict_GetItem; + args_PyDict_GetItem.reserve(al, 2); + args_PyDict_GetItem.push_back(al, {f.base.base.loc, exp}); + args_PyDict_GetItem.push_back(al, {f.base.base.loc, pKey_ref}); + + while_body.push_back(al, + ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, pKey_ref, + ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyIter_Next, nullptr, + args_PyIter_Next.p, args_PyIter_Next.n, ptr_t, nullptr, nullptr)), nullptr))); + + while_body.push_back(al, ASRUtils::STMT(ASR::make_DictInsert_t(al, f.base.base.loc, pResult_ref, + cpython_to_native(al, pKey_ref, dict->m_key_type, f, while_body), + cpython_to_native(al, ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, + sym_PyDict_GetItem, nullptr, args_PyDict_GetItem.p, args_PyDict_GetItem.n, ptr_t, nullptr, + nullptr)), + dict->m_value_type, f, while_body)))); + + body.push_back(al, ASRUtils::STMT(ASR::make_WhileLoop_t(al, f.base.base.loc, nullptr, + ASRUtils::EXPR(ASR::make_IntegerCompare_t(al, f.base.base.loc, pI_ref, ASR::cmpopType::Lt, pSize_ref, + i1_type, nullptr)), + while_body.p, while_body.n, nullptr, 0))); + + conv_result = pResult_ref; + } else { throw LCompilersException( "Returning from CPython with " + ASRUtils::get_type_code(type) + " type not supported"); @@ -80,8 +416,8 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty return conv_result; } -ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Function_t &f, - SymbolTable &parent_scope) { +ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Function_t &f, Vec &body) { + ASR::ttype_t *i1_type = ASRUtils::TYPE(ASR::make_Logical_t(al, f.base.base.loc, 1)); ASR::ttype_t *i4_type = ASRUtils::TYPE(ASR::make_Integer_t(al, f.base.base.loc, 4)); ASR::ttype_t *i8_type = ASRUtils::TYPE(ASR::make_Integer_t(al, f.base.base.loc, 8)); ASR::ttype_t *u8_type = ASRUtils::TYPE(ASR::make_UnsignedInteger_t(al, f.base.base.loc, 8)); @@ -91,7 +427,7 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct ASR::expr_t *conv_result = nullptr; ASR::ttype_t *type = ASRUtils::expr_type(exp); if (type->type == ASR::ttypeType::Integer) { - ASR::symbol_t *sym_PyLong_FromLongLong = parent_scope.resolve_symbol("PyLong_FromLongLong"); + ASR::symbol_t *sym_PyLong_FromLongLong = f.m_symtab->resolve_symbol("PyLong_FromLongLong"); Vec args_PyLong_FromLongLong; args_PyLong_FromLongLong.reserve(al, 1); args_PyLong_FromLongLong.push_back(al, @@ -101,7 +437,7 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct sym_PyLong_FromLongLong, nullptr, args_PyLong_FromLongLong.p, args_PyLong_FromLongLong.n, ptr_t, nullptr, nullptr)); } else if (type->type == ASR::ttypeType::UnsignedInteger) { - ASR::symbol_t *sym_PyLong_FromUnsignedLongLong = parent_scope.resolve_symbol("PyLong_FromUnsignedLongLong"); + ASR::symbol_t *sym_PyLong_FromUnsignedLongLong = f.m_symtab->resolve_symbol("PyLong_FromUnsignedLongLong"); Vec args_PyLong_FromUnsignedLongLong; args_PyLong_FromUnsignedLongLong.reserve(al, 1); args_PyLong_FromUnsignedLongLong.push_back(al, @@ -111,7 +447,7 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct sym_PyLong_FromUnsignedLongLong, nullptr, args_PyLong_FromUnsignedLongLong.p, args_PyLong_FromUnsignedLongLong.n, ptr_t, nullptr, nullptr)); } else if (type->type == ASR::ttypeType::Logical) { - ASR::symbol_t *sym_PyBool_FromLong = parent_scope.resolve_symbol("PyBool_FromLong"); + ASR::symbol_t *sym_PyBool_FromLong = f.m_symtab->resolve_symbol("PyBool_FromLong"); Vec args_PyBool_FromLong; args_PyBool_FromLong.reserve(al, 1); args_PyBool_FromLong.push_back(al, @@ -120,7 +456,7 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct conv_result = ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyBool_FromLong, nullptr, args_PyBool_FromLong.p, args_PyBool_FromLong.n, ptr_t, nullptr, nullptr)); } else if (type->type == ASR::ttypeType::Real) { - ASR::symbol_t *sym_PyFloat_FromDouble = parent_scope.resolve_symbol("PyFloat_FromDouble"); + ASR::symbol_t *sym_PyFloat_FromDouble = f.m_symtab->resolve_symbol("PyFloat_FromDouble"); Vec args_PyFloat_FromDouble; args_PyFloat_FromDouble.reserve(al, 1); args_PyFloat_FromDouble.push_back(al, @@ -129,13 +465,236 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct conv_result = ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyFloat_FromDouble, nullptr, args_PyFloat_FromDouble.p, args_PyFloat_FromDouble.n, ptr_t, nullptr, nullptr)); } else if (type->type == ASR::ttypeType::Character) { - ASR::symbol_t *sym_PyUnicode_FromString = parent_scope.resolve_symbol("PyUnicode_FromString"); + ASR::symbol_t *sym_PyUnicode_FromString = f.m_symtab->resolve_symbol("PyUnicode_FromString"); Vec args_PyUnicode_FromString; args_PyUnicode_FromString.reserve(al, 1); args_PyUnicode_FromString.push_back(al, {f.base.base.loc, exp}); conv_result = ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyUnicode_FromString, nullptr, args_PyUnicode_FromString.p, args_PyUnicode_FromString.n, ptr_t, nullptr, nullptr)); + } else if (type->type == ASR::ttypeType::Tuple) { + ASR::Tuple_t *tuple = ASR::down_cast(type); + Str s; + + ASR::symbol_t *sym_PyTuple_New = f.m_symtab->resolve_symbol("PyTuple_New"); + Vec args_PyTuple_New; + args_PyTuple_New.reserve(al, 1); + args_PyTuple_New.push_back(al, {f.base.base.loc, ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, f.base.base.loc, + tuple->n_type, i4_type))}); + std::string p = "_" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pArgs = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, ptr_t, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pArgs_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pArgs))); + f.m_symtab->add_symbol(p, ASR::down_cast(pArgs)); + body.push_back(al, ASRUtils::STMT( + ASR::make_Assignment_t(al, f.base.base.loc, pArgs_ref, + ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyTuple_New, nullptr, + args_PyTuple_New.p, args_PyTuple_New.n, ptr_t, nullptr, nullptr)), nullptr))); + conv_result = pArgs_ref; + + ASR::symbol_t *sym_PyTuple_SetItem = f.m_symtab->resolve_symbol("PyTuple_SetItem"); + for (size_t i = 0; i < tuple->n_type; i++) { + Vec args_PyTuple_SetItem; + args_PyTuple_SetItem.reserve(al, 3); + args_PyTuple_SetItem.push_back(al, {f.base.base.loc, pArgs_ref}); + ASR::expr_t *n = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, f.base.base.loc, i, i4_type)); + args_PyTuple_SetItem.push_back(al, {f.base.base.loc, n}); + args_PyTuple_SetItem.push_back(al, {f.base.base.loc, native_to_cpython(al, + ASRUtils::EXPR(ASR::make_TupleItem_t(al, + f.base.base.loc, exp, n, tuple->m_type[i], + nullptr)), + f, body)}); + std::string p = "_" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pA = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, i4_type, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pA_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pA))); + f.m_symtab->add_symbol(p, ASR::down_cast(pA)); + body.push_back(al, + ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, pA_ref, + ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyTuple_SetItem, nullptr, + args_PyTuple_SetItem.p, args_PyTuple_SetItem.n, i4_type, nullptr, nullptr)), nullptr))); + } + } else if (type->type == ASR::ttypeType::List) { + ASR::List_t *list = ASR::down_cast(type); + Str s; + + ASR::symbol_t *sym_PyList_New = f.m_symtab->resolve_symbol("PyList_New"); + Vec args_PyList_New; + args_PyList_New.reserve(al, 1); + args_PyList_New.push_back(al, {f.base.base.loc, ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, f.base.base.loc, + 0, i8_type))}); + std::string p = "_" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pArgs = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, ptr_t, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pArgs_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pArgs))); + f.m_symtab->add_symbol(p, ASR::down_cast(pArgs)); + body.push_back(al, ASRUtils::STMT( + ASR::make_Assignment_t(al, f.base.base.loc, pArgs_ref, + ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyList_New, nullptr, + args_PyList_New.p, args_PyList_New.n, ptr_t, nullptr, nullptr)), nullptr))); + conv_result = pArgs_ref; + + p = "_size" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pSize = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, i4_type, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pSize_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pSize))); + f.m_symtab->add_symbol(p, ASR::down_cast(pSize)); + body.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, pSize_ref, + ASRUtils::EXPR(ASR::make_ListLen_t(al, f.base.base.loc, exp, i4_type, nullptr)), nullptr))); + + p = "_i" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pI = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, i4_type, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pI_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pI))); + f.m_symtab->add_symbol(p, ASR::down_cast(pI)); + body.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, pI_ref, + ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, f.base.base.loc, 0, i4_type)), nullptr))); + + ASR::symbol_t *sym_PyList_Append = f.m_symtab->resolve_symbol("PyList_Append"); + p = "_item" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pItem = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, list->m_type, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pItem_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pItem))); + f.m_symtab->add_symbol(p, ASR::down_cast(pItem)); + + Vec while_body; + while_body.reserve(al, 3); + + while_body.push_back(al, ASRUtils::STMT( + ASR::make_Assignment_t(al, f.base.base.loc, + pItem_ref, + ASRUtils::EXPR(ASR::make_ListItem_t(al, f.base.base.loc, exp, pI_ref, type, nullptr)), + nullptr))); + + while_body.push_back(al, ASRUtils::STMT( + ASR::make_Assignment_t(al, f.base.base.loc, + pI_ref, + ASRUtils::EXPR(ASR::make_IntegerBinOp_t(al, f.base.base.loc, pI_ref, ASR::binopType::Add, + ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, f.base.base.loc, 1, i4_type)), i4_type, nullptr)), + nullptr))); + + Vec args_PyList_Append; + args_PyList_Append.reserve(al, 2); + args_PyList_Append.push_back(al, {f.base.base.loc, pArgs_ref}); + args_PyList_Append.push_back(al, {f.base.base.loc, native_to_cpython(al, pItem_ref, f, while_body)}); // TODO: decrement the reference count of the return value of native_to_cpython after the PyList_Append subroutine call in next line + + while_body.push_back(al, ASRUtils::STMT((ASRUtils::make_SubroutineCall_t_util(al, f.base.base.loc, + sym_PyList_Append, nullptr, args_PyList_Append.p, + args_PyList_Append.n, nullptr, nullptr, false, false)))); + + body.push_back(al, ASRUtils::STMT( + ASR::make_WhileLoop_t(al, f.base.base.loc, nullptr, + ASRUtils::EXPR(ASR::make_IntegerCompare_t(al, f.base.base.loc, pI_ref, ASR::cmpopType::Lt, pSize_ref, + i1_type, nullptr)), + while_body.p, while_body.n, nullptr, 0))); + + } else if (type->type == ASR::ttypeType::Set) { + ASR::Set_t *set = ASR::down_cast(type); + Str s; + + ASR::symbol_t *sym_PySet_New = f.m_symtab->resolve_symbol("PySet_New"); + Vec args_PySet_New; + args_PySet_New.reserve(al, 1); + args_PySet_New.push_back(al, {f.base.base.loc, ASRUtils::EXPR(ASR::make_PointerNullConstant_t(al, + f.base.base.loc, ptr_t))}); + std::string p = "_" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pArgs = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, ptr_t, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pArgs_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pArgs))); + f.m_symtab->add_symbol(p, ASR::down_cast(pArgs)); + body.push_back(al, ASRUtils::STMT( + ASR::make_Assignment_t(al, f.base.base.loc, pArgs_ref, + ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PySet_New, nullptr, + args_PySet_New.p, args_PySet_New.n, ptr_t, nullptr, nullptr)), nullptr))); + conv_result = pArgs_ref; + + p = "_" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pItem = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, set->m_type, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pItem_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pItem))); + f.m_symtab->add_symbol(p, ASR::down_cast(pItem)); + + Vec for_body; + for_body.reserve(al, 1); + ASR::symbol_t *sym_PySet_Add = f.m_symtab->resolve_symbol("PySet_Add"); + Vec args_PySet_Add; + args_PySet_Add.reserve(al, 2); + args_PySet_Add.push_back(al, {f.base.base.loc, pArgs_ref}); + args_PySet_Add.push_back(al, {f.base.base.loc, native_to_cpython(al, pItem_ref, f, for_body)}); // TODO: decrement the reference count of the return value of native_to_cpython after the PyList_Append subroutine call in next line + for_body.push_back(al, ASRUtils::STMT((ASRUtils::make_SubroutineCall_t_util(al, f.base.base.loc, + sym_PySet_Add, nullptr, args_PySet_Add.p, + args_PySet_Add.n, nullptr, nullptr, false, false)))); + + body.push_back(al, ASRUtils::STMT(ASR::make_ForEach_t(al, f.base.base.loc, pItem_ref, exp, for_body.p, for_body.n))); + + } else if (type->type == ASR::ttypeType::Dict) { + ASR::Dict_t *dict = ASR::down_cast(type); + Str s; + + ASR::symbol_t *sym_PyDict_New = f.m_symtab->resolve_symbol("PyDict_New"); // TODO: decrement + std::string p = "_" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pArgs = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, ptr_t, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pArgs_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pArgs))); + f.m_symtab->add_symbol(p, ASR::down_cast(pArgs)); + body.push_back(al, ASRUtils::STMT( + ASR::make_Assignment_t(al, f.base.base.loc, pArgs_ref, + ASRUtils::EXPR(ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_PyDict_New, nullptr, + nullptr, 0, ptr_t, nullptr, nullptr)), nullptr))); + conv_result = pArgs_ref; + + p = "_" + std::to_string(get_random_number()); + s.from_str(al, p); + ASR::asr_t *pItem = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, + ASRUtils::intent_local, nullptr, nullptr, ASR::storage_typeType::Default, dict->m_key_type, + nullptr, ASR::abiType::Source, ASR::Public, ASR::presenceType::Required, false); + ASR::expr_t *pItem_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, + ASR::down_cast(pItem))); + f.m_symtab->add_symbol(p, ASR::down_cast(pItem)); + + Vec for_body; + for_body.reserve(al, 1); + ASR::symbol_t *sym_PyDict_SetItem = f.m_symtab->resolve_symbol("PyDict_SetItem"); + Vec args_PyDict_SetItem; + args_PyDict_SetItem.reserve(al, 3); + args_PyDict_SetItem.push_back(al, {f.base.base.loc, pArgs_ref}); + args_PyDict_SetItem.push_back(al, {f.base.base.loc, native_to_cpython(al, pItem_ref, f, for_body)}); // TODO: decrement the reference count of the return value of native_to_cpython after the PyList_Append subroutine call in next line + args_PyDict_SetItem.push_back(al, {f.base.base.loc, native_to_cpython(al, + ASRUtils::EXPR(ASR::make_DictItem_t(al, f.base.base.loc, exp, pItem_ref, nullptr, dict->m_value_type, nullptr)) + , f, for_body)}); // TODO: decrement the reference count of the return value of native_to_cpython after the PyList_Append subroutine call in next line + for_body.push_back(al, ASRUtils::STMT((ASRUtils::make_SubroutineCall_t_util(al, f.base.base.loc, + sym_PyDict_SetItem, nullptr, args_PyDict_SetItem.p, + args_PyDict_SetItem.n, nullptr, nullptr, false, false)))); + + body.push_back(al, ASRUtils::STMT(ASR::make_ForEach_t(al, f.base.base.loc, pItem_ref, exp, for_body.p, for_body.n))); + } else { throw LCompilersException( "Calling CPython with " + ASRUtils::get_type_code(ASRUtils::expr_type(exp)) + " type not supported"); @@ -145,7 +704,7 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct return conv_result; } -void generate_body(Allocator &al, ASR::Function_t &f, SymbolTable &parent_scope) { +void generate_body(Allocator &al, ASR::Function_t &f) { Vec body; body.reserve(al, 1); Str s; @@ -160,8 +719,8 @@ void generate_body(Allocator &al, ASR::Function_t &f, SymbolTable &parent_scope) ASR::ttype_t *i4_type = ASRUtils::TYPE(ASR::make_Integer_t(al, f.base.base.loc, 4)); ASR::ttype_t *ptr_t = ASRUtils::TYPE(ASR::make_CPtr_t(al, f.base.base.loc)); - ASR::symbol_t *sym_Py_IsInitialized = parent_scope.resolve_symbol("Py_IsInitialized"); - ASR::symbol_t *sym_Py_Initialize = parent_scope.resolve_symbol("Py_Initialize"); + ASR::symbol_t *sym_Py_IsInitialized = f.m_symtab->resolve_symbol("Py_IsInitialized"); + ASR::symbol_t *sym_Py_Initialize = f.m_symtab->resolve_symbol("Py_Initialize"); LCOMPILERS_ASSERT(sym_Py_IsInitialized) ASR::asr_t *call_Py_IsInitialized = ASRUtils::make_FunctionCall_t_util(al, f.base.base.loc, sym_Py_IsInitialized, nullptr, nullptr, 0, i4_type, nullptr, nullptr); @@ -174,7 +733,7 @@ void generate_body(Allocator &al, ASR::Function_t &f, SymbolTable &parent_scope) nullptr, nullptr, 0, nullptr, nullptr, false, false); if_body.push_back(al, ASRUtils::STMT(call_Py_Initialize)); - ASR::symbol_t *sym_Py_DecodeLocale = parent_scope.resolve_symbol("Py_DecodeLocale"); + ASR::symbol_t *sym_Py_DecodeLocale = f.m_symtab->resolve_symbol("Py_DecodeLocale"); Vec args_Py_DecodeLocale; s.from_str(al, ""); args_Py_DecodeLocale.reserve(al, 1); @@ -195,7 +754,7 @@ void generate_body(Allocator &al, ASR::Function_t &f, SymbolTable &parent_scope) args_Py_DecodeLocale.p, args_Py_DecodeLocale.n, ptr_t, nullptr, nullptr)), nullptr))); - ASR::symbol_t *sym_PySys_SetArgv = parent_scope.resolve_symbol("PySys_SetArgv"); + ASR::symbol_t *sym_PySys_SetArgv = f.m_symtab->resolve_symbol("PySys_SetArgv"); Vec args_PySys_SetArgv; s.from_str(al, ""); args_PySys_SetArgv.reserve(al, 1); @@ -216,7 +775,7 @@ void generate_body(Allocator &al, ASR::Function_t &f, SymbolTable &parent_scope) void *pFunc = PyObject_GetAttrString(pModule, func_name); */ - ASR::symbol_t *sym_PyUnicode_FromString = parent_scope.resolve_symbol("PyUnicode_FromString"); + ASR::symbol_t *sym_PyUnicode_FromString = f.m_symtab->resolve_symbol("PyUnicode_FromString"); Vec args_PyUnicode_FromString; s.from_str(al, f.m_module_file); args_PyUnicode_FromString.reserve(al, 1); @@ -235,7 +794,7 @@ void generate_body(Allocator &al, ASR::Function_t &f, SymbolTable &parent_scope) args_PyUnicode_FromString.p, args_PyUnicode_FromString.n, ptr_t, nullptr, nullptr)), nullptr))); - ASR::symbol_t *sym_PyImport_Import = parent_scope.resolve_symbol("PyImport_Import"); + ASR::symbol_t *sym_PyImport_Import = f.m_symtab->resolve_symbol("PyImport_Import"); Vec args_PyImport_Import; args_PyImport_Import.reserve(al, 1); args_PyImport_Import.push_back(al, {f.base.base.loc, pName_ref}); @@ -252,7 +811,7 @@ void generate_body(Allocator &al, ASR::Function_t &f, SymbolTable &parent_scope) args_PyImport_Import.p, args_PyImport_Import.n, ptr_t, nullptr, nullptr)), nullptr))); - ASR::symbol_t *sym_PyObject_GetAttrString = parent_scope.resolve_symbol("PyObject_GetAttrString"); + ASR::symbol_t *sym_PyObject_GetAttrString = f.m_symtab->resolve_symbol("PyObject_GetAttrString"); Vec args_PyObject_GetAttrString; s.from_str(al, f.m_module_file); args_PyObject_GetAttrString.reserve(al, 2); @@ -274,7 +833,7 @@ void generate_body(Allocator &al, ASR::Function_t &f, SymbolTable &parent_scope) nullptr)), nullptr))); // creating CPython tuple for arguments list - ASR::symbol_t *sym_PyTuple_New = parent_scope.resolve_symbol("PyTuple_New"); + ASR::symbol_t *sym_PyTuple_New = f.m_symtab->resolve_symbol("PyTuple_New"); Vec args_PyTuple_New; args_PyTuple_New.reserve(al, 1); args_PyTuple_New.push_back(al, {f.base.base.loc, ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, f.base.base.loc, @@ -291,14 +850,14 @@ void generate_body(Allocator &al, ASR::Function_t &f, SymbolTable &parent_scope) args_PyTuple_New.p, args_PyTuple_New.n, ptr_t, nullptr, nullptr)), nullptr))); // Converting arguments to CPython types - ASR::symbol_t *sym_PyTuple_SetItem = parent_scope.resolve_symbol("PyTuple_SetItem"); + ASR::symbol_t *sym_PyTuple_SetItem = f.m_symtab->resolve_symbol("PyTuple_SetItem"); for (size_t i = 0; i < f.n_args; i++) { Vec args_PyTuple_SetItem; args_PyTuple_SetItem.reserve(al, 3); args_PyTuple_SetItem.push_back(al, {f.base.base.loc, pArgs_ref}); args_PyTuple_SetItem.push_back(al, {f.base.base.loc, ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, f.base.base.loc, i, i4_type))}); - args_PyTuple_SetItem.push_back(al, {f.base.base.loc, native_to_cpython(al, f.m_args[i], f, parent_scope)}); + args_PyTuple_SetItem.push_back(al, {f.base.base.loc, native_to_cpython(al, f.m_args[i], f, body)}); std::string p = "pA" + std::to_string(i); s.from_str(al, p); ASR::asr_t *pA = ASR::make_Variable_t(al, f.base.base.loc, f.m_symtab, s.c_str(al), nullptr, 0, @@ -313,7 +872,7 @@ void generate_body(Allocator &al, ASR::Function_t &f, SymbolTable &parent_scope) } // calling CPython Function - ASR::symbol_t *sym_PyObject_CallObject = parent_scope.resolve_symbol("PyObject_CallObject"); + ASR::symbol_t *sym_PyObject_CallObject = f.m_symtab->resolve_symbol("PyObject_CallObject"); Vec args_PyObject_CallObject; args_PyObject_CallObject.reserve(al, 2); args_PyObject_CallObject.push_back(al, {f.base.base.loc, pFunc_ref}); @@ -339,7 +898,7 @@ void generate_body(Allocator &al, ASR::Function_t &f, SymbolTable &parent_scope) LCOMPILERS_ASSERT(ret_var); ASR::expr_t *ret_var_ref = ASRUtils::EXPR(ASR::make_Var_t(al, f.base.base.loc, ASR::down_cast(ret_var))); - ASR::expr_t *ret_conv_result = cpython_to_native(al, pReturn_ref, ret_type, f, parent_scope); + ASR::expr_t *ret_conv_result = cpython_to_native(al, pReturn_ref, ret_type, f, body); body.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, ret_var_ref, ret_conv_result, nullptr))); } @@ -349,7 +908,7 @@ void generate_body(Allocator &al, ASR::Function_t &f, SymbolTable &parent_scope) Py_DecRef(pArgs); Py_DecRef(pReturn); */ - ASR::symbol_t *sym_Py_DecRef = parent_scope.resolve_symbol("Py_DecRef"); + ASR::symbol_t *sym_Py_DecRef = f.m_symtab->resolve_symbol("Py_DecRef"); Vec args_Py_DecRef; args_Py_DecRef.reserve(al, 1); @@ -407,6 +966,7 @@ void pass_python_bind(Allocator &al, ASR::TranslationUnit_t &unit, const PassOpt fns.push_back({"PyObject_GetAttrString", {ASRUtils::PTR, ASRUtils::STR}, ASRUtils::PTR}); fns.push_back({"PyTuple_New", {ASRUtils::I32}, ASRUtils::PTR}); fns.push_back({"PyTuple_SetItem", {ASRUtils::PTR, ASRUtils::I32, ASRUtils::PTR}, ASRUtils::I32}); + fns.push_back({"PyTuple_GetItem", {ASRUtils::PTR, ASRUtils::I64}, ASRUtils::PTR}); fns.push_back({"PyObject_CallObject", {ASRUtils::PTR, ASRUtils::PTR}, ASRUtils::PTR}); fns.push_back({"PyLong_AsLongLong", {ASRUtils::PTR}, ASRUtils::I64}); fns.push_back({"PyLong_AsUnsignedLongLong", {ASRUtils::PTR}, ASRUtils::U64}); @@ -416,6 +976,19 @@ void pass_python_bind(Allocator &al, ASR::TranslationUnit_t &unit, const PassOpt fns.push_back({"PyFloat_AsDouble", {ASRUtils::PTR}, ASRUtils::F64}); fns.push_back({"PyBool_FromLong", {ASRUtils::I32}, ASRUtils::PTR}); fns.push_back({"PyObject_IsTrue", {ASRUtils::PTR}, ASRUtils::I32}); + fns.push_back({"PyList_New", {ASRUtils::I64}, ASRUtils::PTR}); + fns.push_back({"PyList_Append", {ASRUtils::PTR, ASRUtils::PTR}, ASRUtils::I32}); + fns.push_back({"PyList_GetItem", {ASRUtils::PTR, ASRUtils::I64}, ASRUtils::PTR}); + fns.push_back({"PyList_Size", {ASRUtils::PTR}, ASRUtils::I64}); + fns.push_back({"PySet_New", {ASRUtils::PTR}, ASRUtils::PTR}); + fns.push_back({"PySet_Add", {ASRUtils::PTR, ASRUtils::PTR}, ASRUtils::PTR}); + fns.push_back({"PySet_Size", {ASRUtils::PTR}, ASRUtils::I64}); + fns.push_back({"PyDict_New", {}, ASRUtils::PTR}); + fns.push_back({"PyDict_SetItem", {ASRUtils::PTR, ASRUtils::PTR, ASRUtils::PTR}, ASRUtils::I32}); + fns.push_back({"PyDict_GetItem", {ASRUtils::PTR, ASRUtils::PTR}, ASRUtils::PTR}); + fns.push_back({"PyDict_Size", {ASRUtils::PTR}, ASRUtils::I64}); + fns.push_back({"PyObject_GetIter", {ASRUtils::PTR}, ASRUtils::PTR}); + fns.push_back({"PyIter_Next", {ASRUtils::PTR}, ASRUtils::PTR}); Location *l = al.make_new(); l->first = 0; @@ -428,7 +1001,7 @@ void pass_python_bind(Allocator &al, ASR::TranslationUnit_t &unit, const PassOpt ASR::Function_t *f = ASR::down_cast(item.second); if (ASRUtils::get_FunctionType(f)->m_abi == ASR::abiType::BindPython) { if (f->n_body == 0 && f->m_module_file) { - generate_body(al, *f, *unit.m_symtab); + generate_body(al, *f); } } } @@ -439,7 +1012,7 @@ void pass_python_bind(Allocator &al, ASR::TranslationUnit_t &unit, const PassOpt ASR::Function_t *f = ASR::down_cast(module_item.second); if (ASRUtils::get_FunctionType(f)->m_abi == ASR::abiType::BindPython) { if (f->n_body == 0 && f->m_module_file) { - generate_body(al, *f, *module->m_symtab); + generate_body(al, *f); } } }