Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Merge call in visit_Expr() with visit_Call() #2306

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions integration_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,7 @@ RUN(NAME func_static_02 LABELS cpython llvm c wasm)
RUN(NAME func_dep_03 LABELS cpython llvm c)
RUN(NAME func_dep_04 LABELS cpython llvm c)
RUN(NAME func_internal_def_01 LABELS cpython llvm NOFAST)
RUN(NAME func_01 LABELS cpython llvm)

RUN(NAME float_01 LABELS cpython llvm c wasm wasm_x64)
RUN(NAME recursive_01 LABELS cpython llvm c wasm wasm_x64 wasm_x86)
Expand Down
14 changes: 14 additions & 0 deletions integration_tests/func_01.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from lpython import i32, InOut

def reserve(a: InOut[list[i32]], b: i32):
a.append(b)
print("user defined reserve() called")

def main0():
x: list[i32] = []
reserve(x, 5)

assert len(x) == 1
assert x[0] == 5

main0()
199 changes: 79 additions & 120 deletions src/lpython/semantics/python_ast_to_asr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1168,7 +1168,7 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
// generic symbol then it changes the name accordingly.
ASR::asr_t* make_call_helper(Allocator &al, ASR::symbol_t* s, SymbolTable *current_scope,
Vec<ASR::call_arg_t> args, std::string call_name, const Location &loc,
bool ignore_return_value=false, AST::expr_t** pos_args=nullptr, size_t n_pos_args=0,
AST::expr_t** pos_args=nullptr, size_t n_pos_args=0,
AST::keyword_t* kwargs=nullptr, size_t n_kwargs=0) {
if (intrinsic_node_handler.is_present(call_name)) {
return intrinsic_node_handler.get_intrinsic_node(call_name, al, loc,
Expand Down Expand Up @@ -1293,7 +1293,7 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
new_call_arg.loc = args.p[i].loc;
new_args.push_back(al, new_call_arg);
}
return make_call_helper(al, t, current_scope, new_args, new_call_name, loc, ignore_return_value);
return make_call_helper(al, t, current_scope, new_args, new_call_name, loc);
}
if (args.size() != func->n_args) {
std::string fnd = std::to_string(args.size());
Expand Down Expand Up @@ -1326,14 +1326,9 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
visit_expr_list_with_cast(func->m_args, func->n_args, args_new, args,
!ASRUtils::is_intrinsic_function2(func));
dependencies.push_back(al, ASRUtils::symbol_name(stemp));
ASR::asr_t* func_call_asr = ASRUtils::make_FunctionCall_t_util(al, loc, stemp,
return ASRUtils::make_FunctionCall_t_util(al, loc, stemp,
s_generic, args_new.p, args_new.size(),
a_type, value, nullptr);
if( ignore_return_value ) {
return make_dummy_assignment(ASRUtils::EXPR(func_call_asr));
} else {
return func_call_asr;
}
} else {
Vec<ASR::call_arg_t> args_new;
args_new.reserve(al, func->n_args);
Expand Down Expand Up @@ -6657,112 +6652,7 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
void visit_Expr(const AST::Expr_t &x) {
if (AST::is_a<AST::Call_t>(*x.m_value)) {
AST::Call_t *c = AST::down_cast<AST::Call_t>(x.m_value);
std::string call_name;
if (AST::is_a<AST::Name_t>(*c->m_func)) {
AST::Name_t *n = AST::down_cast<AST::Name_t>(c->m_func);
call_name = n->m_id;
ASR::symbol_t* s = current_scope->resolve_symbol(call_name);
if( call_name == "p_c_pointer" && !s ) {
tmp = create_PointerToCPtr(*c);
return;
}
} else if (AST::is_a<AST::Attribute_t>(*c->m_func)) {
Vec<ASR::call_arg_t> args;
parse_args(*c, args);
AST::Attribute_t *at = AST::down_cast<AST::Attribute_t>(c->m_func);
handle_attribute(at, args, x.base.base.loc);
return;
} else {
throw SemanticError("Only Name/Attribute supported in Call",
x.base.base.loc);
}

Vec<ASR::call_arg_t> args;
// Keyword arguments to be handled in make_call_helper
args.reserve(al, c->n_args);
visit_expr_list(c->m_args, c->n_args, args);
// TODO: Avoid overriding of user defined functions with same name as
// intrinsics like print, quit and reserve. Right now, user defined
// functions will never be considered.
if (call_name == "print") {
ASR::expr_t *fmt = nullptr;
Vec<ASR::expr_t*> args_expr = ASRUtils::call_arg2expr(al, args);
ASR::expr_t *separator = nullptr;
ASR::expr_t *end = nullptr;
if (c->n_keywords > 0) {
std::string arg_name;
for (size_t i = 0; i < c->n_keywords; i++) {
arg_name = c->m_keywords[i].m_arg;
if (arg_name == "sep") {
visit_expr(*c->m_keywords[i].m_value);
separator = ASRUtils::EXPR(tmp);
ASR::ttype_t *type = ASRUtils::expr_type(separator);
if (!ASRUtils::is_character(*type)) {
std::string found = ASRUtils::type_to_str(type);
diag.add(diag::Diagnostic(
"Separator is expected to be of string type",
diag::Level::Error, diag::Stage::Semantic, {
diag::Label("Expected string, found: " + found,
{separator->base.loc})
})
);
throw SemanticAbort();
}
}
if (arg_name == "end") {
visit_expr(*c->m_keywords[i].m_value);
end = ASRUtils::EXPR(tmp);
ASR::ttype_t *type = ASRUtils::expr_type(end);
if (!ASRUtils::is_character(*type)) {
std::string found = ASRUtils::type_to_str(type);
diag.add(diag::Diagnostic(
"End is expected to be of string type",
diag::Level::Error, diag::Stage::Semantic, {
diag::Label("Expected string, found: " + found,
{end->base.loc})
})
);
throw SemanticAbort();
}
}
}
}
tmp = ASR::make_Print_t(al, x.base.base.loc, fmt,
args_expr.p, args_expr.size(), separator, end);
return;

} else if (call_name == "quit") {
ASR::expr_t *code;
if (args.size() == 0) {
code = nullptr;
} else if (args.size() == 1) {
code = args[0].m_value;
} else {
throw SemanticError("The function quit() requires 0 or 1 arguments",
x.base.base.loc);
}
tmp = ASR::make_Stop_t(al, x.base.base.loc, code);
return;
} else if( call_name == "reserve" ) {
ASRUtils::create_intrinsic_function create_func =
ASRUtils::IntrinsicScalarFunctionRegistry::get_create_function("reserve");
Vec<ASR::expr_t*> args_exprs; args_exprs.reserve(al, args.size());
for( size_t i = 0; i < args.size(); i++ ) {
args_exprs.push_back(al, args[i].m_value);
}
tmp = create_func(al, x.base.base.loc, args_exprs,
[&](const std::string &msg, const Location &loc) {
throw SemanticError(msg, loc); });
return ;
}
ASR::symbol_t *s = current_scope->resolve_symbol(call_name);
if (!s) {
throw SemanticError("Function '" + call_name + "' is not declared",
x.base.base.loc);
}
tmp = make_call_helper(al, s, current_scope, args, call_name,
x.base.base.loc, true, c->m_args, c->n_args, c->m_keywords,
c->n_keywords);
visit_Call(*c);
return;
}
this->visit_expr(*x.m_value);
Expand Down Expand Up @@ -7524,12 +7414,78 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
/*
throw SemanticError("The function '" + call_name + "' is not declared and not intrinsic",
x.base.base.loc);
}
if (false) {
*/
// This will all be removed once we port it to intrinsic functions
// Intrinsic functions
if (call_name == "size") {
if (call_name == "print") {
args.reserve(al, x.n_args);
visit_expr_list(x.m_args, x.n_args, args);
ASR::expr_t *fmt = nullptr;
Vec<ASR::expr_t*> args_expr = ASRUtils::call_arg2expr(al, args);
ASR::expr_t *separator = nullptr;
ASR::expr_t *end = nullptr;
if (x.n_keywords > 0) {
std::string arg_name;
for (size_t i = 0; i < x.n_keywords; i++) {
arg_name = x.m_keywords[i].m_arg;
if (arg_name == "sep") {
visit_expr(*x.m_keywords[i].m_value);
separator = ASRUtils::EXPR(tmp);
ASR::ttype_t *type = ASRUtils::expr_type(separator);
if (!ASRUtils::is_character(*type)) {
std::string found = ASRUtils::type_to_str(type);
diag.add(diag::Diagnostic(
"Separator is expected to be of string type",
diag::Level::Error, diag::Stage::Semantic, {
diag::Label("Expected string, found: " + found,
{separator->base.loc})
})
);
throw SemanticAbort();
}
}
if (arg_name == "end") {
visit_expr(*x.m_keywords[i].m_value);
end = ASRUtils::EXPR(tmp);
ASR::ttype_t *type = ASRUtils::expr_type(end);
if (!ASRUtils::is_character(*type)) {
std::string found = ASRUtils::type_to_str(type);
diag.add(diag::Diagnostic(
"End is expected to be of string type",
diag::Level::Error, diag::Stage::Semantic, {
diag::Label("Expected string, found: " + found,
{end->base.loc})
})
);
throw SemanticAbort();
}
}
}
}
tmp = ASR::make_Print_t(al, x.base.base.loc, fmt,
args_expr.p, args_expr.size(), separator, end);
return;
} else if (call_name == "quit") {
parse_args(x, args);
ASR::expr_t *code;
if (args.size() == 0) {
code = nullptr;
} else if (args.size() == 1) {
code = args[0].m_value;
} else {
throw SemanticError("The function quit() requires 0 or 1 arguments",
x.base.base.loc);
}
tmp = ASR::make_Stop_t(al, x.base.base.loc, code);
return;
} else if( call_name == "reserve" ) {
parse_args(x, args);
ASRUtils::create_intrinsic_function create_func =
ASRUtils::IntrinsicScalarFunctionRegistry::get_create_function("reserve");
Vec<ASR::expr_t*> args_exprs = ASRUtils::call_arg2expr(al, args);
tmp = create_func(al, x.base.base.loc, args_exprs,
[&](const std::string &msg, const Location &loc) {
throw SemanticError(msg, loc); });
return ;
} else if (call_name == "size") {
parse_args(x, args);
if( args.size() < 1 || args.size() > 2 ) {
throw SemanticError("array accepts only 1 (arr) or 2 (arr, axis) arguments, got " +
Expand All @@ -7555,6 +7511,9 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
} else if (call_name == "c_p_pointer") {
tmp = create_CPtrToPointer(x);
return;
} else if( call_name == "p_c_pointer" && !s ) {
tmp = create_PointerToCPtr(x);
return;
} else if (call_name == "empty_c_void_p") {
// TODO: check that `empty_c_void_p uses` has arguments that are compatible
// with the type
Expand Down Expand Up @@ -7860,7 +7819,7 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {

parse_args(x, args);
tmp = make_call_helper(al, s, current_scope, args, call_name, x.base.base.loc,
false, x.m_args, x.n_args, x.m_keywords, x.n_keywords);
x.m_args, x.n_args, x.m_keywords, x.n_keywords);
}

void visit_Global(const AST::Global_t &/*x*/) {
Expand Down