Skip to content

Commit

Permalink
List support: remove method (#1790)
Browse files Browse the repository at this point in the history
Add support for the `remove()` method of Python lists to the semantic
stage and Python codegen. This fixes #1693.

**Commit Summary**

- Add a `ListRemove` subclass of `ListMethod`, representing the
`remove()` method. The constructor checks for compatibility between the
type of the `remove()` argument and the type of the list, and raises an
error if they are not homogeneous.
- Add success and error tests for the `remove()` method involving many
scenarios where the function could be used.
  • Loading branch information
Farouk-Echaref committed Mar 19, 2024
1 parent 667b2fc commit 0aca4e1
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file.
- #1739 : Add Python support for set method `clear()`.
- #1739 : Add abstract class `SetMethod` to handle calls to various set methods.
- #1740 : Add Python support for set method `copy()`.
- #1693 : Add Python support for list method `remove()`.

### Fixed

Expand Down
41 changes: 41 additions & 0 deletions pyccel/ast/builtin_methods/list_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
'ListInsert',
'ListMethod',
'ListPop',
'ListRemove',
)

#==============================================================================
Expand Down Expand Up @@ -229,3 +230,43 @@ class ListExtend(ListMethod):

def __init__(self, list_obj, iterable) -> None:
super().__init__(list_obj, iterable)

#==============================================================================
class ListRemove(ListMethod) :
"""
Represents a call to the .remove() method.
Represents a call to the .remove() method which removes the first
occurrence of a given element from the list.
Note that the .remove() method doesn't return any value.
>>> a = [[1, 2], [3, 4]]
>>> a.remove([1, 2])
>>> print(a)
[[3, 4]]
Parameters
----------
list_obj : TypedAstNode
The list object which the method is called from.
removed_obj : TypedAstNode
The object to be removed from the list.
"""
__slots__ = ()
_shape = None
_order = None
_rank = 0
_class_type = VoidType()
name = 'remove'

def __init__(self, list_obj, removed_obj) -> None:
expected_type = list_obj.class_type.element_type
is_homogeneous = (
removed_obj.class_type == expected_type and
list_obj.rank - 1 == removed_obj.rank
)
if not is_homogeneous:
raise TypeError(f"Can't remove an element of type {removed_obj.class_type} from {list_obj.class_type}")
super().__init__(list_obj, removed_obj)

4 changes: 3 additions & 1 deletion pyccel/ast/class_defs.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"""

from pyccel.ast.builtin_methods.set_methods import SetAdd, SetClear, SetCopy, SetPop
from pyccel.ast.builtin_methods.list_methods import ListAppend, ListInsert, ListPop, ListClear, ListExtend
from pyccel.ast.builtin_methods.list_methods import (ListAppend, ListInsert, ListPop,
ListClear, ListExtend, ListRemove)


from .builtins import PythonImag, PythonReal, PythonConjugate
Expand Down Expand Up @@ -145,6 +146,7 @@
PyccelFunctionDef('extend', func_class = ListExtend),
PyccelFunctionDef('insert', func_class = ListInsert),
PyccelFunctionDef('pop', func_class = ListPop),
PyccelFunctionDef('remove', func_class = ListRemove),
])

#=======================================================================================
Expand Down
32 changes: 32 additions & 0 deletions tests/epyccel/test_epyccel_lists.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,38 @@ def test_extend_user_defined_objects(language):
for python_elem, accelerated_elem in zip(python_list, accelerated_list):
assert python_elem.x == accelerated_elem.x

def test_remove_basic(language):
def f():
lst = [1, 2, 3, 4]
lst.remove(3)
return lst
epyc_f = epyccel(f, language=language)
assert f() == epyc_f()

def test_remove_float(language):
def f():
lst = [1.4, 2.3, 3.2, 4.4]
lst.remove(3.2)
return lst
epyc_f = epyccel(f, language=language)
assert f() == epyc_f()

def test_remove_complex(language):
def f():
lst = [1j, 3j, 8j]
lst.remove(3j)
return lst
epyc_f = epyccel(f, language=language)
assert f() == epyc_f()

def test_remove_list_from_list(language):
def f():
lst = [[True, False, True], [False, True]]
lst.remove([False, True])
return lst
epyc_f = epyccel(f, language=language)
assert f() == epyc_f()

def test_extend_list_class_attribute(language):
import modules.list_class_attr as mod

Expand Down

0 comments on commit 0aca4e1

Please sign in to comment.