From 0ad7de64dfc837d7c4a2cdf32db2becb1bf0f71f Mon Sep 17 00:00:00 2001 From: Thirumalai-Shaktivel <thirumalaishaktivel@gmail.com> Date: Tue, 18 Oct 2022 12:24:10 +0530 Subject: [PATCH 1/5] Add an option `-I` to get import source path --- src/bin/lpython.cpp | 42 ++++++++++++++------- src/libasr/utils.h | 1 + src/lpython/semantics/python_ast_to_asr.cpp | 32 ++++++++++------ src/lpython/semantics/python_ast_to_asr.h | 3 +- 4 files changed, 51 insertions(+), 27 deletions(-) diff --git a/src/bin/lpython.cpp b/src/bin/lpython.cpp index a61d846cbc..8c10368cd8 100644 --- a/src/bin/lpython.cpp +++ b/src/bin/lpython.cpp @@ -164,7 +164,8 @@ int emit_asr(const std::string &infile, diagnostics.diagnostics.clear(); LFortran::Result<LFortran::ASR::TranslationUnit_t*> r = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, true, - compiler_options.disable_main, compiler_options.symtab_only, infile); + compiler_options.disable_main, compiler_options.symtab_only, infile, + compiler_options.import_path); std::cerr << diagnostics.render(input, lm, compiler_options); if (!r.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) @@ -207,7 +208,8 @@ int emit_cpp(const std::string &infile, diagnostics.diagnostics.clear(); LFortran::Result<LFortran::ASR::TranslationUnit_t*> r1 = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, true, - compiler_options.disable_main, compiler_options.symtab_only, infile); + compiler_options.disable_main, compiler_options.symtab_only, infile, + compiler_options.import_path); std::cerr << diagnostics.render(input, lm, compiler_options); if (!r1.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) @@ -248,7 +250,8 @@ int emit_c(const std::string &infile, diagnostics.diagnostics.clear(); LFortran::Result<LFortran::ASR::TranslationUnit_t*> r1 = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, true, - compiler_options.disable_main, compiler_options.symtab_only, infile); + compiler_options.disable_main, compiler_options.symtab_only, infile, + compiler_options.import_path); std::cerr << diagnostics.render(input, lm, compiler_options); if (!r1.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) @@ -289,7 +292,8 @@ int emit_wat(const std::string &infile, diagnostics.diagnostics.clear(); LFortran::Result<LFortran::ASR::TranslationUnit_t*> r1 = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, true, - compiler_options.disable_main, compiler_options.symtab_only, infile); + compiler_options.disable_main, compiler_options.symtab_only, infile, + compiler_options.import_path); std::cerr << diagnostics.render(input, lm, compiler_options); if (!r1.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) @@ -333,7 +337,8 @@ int get_symbols (const std::string &infile, LFortran::LPython::AST::ast_t* ast = r1.result; LFortran::Result<LFortran::ASR::TranslationUnit_t*> x = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, true, - compiler_options.disable_main, compiler_options.symtab_only, infile); + compiler_options.disable_main, compiler_options.symtab_only, + infile, compiler_options.import_path); if (!x.ok) { std::cout << "{}\n"; return 0; @@ -426,7 +431,8 @@ int get_errors (const std::string &infile, LFortran::LPython::AST::ast_t* ast = r1.result; LFortran::Result<LFortran::ASR::TranslationUnit_t*> r = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, true, - compiler_options.disable_main, compiler_options.symtab_only, infile); + compiler_options.disable_main, compiler_options.symtab_only, + infile, compiler_options.import_path); } std::vector<LFortran::LPython::error_highlight> diag_lists; LFortran::LPython::error_highlight h; @@ -538,7 +544,8 @@ int emit_llvm(const std::string &infile, diagnostics.diagnostics.clear(); LFortran::Result<LFortran::ASR::TranslationUnit_t*> r1 = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, true, - compiler_options.disable_main, compiler_options.symtab_only, infile); + compiler_options.disable_main, compiler_options.symtab_only, infile, + compiler_options.import_path); std::cerr << diagnostics.render(input, lm, compiler_options); if (!r1.ok) { LFORTRAN_ASSERT(diagnostics.has_error()) @@ -596,7 +603,8 @@ int compile_python_to_object_file( LFortran::Result<LFortran::ASR::TranslationUnit_t*> r1 = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, !(arg_c && compiler_options.disable_main), - compiler_options.disable_main, compiler_options.symtab_only, infile); + compiler_options.disable_main, compiler_options.symtab_only, infile, + compiler_options.import_path); auto ast_to_asr_end = std::chrono::high_resolution_clock::now(); times.push_back(std::make_pair("AST to ASR", std::chrono::duration<double, std::milli>(ast_to_asr_end - ast_to_asr_start).count())); std::cerr << diagnostics.render(input, lm, compiler_options); @@ -679,7 +687,8 @@ int compile_to_binary_wasm( auto ast_to_asr_start = std::chrono::high_resolution_clock::now(); LFortran::Result<LFortran::ASR::TranslationUnit_t*> r1 = LFortran::LPython::python_ast_to_asr(al, *ast, diagnostics, true, - compiler_options.disable_main, compiler_options.symtab_only, infile); + compiler_options.disable_main, compiler_options.symtab_only, infile, + compiler_options.import_path); auto ast_to_asr_end = std::chrono::high_resolution_clock::now(); times.push_back(std::make_pair("AST to ASR", std::chrono::duration<double, std::milli>(ast_to_asr_end - ast_to_asr_start).count())); std::cerr << diagnostics.render(input, lm, compiler_options); @@ -927,7 +936,8 @@ EMSCRIPTEN_KEEPALIVE char* emit_asr_from_source(char *input) { auto casted_ast = (LFortran::LPython::AST::ast_t*)ast.result; LFortran::Result<LFortran::ASR::TranslationUnit_t*> asr = LFortran::LPython::python_ast_to_asr(al, *casted_ast, diagnostics, true, - compiler_options.disable_main, compiler_options.symtab_only, "input"); + compiler_options.disable_main, compiler_options.symtab_only, "input", + compiler_options.import_path); out = diagnostics.render(input, lm, compiler_options); if (asr.ok) { out += LFortran::pickle(*asr.result, compiler_options.use_colors, compiler_options.indent, @@ -946,7 +956,8 @@ EMSCRIPTEN_KEEPALIVE char* emit_wat_from_source(char *input) { auto casted_ast = (LFortran::LPython::AST::ast_t*)ast.result; LFortran::Result<LFortran::ASR::TranslationUnit_t*> asr = LFortran::LPython::python_ast_to_asr(al, *casted_ast, diagnostics, true, - compiler_options.disable_main, compiler_options.symtab_only, "input"); + compiler_options.disable_main, compiler_options.symtab_only, "input", + compiler_options.import_path); out = diagnostics.render(input, lm, compiler_options); if (asr.ok) { LFortran::Result<LFortran::Vec<uint8_t>> @@ -974,7 +985,8 @@ EMSCRIPTEN_KEEPALIVE char* emit_cpp_from_source(char *input) { auto casted_ast = (LFortran::LPython::AST::ast_t*)ast.result; LFortran::Result<LFortran::ASR::TranslationUnit_t*> asr = LFortran::LPython::python_ast_to_asr(al, *casted_ast, diagnostics, true, - compiler_options.disable_main, compiler_options.symtab_only, "input"); + compiler_options.disable_main, compiler_options.symtab_only, "input", + compiler_options.import_path); out = diagnostics.render(input, lm, compiler_options); if (asr.ok) { auto res = LFortran::asr_to_cpp(al, *asr.result, diagnostics, @@ -1013,7 +1025,8 @@ EMSCRIPTEN_KEEPALIVE char* emit_wasm_from_source(char *input) { auto casted_ast = (LFortran::LPython::AST::ast_t*)ast.result; LFortran::Result<LFortran::ASR::TranslationUnit_t*> asr = LFortran::LPython::python_ast_to_asr(al, *casted_ast, diagnostics, true, - compiler_options.disable_main, compiler_options.symtab_only, "input"); + compiler_options.disable_main, compiler_options.symtab_only, "input", + compiler_options.import_path); out = diagnostics.render(input, lm, compiler_options); if (asr.ok) { LFortran::Result<LFortran::Vec<uint8_t>> @@ -1114,7 +1127,8 @@ int main(int argc, char *argv[]) // app.add_flag("-E", arg_E, "Preprocess only; do not compile, assemble or link"); // app.add_option("-l", arg_l, "Link library option"); // app.add_option("-L", arg_L, "Library path option"); - // app.add_option("-I", arg_I, "Include path")->allow_extra_args(false); + app.add_option("-I", compiler_options.import_path, "Specify the path" + "to look for the module")->allow_extra_args(false); // app.add_option("-J", arg_J, "Where to save mod files"); // app.add_flag("-g", arg_g, "Compile with debugging information"); // app.add_option("-D", compiler_options.c_preprocessor_defines, "Define <macro>=<value> (or 1 if <value> omitted)")->allow_extra_args(false); diff --git a/src/libasr/utils.h b/src/libasr/utils.h index cacfb62c10..4e8d4751f3 100644 --- a/src/libasr/utils.h +++ b/src/libasr/utils.h @@ -37,6 +37,7 @@ struct CompilerOptions { bool implicit_typing = false; bool implicit_interface = false; std::string target = ""; + std::string import_path = ""; Platform platform; CompilerOptions () : platform{get_platform()} {}; diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index b0c09beeec..c9bb780b87 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -246,7 +246,7 @@ ASR::TranslationUnit_t* compile_module_till_asr(Allocator& al, LFortran::LocationManager lm; lm.in_filename = infile; Result<ASR::TranslationUnit_t*> r2 = python_ast_to_asr(al, *ast, - diagnostics, false, true, false, infile); + diagnostics, false, true, false, infile, ""); // TODO: Uncomment once a check is added for ensuring // that module.py file hasn't changed between // builds. @@ -324,7 +324,8 @@ ASR::Module_t* load_module(Allocator &al, SymbolTable *symtab, return nullptr; } if (!found) { - err("Could not find the module '" + infile0 + "'", loc); + err("Could not find the module '" + infile0 + "'. If an import path " + "is available, please use the `-I` option to specify it", loc); } if (ltypes) return nullptr; @@ -467,6 +468,7 @@ class CommonVisitor : public AST::BaseVisitor<Struct> { IntrinsicNodeHandler intrinsic_node_handler; std::map<int, ASR::symbol_t*> &ast_overload; std::string parent_dir; + std::string import_path; Vec<ASR::stmt_t*> *current_body; ASR::ttype_t* ann_assign_target_type; @@ -477,9 +479,10 @@ class CommonVisitor : public AST::BaseVisitor<Struct> { CommonVisitor(Allocator &al, SymbolTable *symbol_table, diag::Diagnostics &diagnostics, bool main_module, - std::map<int, ASR::symbol_t*> &ast_overload, std::string parent_dir) + std::map<int, ASR::symbol_t*> &ast_overload, std::string parent_dir, + std::string import_path) : diag{diagnostics}, al{al}, current_scope{symbol_table}, main_module{main_module}, - ast_overload{ast_overload}, parent_dir{parent_dir}, + ast_overload{ast_overload}, parent_dir{parent_dir}, import_path{import_path}, current_body{nullptr}, ann_assign_target_type{nullptr} { current_module_dependencies.reserve(al, 4); } @@ -2865,8 +2868,10 @@ class SymbolTableVisitor : public CommonVisitor<SymbolTableVisitor> { SymbolTableVisitor(Allocator &al, SymbolTable *symbol_table, diag::Diagnostics &diagnostics, bool main_module, - std::map<int, ASR::symbol_t*> &ast_overload, std::string parent_dir) - : CommonVisitor(al, symbol_table, diagnostics, main_module, ast_overload, parent_dir), is_derived_type{false} {} + std::map<int, ASR::symbol_t*> &ast_overload, std::string parent_dir, + std::string import_path) + : CommonVisitor(al, symbol_table, diagnostics, main_module, ast_overload, + parent_dir, import_path), is_derived_type{false} {} ASR::symbol_t* resolve_symbol(const Location &loc, const std::string &sub_name) { @@ -3298,9 +3303,11 @@ class SymbolTableVisitor : public CommonVisitor<SymbolTableVisitor> { Result<ASR::asr_t*> symbol_table_visitor(Allocator &al, const AST::Module_t &ast, diag::Diagnostics &diagnostics, bool main_module, - std::map<int, ASR::symbol_t*> &ast_overload, std::string parent_dir) + std::map<int, ASR::symbol_t*> &ast_overload, std::string parent_dir, + std::string import_path) { - SymbolTableVisitor v(al, nullptr, diagnostics, main_module, ast_overload, parent_dir); + SymbolTableVisitor v(al, nullptr, diagnostics, main_module, ast_overload, + parent_dir, import_path); try { v.visit_Module(ast); } catch (const SemanticError &e) { @@ -3326,8 +3333,8 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> { BodyVisitor(Allocator &al, ASR::asr_t *unit, diag::Diagnostics &diagnostics, bool main_module, std::map<int, ASR::symbol_t*> &ast_overload) - : CommonVisitor(al, nullptr, diagnostics, main_module, ast_overload, ""), asr{unit}, - gotoids{0} + : CommonVisitor(al, nullptr, diagnostics, main_module, ast_overload, "", ""), + asr{unit}, gotoids{0} {} // Transforms statements to a list of ASR statements @@ -5441,7 +5448,8 @@ std::string get_parent_dir(const std::string &path) { Result<ASR::TranslationUnit_t*> python_ast_to_asr(Allocator &al, AST::ast_t &ast, diag::Diagnostics &diagnostics, bool main_module, - bool disable_main, bool symtab_only, std::string file_path) + bool disable_main, bool symtab_only, std::string file_path, + std::string import_path) { std::map<int, ASR::symbol_t*> ast_overload; std::string parent_dir = get_parent_dir(file_path); @@ -5449,7 +5457,7 @@ Result<ASR::TranslationUnit_t*> python_ast_to_asr(Allocator &al, ASR::asr_t *unit; auto res = symbol_table_visitor(al, *ast_m, diagnostics, main_module, - ast_overload, parent_dir); + ast_overload, parent_dir, import_path); if (res.ok) { unit = res.result; } else { diff --git a/src/lpython/semantics/python_ast_to_asr.h b/src/lpython/semantics/python_ast_to_asr.h index 5a7844dd28..729311c698 100644 --- a/src/lpython/semantics/python_ast_to_asr.h +++ b/src/lpython/semantics/python_ast_to_asr.h @@ -10,7 +10,8 @@ namespace LFortran::LPython { std::string pickle_tree_python(AST::ast_t &ast, bool colors=true); Result<ASR::TranslationUnit_t*> python_ast_to_asr(Allocator &al, LPython::AST::ast_t &ast, diag::Diagnostics &diagnostics, - bool main_module, bool disable_main, bool symtab_only, std::string file_path); + bool main_module, bool disable_main, bool symtab_only, std::string file_path, + std::string import_path); int save_pyc_files(const LFortran::ASR::TranslationUnit_t &u, std::string infile); From 535fcd2a83189b40c64db8f73dff195c4ebb6dd6 Mon Sep 17 00:00:00 2001 From: Thirumalai-Shaktivel <thirumalaishaktivel@gmail.com> Date: Tue, 18 Oct 2022 12:34:46 +0530 Subject: [PATCH 2/5] Add is_directory and path_exits functions (using stat) --- src/lpython/utils.cpp | 20 ++++++++++++++++++++ src/lpython/utils.h | 15 +++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/lpython/utils.cpp b/src/lpython/utils.cpp index 5aefe3a1c9..117059b87b 100644 --- a/src/lpython/utils.cpp +++ b/src/lpython/utils.cpp @@ -69,5 +69,25 @@ std::string get_runtime_library_header_dir() return get_runtime_library_dir() + "/impure"; } +bool is_directory(std::string path) { + struct stat buffer; + if (stat(path.c_str(), &buffer) == 0) { + if (S_ISDIR(buffer.st_mode)) { + return true; + } else { + return false; + } + } + return false; +} + +bool path_exits(std::string path) { + struct stat buffer; + if (stat(path.c_str(), &buffer) == 0) { + return true; + } else { + return false; + } +} } diff --git a/src/lpython/utils.h b/src/lpython/utils.h index da5bae1418..44321333b6 100644 --- a/src/lpython/utils.h +++ b/src/lpython/utils.h @@ -4,11 +4,26 @@ #include <string> #include <libasr/utils.h> +#include <sys/types.h> +#include <sys/stat.h> +#ifndef _WIN32 + #include <unistd.h> +#endif + +#ifdef _WIN32 + #define stat _stat + #if !defined S_ISDIR + #define S_ISDIR(m) (((m) & _S_IFDIR) == _S_IFDIR) + #endif +#endif + namespace LFortran { void get_executable_path(std::string &executable_path, int &dirname_length); std::string get_runtime_library_dir(); std::string get_runtime_library_header_dir(); +bool is_directory(std::string path); +bool path_exits(std::string path); } // LFortran From 6292d4f4449f9ddf93daa8cea525456b25aa4910 Mon Sep 17 00:00:00 2001 From: Thirumalai-Shaktivel <thirumalaishaktivel@gmail.com> Date: Tue, 18 Oct 2022 12:35:05 +0530 Subject: [PATCH 3/5] Compile simple python packages and load it into the ASR --- src/lpython/semantics/python_ast_to_asr.cpp | 64 ++++++++++++++++++++- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index c9bb780b87..385248d05a 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -307,6 +307,7 @@ ASR::Module_t* load_module(Allocator &al, SymbolTable *symtab, bool compile_module = true; ASR::TranslationUnit_t* mod1 = nullptr; std::string input; + std::string module_dir_name = ""; bool found = set_module_path(infile0c, rl_path, infile, path_used, input, ltypes, enum_py); if( !found ) { @@ -335,7 +336,15 @@ ASR::Module_t* load_module(Allocator &al, SymbolTable *symtab, // insert into `symtab` std::vector<std::pair<std::string, ASR::Module_t*>> children_modules; - ASRUtils::extract_module_python(*mod1, children_modules, module_name); + if (module_name == "__init__") { + // remove `__init__.py` + module_dir_name = infile.substr(0, infile.find_last_of('/')); + // assign module directory name + module_dir_name = module_dir_name.substr(module_dir_name.find_last_of('/') + 1); + ASRUtils::extract_module_python(*mod1, children_modules, module_dir_name); + } else { + ASRUtils::extract_module_python(*mod1, children_modules, module_name); + } ASR::Module_t* mod2 = nullptr; for( auto& a: children_modules ) { std::string a_name = a.first; @@ -344,6 +353,10 @@ ASR::Module_t* load_module(Allocator &al, SymbolTable *symtab, a_mod->m_name = s2c(al, module_name); a_mod->m_intrinsic = intrinsic; mod2 = a_mod; + } else if (a_name == module_dir_name) { + a_mod->m_name = s2c(al, module_dir_name); + a_mod->m_intrinsic = intrinsic; + mod2 = a_mod; } symtab->add_symbol(a_name, (ASR::symbol_t*)a_mod); a_mod->m_symtab->parent = symtab; @@ -429,9 +442,18 @@ ASR::symbol_t* import_from_module(Allocator &al, ASR::Module_t *m, SymbolTable * ASR::accessType::Public ); return ASR::down_cast<ASR::symbol_t>(v); + } else if (ASR::is_a<ASR::ExternalSymbol_t>(*t)) { + ASR::ExternalSymbol_t *es = ASR::down_cast<ASR::ExternalSymbol_t>(t); + SymbolTable *symtab = current_scope; + while (symtab->parent != nullptr) symtab = symtab->parent; + ASR::symbol_t *sym = symtab->get_symbol(es->m_module_name); + ASR::Module_t *m = ASR::down_cast<ASR::Module_t>(sym); + + return import_from_module(al, m, symtab, es->m_name, + cur_sym_name, new_sym_name, loc); } else { - throw SemanticError("Only Subroutines, Functions and Variables are currently supported in 'import'", - loc); + throw SemanticError("Only Subroutines, Functions, Variables and " + "ExternalSymbol are currently supported in 'import'", loc); } LFORTRAN_ASSERT(false); return nullptr; @@ -3157,6 +3179,24 @@ class SymbolTableVisitor : public CommonVisitor<SymbolTableVisitor> { st = st->parent; } bool ltypes, enum_py; + if (msym != "ltypes") { + if (import_path != "" && + !path_exits(paths[0] + '/' + msym + ".py")) { + paths = {import_path}; + if (parent_dir != "") paths[0] += '/' + parent_dir; + if(is_directory(paths[0])) { + paths[0] += '/' + msym; + msym = "__init__"; + } + } else if (is_directory(msym)) { + paths = {rl_path, msym}; + msym = "__init__"; + } else if (paths[1] != "" + && is_directory(paths[1] + '/' + msym)) { + paths[1] += '/' + msym; + msym = "__init__"; + } + } t = (ASR::symbol_t*)(load_module(al, st, msym, x.base.base.loc, false, paths, ltypes, enum_py, [&](const std::string &msg, const Location &loc) { throw SemanticError(msg, loc); } @@ -3202,6 +3242,24 @@ class SymbolTableVisitor : public CommonVisitor<SymbolTableVisitor> { } for (auto &mod_sym : mods) { bool ltypes, enum_py; + if (mod_sym != "ltypes") { + if (import_path != "" && + !path_exits(paths[0] + '/' + mod_sym + ".py")) { + paths = {import_path}; + if (parent_dir != "") paths[0] += '/' + parent_dir; + if(is_directory(paths[0])) { + paths[0] += '/' + mod_sym; + mod_sym = "__init__"; + } + } else if (is_directory(mod_sym)) { + paths = {rl_path, mod_sym}; + mod_sym = "__init__"; + } else if (paths[1] != "" + && is_directory(paths[1] + '/' + mod_sym)) { + paths[1] += '/' + mod_sym; + mod_sym = "__init__"; + } + } t = (ASR::symbol_t*)(load_module(al, st, mod_sym, x.base.base.loc, false, paths, ltypes, enum_py, [&](const std::string &msg, const Location &loc) { throw SemanticError(msg, loc); } From b12fab0a02cd35ae97808364d0de5f4bf50ca58c Mon Sep 17 00:00:00 2001 From: Thirumalai-Shaktivel <thirumalaishaktivel@gmail.com> Date: Tue, 18 Oct 2022 15:59:56 +0530 Subject: [PATCH 4/5] Add tests and register in CMakeList --- integration_tests/CMakeLists.txt | 1 + integration_tests/test_import/__init__.py | 2 ++ integration_tests/test_import/test_import_1.py | 5 +++++ integration_tests/test_import/test_import_2.py | 2 ++ integration_tests/test_import_01.py | 6 ++++++ 5 files changed, 16 insertions(+) create mode 100644 integration_tests/test_import/__init__.py create mode 100644 integration_tests/test_import/test_import_1.py create mode 100644 integration_tests/test_import/test_import_2.py create mode 100644 integration_tests/test_import_01.py diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index 3f8543b992..0ff6ec014c 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -192,6 +192,7 @@ RUN(NAME test_dict_05 LABELS cpython llvm) RUN(NAME test_for_loop LABELS cpython llvm c) RUN(NAME modules_01 LABELS cpython llvm) RUN(NAME modules_02 LABELS cpython llvm) +RUN(NAME test_import_01 LABELS cpython llvm) RUN(NAME test_math LABELS cpython llvm) RUN(NAME test_numpy_01 LABELS cpython llvm c) RUN(NAME test_numpy_02 LABELS cpython llvm c) diff --git a/integration_tests/test_import/__init__.py b/integration_tests/test_import/__init__.py new file mode 100644 index 0000000000..38b264b931 --- /dev/null +++ b/integration_tests/test_import/__init__.py @@ -0,0 +1,2 @@ +from .test_import_1 import print_a, print_b +from .test_import_2 import print_c diff --git a/integration_tests/test_import/test_import_1.py b/integration_tests/test_import/test_import_1.py new file mode 100644 index 0000000000..347788a1ca --- /dev/null +++ b/integration_tests/test_import/test_import_1.py @@ -0,0 +1,5 @@ +def print_a() -> str: + return "A" + +def print_b() -> str: + return "B" diff --git a/integration_tests/test_import/test_import_2.py b/integration_tests/test_import/test_import_2.py new file mode 100644 index 0000000000..2c1064f112 --- /dev/null +++ b/integration_tests/test_import/test_import_2.py @@ -0,0 +1,2 @@ +def print_c() -> str: + return "C" diff --git a/integration_tests/test_import_01.py b/integration_tests/test_import_01.py new file mode 100644 index 0000000000..e2bcccc9ac --- /dev/null +++ b/integration_tests/test_import_01.py @@ -0,0 +1,6 @@ +import test_import +from test_import import print_a + +print(print_a()) +print(test_import.print_b()) +print(test_import.print_c()) From 2d5f401c0d51f45470427e76a454ce2191980362 Mon Sep 17 00:00:00 2001 From: Thirumalai-Shaktivel <thirumalaishaktivel@gmail.com> Date: Wed, 19 Oct 2022 13:22:48 +0530 Subject: [PATCH 5/5] Move `stat` include statement to `utils.cpp` --- src/lpython/utils.cpp | 13 +++++++++++++ src/lpython/utils.h | 13 ------------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/lpython/utils.cpp b/src/lpython/utils.cpp index 117059b87b..874b5268fc 100644 --- a/src/lpython/utils.cpp +++ b/src/lpython/utils.cpp @@ -13,6 +13,19 @@ #include <lpython/utils.h> #include <libasr/string_utils.h> +#include <sys/types.h> +#include <sys/stat.h> +#ifndef _WIN32 + #include <unistd.h> +#endif + +#ifdef _WIN32 + #define stat _stat + #if !defined S_ISDIR + #define S_ISDIR(m) (((m) & _S_IFDIR) == _S_IFDIR) + #endif +#endif + namespace LFortran { void get_executable_path(std::string &executable_path, int &dirname_length) diff --git a/src/lpython/utils.h b/src/lpython/utils.h index 44321333b6..4fadfe7140 100644 --- a/src/lpython/utils.h +++ b/src/lpython/utils.h @@ -4,19 +4,6 @@ #include <string> #include <libasr/utils.h> -#include <sys/types.h> -#include <sys/stat.h> -#ifndef _WIN32 - #include <unistd.h> -#endif - -#ifdef _WIN32 - #define stat _stat - #if !defined S_ISDIR - #define S_ISDIR(m) (((m) & _S_IFDIR) == _S_IFDIR) - #endif -#endif - namespace LFortran { void get_executable_path(std::string &executable_path, int &dirname_length);