Skip to content

Commit e15b4b0

Browse files
Handle the importing of global statements,
- Each module contains two functions: `global_statements` and `global_initializer`. - `global_statements` contains all the global statements in the module. - `global_initializer` contains the assign statements that are used to initialize the list or other types that cannot be handled in LLVM's global scope.
1 parent c28cef0 commit e15b4b0

File tree

2 files changed

+144
-83
lines changed

2 files changed

+144
-83
lines changed

src/libasr/asr_scopes.cpp

Lines changed: 0 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -206,47 +206,6 @@ void SymbolTable::move_symbols_from_global_scope(Allocator &al,
206206
es->m_parent_symtab = module_scope;
207207
ASR::symbol_t *s = ASRUtils::symbol_get_past_external(a.second);
208208
LCOMPILERS_ASSERT(s);
209-
if (ASR::is_a<ASR::Variable_t>(*s)) {
210-
ASR::Variable_t *v = ASR::down_cast<ASR::Variable_t>(s);
211-
if (v->m_symbolic_value && !ASR::is_a<ASR::Const_t>(*v->m_type)
212-
&& ASR::is_a<ASR::List_t>(*v->m_type)) {
213-
ASR::expr_t* target = ASRUtils::EXPR(ASR::make_Var_t(
214-
al, v->base.base.loc, (ASR::symbol_t *) es));
215-
ASR::expr_t *value = v->m_symbolic_value;
216-
v->m_symbolic_value = nullptr;
217-
v->m_value = nullptr;
218-
if (ASR::is_a<ASR::FunctionCall_t>(*value)) {
219-
ASR::FunctionCall_t *call =
220-
ASR::down_cast<ASR::FunctionCall_t>(value);
221-
ASR::Module_t *m = ASRUtils::get_sym_module(s);
222-
ASR::symbol_t *func = m->m_symtab->get_symbol(
223-
ASRUtils::symbol_name(call->m_name));
224-
ASR::Function_t *f = ASR::down_cast<ASR::Function_t>(func);
225-
std::string func_name = std::string(m->m_name) +
226-
"@" + f->m_name;
227-
ASR::symbol_t *es_func;
228-
if (!module_scope->get_symbol(func_name)) {
229-
es_func = ASR::down_cast<ASR::symbol_t>(
230-
ASR::make_ExternalSymbol_t(al, f->base.base.loc,
231-
module_scope, s2c(al, func_name), func, m->m_name,
232-
nullptr, 0, s2c(al, f->m_name), ASR::accessType::Public));
233-
module_scope->add_symbol(func_name, es_func);
234-
if (!present(func_dependencies, s2c(al, func_name))) {
235-
func_dependencies.push_back(al, s2c(al,func_name));
236-
}
237-
} else {
238-
es_func = module_scope->get_symbol(func_name);
239-
}
240-
value = ASRUtils::EXPR(ASR::make_FunctionCall_t(al,
241-
call->base.base.loc, es_func, call->m_original_name,
242-
call->m_args, call->n_args, call->m_type,
243-
call->m_value, call->m_dt));
244-
}
245-
ASR::asr_t* assign = ASR::make_Assignment_t(al,
246-
v->base.base.loc, target, value, nullptr);
247-
var_init.push_back(al, ASRUtils::STMT(assign));
248-
}
249-
}
250209
module_scope->add_symbol(a.first, (ASR::symbol_t *) es);
251210
syms.push_back(al, s2c(al, a.first));
252211
break;
@@ -271,24 +230,6 @@ void SymbolTable::move_symbols_from_global_scope(Allocator &al,
271230
} case (ASR::symbolType::Variable) : {
272231
ASR::Variable_t *v = ASR::down_cast<ASR::Variable_t>(a.second);
273232
v->m_parent_symtab = module_scope;
274-
// Make the Assignment statement only for the data-types (List,
275-
// Dict, ...), that cannot be handled in the LLVM global scope
276-
if (v->m_symbolic_value && !ASR::is_a<ASR::Const_t>(*v->m_type)
277-
&& ASR::is_a<ASR::List_t>(*v->m_type)) {
278-
ASR::expr_t* v_expr = ASRUtils::EXPR(ASR::make_Var_t(
279-
al, v->base.base.loc, (ASR::symbol_t *) v));
280-
ASR::asr_t* assign = ASR::make_Assignment_t(al,
281-
v->base.base.loc, v_expr, v->m_symbolic_value, nullptr);
282-
var_init.push_back(al, ASRUtils::STMT(assign));
283-
v->m_symbolic_value = nullptr;
284-
v->m_value = nullptr;
285-
Vec<char*> v_dependencies;
286-
v_dependencies.reserve(al, 1);
287-
ASRUtils::collect_variable_dependencies(al,
288-
v_dependencies, v->m_type);
289-
v->m_dependencies = v_dependencies.p;
290-
v->n_dependencies = v_dependencies.size();
291-
}
292233
module_scope->add_symbol(a.first, (ASR::symbol_t *) v);
293234
syms.push_back(al, s2c(al, a.first));
294235
break;

src/lpython/semantics/python_ast_to_asr.cpp

Lines changed: 144 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <libasr/utils.h>
2020
#include <libasr/pass/global_stmts_program.h>
2121
#include <libasr/pass/instantiate_template.h>
22+
#include <libasr/pass/global_stmts.h>
2223
#include <libasr/modfile.h>
2324

2425
#include <lpython/python_ast.h>
@@ -520,6 +521,9 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
520521
*/
521522
std::vector<ASR::asr_t *> tmp_vec;
522523

524+
// Used to store the initializer for the global variables like list, ...
525+
Vec<ASR::asr_t *> global_init;
526+
523527
Allocator &al;
524528
LocationManager &lm;
525529
SymbolTable *current_scope;
@@ -557,6 +561,7 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
557561
current_body{nullptr}, ann_assign_target_type{nullptr},
558562
assign_ast_target{nullptr}, is_c_p_pointer_call{false}, allow_implicit_casting{allow_implicit_casting_} {
559563
current_module_dependencies.reserve(al, 4);
564+
global_init.reserve(al, 1);
560565
}
561566

562567
ASR::asr_t* resolve_variable(const Location &loc, const std::string &var_name) {
@@ -2239,13 +2244,17 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
22392244
ASR::symbol_t* v_sym = ASR::down_cast<ASR::symbol_t>(v);
22402245
ASR::Variable_t* v_variable = ASR::down_cast<ASR::Variable_t>(v_sym);
22412246

2242-
if( init_expr && current_body &&
2247+
if( init_expr && (current_body || ASR::is_a<ASR::List_t>(*type)) &&
22432248
(is_runtime_expression || !is_variable_const)) {
22442249
ASR::expr_t* v_expr = ASRUtils::EXPR(ASR::make_Var_t(al, loc, v_sym));
22452250
cast_helper(v_expr, init_expr, true);
22462251
ASR::asr_t* assign = ASR::make_Assignment_t(al, loc, v_expr,
22472252
init_expr, nullptr);
2248-
current_body->push_back(al, ASRUtils::STMT(assign));
2253+
if (current_body) {
2254+
current_body->push_back(al, ASRUtils::STMT(assign));
2255+
} else if (ASR::is_a<ASR::List_t>(*type)) {
2256+
global_init.push_back(al, assign);
2257+
}
22492258

22502259
v_variable->m_symbolic_value = nullptr;
22512260
v_variable->m_value = nullptr;
@@ -3945,10 +3954,53 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
39453954
mod->m_dependencies = current_module_dependencies.p;
39463955
mod->n_dependencies = current_module_dependencies.size();
39473956
}
3948-
// These global statements are added to the translation unit for now,
3949-
// but they should be adding to a module initialization function
3957+
3958+
if (global_init.n > 0 && main_module_sym) {
3959+
// unit->m_items is used and set to nullptr in the
3960+
// `pass_wrap_global_stmts_into_function` pass
3961+
unit->m_items = global_init.p;
3962+
unit->n_items = global_init.size();
3963+
std::string func_name = "global_initializer";
3964+
LCompilers::PassOptions pass_options;
3965+
pass_options.run_fun = func_name;
3966+
pass_wrap_global_stmts_into_function(al, *unit, pass_options);
3967+
3968+
ASR::Module_t *mod = ASR::down_cast<ASR::Module_t>(main_module_sym);
3969+
ASR::symbol_t *f_sym = unit->m_global_scope->get_symbol(func_name);
3970+
if (f_sym) {
3971+
// Add the `global_initilaizer` function into the `__main__`
3972+
// module and later call this function to initialize the
3973+
// global variables like list, ...
3974+
ASR::Function_t *f = ASR::down_cast<ASR::Function_t>(f_sym);
3975+
f->m_symtab->parent = mod->m_symtab;
3976+
mod->m_symtab->add_symbol(func_name, (ASR::symbol_t *) f);
3977+
// Erase the function in TranslationUnit
3978+
unit->m_global_scope->erase_symbol(func_name);
3979+
}
3980+
}
3981+
39503982
unit->m_items = items.p;
39513983
unit->n_items = items.size();
3984+
if (items.n > 0 && main_module_sym) {
3985+
std::string func_name = "global_statements";
3986+
// Wrap all the global statements into a Function
3987+
LCompilers::PassOptions pass_options;
3988+
pass_options.run_fun = func_name;
3989+
pass_wrap_global_stmts_into_function(al, *unit, pass_options);
3990+
3991+
ASR::Module_t *mod = ASR::down_cast<ASR::Module_t>(main_module_sym);
3992+
ASR::symbol_t *f_sym = unit->m_global_scope->get_symbol(func_name);
3993+
if (f_sym) {
3994+
// Add the `global_statements` function into the `__main__`
3995+
// module and later call this function to execute the
3996+
// global_statements
3997+
ASR::Function_t *f = ASR::down_cast<ASR::Function_t>(f_sym);
3998+
f->m_symtab->parent = mod->m_symtab;
3999+
mod->m_symtab->add_symbol(func_name, (ASR::symbol_t *) f);
4000+
// Erase the function in TranslationUnit
4001+
unit->m_global_scope->erase_symbol(func_name);
4002+
}
4003+
}
39524004

39534005
tmp = asr;
39544006
}
@@ -4009,8 +4061,81 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
40094061
}
40104062
}
40114063

4012-
void visit_Import(const AST::Import_t &/*x*/) {
4013-
// visited in symbol visitor
4064+
void visit_Import(const AST::Import_t &x) {
4065+
// All the modules are imported in the SymbolTable visitor
4066+
// Here, we call the global_initializer & global_statements to
4067+
// initialize and execute the global symbols
4068+
for (size_t i = 0; i < x.n_names; i++) {
4069+
std::string mod_name = x.m_names[i].m_name;
4070+
ASR::symbol_t *mod_sym = current_scope->resolve_symbol(mod_name);
4071+
if (mod_sym) {
4072+
ASR::Module_t *mod = ASR::down_cast<ASR::Module_t>(mod_sym);
4073+
4074+
std::string g_func_name = mod_name + "@global_initializer";
4075+
ASR::symbol_t *g_func = mod->m_symtab->get_symbol("global_initializer");
4076+
if (g_func && !current_scope->get_symbol(g_func_name)) {
4077+
ASR::symbol_t *es = ASR::down_cast<ASR::symbol_t>(
4078+
ASR::make_ExternalSymbol_t(al, mod->base.base.loc,
4079+
current_scope, s2c(al, g_func_name), g_func,
4080+
s2c(al, mod_name), nullptr, 0, s2c(al, "global_initializer"),
4081+
ASR::accessType::Public));
4082+
current_scope->add_symbol(g_func_name, es);
4083+
tmp_vec.push_back(ASR::make_SubroutineCall_t(al, x.base.base.loc,
4084+
es, g_func, nullptr, 0, nullptr));
4085+
}
4086+
4087+
g_func_name = mod_name + "@global_statements";
4088+
g_func = mod->m_symtab->get_symbol("global_statements");
4089+
if (g_func && !current_scope->get_symbol(g_func_name)) {
4090+
ASR::symbol_t *es = ASR::down_cast<ASR::symbol_t>(
4091+
ASR::make_ExternalSymbol_t(al, mod->base.base.loc,
4092+
current_scope, s2c(al, g_func_name), g_func,
4093+
s2c(al, mod_name), nullptr, 0, s2c(al, "global_statements"),
4094+
ASR::accessType::Public));
4095+
current_scope->add_symbol(g_func_name, es);
4096+
tmp_vec.push_back(ASR::make_SubroutineCall_t(al, x.base.base.loc,
4097+
es, g_func, nullptr, 0, nullptr));
4098+
}
4099+
}
4100+
}
4101+
}
4102+
4103+
void visit_ImportFrom(const AST::ImportFrom_t &x) {
4104+
// Handled by SymbolTableVisitor already
4105+
// Here, we call the global_initializer & global_statements to
4106+
// initialize and execute the global symbols
4107+
std::string mod_name = x.m_module;
4108+
ASR::symbol_t *mod_sym = current_scope->resolve_symbol(mod_name);
4109+
if (mod_sym) {
4110+
ASR::Module_t *mod = ASR::down_cast<ASR::Module_t>(mod_sym);
4111+
4112+
std::string g_func_name = mod_name + "@global_initializer";
4113+
ASR::symbol_t *g_func = mod->m_symtab->get_symbol("global_initializer");
4114+
if (g_func && !current_scope->get_symbol(g_func_name)) {
4115+
ASR::symbol_t *es = ASR::down_cast<ASR::symbol_t>(
4116+
ASR::make_ExternalSymbol_t(al, mod->base.base.loc,
4117+
current_scope, s2c(al, g_func_name), g_func,
4118+
s2c(al, mod_name), nullptr, 0, s2c(al, "global_initializer"),
4119+
ASR::accessType::Public));
4120+
current_scope->add_symbol(g_func_name, es);
4121+
tmp_vec.push_back(ASR::make_SubroutineCall_t(al, x.base.base.loc,
4122+
es, g_func, nullptr, 0, nullptr));
4123+
}
4124+
4125+
g_func_name = mod_name + "@global_statements";
4126+
g_func = mod->m_symtab->get_symbol("global_statements");
4127+
if (g_func && !current_scope->get_symbol(g_func_name)) {
4128+
ASR::symbol_t *es = ASR::down_cast<ASR::symbol_t>(
4129+
ASR::make_ExternalSymbol_t(al, mod->base.base.loc,
4130+
current_scope, s2c(al, g_func_name), g_func,
4131+
s2c(al, mod_name), nullptr, 0, s2c(al, "global_statements"),
4132+
ASR::accessType::Public));
4133+
current_scope->add_symbol(g_func_name, es);
4134+
tmp_vec.push_back(ASR::make_SubroutineCall_t(al, x.base.base.loc,
4135+
es, g_func, nullptr, 0, nullptr));
4136+
}
4137+
}
4138+
tmp = nullptr;
40144139
}
40154140

40164141
void visit_AnnAssign(const AST::AnnAssign_t &x) {
@@ -5749,15 +5874,15 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
57495874
fn_args.push_back(al, suffix);
57505875
} else if (attr_name == "partition") {
57515876

5752-
/*
5877+
/*
57535878
str.partition(seperator) ---->
57545879
5755-
Split the string at the first occurrence of sep, and return a 3-tuple containing the part
5756-
before the separator, the separator itself, and the part after the separator.
5757-
If the separator is not found, return a 3-tuple containing the string itself, followed
5880+
Split the string at the first occurrence of sep, and return a 3-tuple containing the part
5881+
before the separator, the separator itself, and the part after the separator.
5882+
If the separator is not found, return a 3-tuple containing the string itself, followed
57585883
by two empty strings.
57595884
*/
5760-
5885+
57615886
if(args.size() != 1) {
57625887
throw SemanticError("str.partition() takes one argument",
57635888
loc);
@@ -5830,7 +5955,7 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
58305955
return res;
58315956
}
58325957

5833-
ASR::expr_t* eval_partition(std::string &s_var, ASR::expr_t* arg_seperator,
5958+
ASR::expr_t* eval_partition(std::string &s_var, ASR::expr_t* arg_seperator,
58345959
const Location &loc, ASR::ttype_t *arg_seperator_type) {
58355960
/*
58365961
Invoked when Seperator argument is provided as a constant string
@@ -5841,16 +5966,16 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
58415966
throw SemanticError("empty separator", arg_seperator->base.loc);
58425967
}
58435968
/*
5844-
using KMP algorithm to find seperator inside string
5845-
res_tuple: stores the resulting 3-tuple expression --->
5969+
using KMP algorithm to find seperator inside string
5970+
res_tuple: stores the resulting 3-tuple expression --->
58465971
(if seperator exist) tuple: (left of seperator, seperator, right of seperator)
58475972
(if seperator does not exist) tuple: (string, "", "")
58485973
res_tuple_type: stores the type of each expression present in resulting 3-tuple
58495974
*/
58505975
int seperator_pos = KMP_string_match(s_var, seperator);
58515976
Vec<ASR::expr_t *> res_tuple;
58525977
Vec<ASR::ttype_t *> res_tuple_type;
5853-
res_tuple.reserve(al, 3);
5978+
res_tuple.reserve(al, 3);
58545979
res_tuple_type.reserve(al, 3);
58555980
std :: string first_res, second_res, third_res;
58565981
if(seperator_pos == -1) {
@@ -6104,11 +6229,11 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
61046229
}
61056230
return;
61066231
} else if (attr_name == "partition") {
6107-
/*
6232+
/*
61086233
str.partition(seperator) ---->
6109-
Split the string at the first occurrence of sep, and return a 3-tuple containing the part
6110-
before the separator, the separator itself, and the part after the separator.
6111-
If the separator is not found, return a 3-tuple containing the string itself, followed
6234+
Split the string at the first occurrence of sep, and return a 3-tuple containing the part
6235+
before the separator, the separator itself, and the part after the separator.
6236+
If the separator is not found, return a 3-tuple containing the string itself, followed
61126237
by two empty strings.
61136238
*/
61146239
if (args.size() != 1) {
@@ -6438,11 +6563,6 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
64386563
false, x.m_args, x.n_args, x.m_keywords, x.n_keywords);
64396564
}
64406565

6441-
void visit_ImportFrom(const AST::ImportFrom_t &/*x*/) {
6442-
// Handled by SymbolTableVisitor already
6443-
tmp = nullptr;
6444-
}
6445-
64466566
void visit_Global(const AST::Global_t &/*x*/) {
64476567
tmp = nullptr;
64486568
}

0 commit comments

Comments
 (0)