Skip to content
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

Printing top-level Expressions #2716

Merged
merged 5 commits into from
May 26, 2024

Conversation

Vipul-Cariappa
Copy link
Contributor

Example:

❯ lp 
>>> i: i32 = 9
>>> i * i
81
>>> i ** i
387420480

I have rebased this branch of #2713.

@Vipul-Cariappa Vipul-Cariappa marked this pull request as ready for review May 24, 2024 14:26
@Vipul-Cariappa
Copy link
Contributor Author

cc @Shaikh-Ubaid

Copy link
Collaborator

@Shaikh-Ubaid Shaikh-Ubaid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shared some comments below.

result.type = EvalResult::none;
} else {
throw LCompilersException("FortranEvaluator::evaluate(): Return type not supported");
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did we previously add all the above code somewhere else? (It feels like we added it somewhere before).

If this is being duplicated then I think we should create a function out of it and call that function here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had initially implemented this in #2698, but we did not merge. That PR lacked tests. We also merged other changes between that PR and this. I was thinking of closing that PR without merging it once we merge this PR.

@@ -608,7 +608,7 @@ define float @f()
CHECK(std::abs(r - 8) < 1e-6);
}

TEST_CASE("PythonCompiler 1") {
TEST_CASE("PythonCompiler i32 expressions") {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add this as a separate test and not change the existing test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. I can do that.

Comment on lines 6698 to 6700
if ((tmp) && (!ASR::is_a<ASR::expr_t>(*tmp))) {
LCOMPILERS_ASSERT(ASR::is_a<ASR::expr_t>(*tmp));
tmp = nullptr;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not quite get the logic here. It says if tmp exists and it is not an expression, then right inside the if, we have assert that tmp is an expression. tmp is not an expresssion in if and tmp is an expression in the assert are contradicting, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. It does not make sense. I should remove that assertion.

@Shaikh-Ubaid Shaikh-Ubaid marked this pull request as draft May 25, 2024 04:02
@Shaikh-Ubaid
Copy link
Collaborator

Please mark as "Ready for review" when ready.

@Shaikh-Ubaid
Copy link
Collaborator

Also, I think we have some previous discussion about printing top-level expressions. Would you mind linking that PR here so that others can have a better context about this?

@Vipul-Cariappa
Copy link
Contributor Author

Also, I think we have some previous discussion about printing top-level expressions. Would you mind linking that PR here so that others can have a better context about this?

We discussed this in #2698.
I had implemented some of this in that PR. That PR lacked tests. We also merged other changes between that PR and this. I was thinking of closing that PR without merging it once we merge this PR.

@Vipul-Cariappa Vipul-Cariappa marked this pull request as ready for review May 25, 2024 05:05
Comment on lines 6698 to 6700
if ((tmp) && (!ASR::is_a<ASR::expr_t>(*tmp))) {
tmp = nullptr;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a bit confused here. We make tmp as nullptr everytime it is not an expression. But, why do we do so? I think this means, if tmp is a statement, then we are skipping it. Any specific reason to skip statements @Vipul-Cariappa ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If tmp is an expression then we return it. So that we can print it. The pass_wrap_global_stmts function uses this tmp expression and returns the evaluated result of the expression for us to print it later using PythonCompiler::evaluate and interactive_python_repl.
If tmp is a statement, for example, an assignment x = 5 then we would not want to print anything, so we set tmp to nullptr.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

x = 5 then we would not want to print anything, so we set tmp to nullptr

Although we do not want to print anything, but we do want x to be updated to 5. I am unsure, but if we skip the whole x = 5 statement, then would the value of x be updated to 5?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pass_wrap_global_stmts function uses this tmp expression and returns the evaluated result of the expression for us

Does it actually return an evaluated result? Or does it simply convert expressions into assignment statements?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. The statement will be executed and x will be updated to 5.

❯ lp
>>> x: i32
>>> x
0
>>> x = 5
>>> x
5

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it actually return an evaluated result? Or does it simply convert expressions into assignment statements?

It returns the evaluated result. You can run the interactive in verbose mode with -v flag to see the AST, ASR, and the LLVM IR generated. Doing so, you can see that it returns the result.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the current approach, I doubt that we are/would-be skipping some stmts like empty() and c_p_pointer()

// This happens for c_p_pointer() and
// empty() (if target is of type allocatable)

See my comment below https://github.com/lcompilers/lpython/pull/2716/files#r1614616838 which I think would avoid this.

Comment on lines +682 to +691
r = e.evaluate2("i: i32");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::none);
r = e.evaluate2("i = 5");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::statement);
r = e.evaluate2("i");
CHECK(r.ok);
CHECK(r.result.type == PythonCompiler::EvalResult::integer4);
CHECK(r.result.i32 == 5);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test here makes sure that the execution of statements is not skipped.

Comment on lines 6696 to 6701
if (eval_count > 0) {
// In Interactive mode
if ((tmp) && (!ASR::is_a<ASR::expr_t>(*tmp))) {
tmp = nullptr;
}
} else if (tmp && !ASR::is_a<ASR::stmt_t>(*tmp)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you check if doing the following works?

Suggested change
if (eval_count > 0) {
// In Interactive mode
if ((tmp) && (!ASR::is_a<ASR::expr_t>(*tmp))) {
tmp = nullptr;
}
} else if (tmp && !ASR::is_a<ASR::stmt_t>(*tmp)) {
if (eval_count == 0 && tmp && !ASR::is_a<ASR::stmt_t>(*tmp)) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes work. I have committed it.

Copy link
Collaborator

@Shaikh-Ubaid Shaikh-Ubaid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, Thanks! Nice work!

@Shaikh-Ubaid Shaikh-Ubaid merged commit 2420448 into lcompilers:main May 26, 2024
14 checks passed
@Vipul-Cariappa Vipul-Cariappa deleted the global_stmts-pass branch May 28, 2024 10:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants