From 424107c10d959f07cd4da36e1ccc7786e6db9186 Mon Sep 17 00:00:00 2001 From: Amrita kumari mishra Date: Sat, 6 Dec 2025 20:38:48 +0000 Subject: [PATCH 1/6] Fix: Support 'import module as alias' in semantic analysis --- src/lpython/semantics/python_ast_to_asr.cpp | 42 +++++++++++++++++---- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 2ce695f68b..2bf8986a31 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -4959,21 +4959,20 @@ class SymbolTableVisitor : public CommonVisitor { } paths.push_back(rl_path); paths.push_back(parent_dir); - std::vector mods; + for (size_t i=0; i { throw SemanticError("The module '" + mod_sym + "' cannot be loaded", x.base.base.loc); } + if( mod_sym == "__init__" ) { for( auto item: ASRUtils::symbol_symtab(t)->get_scope() ) { if( ASR::is_a(*item.second) ) { @@ -4991,6 +4991,34 @@ class SymbolTableVisitor : public CommonVisitor { } else { current_module_dependencies.push_back(al, s2c(al, mod_sym)); } + + // --- ALIAS LOGIC (FIXED) --- + if (alias) { + std::string alias_str = std::string(alias); + + if (current_scope->get_symbol(alias_str) == nullptr) { + + // The Corrected Constructor Call + ASR::asr_t *ext_sym = ASR::make_ExternalSymbol_t( + al, + x.base.base.loc, + current_scope, // Parent Symbol Table + s2c(al, alias_str), // Name: "np" + t, // Symbol: Pointer to numpy module + s2c(al, mod_sym), // Module Name: "numpy" + nullptr, // scope_names (dependencies) + 0, // n_scope_names (MUST BE 0, NOT nullptr) + s2c(al, mod_sym), // original_name: "numpy" + ASR::accessType::Public // Access + ); + + current_scope->add_symbol(alias_str, ASR::down_cast(ext_sym)); + } + } else { + if (current_scope->get_symbol(mod_sym) == nullptr) { + current_scope->add_symbol(mod_sym, t); + } + } } } From a802b363b76c7d0d2aefb3d9a53f1f38797209cb Mon Sep 17 00:00:00 2001 From: Amrita kumari mishra Date: Sat, 6 Dec 2025 21:13:56 +0000 Subject: [PATCH 2/6] Fix: Restore visit_ImportFrom and finalize aliasing logic --- src/lpython/semantics/python_ast_to_asr.cpp | 176 ++++---------------- 1 file changed, 36 insertions(+), 140 deletions(-) diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 2bf8986a31..793f20f218 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -4872,6 +4872,7 @@ class SymbolTableVisitor : public CommonVisitor { } } + // --- RESTORED visit_ImportFrom --- void visit_ImportFrom(const AST::ImportFrom_t &x) { if (!x.m_module) { throw SemanticError("Not implemented: The import statement must currently specify the module name", x.base.base.loc); @@ -4879,43 +4880,39 @@ class SymbolTableVisitor : public CommonVisitor { std::string msym = x.m_module; // Module name // Get the module, for now assuming it is not loaded, so we load it: - ASR::symbol_t *t = nullptr; // current_scope->parent->resolve_symbol(msym); - if (!t) { - std::string rl_path = get_runtime_library_dir(); - std::vector paths; - for (auto &path:import_paths) { - paths.push_back(path); - } - paths.push_back(rl_path); - paths.push_back(parent_dir); + ASR::symbol_t *t = nullptr; + std::string rl_path = get_runtime_library_dir(); + std::vector paths; + for (auto &path:import_paths) { + paths.push_back(path); + } + paths.push_back(rl_path); + paths.push_back(parent_dir); - bool lpython, enum_py, copy, sympy; - set_module_symbol(msym, paths); - t = (ASR::symbol_t*)(load_module(al, global_scope, - msym, x.base.base.loc, diag, lm, false, paths, lpython, enum_py, copy, sympy, - [&](const std::string &msg, const Location &loc) { throw SemanticError(msg, loc); }, - allow_implicit_casting)); - if (lpython || enum_py || copy || sympy) { - // TODO: For now we skip lpython import completely. Later on we should note what symbols - // got imported from it, and give an error message if an annotation is used without - // importing it. - tmp = nullptr; - return; - } - if (!t) { - throw SemanticError("The module '" + msym + "' cannot be loaded", - x.base.base.loc); - } - if( msym == "__init__" ) { - for( auto item: ASRUtils::symbol_symtab(t)->get_scope() ) { - if( ASR::is_a(*item.second) ) { - current_module_dependencies.push_back(al, - ASR::down_cast(item.second)->m_module_name); - } + bool lpython, enum_py, copy, sympy; + set_module_symbol(msym, paths); + t = (ASR::symbol_t*)(load_module(al, global_scope, + msym, x.base.base.loc, diag, lm, false, paths, lpython, enum_py, copy, sympy, + [&](const std::string &msg, const Location &loc) { throw SemanticError(msg, loc); }, + allow_implicit_casting)); + + if (lpython || enum_py || copy || sympy) { + tmp = nullptr; + return; + } + if (!t) { + throw SemanticError("The module '" + msym + "' cannot be loaded", + x.base.base.loc); + } + if( msym == "__init__" ) { + for( auto item: ASRUtils::symbol_symtab(t)->get_scope() ) { + if( ASR::is_a(*item.second) ) { + current_module_dependencies.push_back(al, + ASR::down_cast(item.second)->m_module_name); } - } else { - current_module_dependencies.push_back(al, s2c(al, msym)); } + } else { + current_module_dependencies.push_back(al, s2c(al, msym)); } ASR::Module_t *m = ASR::down_cast(t); @@ -4931,7 +4928,7 @@ class SymbolTableVisitor : public CommonVisitor { new_sym_name = ASRUtils::get_mangled_name(m, x.m_names[j].m_asname); } ASR::symbol_t *t = import_from_module(al, m, current_scope, msym, - remote_sym, new_sym_name, x.m_names[i].loc, true); + remote_sym, new_sym_name, x.m_names[i].loc, true); if (current_scope->get_scope().find(new_sym_name) != current_scope->get_scope().end()) { ASR::symbol_t *old_sym = current_scope->get_scope().find(new_sym_name)->second; diag.add(diag::Diagnostic( @@ -4946,10 +4943,9 @@ class SymbolTableVisitor : public CommonVisitor { current_scope->add_symbol(new_sym_name, t); } } - tmp = nullptr; } - + // --- YOUR FIXED visit_Import --- void visit_Import(const AST::Import_t &x) { ASR::symbol_t *t = nullptr; std::string rl_path = get_runtime_library_dir(); @@ -4992,116 +4988,16 @@ class SymbolTableVisitor : public CommonVisitor { current_module_dependencies.push_back(al, s2c(al, mod_sym)); } - // --- ALIAS LOGIC (FIXED) --- if (alias) { std::string alias_str = std::string(alias); - if (current_scope->get_symbol(alias_str) == nullptr) { - - // The Corrected Constructor Call ASR::asr_t *ext_sym = ASR::make_ExternalSymbol_t( - al, - x.base.base.loc, - current_scope, // Parent Symbol Table - s2c(al, alias_str), // Name: "np" - t, // Symbol: Pointer to numpy module - s2c(al, mod_sym), // Module Name: "numpy" - nullptr, // scope_names (dependencies) - 0, // n_scope_names (MUST BE 0, NOT nullptr) - s2c(al, mod_sym), // original_name: "numpy" - ASR::accessType::Public // Access + al, x.base.base.loc, current_scope, + s2c(al, alias_str), t, s2c(al, mod_sym), + nullptr, 0, s2c(al, mod_sym), ASR::accessType::Public ); - current_scope->add_symbol(alias_str, ASR::down_cast(ext_sym)); } - } else { - if (current_scope->get_symbol(mod_sym) == nullptr) { - current_scope->add_symbol(mod_sym, t); - } - } - } - } - - void visit_AugAssign(const AST::AugAssign_t &/*x*/) { - // We skip this in the SymbolTable visitor, but visit it in the BodyVisitor - } - - void visit_AnnAssign(const AST::AnnAssign_t &/*x*/) { - // We skip this in the SymbolTable visitor, but visit it in the BodyVisitor - } - - void visit_Assign(const AST::Assign_t &x) { - /** - * Type variables have to be put in the symbol table before checking function definitions. - * This describes a different treatment for Assign in the form of `T = TypeVar('T', ...)` - */ - if (x.n_targets == 1 && AST::is_a(*x.m_value)) { - AST::Call_t *rh = AST::down_cast(x.m_value); - if (AST::is_a(*rh->m_func)) { - AST::Name_t *tv = AST::down_cast(rh->m_func); - std::string f_name = tv->m_id; - if (strcmp(s2c(al, f_name), "TypeVar") == 0 && - rh->n_args > 0 && AST::is_a(*rh->m_args[0])) { - if (AST::is_a(*x.m_targets[0])) { - std::string tvar_name = AST::down_cast(x.m_targets[0])->m_id; - // Check if the type variable name is a reserved type keyword - const char* type_list[15] - = { "list", "set", "dict", "tuple", - "i8", "i16", "i32", "i64", "f32", - "f64", "c32", "c64", "str", "bool", "i1"}; - for (int i = 0; i < 15; i++) { - if (strcmp(s2c(al, tvar_name), type_list[i]) == 0) { - throw SemanticError(tvar_name + " is a reserved type, consider a different type variable name", - x.base.base.loc); - } - } - // Check if the type variable is already defined - if (current_scope->get_scope().find(tvar_name) != - current_scope->get_scope().end()) { - ASR::symbol_t *orig_decl = current_scope->get_symbol(tvar_name); - throw SemanticError(diag::Diagnostic( - "Variable " + tvar_name + " is already declared in the same scope", - diag::Level::Error, diag::Stage::Semantic, { - diag::Label("original declaration", {orig_decl->base.loc}, false), - diag::Label("redeclaration", {x.base.base.loc}), - })); - } - - // Build ttype - Vec dims; - dims.reserve(al, 4); - - ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_TypeParameter_t(al, x.base.base.loc, - s2c(al, tvar_name))); - type = ASRUtils::make_Array_t_util(al, x.base.base.loc, type, dims.p, dims.size()); - - ASR::expr_t *value = nullptr; - ASR::expr_t *init_expr = nullptr; - ASR::intentType s_intent = ASRUtils::intent_local; - ASR::storage_typeType storage_type = ASR::storage_typeType::Default; - ASR::abiType current_procedure_abi_type = ASR::abiType::Source; - ASR::accessType s_access = ASR::accessType::Public; - ASR::presenceType s_presence = ASR::presenceType::Required; - bool value_attr = false; - - SetChar variable_dependencies_vec; - variable_dependencies_vec.reserve(al, 1); - ASRUtils::collect_variable_dependencies(al, variable_dependencies_vec, type, init_expr, value); - // Build the variable and add it to the scope - ASR::asr_t *v = ASR::make_Variable_t(al, x.base.base.loc, current_scope, - s2c(al, tvar_name), variable_dependencies_vec.p, variable_dependencies_vec.size(), - s_intent, init_expr, value, storage_type, type, nullptr, current_procedure_abi_type, - s_access, s_presence, value_attr, false, false, nullptr, false, false); - current_scope->add_symbol(tvar_name, ASR::down_cast(v)); - - tmp = nullptr; - - return; - } else { - // This error might need to be further elaborated - throw SemanticError("Type variable must be a variable", x.base.base.loc); - } - } } } } From 90b2ce3444ea2f5240e2ad0592f8a1206274afd2 Mon Sep 17 00:00:00 2001 From: Amrita kumari mishra Date: Sat, 6 Dec 2025 21:34:29 +0000 Subject: [PATCH 3/6] Fix: Restore visit_ImportFrom and remove double registration --- src/lpython/semantics/python_ast_to_asr.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 793f20f218..ba234855e9 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -4873,6 +4873,7 @@ class SymbolTableVisitor : public CommonVisitor { } // --- RESTORED visit_ImportFrom --- + // --- 1. The Missing Function (RESTORE THIS) --- void visit_ImportFrom(const AST::ImportFrom_t &x) { if (!x.m_module) { throw SemanticError("Not implemented: The import statement must currently specify the module name", x.base.base.loc); @@ -4945,7 +4946,8 @@ class SymbolTableVisitor : public CommonVisitor { } tmp = nullptr; } - // --- YOUR FIXED visit_Import --- + + // --- 2. Your Fixed Function (CORRECT VERSION WITHOUT 'ELSE') --- void visit_Import(const AST::Import_t &x) { ASR::symbol_t *t = nullptr; std::string rl_path = get_runtime_library_dir(); @@ -4988,6 +4990,7 @@ class SymbolTableVisitor : public CommonVisitor { current_module_dependencies.push_back(al, s2c(al, mod_sym)); } + // ALIAS LOGIC (No else block!) if (alias) { std::string alias_str = std::string(alias); if (current_scope->get_symbol(alias_str) == nullptr) { From b4e6589ff04fd7bd2b1b35b88b04d6ac67752690 Mon Sep 17 00:00:00 2001 From: Amrita kumari mishra Date: Sat, 6 Dec 2025 22:05:58 +0000 Subject: [PATCH 4/6] Fix: Restore visit_ImportFrom and finalize aliasing logic --- src/lpython/semantics/python_ast_to_asr.cpp | 41 ++++++++++++++------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index ba234855e9..9d2a518656 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -4872,8 +4872,7 @@ class SymbolTableVisitor : public CommonVisitor { } } - // --- RESTORED visit_ImportFrom --- - // --- 1. The Missing Function (RESTORE THIS) --- + // --- 1. RESTORED & FIXED: visit_ImportFrom --- void visit_ImportFrom(const AST::ImportFrom_t &x) { if (!x.m_module) { throw SemanticError("Not implemented: The import statement must currently specify the module name", x.base.base.loc); @@ -4890,7 +4889,9 @@ class SymbolTableVisitor : public CommonVisitor { paths.push_back(rl_path); paths.push_back(parent_dir); - bool lpython, enum_py, copy, sympy; + // FIX: Initialize bools to false to avoid undefined behavior + bool lpython = false, enum_py = false, copy = false, sympy = false; + set_module_symbol(msym, paths); t = (ASR::symbol_t*)(load_module(al, global_scope, msym, x.base.base.loc, diag, lm, false, paths, lpython, enum_py, copy, sympy, @@ -4928,26 +4929,29 @@ class SymbolTableVisitor : public CommonVisitor { if (x.m_names[j].m_asname) { new_sym_name = ASRUtils::get_mangled_name(m, x.m_names[j].m_asname); } - ASR::symbol_t *t = import_from_module(al, m, current_scope, msym, + + // FIX: Renamed 't' to 'imported_sym' to avoid shadowing the outer module pointer 't' + ASR::symbol_t *imported_sym = import_from_module(al, m, current_scope, msym, remote_sym, new_sym_name, x.m_names[i].loc, true); + if (current_scope->get_scope().find(new_sym_name) != current_scope->get_scope().end()) { ASR::symbol_t *old_sym = current_scope->get_scope().find(new_sym_name)->second; diag.add(diag::Diagnostic( "The symbol '" + new_sym_name + "' imported from " + std::string(m->m_name) +" will shadow the existing symbol '" + new_sym_name + "'", diag::Level::Warning, diag::Stage::Semantic, { diag::Label("old symbol", {old_sym->base.loc}), - diag::Label("new symbol", {t->base.loc}), + diag::Label("new symbol", {imported_sym->base.loc}), }) ); - current_scope->overwrite_symbol(new_sym_name, t); + current_scope->overwrite_symbol(new_sym_name, imported_sym); } else { - current_scope->add_symbol(new_sym_name, t); + current_scope->add_symbol(new_sym_name, imported_sym); } } tmp = nullptr; } - // --- 2. Your Fixed Function (CORRECT VERSION WITHOUT 'ELSE') --- + // --- 2. FIXED: visit_Import (Safe Bools + No Else) --- void visit_Import(const AST::Import_t &x) { ASR::symbol_t *t = nullptr; std::string rl_path = get_runtime_library_dir(); @@ -4962,7 +4966,9 @@ class SymbolTableVisitor : public CommonVisitor { std::string mod_sym = x.m_names[i].m_name; char* alias = x.m_names[i].m_asname; - bool lpython, enum_py, copy, sympy; + // FIX: Initialize bools + bool lpython = false, enum_py = false, copy = false, sympy = false; + set_module_symbol(mod_sym, paths); t = (ASR::symbol_t*)(load_module(al, global_scope, @@ -4990,18 +4996,27 @@ class SymbolTableVisitor : public CommonVisitor { current_module_dependencies.push_back(al, s2c(al, mod_sym)); } - // ALIAS LOGIC (No else block!) + // ALIAS LOGIC if (alias) { std::string alias_str = std::string(alias); if (current_scope->get_symbol(alias_str) == nullptr) { + // Note: Using the signature that matches your local libasr version ASR::asr_t *ext_sym = ASR::make_ExternalSymbol_t( - al, x.base.base.loc, current_scope, - s2c(al, alias_str), t, s2c(al, mod_sym), - nullptr, 0, s2c(al, mod_sym), ASR::accessType::Public + al, + x.base.base.loc, + current_scope, + s2c(al, alias_str), + t, + s2c(al, mod_sym), + nullptr, + 0, + s2c(al, mod_sym), + ASR::accessType::Public ); current_scope->add_symbol(alias_str, ASR::down_cast(ext_sym)); } } + // NO ELSE BLOCK: Standard imports are handled by load_module logic implicitly. } } From 78abfa61a7d0576e21c8f4d4ba3a6ee1805a44b8 Mon Sep 17 00:00:00 2001 From: Amrita kumari mishra Date: Sun, 7 Dec 2025 10:36:08 +0000 Subject: [PATCH 5/6] Fix: Clean reset and correct alias patch --- src/lpython/semantics/python_ast_to_asr.cpp | 185 ++++++++++++++------ 1 file changed, 129 insertions(+), 56 deletions(-) diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 9d2a518656..52ebceb66c 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -4872,7 +4872,6 @@ class SymbolTableVisitor : public CommonVisitor { } } - // --- 1. RESTORED & FIXED: visit_ImportFrom --- void visit_ImportFrom(const AST::ImportFrom_t &x) { if (!x.m_module) { throw SemanticError("Not implemented: The import statement must currently specify the module name", x.base.base.loc); @@ -4880,41 +4879,43 @@ class SymbolTableVisitor : public CommonVisitor { std::string msym = x.m_module; // Module name // Get the module, for now assuming it is not loaded, so we load it: - ASR::symbol_t *t = nullptr; - std::string rl_path = get_runtime_library_dir(); - std::vector paths; - for (auto &path:import_paths) { - paths.push_back(path); - } - paths.push_back(rl_path); - paths.push_back(parent_dir); - - // FIX: Initialize bools to false to avoid undefined behavior - bool lpython = false, enum_py = false, copy = false, sympy = false; - - set_module_symbol(msym, paths); - t = (ASR::symbol_t*)(load_module(al, global_scope, - msym, x.base.base.loc, diag, lm, false, paths, lpython, enum_py, copy, sympy, - [&](const std::string &msg, const Location &loc) { throw SemanticError(msg, loc); }, - allow_implicit_casting)); - - if (lpython || enum_py || copy || sympy) { - tmp = nullptr; - return; - } + ASR::symbol_t *t = nullptr; // current_scope->parent->resolve_symbol(msym); if (!t) { - throw SemanticError("The module '" + msym + "' cannot be loaded", - x.base.base.loc); - } - if( msym == "__init__" ) { - for( auto item: ASRUtils::symbol_symtab(t)->get_scope() ) { - if( ASR::is_a(*item.second) ) { - current_module_dependencies.push_back(al, - ASR::down_cast(item.second)->m_module_name); + std::string rl_path = get_runtime_library_dir(); + std::vector paths; + for (auto &path:import_paths) { + paths.push_back(path); + } + paths.push_back(rl_path); + paths.push_back(parent_dir); + + bool lpython, enum_py, copy, sympy; + set_module_symbol(msym, paths); + t = (ASR::symbol_t*)(load_module(al, global_scope, + msym, x.base.base.loc, diag, lm, false, paths, lpython, enum_py, copy, sympy, + [&](const std::string &msg, const Location &loc) { throw SemanticError(msg, loc); }, + allow_implicit_casting)); + if (lpython || enum_py || copy || sympy) { + // TODO: For now we skip lpython import completely. Later on we should note what symbols + // got imported from it, and give an error message if an annotation is used without + // importing it. + tmp = nullptr; + return; + } + if (!t) { + throw SemanticError("The module '" + msym + "' cannot be loaded", + x.base.base.loc); + } + if( msym == "__init__" ) { + for( auto item: ASRUtils::symbol_symtab(t)->get_scope() ) { + if( ASR::is_a(*item.second) ) { + current_module_dependencies.push_back(al, + ASR::down_cast(item.second)->m_module_name); + } } + } else { + current_module_dependencies.push_back(al, s2c(al, msym)); } - } else { - current_module_dependencies.push_back(al, s2c(al, msym)); } ASR::Module_t *m = ASR::down_cast(t); @@ -4929,29 +4930,26 @@ class SymbolTableVisitor : public CommonVisitor { if (x.m_names[j].m_asname) { new_sym_name = ASRUtils::get_mangled_name(m, x.m_names[j].m_asname); } - - // FIX: Renamed 't' to 'imported_sym' to avoid shadowing the outer module pointer 't' - ASR::symbol_t *imported_sym = import_from_module(al, m, current_scope, msym, - remote_sym, new_sym_name, x.m_names[i].loc, true); - + ASR::symbol_t *t = import_from_module(al, m, current_scope, msym, + remote_sym, new_sym_name, x.m_names[i].loc, true); if (current_scope->get_scope().find(new_sym_name) != current_scope->get_scope().end()) { ASR::symbol_t *old_sym = current_scope->get_scope().find(new_sym_name)->second; diag.add(diag::Diagnostic( "The symbol '" + new_sym_name + "' imported from " + std::string(m->m_name) +" will shadow the existing symbol '" + new_sym_name + "'", diag::Level::Warning, diag::Stage::Semantic, { diag::Label("old symbol", {old_sym->base.loc}), - diag::Label("new symbol", {imported_sym->base.loc}), + diag::Label("new symbol", {t->base.loc}), }) ); - current_scope->overwrite_symbol(new_sym_name, imported_sym); + current_scope->overwrite_symbol(new_sym_name, t); } else { - current_scope->add_symbol(new_sym_name, imported_sym); + current_scope->add_symbol(new_sym_name, t); } } + tmp = nullptr; } - // --- 2. FIXED: visit_Import (Safe Bools + No Else) --- void visit_Import(const AST::Import_t &x) { ASR::symbol_t *t = nullptr; std::string rl_path = get_runtime_library_dir(); @@ -4966,7 +4964,7 @@ class SymbolTableVisitor : public CommonVisitor { std::string mod_sym = x.m_names[i].m_name; char* alias = x.m_names[i].m_asname; - // FIX: Initialize bools + // Initialize bools bool lpython = false, enum_py = false, copy = false, sympy = false; set_module_symbol(mod_sym, paths); @@ -4981,7 +4979,7 @@ class SymbolTableVisitor : public CommonVisitor { continue; } if (!t) { - throw SemanticError("The module '" + mod_sym + "' cannot be loaded", + throw SemanticError("The module " + mod_sym + " cannot be loaded", x.base.base.loc); } @@ -5000,23 +4998,98 @@ class SymbolTableVisitor : public CommonVisitor { if (alias) { std::string alias_str = std::string(alias); if (current_scope->get_symbol(alias_str) == nullptr) { - // Note: Using the signature that matches your local libasr version ASR::asr_t *ext_sym = ASR::make_ExternalSymbol_t( - al, - x.base.base.loc, - current_scope, - s2c(al, alias_str), - t, - s2c(al, mod_sym), - nullptr, - 0, - s2c(al, mod_sym), - ASR::accessType::Public + al, x.base.base.loc, current_scope, + s2c(al, alias_str), t, s2c(al, mod_sym), + nullptr, 0, s2c(al, mod_sym), ASR::accessType::Public ); current_scope->add_symbol(alias_str, ASR::down_cast(ext_sym)); } } - // NO ELSE BLOCK: Standard imports are handled by load_module logic implicitly. + } + } + + void visit_AugAssign(const AST::AugAssign_t &/*x*/) { + // We skip this in the SymbolTable visitor, but visit it in the BodyVisitor + } + + void visit_AnnAssign(const AST::AnnAssign_t &/*x*/) { + // We skip this in the SymbolTable visitor, but visit it in the BodyVisitor + } + + void visit_Assign(const AST::Assign_t &x) { + /** + * Type variables have to be put in the symbol table before checking function definitions. + * This describes a different treatment for Assign in the form of `T = TypeVar('T', ...)` + */ + if (x.n_targets == 1 && AST::is_a(*x.m_value)) { + AST::Call_t *rh = AST::down_cast(x.m_value); + if (AST::is_a(*rh->m_func)) { + AST::Name_t *tv = AST::down_cast(rh->m_func); + std::string f_name = tv->m_id; + if (strcmp(s2c(al, f_name), "TypeVar") == 0 && + rh->n_args > 0 && AST::is_a(*rh->m_args[0])) { + if (AST::is_a(*x.m_targets[0])) { + std::string tvar_name = AST::down_cast(x.m_targets[0])->m_id; + // Check if the type variable name is a reserved type keyword + const char* type_list[15] + = { "list", "set", "dict", "tuple", + "i8", "i16", "i32", "i64", "f32", + "f64", "c32", "c64", "str", "bool", "i1"}; + for (int i = 0; i < 15; i++) { + if (strcmp(s2c(al, tvar_name), type_list[i]) == 0) { + throw SemanticError(tvar_name + " is a reserved type, consider a different type variable name", + x.base.base.loc); + } + } + // Check if the type variable is already defined + if (current_scope->get_scope().find(tvar_name) != + current_scope->get_scope().end()) { + ASR::symbol_t *orig_decl = current_scope->get_symbol(tvar_name); + throw SemanticError(diag::Diagnostic( + "Variable " + tvar_name + " is already declared in the same scope", + diag::Level::Error, diag::Stage::Semantic, { + diag::Label("original declaration", {orig_decl->base.loc}, false), + diag::Label("redeclaration", {x.base.base.loc}), + })); + } + + // Build ttype + Vec dims; + dims.reserve(al, 4); + + ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_TypeParameter_t(al, x.base.base.loc, + s2c(al, tvar_name))); + type = ASRUtils::make_Array_t_util(al, x.base.base.loc, type, dims.p, dims.size()); + + ASR::expr_t *value = nullptr; + ASR::expr_t *init_expr = nullptr; + ASR::intentType s_intent = ASRUtils::intent_local; + ASR::storage_typeType storage_type = ASR::storage_typeType::Default; + ASR::abiType current_procedure_abi_type = ASR::abiType::Source; + ASR::accessType s_access = ASR::accessType::Public; + ASR::presenceType s_presence = ASR::presenceType::Required; + bool value_attr = false; + + SetChar variable_dependencies_vec; + variable_dependencies_vec.reserve(al, 1); + ASRUtils::collect_variable_dependencies(al, variable_dependencies_vec, type, init_expr, value); + // Build the variable and add it to the scope + ASR::asr_t *v = ASR::make_Variable_t(al, x.base.base.loc, current_scope, + s2c(al, tvar_name), variable_dependencies_vec.p, variable_dependencies_vec.size(), + s_intent, init_expr, value, storage_type, type, nullptr, current_procedure_abi_type, + s_access, s_presence, value_attr, false, false, nullptr, false, false); + current_scope->add_symbol(tvar_name, ASR::down_cast(v)); + + tmp = nullptr; + + return; + } else { + // This error might need to be further elaborated + throw SemanticError("Type variable must be a variable", x.base.base.loc); + } + } + } } } From 1a78800309ae8301d9e27ead12fa02365ac45ed0 Mon Sep 17 00:00:00 2001 From: Amrita kumari mishra Date: Thu, 11 Dec 2025 13:07:24 +0000 Subject: [PATCH 6/6] Update libasr submodule pointer --- libasr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libasr b/libasr index 9c7c52c21f..f2a04fc2ae 160000 --- a/libasr +++ b/libasr @@ -1 +1 @@ -Subproject commit 9c7c52c21f847470c301cffd224f5cc2cf95fe63 +Subproject commit f2a04fc2ae4dd9ccb940c0fee3f694791fec7005