Skip to content

Commit b94d46d

Browse files
authored
Sync libasr from LFortran (#2148)
1 parent b39a2cb commit b94d46d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+2893
-1808
lines changed

integration_tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,7 @@ RUN(NAME loop_02 LABELS cpython llvm c wasm wasm_x86 wasm_x64)
432432
RUN(NAME loop_03 LABELS cpython llvm c wasm wasm_x64)
433433
RUN(NAME loop_04 LABELS cpython llvm c)
434434
RUN(NAME loop_05 LABELS cpython llvm c)
435+
RUN(NAME loop_06 LABELS cpython llvm c NOFAST)
435436
RUN(NAME if_01 LABELS cpython llvm c wasm wasm_x86 wasm_x64)
436437
RUN(NAME if_02 LABELS cpython llvm c wasm wasm_x86 wasm_x64)
437438
RUN(NAME if_03 FAIL LABELS cpython llvm c NOFAST)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
1+
from lpython import i32
12
from sys import exit
23

34
def test_for():
45
i: i32
6+
j: i32; k: i32;
7+
k = 0
58
for i in range(0, 10):
69
if i == 0:
10+
j = 0
711
continue
812
if i > 5:
13+
k = k + i
914
break
1015
if i == 3:
16+
print(j, k)
17+
assert j == 0
18+
assert k == 0
1119
quit()
20+
print(j, k)
1221
exit(2)
1322

1423
test_for()

src/libasr/ASR.asdl

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,10 @@ symbol
111111
identifier proc_name, symbol proc, abi abi, bool is_deferred)
112112
| AssociateBlock(symbol_table symtab, identifier name, stmt* body)
113113
| Block(symbol_table symtab, identifier name, stmt* body)
114-
| Requirement(symbol_table symtab, identifier name, identifier* args)
115-
| Template(symbol_table symtab, identifier name, identifier* args)
114+
| Requirement(symbol_table symtab, identifier name, identifier* args,
115+
require_instantiation* requires)
116+
| Template(symbol_table symtab, identifier name, identifier* args,
117+
require_instantiation* requires)
116118

117119
storage_type = Default | Save | Parameter
118120
access = Public | Private
@@ -237,6 +239,8 @@ expr
237239
ttype type, expr? value, expr? dt)
238240
| IntrinsicFunction(int intrinsic_id, expr* args, int overload_id,
239241
ttype? type, expr? value)
242+
| IntrinsicImpureFunction(int impure_intrinsic_id, expr* args, int overload_id,
243+
ttype? type, expr? value)
240244
| StructTypeConstructor(symbol dt_sym, call_arg* args, ttype type, expr? value)
241245
| EnumTypeConstructor(symbol dt_sym, expr* args, ttype type, expr? value)
242246
| UnionTypeConstructor(symbol dt_sym, expr* args, ttype type, expr? value)
@@ -289,6 +293,7 @@ expr
289293
| StringCompare(expr left, cmpop op, expr right, ttype type, expr? value)
290294
| StringOrd(expr arg, ttype type, expr? value)
291295
| StringChr(expr arg, ttype type, expr? value)
296+
| StringFormat(expr fmt, expr* args, string_format_kind kind, ttype type, expr? value)
292297

293298
| CPtrCompare(expr left, cmpop op, expr right, ttype type, expr? value)
294299
| SymbolicCompare(expr left, cmpop op, expr right, ttype type, expr? value)
@@ -461,7 +466,7 @@ cast_kind
461466

462467
dimension = (expr? start, expr? length)
463468

464-
alloc_arg = (expr a, dimension* dims)
469+
alloc_arg = (expr a, dimension* dims, expr? len_expr, ttype? type)
465470

466471
attribute = Attribute(identifier name, attribute_arg *args)
467472

@@ -484,4 +489,13 @@ type_stmt
484489

485490
enumtype = IntegerConsecutiveFromZero | IntegerUnique | IntegerNotUnique | NonInteger
486491

492+
require_instantiation = Require(identifier name, identifier* args)
493+
494+
string_format_kind
495+
= FormatFortran -- "(f8.3,i4.2)", a, b
496+
| FormatC -- "%f: %d", a, b
497+
| FormatPythonPercent -- "%f: %d" % (a, b)
498+
| FormatPythonFString -- f"{a}: {b}"
499+
| FormatPythonFormat -- "{}: {}".format(a, b)
500+
487501
}

src/libasr/asdl_cpp.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,6 +1109,8 @@ def visitField(self, field):
11091109
self.emit(" ASR::alloc_arg_t alloc_arg_copy;", level)
11101110
self.emit(" alloc_arg_copy.loc = x->m_%s[i].loc;"%(field.name), level)
11111111
self.emit(" alloc_arg_copy.m_a = self().duplicate_expr(x->m_%s[i].m_a);"%(field.name), level)
1112+
self.emit(" alloc_arg_copy.m_len_expr = self().duplicate_expr(x->m_%s[i].m_len_expr);"%(field.name), level)
1113+
self.emit(" alloc_arg_copy.m_type = self().duplicate_ttype(x->m_%s[i].m_type);"%(field.name), level)
11121114
self.emit(" alloc_arg_copy.n_dims = x->m_%s[i].n_dims;"%(field.name), level)
11131115
self.emit(" Vec<ASR::dimension_t> dims_copy;", level)
11141116
self.emit(" dims_copy.reserve(al, alloc_arg_copy.n_dims);", level)
@@ -1678,6 +1680,8 @@ def visitField(self, field, cons):
16781680
else:
16791681
if field.name == "intrinsic_id":
16801682
self.emit('s.append(self().convert_intrinsic_id(x.m_%s));' % field.name, 2)
1683+
elif field.name == "impure_intrinsic_id":
1684+
self.emit('s.append(self().convert_impure_intrinsic_id(x.m_%s));' % field.name, 2)
16811685
else:
16821686
self.emit('s.append(std::to_string(x.m_%s));' % field.name, 2)
16831687
elif field.type == "float" and not field.seq and not field.opt:

src/libasr/asr_scopes.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,11 @@ ASR::symbol_t *SymbolTable::find_scoped_symbol(const std::string &name,
8282
}
8383
}
8484

85-
std::string SymbolTable::get_unique_name(const std::string &name) {
85+
std::string SymbolTable::get_unique_name(const std::string &name, bool use_unique_id) {
8686
std::string unique_name = name;
87+
if( use_unique_id ) {
88+
unique_name += "_" + lcompilers_unique_ID;
89+
}
8790
int counter = 1;
8891
while (scope.find(unique_name) != scope.end()) {
8992
unique_name = name + std::to_string(counter);

src/libasr/asr_scopes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ struct SymbolTable {
9595
ASR::symbol_t *find_scoped_symbol(const std::string &name,
9696
size_t n_scope_names, char **m_scope_names);
9797

98-
std::string get_unique_name(const std::string &name);
98+
std::string get_unique_name(const std::string &name, bool use_unique_id=true);
9999

100100
void move_symbols_from_global_scope(Allocator &al,
101101
SymbolTable *module_scope, Vec<char *> &syms,

src/libasr/asr_utils.cpp

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,91 @@ void extract_module_python(const ASR::TranslationUnit_t &m,
133133
}
134134
}
135135

136+
void update_call_args(Allocator &al, SymbolTable *current_scope, bool implicit_interface) {
137+
/*
138+
Iterate over body of program, check if there are any subroutine calls if yes, iterate over its args
139+
and update the args if they are equal to the old symbol
140+
For example:
141+
function func(f)
142+
double precision c
143+
call sub2(c)
144+
print *, c(d)
145+
end function
146+
This function updates `sub2` to use the new symbol `c` that is now a function, not a variable.
147+
Along with this, it also updates the args of `sub2` to use the new symbol `c` instead of the old one.
148+
*/
149+
class UpdateArgsVisitor : public PassUtils::PassVisitor<UpdateArgsVisitor>
150+
{
151+
public:
152+
SymbolTable* scope = current_scope;
153+
UpdateArgsVisitor(Allocator &al) : PassVisitor(al, nullptr) {}
154+
155+
ASR::symbol_t* fetch_sym(ASR::symbol_t* arg_sym_underlying) {
156+
ASR::symbol_t* sym = nullptr;
157+
if (ASR::is_a<ASR::Variable_t>(*arg_sym_underlying)) {
158+
ASR::Variable_t* arg_variable = ASR::down_cast<ASR::Variable_t>(arg_sym_underlying);
159+
std::string arg_variable_name = std::string(arg_variable->m_name);
160+
sym = arg_variable->m_parent_symtab->get_symbol(arg_variable_name);
161+
} else if (ASR::is_a<ASR::Function_t>(*arg_sym_underlying)) {
162+
ASR::Function_t* arg_function = ASR::down_cast<ASR::Function_t>(arg_sym_underlying);
163+
std::string arg_function_name = std::string(arg_function->m_name);
164+
sym = arg_function->m_symtab->parent->get_symbol(arg_function_name);
165+
}
166+
return sym;
167+
}
168+
169+
void visit_SubroutineCall(const ASR::SubroutineCall_t& x) {
170+
ASR::SubroutineCall_t* subrout_call = (ASR::SubroutineCall_t*)(&x);
171+
for (size_t j = 0; j < subrout_call->n_args; j++) {
172+
ASR::call_arg_t arg = subrout_call->m_args[j];
173+
ASR::expr_t* arg_expr = arg.m_value;
174+
if (ASR::is_a<ASR::Var_t>(*arg_expr)) {
175+
ASR::Var_t* arg_var = ASR::down_cast<ASR::Var_t>(arg_expr);
176+
ASR::symbol_t* arg_sym = arg_var->m_v;
177+
ASR::symbol_t* arg_sym_underlying = ASRUtils::symbol_get_past_external(arg_sym);
178+
ASR::symbol_t* sym = fetch_sym(arg_sym_underlying);
179+
if (sym != arg_sym) {
180+
subrout_call->m_args[j].m_value = ASRUtils::EXPR(ASR::make_Var_t(al, arg_expr->base.loc, sym));
181+
}
182+
}
183+
}
184+
}
185+
186+
void visit_Function(const ASR::Function_t& x) {
187+
ASR::Function_t* func = (ASR::Function_t*)(&x);
188+
for (size_t i = 0; i < func->n_args; i++) {
189+
ASR::expr_t* arg_expr = func->m_args[i];
190+
if (ASR::is_a<ASR::Var_t>(*arg_expr)) {
191+
ASR::Var_t* arg_var = ASR::down_cast<ASR::Var_t>(arg_expr);
192+
ASR::symbol_t* arg_sym = arg_var->m_v;
193+
ASR::symbol_t* arg_sym_underlying = ASRUtils::symbol_get_past_external(arg_sym);
194+
ASR::symbol_t* sym = fetch_sym(arg_sym_underlying);
195+
if (sym != arg_sym) {
196+
func->m_args[i] = ASRUtils::EXPR(ASR::make_Var_t(al, arg_expr->base.loc, sym));
197+
}
198+
}
199+
}
200+
scope = func->m_symtab;
201+
for (auto &it: scope->get_scope()) {
202+
visit_symbol(*it.second);
203+
}
204+
scope = func->m_symtab;
205+
for (size_t i = 0; i < func->n_body; i++) {
206+
visit_stmt(*func->m_body[i]);
207+
}
208+
scope = func->m_symtab;
209+
}
210+
};
211+
212+
if (implicit_interface) {
213+
UpdateArgsVisitor v(al);
214+
SymbolTable *tu_symtab = ASRUtils::get_tu_symtab(current_scope);
215+
ASR::asr_t* asr_ = tu_symtab->asr_owner;
216+
ASR::TranslationUnit_t* tu = ASR::down_cast2<ASR::TranslationUnit_t>(asr_);
217+
v.visit_TranslationUnit(*tu);
218+
}
219+
}
220+
136221
ASR::Module_t* extract_module(const ASR::TranslationUnit_t &m) {
137222
LCOMPILERS_ASSERT(m.m_global_scope->get_scope().size()== 1);
138223
for (auto &a : m.m_global_scope->get_scope()) {
@@ -368,7 +453,7 @@ ASR::asr_t* getStructInstanceMember_t(Allocator& al, const Location& loc,
368453
}
369454
std::string mangled_name = current_scope->get_unique_name(
370455
std::string(module_name) + "_" +
371-
std::string(der_type_name));
456+
std::string(der_type_name), false);
372457
char* mangled_name_char = s2c(al, mangled_name);
373458
if( current_scope->get_symbol(mangled_name) == nullptr ) {
374459
bool make_new_ext_sym = true;
@@ -789,7 +874,7 @@ void process_overloaded_assignment_function(ASR::symbol_t* proc, ASR::expr_t* ta
789874
ASRUtils::insert_module_dependency(a_name, al, current_module_dependencies);
790875
ASRUtils::set_absent_optional_arguments_to_null(a_args, subrout, al);
791876
asr = ASRUtils::make_SubroutineCall_t_util(al, loc, a_name, sym,
792-
a_args.p, 2, nullptr);
877+
a_args.p, 2, nullptr, nullptr, false);
793878
}
794879
}
795880
}
@@ -1129,7 +1214,7 @@ ASR::asr_t* symbol_resolve_external_generic_procedure_without_eval(
11291214
}
11301215
return ASRUtils::make_SubroutineCall_t_util(al, loc, final_sym,
11311216
v, args.p, args.size(),
1132-
nullptr);
1217+
nullptr, nullptr, false);
11331218
} else {
11341219
if( func ) {
11351220
ASRUtils::set_absent_optional_arguments_to_null(args, func, al);

0 commit comments

Comments
 (0)