lpython icon indicating copy to clipboard operation
lpython copied to clipboard

Fix list.pop() for negative arguments

Open faze-geek opened this issue 1 year ago • 13 comments

Snippet

def f():
    a :list[i32] = [1, 2, 3, 4, 5]
    print(a.pop(-1))
    print(a.pop(-4))
    print(a)
    
f()

(lp) C:\Users\kunni\lpython>python try.py
5
1
[2, 3, 4]

On master -

(lp) C:\Users\kunni\lpython>src\bin\lpython try.py
IndexError: List index is out of range. Index range is (0, 4), but the given index is -1

On branch -

(lp) C:\Users\kunni\lpython>src\bin\lpython try.py
5
1
[2, 3, 4]

faze-geek avatar Jan 08 '24 03:01 faze-geek

I just went over post 1 of this GSoC blog. The work done in the project is commendable. I will try to make some contributions if I see any possible improvements. Thanks!

faze-geek avatar Jan 08 '24 03:01 faze-geek

Been a few days since I pushed the code. Does it look good to you ? @certik

faze-geek avatar Jan 21 '24 10:01 faze-geek

For arrays we do not support negative indices (if I am not mistaken), due to runtime overhead that cannot be removed even in Release mode. This PR I think introduces a similar runtime slowdown that cannot be optimized out, correct?

If so, the question to discuss is if we want to introduce such a slowdown in exchange to support negative indices, or should we rather disallow negative indices in exchange for faster runtime.

certik avatar Jan 21 '24 20:01 certik

For arrays we do not support negative indices (if I am not mistaken), due to runtime overhead that cannot be removed even in Release mode.

As far as I remember, negative indexing works and gives correct results with lists -

def main0():
    l: list[i32] = [1, 2, 3]
    print(l[-1])
    # I think x : i32 = 2 ; print(l[-x]) is the one you refer to as not working (or totally unwanted).

main0()

~/lpython/lpython$ ./src/bin/lpython examples/expr2.py 
3

If so, the question to discuss is if we want to introduce such a slowdown in exchange to support negative indices, or should we rather disallow negative indices in exchange for faster runtime.

I came across this issue and felt the need for it because if it is not discarded and returning answers, the output might as well be correct (over incorrect).

Stating @czgdp1807 statement from this comment here - "" The source of confusion in lists is that we are allowing runtime indices for positive values but not for negative values. On top of that compile time indices of any sign are allowed in lists. For compile time case one can use both positive and negative indexing in lists. So that will intuitively make one think that we can also do the same with runtime indices but then we face the out of bounds error.

Even if we are okay with current status in main, but I think users should receive a detailed error message when they use runtime negative indices in lists,

Something like, "Using negative indices with lists at runtime causes performance slowdowns (<probabaly a link to benchmark where slowdown is observed>), hence LPython doesn't allow such use cases". ""

faze-geek avatar Jan 25 '24 07:01 faze-geek

I think compile time negative indexing can be implemented, but runtime cannot without an overhead. So we can implement compile time, but not runtime.

certik avatar Jan 25 '24 20:01 certik

So we can implement compile time, but not runtime.

I get your point. So should we try to give the correct solution in compile time but give the above mentioned error in runtime cases ?

faze-geek avatar Jan 26 '24 06:01 faze-geek

Yes, runtime should give an error in Debug mode (but not Release mode) for the -1 index.

certik avatar Jan 31 '24 04:01 certik

What is the status of this PR?

Thirumalai-Shaktivel avatar Mar 05 '24 12:03 Thirumalai-Shaktivel

Please mark this PR ready for review once it is ready.

Thirumalai-Shaktivel avatar Mar 23 '24 05:03 Thirumalai-Shaktivel

Hi Thirumalai, unfortunately I do not recall what was wrong in this PR. The latest comments by certik mention -

I think compile time negative indexing can be implemented, but runtime cannot without an overhead. So we can implement compile time, but not runtime.

Yes, runtime should give an error in Debug mode (but not Release mode) for the -1 index.

Can you help me to figure out what exactly I need to do here? The use case here is correct, so let's try to get this merged!

faze-geek avatar Mar 24 '24 14:03 faze-geek

Hi @Shaikh-Ubaid, Could you have a look and kindly explain me the difference between the compile time case and the runtime case here.

faze-geek avatar Mar 24 '24 14:03 faze-geek

I think Ondrej means the following:

  • For compile-time negative index:
    • support list.pop() for negative argument
  • For run-time negative index:
    • Debug mode: throw error for list.pop() when lpython is compiled in debug mode
    • Release mode: let the code segfault for negative index (as it does today for out-of-bounds index), but deliver maximum performance for valid non-negative index

Since we would be checking for negative index in debug mode, it would add a computation overhead. We avoid/tackle this computation overhead by not checking for negative index in release build.

ubaidsk avatar Mar 24 '24 20:03 ubaidsk

Yes, that's exactly what I would do.

certik avatar Apr 02 '24 16:04 certik