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

Fix ASR Slice frontend #1051

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft

Conversation

Smit-create
Copy link
Collaborator

Fixes #332

@Smit-create
Copy link
Collaborator Author

The current PR works fine with this:

def main0():
    arr: i32[4]
    arr[0] = 1
    arr[1] = 0
    arr[2] = -4
    print(arr[:2])
    print(arr[1])
    print(arr[2])

main0()

Output:

1
0
-4

0
-4

The only issue is that the Array Section backend considers the right limit as inclusive whereas other Section backends (List/string) consider the right limit as exclusive. So we need to define some strict way of defining indexes, limits that is followed uniformly in all the backends.

@czgdp1807
Copy link
Collaborator

The only issue is that the Array Section backend considers the right limit as inclusive whereas other

Well. Array is a shared feature between Fortran and Python. Fortran includes end index while slicing an array. However Python excludes end index. I think the backend should always treat the end index inclusive. Its the AST->ASR transition's job to format the indices of an array slices correctly. For example, array[0:3] should be converted to ArraySlice(array, 0, 2) in LPython's AST->ASR transition and ArraySlice(array, 0, 3) in LFortran's AST->ASR transition.

Copy link
Collaborator

@czgdp1807 czgdp1807 left a comment

Choose a reason for hiding this comment

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

Please add a test for your fix.

Comment on lines +8 to +10
print(arr[:2])
print(arr[1])
print(arr[2])
Copy link
Collaborator

Choose a reason for hiding this comment

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

Use assert for verifying that the outputs are actually correct?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I am not sure if we can assign Array Section at present (I think only string is supported).

    p: i32[4]
    arr[0] = 1
    arr[1] = 0
    arr[2] = -4
    p = arr[:2]

Throws this:

LFORTRAN_ASSERT(ASR::is_a<ASR::Character_t>(*ASRUtils::expr_type(x.m_v)) &&
AssertFailed: ASR::is_a<ASR::Character_t>(*ASRUtils::expr_type(x.m_v)) && n_dims == 0

LFORTRAN_API char* _lfortran_str_slice(char* s, int32_t idx1, int32_t idx2, int32_t step,
bool idx1_present, bool idx2_present) {
int s_len = strlen(s);
idx2++;
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 surprised why tests didn't fail after this change. Can you try applying this specific change to LFortran to make sure this works there as well.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Just because the frontend subtracts one and in backend (internally) we add one again. So, logic remains the same. And it's expected to pass all the tests.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Can you try applying this specific change to LFortran to make sure this works there as well.

Yep, tried. All tests passed for me. On the latest main branch of LFortran:

diff --git a/src/libasr/runtime/lfortran_intrinsics.c b/src/libasr/runtime/lfortran_intrinsics.c
index 17399c784..b71bfdd95 100644
--- a/src/libasr/runtime/lfortran_intrinsics.c
+++ b/src/libasr/runtime/lfortran_intrinsics.c
@@ -784,6 +784,7 @@ LFORTRAN_API char* _lfortran_str_copy(char* s, int32_t idx1, int32_t idx2) {
 LFORTRAN_API char* _lfortran_str_slice(char* s, int32_t idx1, int32_t idx2, int32_t step,
                         bool idx1_present, bool idx2_present) {
     int s_len = strlen(s);
+    idx2++;
     if (step == 0) {

Copy link
Collaborator

Choose a reason for hiding this comment

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

Just make a PR there (in LFortran) as well with a similar test. We will merge both together.

@czgdp1807 czgdp1807 self-assigned this Aug 29, 2022
Copy link
Collaborator

@czgdp1807 czgdp1807 left a comment

Choose a reason for hiding this comment

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

Will shepherd this later.

@Smit-create
Copy link
Collaborator Author

Will shepherd this later.

@czgdp1807 Should we merge this? Can we add assertion tests as the follow-up PR to keep this clean?

@certik
Copy link
Contributor

certik commented Sep 20, 2022

@czgdp1807 let me know what needs to get done here.

LFORTRAN_API char* _lfortran_str_slice(char* s, int32_t idx1, int32_t idx2, int32_t step,
bool idx1_present, bool idx2_present) {
int s_len = strlen(s);
idx2++;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Just make a PR there (in LFortran) as well with a similar test. We will merge both together.

@czgdp1807 czgdp1807 marked this pull request as draft October 5, 2022 09:41
@Smit-create Smit-create marked this pull request as ready for review October 6, 2022 13:55
@Smit-create Smit-create added the ready for review PRs that are ready for review label Oct 6, 2022
@Smit-create
Copy link
Collaborator Author

This is ready @czgdp1807

Comment on lines +8 to +10
print(arr[:2])
print(arr[1])
print(arr[2])
Copy link
Collaborator

Choose a reason for hiding this comment

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

Usage of assert possible here to check if the outputs are actually correct?

Suggested change
print(arr[:2])
print(arr[1])
print(arr[2])
print(arr[:2])
print(arr[1])
print(arr[2])
arr_2: i32[2] = arr[:2]
assert arr_2[0] == 1
assert arr_2[1] == 0
assert arr[1] == 0
assert arr[2] == -4

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not yet:

File "/Users/thebigbool/repos/lpython/src/libasr/codegen/asr_to_llvm.cpp", line 1658
    LFORTRAN_ASSERT(ASR::is_a<ASR::Character_t>(*ASRUtils::expr_type(x.m_v)) &&
AssertFailed: ASR::is_a<ASR::Character_t>(*ASRUtils::expr_type(x.m_v)) && n_dims == 0

Copy link
Collaborator

Choose a reason for hiding this comment

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

Makes sense. Can you try fixing the bug?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think the LLVM backend currently only supports string-slicing assignments and not arrays because they can be n-dimensional. Is that intentional?

@czgdp1807 czgdp1807 marked this pull request as draft October 16, 2022 06:30
@czgdp1807 czgdp1807 removed the ready for review PRs that are ready for review label Oct 16, 2022
@czgdp1807
Copy link
Collaborator

Please fix #1051 (comment) and resolve the conflicts. Will merge it then.

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.

Fix array slicing
3 participants