-
Notifications
You must be signed in to change notification settings - Fork 171
Interactive Shell: Printing top level expression #2698
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
Conversation
@@ -91,6 +91,7 @@ void pass_wrap_global_stmts(Allocator &al, | |||
target = return_var_ref; | |||
idx++; | |||
} else { | |||
// TODO: We will need to add support to return other ASR::ttypeType::* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We will need to handle all other cases like list
, set
, dict
, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tests are going to fail due to this reason.
@@ -119,7 +120,7 @@ void pass_wrap_global_stmts(Allocator &al, | |||
/* a_body */ body.p, | |||
/* n_body */ body.size(), | |||
/* a_return_var */ (return_var ? return_var_ref : nullptr), | |||
(return_var ? ASR::abiType::BindC : ASR::abiType::Source), | |||
ASR::abiType::Source, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have changed this because asr_to_llvm
changes the final function depending on ABI type (Look at
lpython/src/libasr/codegen/asr_to_llvm.cpp
Lines 3794 to 3805 in 476d9bb
if (ASRUtils::get_FunctionType(x)->m_abi == ASR::abiType::BindC) { | |
if (ASRUtils::get_FunctionType(x)->m_bindc_name) { | |
fn_name = ASRUtils::get_FunctionType(x)->m_bindc_name; | |
} else { | |
fn_name = sym_name; | |
} | |
} else if (ASRUtils::get_FunctionType(x)->m_deftype == ASR::deftypeType::Interface && | |
ASRUtils::get_FunctionType(x)->m_abi != ASR::abiType::Intrinsic) { | |
fn_name = sym_name; | |
} else { | |
fn_name = mangle_prefix + sym_name; | |
} |
PythonCompile.evaluate
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you check if this change works with LFortran? Simply submit a PR with this exact change and we can see if the CI passes.
} else if (return_type == "none") { | ||
result.type = EvalResult::none; | ||
} else { | ||
throw LCompilersException("FortranEvaluator::evaluate(): Return type not supported"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking we could accept struct
as the return type here for dict
, list
, etc. And handle it accordingly.
But I have no idea how would we print it later.
Example:
>>> n: list[i32] = [1, 2, 3]
>>> n.append(4)
>>> n
We would like to print the list n
in the last line. But it would be returned as a struct
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's wrap this code into a new function that returns the return
variable (or populates it when passed as argument).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok will do it in the next commit.
@@ -6691,8 +6699,7 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> { | |||
// If tmp is a statement and not an expression | |||
// never cast into expression using ASRUtils::EXPR | |||
// Just ignore and exit the function naturally. | |||
if( tmp && !ASR::is_a<ASR::stmt_t>(*tmp) ) { | |||
LCOMPILERS_ASSERT(ASR::is_a<ASR::expr_t>(*tmp)); | |||
if( tmp && !ASR::is_a<ASR::expr_t>(*tmp) ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is changed to keep track of the final expression executed, and printing its result.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't get this. Could you elaborate this, please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please look at the difference in the AST generated with this change and without this change (i.e. this PR and the main branch). It may become easier to understand. Start the interactive shell with -v
option to print the AST and LLVM IR.
With this change, the pass_wrap_global_stmt
will generate a function that returns the result of the expression tmp
, avoiding the modifications you specified with make_dummy_assignment
(#2698 (review)).
@Shaikh-Ubaid, Please have a look at the comments I have left. Do let me know, if I am not clear. After having a look at the comments, read the following part: We can otherwise implement it as an ASR pass. Identify the last expression and wrap the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think LFortran already prints values for global expressions. We just need to follow how it does it.
In LFortran, the pass pass_wrap_global_stmt
is able to give us a function that can return a value. The same does not hold true for LPython. I think it happens because of the make_dummy_assignment
used here
lpython/src/lpython/semantics/python_ast_to_asr.cpp
Lines 4840 to 4850 in 476d9bb
if (ASR::is_a<ASR::expr_t>(*tmp)) { | |
tmp = make_dummy_assignment(ASRUtils::EXPR(tmp)); | |
} | |
ASR::stmt_t* tmp_stmt = ASRUtils::STMT(tmp); | |
body.push_back(al, tmp_stmt); | |
} else if (!tmp_vec.empty()) { | |
for (auto t: tmp_vec) { | |
if (t != nullptr) { | |
if (ASR::is_a<ASR::expr_t>(*t)) { | |
t = make_dummy_assignment(ASRUtils::EXPR(t)); | |
} |
So, we just need to figure out how to avoid creating the dummy assignment (without breaking any existing tests) and we should have it.
@@ -119,7 +120,7 @@ void pass_wrap_global_stmts(Allocator &al, | |||
/* a_body */ body.p, | |||
/* n_body */ body.size(), | |||
/* a_return_var */ (return_var ? return_var_ref : nullptr), | |||
(return_var ? ASR::abiType::BindC : ASR::abiType::Source), | |||
ASR::abiType::Source, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you check if this change works with LFortran? Simply submit a PR with this exact change and we can see if the CI passes.
} else if (return_type == "none") { | ||
result.type = EvalResult::none; | ||
} else { | ||
throw LCompilersException("FortranEvaluator::evaluate(): Return type not supported"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's wrap this code into a new function that returns the return
variable (or populates it when passed as argument).
module_sym->m_dependencies = current_module_dependencies.p; | ||
module_sym->n_dependencies = current_module_dependencies.size(); | ||
if (!overload_defs.empty()) { | ||
create_GenericProcedure(x.base.base.loc); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This portion seems to be the same as that of the if
part. So, let's move this out of the if-else
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we should be able to do that. Will do it in the next commit.
@@ -6691,8 +6699,7 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> { | |||
// If tmp is a statement and not an expression | |||
// never cast into expression using ASRUtils::EXPR | |||
// Just ignore and exit the function naturally. | |||
if( tmp && !ASR::is_a<ASR::stmt_t>(*tmp) ) { | |||
LCOMPILERS_ASSERT(ASR::is_a<ASR::expr_t>(*tmp)); | |||
if( tmp && !ASR::is_a<ASR::expr_t>(*tmp) ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't get this. Could you elaborate this, please?
I clarified this in my review comment above. Also, you need to update the reference tests for the CI to pass. |
Replying to #2698 (review) Let's say we made the necessary modifications such that we return a value from the function generated from Reference: lpython/src/lpython/python_evaluator.cpp Lines 114 to 149 in 6aed371
interactive_python_repl (Look at Lines 890 to 944 in 6aed371
|
@Vipul-Cariappa Is this safe to close? If it is, can you close this? |
Closed by #2716 |
Example:
Present behavior:
Expected behavior (after potentially merging this PR):
Reference for myself
Things to do: