diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index e34f4c7546..4790a26c90 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -61,7 +61,7 @@ macro(RUN) if (import_path) add_custom_command( OUTPUT ${name}.o - COMMAND lpython -c -I ${import_path} ${CMAKE_CURRENT_SOURCE_DIR}/${name}.py -o ${name}.o + COMMAND lpython -c -I ${CMAKE_CURRENT_SOURCE_DIR}/${import_path} ${CMAKE_CURRENT_SOURCE_DIR}/${name}.py -o ${name}.o DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${name}.py VERBATIM) else () @@ -109,7 +109,7 @@ macro(RUN) add_test(${name} python ${CMAKE_CURRENT_SOURCE_DIR}/${name}.py) set_tests_properties(${name} PROPERTIES - ENVIRONMENT "PYTHONPATH=${CMAKE_SOURCE_DIR}/../src/runtime/ltypes;LPYTHON_PY_MOD_NAME=${PY_MOD};LPYTHON_PY_MOD_PATH=${CMAKE_CURRENT_BINARY_DIR}") + ENVIRONMENT "PYTHONPATH=${CMAKE_SOURCE_DIR}/../src/runtime/ltypes:${CMAKE_SOURCE_DIR}/..;LPYTHON_PY_MOD_NAME=${PY_MOD};LPYTHON_PY_MOD_PATH=${CMAKE_CURRENT_BINARY_DIR}") if (RUN_LABELS) set_tests_properties(${name} PROPERTIES LABELS "${RUN_LABELS}") endif() @@ -248,9 +248,10 @@ RUN(NAME test_for_loop LABELS cpython llvm c) RUN(NAME modules_01 LABELS cpython llvm wasm wasm_x86) RUN(NAME modules_02 LABELS cpython llvm wasm wasm_x86) RUN(NAME test_import_01 LABELS cpython llvm) -RUN(NAME test_import_02 IMPORT_PATH integration_tests - LABELS cpython llvm) +RUN(NAME test_import_02 LABELS cpython llvm) RUN(NAME test_import_03 LABELS cpython llvm) +RUN(NAME test_import_04 IMPORT_PATH .. + 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_04.py b/integration_tests/test_import_04.py new file mode 100644 index 0000000000..95938f8ff3 --- /dev/null +++ b/integration_tests/test_import_04.py @@ -0,0 +1,8 @@ +import test_modules + +def main0(): + print(test_modules.sin(0.5)) + print(test_modules.cos(0.5)) + assert abs(test_modules.sin(0.5) + test_modules.cos(0.5) - 1.0) <= 1e-12 + +main0() diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index bb791f6d9e..e7c2aeb1b1 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -421,11 +421,12 @@ ASR::Module_t* load_module(Allocator &al, SymbolTable *symtab, } ASR::symbol_t* import_from_module(Allocator &al, ASR::Module_t *m, SymbolTable *current_scope, - std::string mname, std::string cur_sym_name, std::string new_sym_name, + std::string /*mname*/, std::string cur_sym_name, std::string& new_sym_name, const Location &loc, bool skip_current_scope_check=false) { + new_sym_name = ASRUtils::get_mangled_name(m, new_sym_name); ASR::symbol_t *t = m->m_symtab->resolve_symbol(cur_sym_name); if (!t) { - throw SemanticError("The symbol '" + cur_sym_name + "' not found in the module '" + mname + "'", + throw SemanticError("The symbol '" + cur_sym_name + "' not found in the module '" + std::string(m->m_name) + "'", loc); } if (!skip_current_scope_check && @@ -481,11 +482,19 @@ ASR::symbol_t* import_from_module(Allocator &al, ASR::Module_t *m, SymbolTable * } else if (ASR::is_a(*t)) { ASR::ExternalSymbol_t *es = ASR::down_cast(t); SymbolTable *symtab = current_scope; - while (symtab->parent != nullptr) symtab = symtab->parent; - ASR::symbol_t *sym = symtab->get_symbol(es->m_module_name); + // while (symtab->parent != nullptr) symtab = symtab->parent; + ASR::symbol_t *sym = symtab->resolve_symbol(es->m_module_name); ASR::Module_t *m = ASR::down_cast(sym); - return import_from_module(al, m, symtab, es->m_name, + return import_from_module(al, m, symtab, es->m_module_name, cur_sym_name, new_sym_name, loc); + } else if (ASR::is_a(*t)) { + ASR::Module_t* mt = ASR::down_cast(t); + std::string mangled_cur_sym_name = ASRUtils::get_mangled_name(mt, new_sym_name); + if( cur_sym_name == mangled_cur_sym_name ) { + throw SemanticError("Importing modules isn't supported yet.", loc); + } + return import_from_module(al, mt, current_scope, std::string(mt->m_name), + cur_sym_name, new_sym_name, loc); } else { throw SemanticError("Only Subroutines, Functions, Variables and " "ExternalSymbol are currently supported in 'import'", loc); @@ -1007,6 +1016,7 @@ class CommonVisitor : public AST::BaseVisitor { std::string mod_name = ASR::down_cast(stemp)->m_module_name; ASR::symbol_t *mt = symtab->resolve_symbol(mod_name); ASR::Module_t *m = ASR::down_cast(mt); + local_sym = ASRUtils::get_mangled_name(m, local_sym); stemp = import_from_module(al, m, symtab, mod_name, remote_sym, local_sym, loc); LFORTRAN_ASSERT(ASR::is_a(*stemp)); @@ -3534,7 +3544,18 @@ class SymbolTableVisitor : public CommonVisitor { throw SemanticError("The module '" + msym + "' cannot be loaded", x.base.base.loc); } - current_module_dependencies.push_back(al, s2c(al, msym)); + if( msym == "__init__" ) { + for( auto item: ASRUtils::symbol_symtab(t)->get_scope() ) { + if( ASR::is_a(*item.second) && + !present(current_module_dependencies, + ASR::down_cast(item.second)->m_module_name) ) { + current_module_dependencies.push_back(al, + ASR::down_cast(item.second)->m_module_name); + } + } + } else { + current_module_dependencies.push_back(al, s2c(al, msym)); + } } ASR::Module_t *m = ASR::down_cast(t); @@ -3544,7 +3565,7 @@ class SymbolTableVisitor : public CommonVisitor { } std::string new_sym_name = ASRUtils::get_mangled_name(m, remote_sym); ASR::symbol_t *t = import_from_module(al, m, current_scope, msym, - remote_sym, new_sym_name, x.base.base.loc, false); + remote_sym, new_sym_name, x.base.base.loc, true); current_scope->add_symbol(new_sym_name, t); } @@ -4614,7 +4635,7 @@ class BodyVisitor : public CommonVisitor { ASR::symbol_t *sym = current_scope->resolve_symbol(sym_name); if (!sym) { sym = import_from_module(al, m, current_scope, value, - x.m_attr, sym_name, x.base.base.loc, true); + x.m_attr, sym_name, x.base.base.loc, false); LFORTRAN_ASSERT(ASR::is_a(*sym)); current_scope->add_symbol(sym_name, sym); } @@ -5898,7 +5919,13 @@ Result python_ast_to_asr(Allocator &al, LocationManager } else { return res2.error; } - LFORTRAN_ASSERT(asr_verify(*tu, true, diagnostics)); +#if defined(WITH_LFORTRAN_ASSERT) + diag::Diagnostics diagnostics; + if (!asr_verify(*tu, true, diagnostics)) { + std::cerr << diagnostics.render2(); + throw LCompilersException("Verify failed"); + }; +#endif } if (main_module) { diff --git a/test_modules/__init__.py b/test_modules/__init__.py new file mode 100644 index 0000000000..d3225fef56 --- /dev/null +++ b/test_modules/__init__.py @@ -0,0 +1 @@ +from .mathfn import sin, cos diff --git a/test_modules/mathfn/__init__.py b/test_modules/mathfn/__init__.py new file mode 100644 index 0000000000..a3960d2b3f --- /dev/null +++ b/test_modules/mathfn/__init__.py @@ -0,0 +1 @@ +from .sin import sin, cos diff --git a/test_modules/mathfn/sin.py b/test_modules/mathfn/sin.py new file mode 100644 index 0000000000..8c04aeef9c --- /dev/null +++ b/test_modules/mathfn/sin.py @@ -0,0 +1,7 @@ +from ltypes import f64 + +def sin(x: f64) -> f64: + return x + 1.0 + +def cos(x: f64) -> f64: + return x - 1.0