From 9d881a615db09bf99c7227444ae088dccf2cb02c Mon Sep 17 00:00:00 2001 From: Vipul Cariappa Date: Fri, 16 Aug 2024 12:43:14 +0530 Subject: [PATCH 01/10] native to cpython tuple conversion and refactoring --- src/libasr/pass/python_bind.cpp | 112 +++++++++++++++++++++++--------- 1 file changed, 82 insertions(+), 30 deletions(-) diff --git a/src/libasr/pass/python_bind.cpp b/src/libasr/pass/python_bind.cpp index 5a668a739e..037a202b38 100644 --- a/src/libasr/pass/python_bind.cpp +++ b/src/libasr/pass/python_bind.cpp @@ -8,8 +8,13 @@ namespace LCompilers { -ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *type, const ASR::Function_t &f, - SymbolTable &parent_scope) { + +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) { 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 +25,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 +35,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 +45,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 +55,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 +65,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}); @@ -80,8 +85,7 @@ 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 *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 +95,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 +105,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 +115,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 +124,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 +133,61 @@ 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); + LCOMPILERS_ASSERT(tuple) + + 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 { throw LCompilersException( "Calling CPython with " + ASRUtils::get_type_code(ASRUtils::expr_type(exp)) + " type not supported"); @@ -145,7 +197,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 +212,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 +226,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 +247,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 +268,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 +287,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 +304,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 +326,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 +343,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 +365,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 +391,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.push_back(al, ASRUtils::STMT(ASR::make_Assignment_t(al, f.base.base.loc, ret_var_ref, ret_conv_result, nullptr))); } @@ -349,7 +401,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); @@ -428,7 +480,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 +491,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); } } } From 2b3bd2d61d45e4bd78b86de615f5a8b545cedeb5 Mon Sep 17 00:00:00 2001 From: Vipul Cariappa Date: Fri, 16 Aug 2024 15:29:35 +0530 Subject: [PATCH 02/10] PythonBind ABI: native to cpython list conversion --- src/libasr/pass/python_bind.cpp | 105 +++++++++++++++++++++++++++++--- 1 file changed, 97 insertions(+), 8 deletions(-) diff --git a/src/libasr/pass/python_bind.cpp b/src/libasr/pass/python_bind.cpp index 037a202b38..f51a21b903 100644 --- a/src/libasr/pass/python_bind.cpp +++ b/src/libasr/pass/python_bind.cpp @@ -86,6 +86,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty } 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)); @@ -142,8 +143,6 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct ptr_t, nullptr, nullptr)); } else if (type->type == ASR::ttypeType::Tuple) { ASR::Tuple_t *tuple = ASR::down_cast(type); - LCOMPILERS_ASSERT(tuple) - Str s; ASR::symbol_t *sym_PyTuple_New = f.m_symtab->resolve_symbol("PyTuple_New"); @@ -154,9 +153,10 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct 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))); + 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, @@ -179,15 +179,102 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct 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))); + 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)}); + + 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 { throw LCompilersException( "Calling CPython with " + ASRUtils::get_type_code(ASRUtils::expr_type(exp)) + " type not supported"); @@ -468,6 +555,8 @@ 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}); Location *l = al.make_new(); l->first = 0; From 45a774aa7c0e48a99fe9064d19c82137d665e52f Mon Sep 17 00:00:00 2001 From: Vipul Cariappa Date: Fri, 16 Aug 2024 17:56:44 +0530 Subject: [PATCH 03/10] PythonBind ABI: native to cpython set conversion Backend does not support yet. --- src/libasr/pass/python_bind.cpp | 49 ++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/src/libasr/pass/python_bind.cpp b/src/libasr/pass/python_bind.cpp index f51a21b903..33e2f0e20e 100644 --- a/src/libasr/pass/python_bind.cpp +++ b/src/libasr/pass/python_bind.cpp @@ -263,7 +263,7 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct 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)}); + 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, @@ -275,6 +275,51 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct 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 { throw LCompilersException( "Calling CPython with " + ASRUtils::get_type_code(ASRUtils::expr_type(exp)) + " type not supported"); @@ -557,6 +602,8 @@ void pass_python_bind(Allocator &al, ASR::TranslationUnit_t &unit, const PassOpt 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({"PySet_New", {ASRUtils::PTR}, ASRUtils::PTR}); + fns.push_back({"PySet_Add", {ASRUtils::PTR, ASRUtils::PTR}, ASRUtils::PTR}); Location *l = al.make_new(); l->first = 0; From 4a9771947b52279e137b83f09492ce3df143c70b Mon Sep 17 00:00:00 2001 From: Vipul Cariappa Date: Sun, 18 Aug 2024 08:21:30 +0530 Subject: [PATCH 04/10] PythonBind ABI: native to cpython dict conversion --- src/libasr/pass/python_bind.cpp | 46 +++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/libasr/pass/python_bind.cpp b/src/libasr/pass/python_bind.cpp index 33e2f0e20e..0a3f082b1c 100644 --- a/src/libasr/pass/python_bind.cpp +++ b/src/libasr/pass/python_bind.cpp @@ -319,6 +319,50 @@ ASR::expr_t *native_to_cpython(Allocator &al, ASR::expr_t *exp, const ASR::Funct 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( @@ -604,6 +648,8 @@ void pass_python_bind(Allocator &al, ASR::TranslationUnit_t &unit, const PassOpt fns.push_back({"PyList_Append", {ASRUtils::PTR, ASRUtils::PTR}, ASRUtils::I32}); fns.push_back({"PySet_New", {ASRUtils::PTR}, ASRUtils::PTR}); fns.push_back({"PySet_Add", {ASRUtils::PTR, ASRUtils::PTR}, ASRUtils::PTR}); + fns.push_back({"PyDict_New", {}, ASRUtils::PTR}); + fns.push_back({"PyDict_SetItem", {ASRUtils::PTR, ASRUtils::PTR, ASRUtils::PTR}, ASRUtils::I32}); Location *l = al.make_new(); l->first = 0; From fe46c5e7e213ba1a0f844eac3e41d90eadf45edd Mon Sep 17 00:00:00 2001 From: Vipul Cariappa Date: Sun, 18 Aug 2024 08:48:43 +0530 Subject: [PATCH 05/10] PythonBind ABI: cpython to native list conversion --- src/libasr/pass/python_bind.cpp | 82 ++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 2 deletions(-) diff --git a/src/libasr/pass/python_bind.cpp b/src/libasr/pass/python_bind.cpp index 0a3f082b1c..7db2361e58 100644 --- a/src/libasr/pass/python_bind.cpp +++ b/src/libasr/pass/python_bind.cpp @@ -14,7 +14,8 @@ inline int get_random_number() { return x++; } -ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *type, const ASR::Function_t &f) { +ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *type, const ASR::Function_t &f, + 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)); @@ -76,6 +77,81 @@ 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, 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 { throw LCompilersException( "Returning from CPython with " + ASRUtils::get_type_code(type) + " type not supported"); @@ -567,7 +643,7 @@ void generate_body(Allocator &al, ASR::Function_t &f) { 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); + 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))); } @@ -646,6 +722,8 @@ void pass_python_bind(Allocator &al, ASR::TranslationUnit_t &unit, const PassOpt 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({"PyDict_New", {}, ASRUtils::PTR}); From 4a95a97b25cec09ee859ccf30dc095b00319d8f8 Mon Sep 17 00:00:00 2001 From: Vipul Cariappa Date: Sun, 18 Aug 2024 09:27:53 +0530 Subject: [PATCH 06/10] PythonBind ABI: cpython to native tuple conversion --- src/libasr/pass/python_bind.cpp | 36 ++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/libasr/pass/python_bind.cpp b/src/libasr/pass/python_bind.cpp index 7db2361e58..292682288c 100644 --- a/src/libasr/pass/python_bind.cpp +++ b/src/libasr/pass/python_bind.cpp @@ -120,7 +120,6 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty 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); @@ -152,6 +151,40 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty 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 { throw LCompilersException( "Returning from CPython with " + ASRUtils::get_type_code(type) + " type not supported"); @@ -711,6 +744,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}); From 7c98f660a6180a41d5ebab543e3cf524bf3be869 Mon Sep 17 00:00:00 2001 From: Vipul Cariappa Date: Sun, 18 Aug 2024 11:37:16 +0530 Subject: [PATCH 07/10] PythonBind ABI: cpython to native set conversion --- src/libasr/pass/python_bind.cpp | 120 +++++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 1 deletion(-) diff --git a/src/libasr/pass/python_bind.cpp b/src/libasr/pass/python_bind.cpp index 292682288c..5f6f13c347 100644 --- a/src/libasr/pass/python_bind.cpp +++ b/src/libasr/pass/python_bind.cpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace LCompilers { @@ -133,7 +134,7 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty 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, body) + args_PyList_GetItem.n, ptr_t, nullptr, nullptr)), list->m_type, f, while_body) ))); while_body.push_back(al, ASRUtils::STMT( @@ -185,6 +186,120 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty 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}); + + 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))); + + 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_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))))); + + 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))); + + 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"); @@ -760,8 +875,11 @@ void pass_python_bind(Allocator &al, ASR::TranslationUnit_t &unit, const PassOpt 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({"PyObject_GetIter", {ASRUtils::PTR}, ASRUtils::PTR}); + fns.push_back({"PyIter_Next", {ASRUtils::PTR}, ASRUtils::PTR}); Location *l = al.make_new(); l->first = 0; From b6cbaa0f2f326bc30baf9d87204e8c8028397f0b Mon Sep 17 00:00:00 2001 From: Vipul Cariappa Date: Sun, 18 Aug 2024 12:38:25 +0530 Subject: [PATCH 08/10] PythonBind ABI: cpython to native dict conversion --- src/libasr/pass/python_bind.cpp | 121 ++++++++++++++++++++++++++++++-- 1 file changed, 115 insertions(+), 6 deletions(-) diff --git a/src/libasr/pass/python_bind.cpp b/src/libasr/pass/python_bind.cpp index 5f6f13c347..598ea3cd1b 100644 --- a/src/libasr/pass/python_bind.cpp +++ b/src/libasr/pass/python_bind.cpp @@ -273,26 +273,133 @@ ASR::expr_t *cpython_to_native(Allocator &al, ASR::expr_t *exp, ASR::ttype_t *ty args_PyIter_Next.reserve(al, 1); args_PyIter_Next.push_back(al, {f.base.base.loc, pIterator_ref}); - 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))); - 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, pItem_ref, + 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)), @@ -878,6 +985,8 @@ void pass_python_bind(Allocator &al, ASR::TranslationUnit_t &unit, const PassOpt 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}); From 4f6714fece5d8349cc80b277417c09954ce5259c Mon Sep 17 00:00:00 2001 From: Vipul Cariappa Date: Sun, 18 Aug 2024 12:51:27 +0530 Subject: [PATCH 09/10] PythonBind ABI: testing aggregate type conversions --- integration_tests/CMakeLists.txt | 1 + integration_tests/bindpy_06.py | 72 +++++++++++++++++++++++++++ integration_tests/bindpy_06_module.py | 24 +++++++++ 3 files changed, 97 insertions(+) create mode 100644 integration_tests/bindpy_06.py create mode 100644 integration_tests/bindpy_06_module.py diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index ddc335f7aa..bc645b3749 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 llvm_py EXTRA_ARGS --enable-cpython 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 From ca09e530d33d4566ef1945ecd46e0b6918d4fdb5 Mon Sep 17 00:00:00 2001 From: Vipul Cariappa Date: Sun, 18 Aug 2024 14:40:40 +0530 Subject: [PATCH 10/10] NOFAST for bindpy_06 test --- integration_tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index bc645b3749..fb862da002 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -666,7 +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 llvm_py EXTRA_ARGS --enable-cpython COPY_TO_BIN bindpy_06_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)