-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for the append() method of Python lists to the semantic stage. Add handling of that method to the Python printer. This fixes #1689. **Commit Summary** - Add a class representation for the `append()` method, inheriting from `PyccelInternalFunction`. The constructor ensures compatibility between the datatypes of the `append()` argument and the list for homogenous lists. - Create `ClassDef` representing a `NativeHomogeneousList`. It includes a method `append()` implemented by the `ListAppend` class.` - Update condition in `get_cls_base()` function to properly check on the classtype of the containers. - Add method `_print_ListAppend()` to the Python printer for generating the appropriate Python code for the `append()` method. - Add check on the semantic to ensure that the correct class definition (`PythonList`) is assigned to variables created via expressions such as `a = [1]` - Add tests for the `append()` method involving many scenarios where the function could be used. --------- Co-authored-by: EmilyBourne <louise.bourne@gmail.com> Co-authored-by: Yaman Güçlü <yaman.guclu@gmail.com>
- Loading branch information
1 parent
2a3e16d
commit f614845
Showing
10 changed files
with
221 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# coding: utf-8 | ||
#------------------------------------------------------------------------------------------# | ||
# This file is part of Pyccel which is released under MIT License. See the LICENSE file or # | ||
# go to https://github.com/pyccel/pyccel/blob/master/LICENSE for full license details. # | ||
#------------------------------------------------------------------------------------------# | ||
""" | ||
The List container has a number of built-in methods that are | ||
always available. | ||
This module contains objects which describe these methods within Pyccel's AST. | ||
""" | ||
|
||
from pyccel.ast.datatypes import NativeVoid, NativeGeneric, NativeHomogeneousList | ||
from pyccel.ast.internals import PyccelInternalFunction | ||
|
||
|
||
__all__ = ('ListAppend',) | ||
|
||
|
||
class ListAppend(PyccelInternalFunction): | ||
""" | ||
Represents a call to the .append() method. | ||
Represents a call to the .append() method of an object with a list type, | ||
which adds an element to the end of the list. This method returns `None`. | ||
The append method is called as follows: | ||
>>> a = [1] | ||
>>> a.append(2) | ||
>>> print(a) | ||
[1, 2] | ||
Parameters | ||
---------- | ||
list_variable : Variable | ||
The variable representing the list. | ||
new_elem : Variable | ||
The argument passed to append() method. | ||
""" | ||
__slots__ = ("_list_variable", "_append_arg") | ||
_attribute_nodes = ("_list_variable", "_append_arg") | ||
_dtype = NativeVoid() | ||
_shape = None | ||
_order = None | ||
_rank = 0 | ||
_precision = -1 | ||
_class_type = NativeHomogeneousList() | ||
name = 'append' | ||
|
||
def __init__(self, list_variable, new_elem) -> None: | ||
is_homogeneous = ( | ||
new_elem.dtype is not NativeGeneric() and | ||
list_variable.dtype is not NativeGeneric() and | ||
list_variable.dtype == new_elem.dtype and | ||
list_variable.precision == new_elem.precision and | ||
list_variable.rank - 1 == new_elem.rank | ||
) | ||
if not is_homogeneous: | ||
raise TypeError("Expecting an argument of the same type as the elements of the list") | ||
self._list_variable = list_variable | ||
self._append_arg = new_elem | ||
super().__init__() | ||
|
||
@property | ||
def list_variable(self): | ||
""" | ||
Get the variable representing the list. | ||
Get the variable representing the list. | ||
""" | ||
return self._list_variable | ||
|
||
@property | ||
def append_argument(self): | ||
""" | ||
Get the argument which is passed to append(). | ||
Get the argument which is passed to append(). | ||
""" | ||
return self._append_arg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# pylint: disable=missing-function-docstring, missing-module-docstring, missing-class-docstring | ||
# coding: utf-8 | ||
""" Tests for list methods. | ||
""" | ||
|
||
import pytest | ||
from pyccel.epyccel import epyccel | ||
|
||
@pytest.fixture( params=[ | ||
pytest.param("fortran", marks = [ | ||
pytest.mark.skip(reason="list methods not implemented in fortran"), | ||
pytest.mark.fortran]), | ||
pytest.param("c", marks = [ | ||
pytest.mark.skip(reason="list methods not implemented in c"), | ||
pytest.mark.c]), | ||
pytest.param("python", marks = pytest.mark.python) | ||
], | ||
scope = "module" | ||
) | ||
def language(request): | ||
return request.param | ||
|
||
def test_append_basic(language): | ||
def f(): | ||
a = [1, 2, 3] | ||
a.append(4) | ||
return a | ||
|
||
epyc_f = epyccel(f, language=language) | ||
assert f() == epyc_f() | ||
|
||
def test_append_multiple(language): | ||
def f(): | ||
a = [1, 2, 3] | ||
a.append(4) | ||
a.append(5) | ||
a.append(6) | ||
return a | ||
|
||
epyc_f = epyccel(f, language=language) | ||
assert f() == epyc_f() | ||
|
||
def test_append_list(language): | ||
def f(): | ||
a = [[1, 2, 3]] | ||
a.append([4, 5, 6]) | ||
return a | ||
|
||
epyc_f = epyccel(f, language=language) | ||
assert f() == epyc_f() | ||
|
||
def test_append_range(language): | ||
def f(): | ||
a = [1, 2, 3] | ||
for i in range(0, 1000): | ||
a.append(i) | ||
a.append(1000) | ||
return a | ||
|
||
epyc_f = epyccel(f, language=language) | ||
assert f() == epyc_f() | ||
|
||
def test_append_range_list(language): | ||
def f(): | ||
a = [[1, 2, 3]] | ||
for i in range(0, 1000): | ||
a.append([i, i + 1]) | ||
return a | ||
|
||
epyc_f = epyccel(f, language=language) | ||
assert f() == epyc_f() | ||
|
||
def test_append_range_tuple(language): | ||
def f(): | ||
a = [[1, 2, 3]] | ||
for i in range(0, 1000): | ||
a.append((i, i + 1)) | ||
return a | ||
|
||
epyc_f = epyccel(f, language=language) | ||
assert f() == epyc_f() |
7 changes: 7 additions & 0 deletions
7
tests/errors/semantic/blocking/APPEND_LIST_INCOMPATIBLE_TYPES_0.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# pylint: disable=missing-function-docstring, missing-module-docstring | ||
|
||
import numpy as np | ||
a = [1,2,3] | ||
b = np.int32(4) | ||
a.append(b) | ||
|
6 changes: 6 additions & 0 deletions
6
tests/errors/semantic/blocking/APPEND_LIST_INCOMPATIBLE_TYPES_1.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# pylint: disable=missing-function-docstring, missing-module-docstring | ||
|
||
|
||
a = [1,2,3] | ||
a.append([4]) | ||
|
6 changes: 6 additions & 0 deletions
6
tests/errors/semantic/blocking/APPEND_LIST_INCOMPATIBLE_TYPES_2.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# pylint: disable=missing-function-docstring, missing-module-docstring | ||
|
||
a = [1,2,3] | ||
b = (4,5) | ||
a.append(b) | ||
|
5 changes: 5 additions & 0 deletions
5
tests/errors/semantic/blocking/APPEND_LIST_INCOMPATIBLE_TYPES_4.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# pylint: disable=missing-function-docstring, missing-module-docstring | ||
|
||
a = [[1, 2, 3]] | ||
a.append((4.4, 8.4)) | ||
|