From 409f7df79f48a6022a77fb7933fef1e8eb04085c Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Fri, 1 Mar 2024 11:52:00 +0100 Subject: [PATCH 001/139] add support for disard method and test functions --- CHANGELOG.md | 1 + pyccel/ast/builtin_methods/set_methods.py | 40 +++++++++++++++++++++++ pyccel/ast/class_defs.py | 4 ++- tests/epyccel/test_epyccel_sets.py | 30 +++++++++++++++++ 4 files changed, 74 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ceaee09f9..4d213936ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ All notable changes to this project will be documented in this file. - #1425 : Add support for `numpy.isnan`, `numpy.isinf` and `numpy.isfinite`. - #1738 : Add Python support for creating scalar sets with `{}`. - #1738 : Add Python support for set method `add`. +- #1743 : Add Python support for set method `discard()` ### Fixed diff --git a/pyccel/ast/builtin_methods/set_methods.py b/pyccel/ast/builtin_methods/set_methods.py index c6626df513..ef19d9e549 100644 --- a/pyccel/ast/builtin_methods/set_methods.py +++ b/pyccel/ast/builtin_methods/set_methods.py @@ -12,7 +12,11 @@ from pyccel.ast.datatypes import NativeVoid, NativeGeneric from pyccel.ast.internals import PyccelInternalFunction +<<<<<<< HEAD __all__ = ('SetAdd', 'SetClear', 'SetMethod') +======= +__all__ = ('SetAdd', 'SetClear', 'SetCopy', 'SetMethod', 'SetRemove', 'SetPop', 'SetDiscard') +>>>>>>> 6ddb2d93 (add support for disard method and test functions) class SetMethod(PyccelInternalFunction): """ @@ -104,3 +108,39 @@ class SetClear(SetMethod): def __init__(self, set_variable): super().__init__(set_variable) + + +class SetDiscard(SetMethod): + """ + Represents a call to the .discard() method. + + + + Parameters + ---------- + set_variable : TypedAstNode + The name of the set. + + item : TypedAstNode + The item to search for, and remove. + """ + __slots__ = () + _dtype = NativeVoid() + _shape = None + _order = None + _rank = 0 + _precision = None + _class_type = NativeVoid() + name = 'discard' + + def __init__(self, set_variable, item) -> None: + is_homogeneous = ( + item.dtype is not NativeGeneric() and + set_variable.dtype is not NativeGeneric() and + set_variable.dtype == item.dtype and + set_variable.precision == item.precision and + set_variable.rank - 1 == item.rank + ) + if not is_homogeneous: + raise TypeError("Expecting an argument of the same type as the elements of the set") + super().__init__(set_variable, item) diff --git a/pyccel/ast/class_defs.py b/pyccel/ast/class_defs.py index ecb09b2f08..f9345b6233 100644 --- a/pyccel/ast/class_defs.py +++ b/pyccel/ast/class_defs.py @@ -6,7 +6,7 @@ This module contains all types which define a python class which is automatically recognised by pyccel """ -from pyccel.ast.builtin_methods.set_methods import SetAdd, SetClear +from pyccel.ast.builtin_methods.set_methods import SetAdd, SetClear, SetDiscard from pyccel.ast.builtin_methods.list_methods import ListAppend, ListInsert, ListPop, ListClear @@ -157,6 +157,8 @@ decorators = {}), PyccelFunctionDef('clear', func_class = SetClear, decorators={}), + PyccelFunctionDef('discard', func_class = SetDiscard, + decorators={}), ]) #======================================================================================= diff --git a/tests/epyccel/test_epyccel_sets.py b/tests/epyccel/test_epyccel_sets.py index 4d838911e0..98ac33d64c 100644 --- a/tests/epyccel/test_epyccel_sets.py +++ b/tests/epyccel/test_epyccel_sets.py @@ -77,3 +77,33 @@ def clear_complex(): python_result = clear_complex() assert python_result == pyccel_result + +def test_Discard_int(language): + def Discard_int(): + se = {2.7, 4.3, 9.2} + se.discard(4.3) + return se + epyccel_remove = epyccel(Discard_int, language = language) + pyccel_result = epyccel_remove() + python_result = Discard_int() + assert python_result == pyccel_result + +def test_Discard_complex(language): + def Discard_complex(): + se = {2j, 5j, 3j, 7j} + se.discard(5j) + return se + epyccel_remove = epyccel(Discard_complex, language = language) + pyccel_result = epyccel_remove() + python_result = Discard_complex() + assert python_result == pyccel_result + +def test_Discard_wrong_arg(language): + def Discard_wrong_arg(): + se = {4.7, 1.3, 8.2} + se.discard(8.6) + return se + epyccel_remove = epyccel(Discard_wrong_arg, language = language) + pyccel_result = epyccel_remove() + python_result = Discard_wrong_arg() + assert python_result == pyccel_result From 02513d5453344c8f6fc1b6fdf7e510077d53f73a Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Fri, 1 Mar 2024 11:56:56 +0100 Subject: [PATCH 002/139] fix Codacy issue --- tests/epyccel/test_epyccel_sets.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/epyccel/test_epyccel_sets.py b/tests/epyccel/test_epyccel_sets.py index 98ac33d64c..dc6d6d6233 100644 --- a/tests/epyccel/test_epyccel_sets.py +++ b/tests/epyccel/test_epyccel_sets.py @@ -107,3 +107,4 @@ def Discard_wrong_arg(): pyccel_result = epyccel_remove() python_result = Discard_wrong_arg() assert python_result == pyccel_result + From 3cb376eb50982db8cad05c5cbd8ceea4d71ccc41 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Fri, 1 Mar 2024 12:05:40 +0100 Subject: [PATCH 003/139] add docs for discard method --- pyccel/ast/builtin_methods/set_methods.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pyccel/ast/builtin_methods/set_methods.py b/pyccel/ast/builtin_methods/set_methods.py index ef19d9e549..dffa801b6b 100644 --- a/pyccel/ast/builtin_methods/set_methods.py +++ b/pyccel/ast/builtin_methods/set_methods.py @@ -113,8 +113,10 @@ def __init__(self, set_variable): class SetDiscard(SetMethod): """ Represents a call to the .discard() method. - - + + The discard() is a built-in method to remove elements from the set. + The discard() method takes exactly one argument. + This method does not return any value. Parameters ---------- From 7274bb3ebcd1060b0b9aa74cfd5cf32e41c25629 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Wed, 3 Apr 2024 13:45:11 +0000 Subject: [PATCH 004/139] Check if the result of Pyccel is the same as Python. --- tests/epyccel/test_epyccel_sets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/epyccel/test_epyccel_sets.py b/tests/epyccel/test_epyccel_sets.py index b04e283ff0..d467e9bdef 100644 --- a/tests/epyccel/test_epyccel_sets.py +++ b/tests/epyccel/test_epyccel_sets.py @@ -202,4 +202,4 @@ def Discard_wrong_arg(): epyccel_remove = epyccel(Discard_wrong_arg, language = language) pyccel_result = epyccel_remove() python_result = Discard_wrong_arg() - + assert python_result == pyccel_result From 14d4fb586cf821d1d0594a78d5df59e3c0eb1fa0 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Thu, 4 Apr 2024 14:33:55 +0000 Subject: [PATCH 005/139] Fix a typing mistake. --- .github/workflows/pickle_wheel.yml | 2 +- test.py | 5 +++++ zz/test.py | 4 ++++ 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 test.py create mode 100644 zz/test.py diff --git a/.github/workflows/pickle_wheel.yml b/.github/workflows/pickle_wheel.yml index efe9072f39..ce530a238f 100644 --- a/.github/workflows/pickle_wheel.yml +++ b/.github/workflows/pickle_wheel.yml @@ -26,7 +26,7 @@ env: PR_REPO: ${{ inputs.pr_repo || github.repository }} jobs: -zz Python_version_picker: + Python_version_picker: runs-on: ubuntu-latest if: github.event_name != 'push' || github.repository == 'pyccel/pyccel' outputs: diff --git a/test.py b/test.py new file mode 100644 index 0000000000..6e5c9d1a8f --- /dev/null +++ b/test.py @@ -0,0 +1,5 @@ +l = {1,2,4,5,8} +l.update(range(9, 12)) +print(l) + + diff --git a/zz/test.py b/zz/test.py new file mode 100644 index 0000000000..a45812987e --- /dev/null +++ b/zz/test.py @@ -0,0 +1,4 @@ + +l = [1, 2, 4, 5, 8] +for index in range(0, 6, 1): + l.append(index) From 168045a4e7ac6e31c2e6a92c6ca369ae8cc69659 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Thu, 4 Apr 2024 14:34:52 +0000 Subject: [PATCH 006/139] Delete test files' --- test.py | 5 ----- zz/test.py | 4 ---- 2 files changed, 9 deletions(-) delete mode 100644 test.py delete mode 100644 zz/test.py diff --git a/test.py b/test.py deleted file mode 100644 index 6e5c9d1a8f..0000000000 --- a/test.py +++ /dev/null @@ -1,5 +0,0 @@ -l = {1,2,4,5,8} -l.update(range(9, 12)) -print(l) - - diff --git a/zz/test.py b/zz/test.py deleted file mode 100644 index a45812987e..0000000000 --- a/zz/test.py +++ /dev/null @@ -1,4 +0,0 @@ - -l = [1, 2, 4, 5, 8] -for index in range(0, 6, 1): - l.append(index) From 1761006955b5472fbfcb980b248e95af15e03e5d Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Wed, 17 Apr 2024 10:17:34 +0100 Subject: [PATCH 007/139] add support for Update method. --- pyccel/ast/builtin_methods/set_methods.py | 51 ++++++++++++++++++++-- pyccel/ast/class_defs.py | 3 +- pyccel/parser/semantic.py | 52 ++++++++++++++++++++++- 3 files changed, 99 insertions(+), 7 deletions(-) diff --git a/pyccel/ast/builtin_methods/set_methods.py b/pyccel/ast/builtin_methods/set_methods.py index 441260737a..7ffe1661b1 100644 --- a/pyccel/ast/builtin_methods/set_methods.py +++ b/pyccel/ast/builtin_methods/set_methods.py @@ -13,8 +13,17 @@ from pyccel.ast.internals import PyccelInternalFunction from pyccel.ast.basic import TypedAstNode -__all__ = ('SetAdd', 'SetClear', 'SetMethod', 'SetCopy', 'SetPop', 'SetRemove', 'SetDiscard') - +__all__ = ( + 'SetAdd', + 'SetClear', + 'SetMethod', + 'SetCopy', + 'SetPop', + 'SetRemove', + 'SetDiscard' + ) + +#============================================================================== class SetMethod(PyccelInternalFunction): """ Abstract class for set method calls. @@ -45,7 +54,7 @@ def set_variable(self): """ return self._set_variable - +#============================================================================== class SetAdd(SetMethod) : """ Represents a call to the .add() method. @@ -78,7 +87,7 @@ def __init__(self, set_variable, new_elem) -> None: raise TypeError("Expecting an argument of the same type as the elements of the set") super().__init__(set_variable, new_elem) - +#============================================================================== class SetClear(SetMethod): """ Represents a call to the .clear() method. @@ -101,6 +110,7 @@ class SetClear(SetMethod): def __init__(self, set_variable): super().__init__(set_variable) +#============================================================================== class SetCopy(SetMethod): """ Represents a call to the .copy() method. @@ -123,6 +133,7 @@ def __init__(self, set_variable): self._class_type = set_variable._class_type super().__init__(set_variable) +#============================================================================== class SetPop(SetMethod): """ Represents a call to the .pop() method. @@ -148,6 +159,7 @@ def __init__(self, set_variable): self._class_type = set_variable.class_type.element_type super().__init__(set_variable) +#============================================================================== class SetRemove(SetMethod): """ Represents a call to the .remove() method. @@ -182,6 +194,7 @@ def __init__(self, set_variable, item) -> None: raise TypeError(f"Can't remove an element of type {item.dtype} from a set of {set_variable.dtype}") super().__init__(set_variable, item) +#============================================================================== class SetDiscard(SetMethod): """ Represents a call to the .discard() method. @@ -214,3 +227,33 @@ def __init__(self, set_variable, item) -> None: if not is_homogeneous: raise TypeError("Expecting an argument of the same type as the elements of the set") super().__init__(set_variable, item) + +#============================================================================== +class SetUpdate(SetMethod): + """ + Represents a call to the .update() method. + + Represents a call to the .update() method of an object with a set type, + Which adds items from another set (or any other iterable). + This method is handled through the call to `_visit_SetUpdate` in + the semantic stage. It then attempts to construct a `For` loop node with + a body that calls `add()`, or direct `add()` nodes depending on + the type of the iterable passed to `update()`. + This class should never be instantiated; it's only purpose is to help + construct the annotation_method `_visit_SetUpdate`. + The update method is called as follows: + + Parameters + ---------- + set_variable : TypedAstNode + The set object which the method is called from. + + The argument passed to update() method. + item : TypedAstNode + The item to search for, and remove. + """ + __slots__ = () + name = 'update' + + def __init__(self, set_obj, iterable) -> None: + super().__init__(set_obj, iterable) \ No newline at end of file diff --git a/pyccel/ast/class_defs.py b/pyccel/ast/class_defs.py index a1c97456e1..c2c9b29382 100644 --- a/pyccel/ast/class_defs.py +++ b/pyccel/ast/class_defs.py @@ -6,7 +6,7 @@ This module contains all types which define a python class which is automatically recognised by pyccel """ -from pyccel.ast.builtin_methods.set_methods import SetAdd, SetClear, SetCopy, SetPop, SetRemove, SetDiscard +from pyccel.ast.builtin_methods.set_methods import SetAdd, SetClear, SetCopy, SetPop, SetRemove, SetDiscard,SetUpdate from pyccel.ast.builtin_methods.list_methods import (ListAppend, ListInsert, ListPop, ListClear, ListExtend, ListRemove, ListCopy) @@ -160,6 +160,7 @@ PyccelFunctionDef('pop', func_class = SetPop), PyccelFunctionDef('remove', func_class = SetRemove), PyccelFunctionDef('discard', func_class = SetDiscard), + PyccelFunctionDef('update', func_class = SetUpdate), ]) #======================================================================================= diff --git a/pyccel/parser/semantic.py b/pyccel/parser/semantic.py index b2f1bc8ac9..0bb3708b1b 100644 --- a/pyccel/parser/semantic.py +++ b/pyccel/parser/semantic.py @@ -31,6 +31,7 @@ PythonTuple, Lambda, PythonMap) from pyccel.ast.builtin_methods.list_methods import ListMethod, ListAppend +from pyccel.ast.builtin_methods.set_methods import SetMethod, SetAdd from pyccel.ast.core import Comment, CommentBlock, Pass from pyccel.ast.core import If, IfSection @@ -2780,8 +2781,8 @@ def _visit_ListExtend(self, expr): PyccelAstNode CodeBlock or For containing ListAppend objects. """ + print("I'm hereee 111") iterable = expr.name[1].args[0].value - if isinstance(iterable, (PythonList, PythonTuple)): list_variable = self._visit(expr.name[0]) added_list = self._visit(iterable) @@ -2804,6 +2805,52 @@ def _visit_ListExtend(self, expr): for_obj = For(for_target, iterable, body) pyccel_stage.set_stage('semantic') return self._visit(for_obj) + + def _visit_SetUpdate(self, expr): + """ + Method to navigate the syntactic DottedName node of an `update()` call. + + The purpose of this `_visit` method is to construct new nodes from a syntactic + DottedName node. It checks the type of the iterable passed to `update()`. + If the iterable is an instance of `PythonList`, `PythonSet` or `PythonTuple`, it constructs + a CodeBlock node where its body consists of `SetAdd` objects with the + elements of the iterable. If not, it attempts to construct a syntactic `For` + loop to iterate over the iterable object and added its elements to the set + object. Finally, it passes to a `_visit()` call for semantic parsing. + + Parameters + ---------- + expr : DottedName + The syntactic DottedName node that represent the call to `.update()` + + Returns + ------- + PyccelAstNode + CodeBlock or For containing SetAdd objects. + """ + iterable = expr.name[1].args[0].value + if isinstance(iterable, (PythonList, PythonSet, PythonTuple)): + list_variable = self._visit(expr.name[0]) + added_list = self._visit(iterable) + try: + store = [SetAdd(list_variable, a) for a in added_list] + except TypeError as e: + msg = str(e) + errors.report(msg, symbol=expr, severity='fatal') + return CodeBlock(store) + else: + pyccel_stage.set_stage('syntactic') + for_target = self.scope.get_new_name('index') + arg = FunctionCallArgument(for_target) + func_call = FunctionCall('add', [arg]) + dotted = DottedName(expr.name[0], func_call) + lhs = PyccelSymbol('_', is_temp=True) + assign = Assign(lhs, dotted) + assign.set_current_ast(expr.python_ast) + body = CodeBlock([assign]) + for_obj = For(for_target, iterable, body) + pyccel_stage.set_stage('semantic') + return self._visit(for_obj) def _visit_PyccelOperator(self, expr): args = [self._visit(a) for a in expr.args] @@ -3215,7 +3262,8 @@ def _visit_Assign(self, expr): symbol=expr, severity='error') # Checking for the result of _visit_ListExtend - if isinstance(rhs, For) or (isinstance(rhs, CodeBlock) and isinstance(rhs.body[0], ListMethod)): + if isinstance(rhs, For) or (isinstance(rhs, CodeBlock) and + (isinstance(rhs.body[0], ListMethod) or isinstance(rhs.body[0], SetMethod))): return rhs if isinstance(rhs, ConstructorCall): return rhs From 6145e41166b8a59943e193a96d1fbe55a7f201ec Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Wed, 17 Apr 2024 10:17:54 +0100 Subject: [PATCH 008/139] add test for update method. --- tests/epyccel/test_epyccel_sets.py | 81 +++++++++++++++++++ .../UPDATE_SET_INCOMPATIBLE_TYPES_1.py | 4 + .../UPDATE_SET_INCOMPATIBLE_TYPES_2.py | 5 ++ 3 files changed, 90 insertions(+) create mode 100644 tests/errors/semantic/blocking/UPDATE_SET_INCOMPATIBLE_TYPES_1.py create mode 100644 tests/errors/semantic/blocking/UPDATE_SET_INCOMPATIBLE_TYPES_2.py diff --git a/tests/epyccel/test_epyccel_sets.py b/tests/epyccel/test_epyccel_sets.py index d467e9bdef..b12427c45e 100644 --- a/tests/epyccel/test_epyccel_sets.py +++ b/tests/epyccel/test_epyccel_sets.py @@ -203,3 +203,84 @@ def Discard_wrong_arg(): pyccel_result = epyccel_remove() python_result = Discard_wrong_arg() assert python_result == pyccel_result + + +def test_update_basic(language): + def update_basic(): + a = {1, 2, 3} + b = {4, 5, 6} + a.update(b) + return a + + epyccel_update = epyccel(update_basic, language=language) + pyccel_result = epyccel_update() + python_result = update_basic() + assert python_result == pyccel_result + +def test_update_multiple(language): + def update_multiple(): + a = {1, 2, 3} + a.update({4, 5}) + a.update({6, 7, 8, 9}) + a.update({10}) + return a + + epyccel_update = epyccel(update_multiple, language=language) + pyccel_result = epyccel_update() + python_result = update_multiple() + assert python_result == pyccel_result + + +def test_update_boolean_tuple(language): + def update_boolean_tuple(): + a = {True, False, True} + b = (False, True, False) + a.update(b) + return a + epyccel_update = epyccel(update_boolean_tuple, language=language) + pyccel_result = epyccel_update() + python_result = update_boolean_tuple() + assert python_result == pyccel_result + + +def test_update_complex_list(language): + def update_complex_list(): + a = {1j, 2 + 3j, 0 + 0j} + b = {4j, 5j, 1 + 6j} + a.update(b) + return a + epyccel_update = epyccel(update_complex_list, language=language) + pyccel_result = epyccel_update() + python_result = update_complex_list() + assert python_result == pyccel_result + +def test_update_range(language): + def update_range(): + a = {1, 2, 3} + a.update(range(4, 9)) + return a + epyccel_update = epyccel(update_range, language=language) + pyccel_result = epyccel_update() + python_result = update_range() + assert python_result == pyccel_result + +def test_update_set_as_arg(language): + def update_set_as_arg(): + a = {1, 2, 3} + a.update({4, 5, 6}) + return a + + epyccel_update = epyccel(update_set_as_arg, language=language) + pyccel_result = epyccel_update() + python_result = update_set_as_arg() + assert python_result == pyccel_result + +def test_update_tuple_as_arg(language): + def update_tuple_as_arg(): + a = {1, 2, 3} + a.update((4, 5, 6)) + return a + epyccel_update = epyccel(update_tuple_as_arg, language=language) + pyccel_result = epyccel_update() + python_result = update_tuple_as_arg() + assert python_result == pyccel_result \ No newline at end of file diff --git a/tests/errors/semantic/blocking/UPDATE_SET_INCOMPATIBLE_TYPES_1.py b/tests/errors/semantic/blocking/UPDATE_SET_INCOMPATIBLE_TYPES_1.py new file mode 100644 index 0000000000..49ff697d2a --- /dev/null +++ b/tests/errors/semantic/blocking/UPDATE_SET_INCOMPATIBLE_TYPES_1.py @@ -0,0 +1,4 @@ +# pylint: disable=missing-function-docstring, missing-module-docstring + +a = {1.4, 6.2, 8.1} +a.update({3j}) diff --git a/tests/errors/semantic/blocking/UPDATE_SET_INCOMPATIBLE_TYPES_2.py b/tests/errors/semantic/blocking/UPDATE_SET_INCOMPATIBLE_TYPES_2.py new file mode 100644 index 0000000000..9950f01959 --- /dev/null +++ b/tests/errors/semantic/blocking/UPDATE_SET_INCOMPATIBLE_TYPES_2.py @@ -0,0 +1,5 @@ +# pylint: disable=missing-function-docstring, missing-module-docstring + +a = {2, 9, 5} +b = {8.9, 6.} +a.update(b) From f14518d8b50bf632ed8b8d2e0c1cef72c647b62e Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Wed, 17 Apr 2024 10:48:10 +0100 Subject: [PATCH 009/139] remove a debug line. --- pyccel/parser/semantic.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyccel/parser/semantic.py b/pyccel/parser/semantic.py index 04e22373fe..e765113b01 100644 --- a/pyccel/parser/semantic.py +++ b/pyccel/parser/semantic.py @@ -2705,7 +2705,6 @@ def _visit_ListExtend(self, expr): PyccelAstNode CodeBlock or For containing ListAppend objects. """ - print("I'm hereee 111") iterable = expr.name[1].args[0].value if isinstance(iterable, (PythonList, PythonTuple)): list_variable = self._visit(expr.name[0]) From 673cf1690b7600d90a382123378bfa68095fb4fc Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Wed, 17 Apr 2024 10:49:41 +0100 Subject: [PATCH 010/139] Remove unnecessary change. --- pyccel/parser/semantic.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyccel/parser/semantic.py b/pyccel/parser/semantic.py index e765113b01..fdf6d4d18c 100644 --- a/pyccel/parser/semantic.py +++ b/pyccel/parser/semantic.py @@ -2706,6 +2706,7 @@ def _visit_ListExtend(self, expr): CodeBlock or For containing ListAppend objects. """ iterable = expr.name[1].args[0].value + if isinstance(iterable, (PythonList, PythonTuple)): list_variable = self._visit(expr.name[0]) added_list = self._visit(iterable) From fcf24cd6780e7cdf9d96d3541a38c59f513ff5fa Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Wed, 17 Apr 2024 10:50:35 +0100 Subject: [PATCH 011/139] bad merge --- pyccel/ast/class_defs.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyccel/ast/class_defs.py b/pyccel/ast/class_defs.py index fb9a283d61..775c4cbb77 100644 --- a/pyccel/ast/class_defs.py +++ b/pyccel/ast/class_defs.py @@ -160,7 +160,6 @@ PyccelFunctionDef('discard', func_class = SetDiscard), PyccelFunctionDef('pop', func_class = SetPop), PyccelFunctionDef('remove', func_class = SetRemove), - PyccelFunctionDef('discard', func_class = SetDiscard), PyccelFunctionDef('update', func_class = SetUpdate), ]) From 88b0ecc6bd8a09c4f6aa8028ba74b32070b89cf5 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Wed, 17 Apr 2024 11:00:18 +0100 Subject: [PATCH 012/139] Fix Codacy problem --- tests/epyccel/test_epyccel_sets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/epyccel/test_epyccel_sets.py b/tests/epyccel/test_epyccel_sets.py index 7d45b4b3b5..d9a4436585 100644 --- a/tests/epyccel/test_epyccel_sets.py +++ b/tests/epyccel/test_epyccel_sets.py @@ -232,7 +232,7 @@ def update_multiple(): def test_update_boolean_tuple(language): def update_boolean_tuple(): - a = {True, False, True} + a = {True} b = (False, True, False) a.update(b) return a From 4f3391cbd2cca5673e9247e8e79f0c4067ffd2e7 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Wed, 17 Apr 2024 12:27:51 +0100 Subject: [PATCH 013/139] update changelog and fix bad merge problem --- CHANGELOG.md | 1 + extensions/STC | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 160000 extensions/STC diff --git a/CHANGELOG.md b/CHANGELOG.md index 87950ab534..fcb6cc363e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ All notable changes to this project will be documented in this file. - #1830 : Add a `pyccel.lambdify.lambdify` function to accelerate SymPy expressions. - \[INTERNALS\] Added `container_rank` property to `ast.datatypes.PyccelType` objects. - \[DEVELOPER\] Added an improved traceback to the developer-mode errors for errors in function calls. +- #1754 : Add Python support for set method `update()`. ### Fixed diff --git a/extensions/STC b/extensions/STC deleted file mode 160000 index 09790f024a..0000000000 --- a/extensions/STC +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 09790f024ad29fca6fe60528461eeb589d4a917b From 0d124884bf3bd6148d57c31e9802b8680eabd277 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Wed, 17 Apr 2024 12:38:15 +0100 Subject: [PATCH 014/139] Move the function position to the bottom of the file. --- pyccel/parser/semantic.py | 91 ++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 45 deletions(-) diff --git a/pyccel/parser/semantic.py b/pyccel/parser/semantic.py index fdf6d4d18c..1d88f5ed9c 100644 --- a/pyccel/parser/semantic.py +++ b/pyccel/parser/semantic.py @@ -2730,51 +2730,6 @@ def _visit_ListExtend(self, expr): pyccel_stage.set_stage('semantic') return self._visit(for_obj) - def _visit_SetUpdate(self, expr): - """ - Method to navigate the syntactic DottedName node of an `update()` call. - - The purpose of this `_visit` method is to construct new nodes from a syntactic - DottedName node. It checks the type of the iterable passed to `update()`. - If the iterable is an instance of `PythonList`, `PythonSet` or `PythonTuple`, it constructs - a CodeBlock node where its body consists of `SetAdd` objects with the - elements of the iterable. If not, it attempts to construct a syntactic `For` - loop to iterate over the iterable object and added its elements to the set - object. Finally, it passes to a `_visit()` call for semantic parsing. - - Parameters - ---------- - expr : DottedName - The syntactic DottedName node that represent the call to `.update()` - - Returns - ------- - PyccelAstNode - CodeBlock or For containing SetAdd objects. - """ - iterable = expr.name[1].args[0].value - if isinstance(iterable, (PythonList, PythonSet, PythonTuple)): - list_variable = self._visit(expr.name[0]) - added_list = self._visit(iterable) - try: - store = [SetAdd(list_variable, a) for a in added_list] - except TypeError as e: - msg = str(e) - errors.report(msg, symbol=expr, severity='fatal') - return CodeBlock(store) - else: - pyccel_stage.set_stage('syntactic') - for_target = self.scope.get_new_name('index') - arg = FunctionCallArgument(for_target) - func_call = FunctionCall('add', [arg]) - dotted = DottedName(expr.name[0], func_call) - lhs = PyccelSymbol('_', is_temp=True) - assign = Assign(lhs, dotted) - assign.set_current_ast(expr.python_ast) - body = CodeBlock([assign]) - for_obj = For(for_target, iterable, body) - pyccel_stage.set_stage('semantic') - return self._visit(for_obj) def _visit_PyccelOperator(self, expr): args = [self._visit(a) for a in expr.args] @@ -4688,3 +4643,49 @@ def _visit_FunctionDefResult(self, expr): var = var[0] self.scope.insert_variable(var) return FunctionDefResult(var, annotation = expr.annotation) + + def _visit_SetUpdate(self, expr): + """ + Method to navigate the syntactic DottedName node of an `update()` call. + + The purpose of this `_visit` method is to construct new nodes from a syntactic + DottedName node. It checks the type of the iterable passed to `update()`. + If the iterable is an instance of `PythonList`, `PythonSet` or `PythonTuple`, it constructs + a CodeBlock node where its body consists of `SetAdd` objects with the + elements of the iterable. If not, it attempts to construct a syntactic `For` + loop to iterate over the iterable object and added its elements to the set + object. Finally, it passes to a `_visit()` call for semantic parsing. + + Parameters + ---------- + expr : DottedName + The syntactic DottedName node that represent the call to `.update()` + + Returns + ------- + PyccelAstNode + CodeBlock or For containing SetAdd objects. + """ + iterable = expr.name[1].args[0].value + if isinstance(iterable, (PythonList, PythonSet, PythonTuple)): + list_variable = self._visit(expr.name[0]) + added_list = self._visit(iterable) + try: + store = [SetAdd(list_variable, a) for a in added_list] + except TypeError as e: + msg = str(e) + errors.report(msg, symbol=expr, severity='fatal') + return CodeBlock(store) + else: + pyccel_stage.set_stage('syntactic') + for_target = self.scope.get_new_name('index') + arg = FunctionCallArgument(for_target) + func_call = FunctionCall('add', [arg]) + dotted = DottedName(expr.name[0], func_call) + lhs = PyccelSymbol('_', is_temp=True) + assign = Assign(lhs, dotted) + assign.set_current_ast(expr.python_ast) + body = CodeBlock([assign]) + for_obj = For(for_target, iterable, body) + pyccel_stage.set_stage('semantic') + return self._visit(for_obj) From 1c3b75a874d1aa7553cfe632efea0f5631952d72 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Wed, 17 Apr 2024 12:39:40 +0100 Subject: [PATCH 015/139] Add a newline in the end of file --- pyccel/parser/semantic.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyccel/parser/semantic.py b/pyccel/parser/semantic.py index 0f577682c3..4530404d88 100644 --- a/pyccel/parser/semantic.py +++ b/pyccel/parser/semantic.py @@ -4668,3 +4668,4 @@ def _visit_SetUpdate(self, expr): for_obj = For(for_target, iterable, body) pyccel_stage.set_stage('semantic') return self._visit(for_obj) + From 0a6a2c4d9eb6053822e4c2cc71025dc4fad30564 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Wed, 17 Apr 2024 12:50:53 +0100 Subject: [PATCH 016/139] fix docs --- pyccel/ast/builtin_methods/set_methods.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyccel/ast/builtin_methods/set_methods.py b/pyccel/ast/builtin_methods/set_methods.py index e3edbb1226..0089968178 100644 --- a/pyccel/ast/builtin_methods/set_methods.py +++ b/pyccel/ast/builtin_methods/set_methods.py @@ -220,11 +220,11 @@ class SetUpdate(SetMethod): Parameters ---------- - set_variable : TypedAstNode + set_obj : TypedAstNode The set object which the method is called from. The argument passed to update() method. - item : TypedAstNode + iterable : TypedAstNode The item to search for, and remove. """ __slots__ = () From 80ce7bba65c0d4693b3d684b47d3fcf21c6cc47f Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Wed, 17 Apr 2024 13:04:24 +0100 Subject: [PATCH 017/139] Fix Python linting problem --- pyccel/parser/semantic.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pyccel/parser/semantic.py b/pyccel/parser/semantic.py index 4530404d88..c3e4823650 100644 --- a/pyccel/parser/semantic.py +++ b/pyccel/parser/semantic.py @@ -2711,7 +2711,6 @@ def _visit_ListExtend(self, expr): for_obj = For(for_target, iterable, body) pyccel_stage.set_stage('semantic') return self._visit(for_obj) - def _visit_PyccelOperator(self, expr): args = [self._visit(a) for a in expr.args] @@ -3121,8 +3120,7 @@ def _visit_Assign(self, expr): symbol=expr, severity='error') # Checking for the result of _visit_ListExtend - if isinstance(rhs, For) or (isinstance(rhs, CodeBlock) and - (isinstance(rhs.body[0], ListMethod) or isinstance(rhs.body[0], SetMethod))): + if isinstance(rhs, For) or (isinstance(rhs, CodeBlock) and isinstance(rhs.body[0], ListMethod, SetMethod)): return rhs if isinstance(rhs, ConstructorCall): return rhs From 28eae73a57c3e774c107790ed82f7204703108f2 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Wed, 17 Apr 2024 15:13:19 +0100 Subject: [PATCH 018/139] Fix a small problem in code. --- pyccel/parser/semantic.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyccel/parser/semantic.py b/pyccel/parser/semantic.py index c3e4823650..9707aac4e7 100644 --- a/pyccel/parser/semantic.py +++ b/pyccel/parser/semantic.py @@ -3120,7 +3120,8 @@ def _visit_Assign(self, expr): symbol=expr, severity='error') # Checking for the result of _visit_ListExtend - if isinstance(rhs, For) or (isinstance(rhs, CodeBlock) and isinstance(rhs.body[0], ListMethod, SetMethod)): + if isinstance(rhs, For) or (isinstance(rhs, CodeBlock) and + isinstance(rhs.body[0], (ListMethod, SetMethod))): return rhs if isinstance(rhs, ConstructorCall): return rhs From 1a76965fbf8e2c4ce568e48beee695064f38d709 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Mon, 22 Apr 2024 14:15:26 +0100 Subject: [PATCH 019/139] add support for type annotation --- pyccel/parser/semantic.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyccel/parser/semantic.py b/pyccel/parser/semantic.py index 9707aac4e7..769ce79b80 100644 --- a/pyccel/parser/semantic.py +++ b/pyccel/parser/semantic.py @@ -1885,7 +1885,7 @@ def _get_indexed_type(self, base, args, expr): raise errors.report(f"Unknown annotation base {base}\n"+PYCCEL_RESTRICTION_TODO, severity='fatal', symbol=expr) rank = 1 - if len(args) == 2 and args[1] is LiteralEllipsis(): + if (len(args) == 2 and args[1] is LiteralEllipsis()) or (len(args) > 0): syntactic_annotation = args[0] if not isinstance(syntactic_annotation, SyntacticTypeAnnotation): syntactic_annotation = SyntacticTypeAnnotation(dtype=syntactic_annotation) @@ -2270,6 +2270,7 @@ def _visit_CodeBlock(self, expr): if len(line) != 1: errors.report(f"Variable {line[0]} cannot have multiple types", severity='error', symbol=line[0]) + ls.extend(line) # ---------------------------- End of if block ------------------------------------------ else: ls.append(line) From 034cd2657e662d1babe23d9eac12316f86f83fe6 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Mon, 22 Apr 2024 14:28:28 +0100 Subject: [PATCH 020/139] only changes for type annotation --- CHANGELOG.md | 1 - pyccel/ast/builtin_methods/set_methods.py | 39 +-------- pyccel/ast/class_defs.py | 3 +- pyccel/parser/semantic.py | 51 +----------- tests/epyccel/test_epyccel_sets.py | 80 ------------------- .../UPDATE_SET_INCOMPATIBLE_TYPES_1.py | 4 - .../UPDATE_SET_INCOMPATIBLE_TYPES_2.py | 5 -- 7 files changed, 3 insertions(+), 180 deletions(-) delete mode 100644 tests/errors/semantic/blocking/UPDATE_SET_INCOMPATIBLE_TYPES_1.py delete mode 100644 tests/errors/semantic/blocking/UPDATE_SET_INCOMPATIBLE_TYPES_2.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e0cc1ee04..25de230a48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,6 @@ All notable changes to this project will be documented in this file. - #1830 : Add a `pyccel.lambdify.lambdify` function to accelerate SymPy expressions. - \[INTERNALS\] Added `container_rank` property to `ast.datatypes.PyccelType` objects. - \[DEVELOPER\] Added an improved traceback to the developer-mode errors for errors in function calls. -- #1754 : Add Python support for set method `update()`. ### Fixed diff --git a/pyccel/ast/builtin_methods/set_methods.py b/pyccel/ast/builtin_methods/set_methods.py index 8b827dd5d4..30de60e023 100644 --- a/pyccel/ast/builtin_methods/set_methods.py +++ b/pyccel/ast/builtin_methods/set_methods.py @@ -19,9 +19,7 @@ 'SetCopy', 'SetDiscard', 'SetMethod', - 'SetPop', - 'SetRemove', - 'SetUpdate' + 'SetPop' ) class SetMethod(PyccelFunction): @@ -54,7 +52,6 @@ def set_variable(self): """ return self._set_variable -#============================================================================== class SetAdd(SetMethod) : """ Represents a call to the .add() method. @@ -81,7 +78,6 @@ def __init__(self, set_variable, new_elem) -> None: raise TypeError("Expecting an argument of the same type as the elements of the set") super().__init__(set_variable, new_elem) -#============================================================================== class SetClear(SetMethod): """ Represents a call to the .clear() method. @@ -102,7 +98,6 @@ class SetClear(SetMethod): def __init__(self, set_variable): super().__init__(set_variable) -#============================================================================== class SetCopy(SetMethod): """ Represents a call to the .copy() method. @@ -123,7 +118,6 @@ def __init__(self, set_variable): self._class_type = set_variable._class_type super().__init__(set_variable) -#============================================================================== class SetPop(SetMethod): """ Represents a call to the .pop() method. @@ -147,7 +141,6 @@ def __init__(self, set_variable): self._class_type = set_variable.class_type.element_type super().__init__(set_variable) -#============================================================================== class SetRemove(SetMethod): """ Represents a call to the .remove() method. @@ -175,7 +168,6 @@ def __init__(self, set_variable, item) -> None: raise TypeError(f"Can't remove an element of type {item.dtype} from a set of {set_variable.dtype}") super().__init__(set_variable, item) -#============================================================================== class SetDiscard(SetMethod): """ Represents a call to the .discard() method. @@ -202,32 +194,3 @@ def __init__(self, set_variable, item) -> None: raise TypeError("Expecting an argument of the same type as the elements of the set") super().__init__(set_variable, item) -#============================================================================== -class SetUpdate(SetMethod): - """ - Represents a call to the .update() method. - - Represents a call to the .update() method of an object with a set type, - Which adds items from another set (or any other iterable). - This method is handled through the call to `_visit_SetUpdate` in - the semantic stage. It then attempts to construct a `For` loop node with - a body that calls `add()`, or direct `add()` nodes depending on - the type of the iterable passed to `update()`. - This class should never be instantiated; it's only purpose is to help - construct the annotation_method `_visit_SetUpdate`. - The update method is called as follows: - - Parameters - ---------- - set_obj : TypedAstNode - The set object which the method is called from. - - The argument passed to update() method. - iterable : TypedAstNode - The item to search for, and remove. - """ - __slots__ = () - name = 'update' - - def __init__(self, set_obj, iterable) -> None: - super().__init__(set_obj, iterable) diff --git a/pyccel/ast/class_defs.py b/pyccel/ast/class_defs.py index ecf086d5d5..a09a754d94 100644 --- a/pyccel/ast/class_defs.py +++ b/pyccel/ast/class_defs.py @@ -6,7 +6,7 @@ This module contains all types which define a python class which is automatically recognised by pyccel """ -from pyccel.ast.builtin_methods.set_methods import SetAdd, SetClear, SetCopy, SetPop, SetRemove, SetDiscard, SetUpdate +from pyccel.ast.builtin_methods.set_methods import SetAdd, SetClear, SetCopy, SetPop, SetRemove, SetDiscard from pyccel.ast.builtin_methods.list_methods import (ListAppend, ListInsert, ListPop, ListClear, ListExtend, ListRemove, ListCopy, ListSort) @@ -161,7 +161,6 @@ PyccelFunctionDef('discard', func_class = SetDiscard), PyccelFunctionDef('pop', func_class = SetPop), PyccelFunctionDef('remove', func_class = SetRemove), - PyccelFunctionDef('update', func_class = SetUpdate), ]) #======================================================================================= diff --git a/pyccel/parser/semantic.py b/pyccel/parser/semantic.py index 2e6339b4e7..1a055349cf 100644 --- a/pyccel/parser/semantic.py +++ b/pyccel/parser/semantic.py @@ -29,7 +29,6 @@ PythonTuple, Lambda, PythonMap) from pyccel.ast.builtin_methods.list_methods import ListMethod, ListAppend -from pyccel.ast.builtin_methods.set_methods import SetMethod, SetAdd from pyccel.ast.core import Comment, CommentBlock, Pass from pyccel.ast.core import If, IfSection @@ -3142,8 +3141,7 @@ def _visit_Assign(self, expr): symbol=expr, severity='error') # Checking for the result of _visit_ListExtend - if isinstance(rhs, For) or (isinstance(rhs, CodeBlock) and - isinstance(rhs.body[0], (ListMethod, SetMethod))): + if isinstance(rhs, For) or (isinstance(rhs, CodeBlock) and isinstance(rhs.body[0], ListMethod)): return rhs if isinstance(rhs, ConstructorCall): return rhs @@ -4661,50 +4659,3 @@ def _visit_FunctionDefResult(self, expr): var = var[0] self.scope.insert_variable(var) return FunctionDefResult(var, annotation = expr.annotation) - - def _visit_SetUpdate(self, expr): - """ - Method to navigate the syntactic DottedName node of an `update()` call. - - The purpose of this `_visit` method is to construct new nodes from a syntactic - DottedName node. It checks the type of the iterable passed to `update()`. - If the iterable is an instance of `PythonList`, `PythonSet` or `PythonTuple`, it constructs - a CodeBlock node where its body consists of `SetAdd` objects with the - elements of the iterable. If not, it attempts to construct a syntactic `For` - loop to iterate over the iterable object and added its elements to the set - object. Finally, it passes to a `_visit()` call for semantic parsing. - - Parameters - ---------- - expr : DottedName - The syntactic DottedName node that represent the call to `.update()` - - Returns - ------- - PyccelAstNode - CodeBlock or For containing SetAdd objects. - """ - iterable = expr.name[1].args[0].value - if isinstance(iterable, (PythonList, PythonSet, PythonTuple)): - list_variable = self._visit(expr.name[0]) - added_list = self._visit(iterable) - try: - store = [SetAdd(list_variable, a) for a in added_list] - except TypeError as e: - msg = str(e) - errors.report(msg, symbol=expr, severity='fatal') - return CodeBlock(store) - else: - pyccel_stage.set_stage('syntactic') - for_target = self.scope.get_new_name('index') - arg = FunctionCallArgument(for_target) - func_call = FunctionCall('add', [arg]) - dotted = DottedName(expr.name[0], func_call) - lhs = PyccelSymbol('_', is_temp=True) - assign = Assign(lhs, dotted) - assign.set_current_ast(expr.python_ast) - body = CodeBlock([assign]) - for_obj = For(for_target, iterable, body) - pyccel_stage.set_stage('semantic') - return self._visit(for_obj) - diff --git a/tests/epyccel/test_epyccel_sets.py b/tests/epyccel/test_epyccel_sets.py index d9a4436585..d467e9bdef 100644 --- a/tests/epyccel/test_epyccel_sets.py +++ b/tests/epyccel/test_epyccel_sets.py @@ -203,83 +203,3 @@ def Discard_wrong_arg(): pyccel_result = epyccel_remove() python_result = Discard_wrong_arg() assert python_result == pyccel_result - -def test_update_basic(language): - def update_basic(): - a = {1, 2, 3} - b = {4, 5, 6} - a.update(b) - return a - - epyccel_update = epyccel(update_basic, language=language) - pyccel_result = epyccel_update() - python_result = update_basic() - assert python_result == pyccel_result - -def test_update_multiple(language): - def update_multiple(): - a = {1, 2, 3} - a.update({4, 5}) - a.update({6, 7, 8, 9}) - a.update({10}) - return a - - epyccel_update = epyccel(update_multiple, language=language) - pyccel_result = epyccel_update() - python_result = update_multiple() - assert python_result == pyccel_result - - -def test_update_boolean_tuple(language): - def update_boolean_tuple(): - a = {True} - b = (False, True, False) - a.update(b) - return a - epyccel_update = epyccel(update_boolean_tuple, language=language) - pyccel_result = epyccel_update() - python_result = update_boolean_tuple() - assert python_result == pyccel_result - - -def test_update_complex_list(language): - def update_complex_list(): - a = {1j, 2 + 3j, 0 + 0j} - b = {4j, 5j, 1 + 6j} - a.update(b) - return a - epyccel_update = epyccel(update_complex_list, language=language) - pyccel_result = epyccel_update() - python_result = update_complex_list() - assert python_result == pyccel_result - -def test_update_range(language): - def update_range(): - a = {1, 2, 3} - a.update(range(4, 9)) - return a - epyccel_update = epyccel(update_range, language=language) - pyccel_result = epyccel_update() - python_result = update_range() - assert python_result == pyccel_result - -def test_update_set_as_arg(language): - def update_set_as_arg(): - a = {1, 2, 3} - a.update({4, 5, 6}) - return a - - epyccel_update = epyccel(update_set_as_arg, language=language) - pyccel_result = epyccel_update() - python_result = update_set_as_arg() - assert python_result == pyccel_result - -def test_update_tuple_as_arg(language): - def update_tuple_as_arg(): - a = {1, 2, 3} - a.update((4, 5, 6)) - return a - epyccel_update = epyccel(update_tuple_as_arg, language=language) - pyccel_result = epyccel_update() - python_result = update_tuple_as_arg() - assert python_result == pyccel_result diff --git a/tests/errors/semantic/blocking/UPDATE_SET_INCOMPATIBLE_TYPES_1.py b/tests/errors/semantic/blocking/UPDATE_SET_INCOMPATIBLE_TYPES_1.py deleted file mode 100644 index 49ff697d2a..0000000000 --- a/tests/errors/semantic/blocking/UPDATE_SET_INCOMPATIBLE_TYPES_1.py +++ /dev/null @@ -1,4 +0,0 @@ -# pylint: disable=missing-function-docstring, missing-module-docstring - -a = {1.4, 6.2, 8.1} -a.update({3j}) diff --git a/tests/errors/semantic/blocking/UPDATE_SET_INCOMPATIBLE_TYPES_2.py b/tests/errors/semantic/blocking/UPDATE_SET_INCOMPATIBLE_TYPES_2.py deleted file mode 100644 index 9950f01959..0000000000 --- a/tests/errors/semantic/blocking/UPDATE_SET_INCOMPATIBLE_TYPES_2.py +++ /dev/null @@ -1,5 +0,0 @@ -# pylint: disable=missing-function-docstring, missing-module-docstring - -a = {2, 9, 5} -b = {8.9, 6.} -a.update(b) From 188466f573bc8b58ff5bfd96fe9a13a8f278b9d2 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Mon, 22 Apr 2024 14:30:16 +0100 Subject: [PATCH 021/139] only changes for type annotation --- pyccel/ast/builtin_methods/set_methods.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/pyccel/ast/builtin_methods/set_methods.py b/pyccel/ast/builtin_methods/set_methods.py index 30de60e023..74f0010634 100644 --- a/pyccel/ast/builtin_methods/set_methods.py +++ b/pyccel/ast/builtin_methods/set_methods.py @@ -19,7 +19,8 @@ 'SetCopy', 'SetDiscard', 'SetMethod', - 'SetPop' + 'SetPop', + 'SetRemove' ) class SetMethod(PyccelFunction): @@ -52,6 +53,7 @@ def set_variable(self): """ return self._set_variable + class SetAdd(SetMethod) : """ Represents a call to the .add() method. @@ -78,6 +80,7 @@ def __init__(self, set_variable, new_elem) -> None: raise TypeError("Expecting an argument of the same type as the elements of the set") super().__init__(set_variable, new_elem) + class SetClear(SetMethod): """ Represents a call to the .clear() method. @@ -98,6 +101,7 @@ class SetClear(SetMethod): def __init__(self, set_variable): super().__init__(set_variable) + class SetCopy(SetMethod): """ Represents a call to the .copy() method. @@ -118,6 +122,7 @@ def __init__(self, set_variable): self._class_type = set_variable._class_type super().__init__(set_variable) + class SetPop(SetMethod): """ Represents a call to the .pop() method. @@ -141,6 +146,7 @@ def __init__(self, set_variable): self._class_type = set_variable.class_type.element_type super().__init__(set_variable) + class SetRemove(SetMethod): """ Represents a call to the .remove() method. @@ -168,6 +174,7 @@ def __init__(self, set_variable, item) -> None: raise TypeError(f"Can't remove an element of type {item.dtype} from a set of {set_variable.dtype}") super().__init__(set_variable, item) + class SetDiscard(SetMethod): """ Represents a call to the .discard() method. @@ -193,4 +200,3 @@ def __init__(self, set_variable, item) -> None: if set_variable.class_type.element_type != item.class_type: raise TypeError("Expecting an argument of the same type as the elements of the set") super().__init__(set_variable, item) - From d0bd13cadeecc053b29c99e826e032ba84e4dfaf Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Tue, 23 Apr 2024 11:45:50 +0100 Subject: [PATCH 022/139] Modify the condition to be more general. --- pyccel/parser/semantic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyccel/parser/semantic.py b/pyccel/parser/semantic.py index 1a055349cf..2810e14acb 100644 --- a/pyccel/parser/semantic.py +++ b/pyccel/parser/semantic.py @@ -1896,7 +1896,7 @@ def _get_indexed_type(self, base, args, expr): raise errors.report(f"Unknown annotation base {base}\n"+PYCCEL_RESTRICTION_TODO, severity='fatal', symbol=expr) rank = 1 - if (len(args) == 2 and args[1] is LiteralEllipsis()) or (len(args) > 0): + if len(args) > 0: syntactic_annotation = args[0] if not isinstance(syntactic_annotation, SyntacticTypeAnnotation): pyccel_stage.set_stage('syntactic') From 9fa2aa3df9bdfa4d5a9874ffcfab6acc38896cc6 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Tue, 23 Apr 2024 15:42:19 +0100 Subject: [PATCH 023/139] list declare in c: prototype --- pyccel/codegen/printing/ccode.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index bc29c4118b..3ba075ced9 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -821,6 +821,10 @@ def _print_Module(self, expr): self.exit_scope() return code + def _print_PythonList(self, expr): + vec_declare = 'vec_' + expr.dtype._name + return vec_declare + def _print_Break(self, expr): return 'break;\n' From de72d1db21dc12505798ee41b4b3797bf33da521 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Mon, 29 Apr 2024 10:55:22 +0100 Subject: [PATCH 024/139] Add support for sets in semantic and codegen stages. --- pyccel/ast/builtins.py | 1 + pyccel/codegen/codegen.py | 12 ++++++------ pyccel/codegen/printing/ccode.py | 27 ++++++++++++++++++++++----- pyccel/parser/semantic.py | 4 +++- 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/pyccel/ast/builtins.py b/pyccel/ast/builtins.py index ba98c537b2..c2b9e98055 100644 --- a/pyccel/ast/builtins.py +++ b/pyccel/ast/builtins.py @@ -1226,6 +1226,7 @@ def print_string(self): 'min' : PythonMin, 'not' : PyccelNot, 'map' : PythonMap, + 'set' : PythonSet, 'str' : LiteralString, 'type' : PythonType, 'tuple' : PythonTupleFunction, diff --git a/pyccel/codegen/codegen.py b/pyccel/codegen/codegen.py index 3da73d1ff9..7777d55955 100644 --- a/pyccel/codegen/codegen.py +++ b/pyccel/codegen/codegen.py @@ -216,6 +216,12 @@ def export(self, filename): header_filename = f'{filename}.{header_ext}' filename = f'{filename}.{ext}' + # print module + code = self._printer.doprint(self.ast) + with open(filename, 'w') as f: + for line in code: + f.write(line) + # print module header if header_ext is not None: code = self._printer.doprint(ModuleHeader(self.ast)) @@ -223,12 +229,6 @@ def export(self, filename): for line in code: f.write(line) - # print module - code = self._printer.doprint(self.ast) - with open(filename, 'w') as f: - for line in code: - f.write(line) - # print program prog_filename = None if self.is_program and self.language != 'python': diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index bc29c4118b..c021ecea6a 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -27,7 +27,7 @@ from pyccel.ast.datatypes import PythonNativeInt, PythonNativeBool, VoidType from pyccel.ast.datatypes import TupleType, FixedSizeNumericType -from pyccel.ast.datatypes import CustomDataType, StringType, HomogeneousTupleType +from pyccel.ast.datatypes import CustomDataType, StringType, HomogeneousTupleType, HomogeneousListType, HomogeneousSetType from pyccel.ast.datatypes import PrimitiveBooleanType, PrimitiveIntegerType, PrimitiveFloatingPointType, PrimitiveComplexType from pyccel.ast.datatypes import HomogeneousContainerType @@ -225,6 +225,11 @@ import_dict = {'omp_lib' : 'omp' } +import_stc = {'_SET_INT' : '#ifndef _SET_INT\n#define _STC_INT\n\n#define i_key int\n', + '_SET_FLOAT_' : '#ifndef _SET_FLAOT\n#define _STC_FLAOT\n\n#define i_key float\n', + 'stc/hset' : '#include "stc/hset.h"\n#endif\n', + } + c_imports = {n : Import(n, Module(n, (), ())) for n in ['stdlib', 'math', @@ -237,7 +242,8 @@ "inttypes", 'stdbool', 'assert', - 'numpy_c']} + 'numpy_c', + 'stc/hset',]} class CCodePrinter(CodePrinter): """ @@ -312,7 +318,7 @@ def get_additional_imports(self): return self._additional_imports.keys() def add_import(self, import_obj): - if import_obj.source not in self._additional_imports: + if import_obj.source not in self._additional_imports: self._additional_imports[import_obj.source] = import_obj def _get_statement(self, codestring): @@ -788,8 +794,9 @@ def _print_ModuleHeader(self, expr): # Print imports last to be sure that all additional_imports have been collected imports = [*expr.module.imports, *self._additional_imports.values()] - imports = ''.join(self._print(i) for i in imports) + + imports = ''.join(self._print(i) for i in imports) self._in_header = False self.exit_scope() return (f"#ifndef {name.upper()}_H\n \ @@ -944,7 +951,8 @@ def _print_Import(self, expr): source = source.name[-1] else: source = self._print(source) - + if source in import_stc: + return import_stc[source] # Get with a default value is not used here as it is # slower and on most occasions the import will not be in the # dictionary @@ -1160,6 +1168,12 @@ def find_in_dtype_registry(self, dtype): return 'bool' key = (primitive_type, dtype.precision) + elif isinstance(dtype, HomogeneousSetType): + key = 'hset_' + dtype._name + defi = '_SET_' + dtype.datatype._name.upper() + self.add_import(Import(defi, Module(defi, (), ()))) + self.add_import(c_imports['stc/hset']) + return key else: key = dtype @@ -1238,6 +1252,9 @@ def get_declare_type(self, expr): if expr.is_ndarray or isinstance(expr.class_type, HomogeneousContainerType): if expr.rank > 15: errors.report(UNSUPPORTED_ARRAY_RANK, symbol=expr, severity='fatal') + if isinstance(expr.class_type, HomogeneousSetType): + dtype = self.find_in_dtype_registry(expr.class_type) + return dtype self.add_import(c_imports['ndarrays']) dtype = 't_ndarray' else: diff --git a/pyccel/parser/semantic.py b/pyccel/parser/semantic.py index cb71c4888e..3cdd522b97 100644 --- a/pyccel/parser/semantic.py +++ b/pyccel/parser/semantic.py @@ -60,7 +60,7 @@ from pyccel.ast.class_defs import NumpyArrayClass, TupleClass, get_cls_base from pyccel.ast.datatypes import CustomDataType, PyccelType, TupleType, VoidType, GenericType -from pyccel.ast.datatypes import PrimitiveIntegerType, HomogeneousListType, StringType, SymbolicType +from pyccel.ast.datatypes import PrimitiveIntegerType, HomogeneousListType, StringType, SymbolicType, HomogeneousSetType from pyccel.ast.datatypes import PythonNativeBool, PythonNativeInt, PythonNativeFloat from pyccel.ast.datatypes import DataTypeFactory, PrimitiveFloatingPointType from pyccel.ast.datatypes import InhomogeneousTupleType, HomogeneousTupleType @@ -1929,6 +1929,8 @@ def _get_indexed_type(self, base, args, expr): class_type = HomogeneousTupleType elif dtype_cls is PythonList: class_type = HomogeneousListType + elif dtype_cls is PythonSet: + class_type = HomogeneousSetType else: raise errors.report(f"Unknown annotation base {base}\n"+PYCCEL_RESTRICTION_TODO, severity='fatal', symbol=expr) From f11f946cd2ba173b2454c627ae70fc579603e3f4 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Tue, 30 Apr 2024 11:21:17 +0100 Subject: [PATCH 025/139] Move all the imports to the header file and include STC, defining the exact type. --- pyccel/codegen/printing/ccode.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index c021ecea6a..455bb5d18b 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -225,10 +225,9 @@ import_dict = {'omp_lib' : 'omp' } -import_stc = {'_SET_INT' : '#ifndef _SET_INT\n#define _STC_INT\n\n#define i_key int\n', - '_SET_FLOAT_' : '#ifndef _SET_FLAOT\n#define _STC_FLAOT\n\n#define i_key float\n', - 'stc/hset' : '#include "stc/hset.h"\n#endif\n', - } +import_stc = {'_SET_INT' : 'int', + '_SET_FLOAT' : 'float', +} c_imports = {n : Import(n, Module(n, (), ())) for n in ['stdlib', @@ -242,8 +241,7 @@ "inttypes", 'stdbool', 'assert', - 'numpy_c', - 'stc/hset',]} + 'numpy_c']} class CCodePrinter(CodePrinter): """ @@ -815,8 +813,8 @@ def _print_Module(self, expr): global_variables = ''.join([self._print(d) for d in expr.declarations]) # Print imports last to be sure that all additional_imports have been collected - imports = [Import(expr.name, Module(expr.name,(),())), *self._additional_imports.values()] - imports = ''.join(self._print(i) for i in imports) + imports = Import(expr.name, Module(expr.name,(),())) + imports = self._print(imports) code = ('{imports}\n' '{variables}\n' @@ -952,7 +950,12 @@ def _print_Import(self, expr): else: source = self._print(source) if source in import_stc: - return import_stc[source] + dtype = import_stc[source] + return (f'#ifndef {source}\n' + f'#define {source}\n' + f'#define i_key {dtype}\n' + f'#include "stc/hset.h"\n' + f'#endif\n') # Get with a default value is not used here as it is # slower and on most occasions the import will not be in the # dictionary @@ -1172,7 +1175,6 @@ def find_in_dtype_registry(self, dtype): key = 'hset_' + dtype._name defi = '_SET_' + dtype.datatype._name.upper() self.add_import(Import(defi, Module(defi, (), ()))) - self.add_import(c_imports['stc/hset']) return key else: key = dtype From 78d08ef912f278328f1d7c8708fcbd18b360797f Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Tue, 30 Apr 2024 11:36:42 +0100 Subject: [PATCH 026/139] Remove unnecessary changes. --- pyccel/codegen/printing/ccode.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 455bb5d18b..b3e534fa8c 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -316,7 +316,7 @@ def get_additional_imports(self): return self._additional_imports.keys() def add_import(self, import_obj): - if import_obj.source not in self._additional_imports: + if import_obj.source not in self._additional_imports: self._additional_imports[import_obj.source] = import_obj def _get_statement(self, codestring): @@ -792,7 +792,6 @@ def _print_ModuleHeader(self, expr): # Print imports last to be sure that all additional_imports have been collected imports = [*expr.module.imports, *self._additional_imports.values()] - imports = ''.join(self._print(i) for i in imports) self._in_header = False @@ -949,6 +948,7 @@ def _print_Import(self, expr): source = source.name[-1] else: source = self._print(source) + if source in import_stc: dtype = import_stc[source] return (f'#ifndef {source}\n' From 3234426567731098cdae5a6cee7295bd190da859 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Tue, 30 Apr 2024 11:38:04 +0100 Subject: [PATCH 027/139] Remove unnecessary changes. --- pyccel/codegen/printing/ccode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index b3e534fa8c..c718e58326 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -792,8 +792,8 @@ def _print_ModuleHeader(self, expr): # Print imports last to be sure that all additional_imports have been collected imports = [*expr.module.imports, *self._additional_imports.values()] - imports = ''.join(self._print(i) for i in imports) + self._in_header = False self.exit_scope() return (f"#ifndef {name.upper()}_H\n \ From b4d1ddd5b6bcf11b413ec4d43bb91f38914f7e93 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Tue, 30 Apr 2024 15:45:06 +0100 Subject: [PATCH 028/139] Rewrite the solution. --- pyccel/codegen/printing/ccode.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index c718e58326..64d6af5aba 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -225,9 +225,6 @@ import_dict = {'omp_lib' : 'omp' } -import_stc = {'_SET_INT' : 'int', - '_SET_FLOAT' : 'float', -} c_imports = {n : Import(n, Module(n, (), ())) for n in ['stdlib', @@ -302,7 +299,7 @@ def __init__(self, filename, prefix_module = None): errors.set_target(filename, 'file') - super().__init__() + super().__init__() self.prefix_module = prefix_module self._additional_imports = {'stdlib':c_imports['stdlib']} self._additional_code = '' @@ -936,7 +933,8 @@ def _print_PyccelPow(self, expr): e = self._print(e if e.dtype.primitive_type is PrimitiveFloatingPointType() else NumpyFloat(e)) code = 'pow({}, {})'.format(b, e) return self._cast_to(expr, expr.dtype).format(code) - + + def _print_Import(self, expr): if expr.ignore: return '' @@ -948,14 +946,16 @@ def _print_Import(self, expr): source = source.name[-1] else: source = self._print(source) + if expr.target: + dtype = expr.target.pop().name + if source == ('stc/hset_' + str(dtype)): + dtype_macro = dtype.upper() + return (f'#ifndef _SET_{dtype_macro}\n' + f'#define _SET_{dtype_macro}\n' + f'#define i_key {dtype}\n' + f'#include "stc/hset.h"\n' + f'#endif\n') - if source in import_stc: - dtype = import_stc[source] - return (f'#ifndef {source}\n' - f'#define {source}\n' - f'#define i_key {dtype}\n' - f'#include "stc/hset.h"\n' - f'#endif\n') # Get with a default value is not used here as it is # slower and on most occasions the import will not be in the # dictionary @@ -1173,8 +1173,9 @@ def find_in_dtype_registry(self, dtype): key = (primitive_type, dtype.precision) elif isinstance(dtype, HomogeneousSetType): key = 'hset_' + dtype._name - defi = '_SET_' + dtype.datatype._name.upper() - self.add_import(Import(defi, Module(defi, (), ()))) + types = dtype.datatype._name + source = 'stc/hset_' + types + self.add_import(Import(source, Module(types, (), ()))) return key else: key = dtype From 1537b39b5bae150f53d20997750221aec4b254fa Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Tue, 30 Apr 2024 15:59:32 +0100 Subject: [PATCH 029/139] assign generic empty list to typed list variable --- pyccel/parser/semantic.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyccel/parser/semantic.py b/pyccel/parser/semantic.py index 5da2f8c23b..9a0209cea5 100644 --- a/pyccel/parser/semantic.py +++ b/pyccel/parser/semantic.py @@ -1614,7 +1614,7 @@ def _ensure_inferred_type_matches_existing(self, class_type, d_var, var, is_auga # to remove memory leaks new_expressions.append(Deallocate(var)) - elif class_type != var.class_type: + elif class_type != var.class_type and not isinstance(class_type.datatype, GenericType): if is_augassign: tmp_result = PyccelAdd(var, rhs) result_type = tmp_result.class_type @@ -1916,8 +1916,7 @@ def _get_indexed_type(self, base, args, expr): else: raise errors.report(f"Unknown annotation base {base}\n"+PYCCEL_RESTRICTION_TODO, severity='fatal', symbol=expr) - rank = 1 - if len(args) == 2 and args[1] is LiteralEllipsis(): + if len(args) > 0: syntactic_annotation = args[0] if not isinstance(syntactic_annotation, SyntacticTypeAnnotation): pyccel_stage.set_stage('syntactic') @@ -2310,6 +2309,7 @@ def _visit_CodeBlock(self, expr): if len(line) != 1: errors.report(f"Variable {line[0]} cannot have multiple types", severity='error', symbol=line[0]) + ls.extend(line) # ---------------------------- End of if block ------------------------------------------ else: ls.append(line) From a0273cc7fda08b8090a65c2879fbe99c627a6418 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Tue, 30 Apr 2024 16:37:25 +0100 Subject: [PATCH 030/139] Make the conditions global. --- pyccel/codegen/printing/ccode.py | 33 ++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 64d6af5aba..8382574c5d 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -948,13 +948,20 @@ def _print_Import(self, expr): source = self._print(source) if expr.target: dtype = expr.target.pop().name - if source == ('stc/hset_' + str(dtype)): + if source.startswith('stc'): dtype_macro = dtype.upper() - return (f'#ifndef _SET_{dtype_macro}\n' - f'#define _SET_{dtype_macro}\n' - f'#define i_key {dtype}\n' - f'#include "stc/hset.h"\n' - f'#endif\n') + _,container_type = source.split("/") + class_type_macro = "SET" if container_type.startswith("hset") else "VEC" + import_file,_ = source.split('_') + if class_type_macro == 'SET': + additional_defines = '' + additional_defines = '' if class_type_macro == 'SET' else "#define i_use_cmp\n" + return '\n'.join((f'#ifndef _{class_type_macro}_{dtype_macro}', + f'#define _{class_type_macro}_{dtype_macro}', + f'#define i_key {dtype}', + additional_defines, + f'#include "{import_file}.h"', + f'#endif\n')) # Get with a default value is not used here as it is # slower and on most occasions the import will not be in the @@ -1171,11 +1178,13 @@ def find_in_dtype_registry(self, dtype): return 'bool' key = (primitive_type, dtype.precision) - elif isinstance(dtype, HomogeneousSetType): - key = 'hset_' + dtype._name - types = dtype.datatype._name - source = 'stc/hset_' + types - self.add_import(Import(source, Module(types, (), ()))) + elif isinstance(dtype, (HomogeneousSetType, HomogeneousListType)): + cointainer_type = 'hset_' if dtype._name == 'set' else 'vec_' + dtype = dtype.element_type._name + key = cointainer_type + dtype + source = 'stc/'+ cointainer_type + dtype + + self.add_import(Import(source, Module(dtype, (), ()))) return key else: key = dtype @@ -1255,7 +1264,7 @@ def get_declare_type(self, expr): if expr.is_ndarray or isinstance(expr.class_type, HomogeneousContainerType): if expr.rank > 15: errors.report(UNSUPPORTED_ARRAY_RANK, symbol=expr, severity='fatal') - if isinstance(expr.class_type, HomogeneousSetType): + if isinstance(expr.class_type, (HomogeneousSetType, HomogeneousListType)): dtype = self.find_in_dtype_registry(expr.class_type) return dtype self.add_import(c_imports['ndarrays']) From 81411c452c31d0b5c7283abebc0bf1122bb52c2b Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Tue, 30 Apr 2024 17:41:42 +0100 Subject: [PATCH 031/139] New modification has been made. --- pyccel/codegen/printing/ccode.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 8382574c5d..f241a4e630 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -948,20 +948,18 @@ def _print_Import(self, expr): source = self._print(source) if expr.target: dtype = expr.target.pop().name - if source.startswith('stc'): + if source.startswith('stc/'): dtype_macro = dtype.upper() _,container_type = source.split("/") class_type_macro = "SET" if container_type.startswith("hset") else "VEC" import_file,_ = source.split('_') - if class_type_macro == 'SET': - additional_defines = '' - additional_defines = '' if class_type_macro == 'SET' else "#define i_use_cmp\n" + additional_defines = '#define i_use_cmp\n' if class_type_macro == 'VEC' else '' return '\n'.join((f'#ifndef _{class_type_macro}_{dtype_macro}', - f'#define _{class_type_macro}_{dtype_macro}', - f'#define i_key {dtype}', - additional_defines, - f'#include "{import_file}.h"', - f'#endif\n')) + f'#define _{class_type_macro}_{dtype_macro}', + f'#define i_key {dtype}', + additional_defines, + f'#include "{import_file}.h"', + f'#endif\n')) # Get with a default value is not used here as it is # slower and on most occasions the import will not be in the From 62e769412409cc6f0f16d67c34d2997d0507f1d8 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Thu, 2 May 2024 11:13:09 +0100 Subject: [PATCH 032/139] Make a dictionary to get the exact 'class_type_macro'. --- pyccel/codegen/printing/ccode.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index f241a4e630..92fe1c258e 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -225,6 +225,9 @@ import_dict = {'omp_lib' : 'omp' } +import_stc = {'hset' : 'SET', + 'vec' : 'VEC' + } c_imports = {n : Import(n, Module(n, (), ())) for n in ['stdlib', @@ -951,7 +954,8 @@ def _print_Import(self, expr): if source.startswith('stc/'): dtype_macro = dtype.upper() _,container_type = source.split("/") - class_type_macro = "SET" if container_type.startswith("hset") else "VEC" + if container_type in import_stc: + class_type_macro = import_stc[container_type] import_file,_ = source.split('_') additional_defines = '#define i_use_cmp\n' if class_type_macro == 'VEC' else '' return '\n'.join((f'#ifndef _{class_type_macro}_{dtype_macro}', From cad722d51e38093636a09f8ac287ea82e8ac4124 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Thu, 2 May 2024 11:43:46 +0100 Subject: [PATCH 033/139] Rearrange a line. --- pyccel/codegen/printing/ccode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 306ee3c7ba..8ac94c5d2a 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -954,9 +954,9 @@ def _print_Import(self, expr): if source.startswith('stc/'): dtype_macro = dtype.upper() _,container_type = source.split("/") + import_file,_ = source.split('_') if container_type in import_stc: class_type_macro = import_stc[container_type] - import_file,_ = source.split('_') additional_defines = '#define i_use_cmp\n' if class_type_macro == 'VEC' else '' return '\n'.join((f'#ifndef _{class_type_macro}_{dtype_macro}', f'#define _{class_type_macro}_{dtype_macro}', From 01150c5471cc62ac55d941c6fd859e22c608d815 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Thu, 2 May 2024 12:33:26 +0100 Subject: [PATCH 034/139] New changes --- pyccel/codegen/printing/ccode.py | 4 ++-- pyccel/parser/semantic.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 8ac94c5d2a..fc5458ec84 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -952,9 +952,9 @@ def _print_Import(self, expr): if expr.target: dtype = expr.target.pop().name if source.startswith('stc/'): - dtype_macro = dtype.upper() - _,container_type = source.split("/") import_file,_ = source.split('_') + dtype_macro = dtype.upper() + _,container_type = import_file.split("/") if container_type in import_stc: class_type_macro = import_stc[container_type] additional_defines = '#define i_use_cmp\n' if class_type_macro == 'VEC' else '' diff --git a/pyccel/parser/semantic.py b/pyccel/parser/semantic.py index a95b280eca..7bead6aa7f 100644 --- a/pyccel/parser/semantic.py +++ b/pyccel/parser/semantic.py @@ -2312,7 +2312,6 @@ def _visit_CodeBlock(self, expr): if len(line) != 1: errors.report(f"Variable {line[0]} cannot have multiple types", severity='error', symbol=line[0]) - ls.extend(line) # ---------------------------- End of if block ------------------------------------------ else: ls.append(line) From d242a4a6d8a789add78dba5734637b1b28365480 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Thu, 2 May 2024 12:44:45 +0100 Subject: [PATCH 035/139] Fix: Codacy problem. --- pyccel/codegen/printing/ccode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index fc5458ec84..20a898b60a 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -936,7 +936,7 @@ def _print_PyccelPow(self, expr): e = self._print(e if e.dtype.primitive_type is PrimitiveFloatingPointType() else NumpyFloat(e)) code = 'pow({}, {})'.format(b, e) return self._cast_to(expr, expr.dtype).format(code) - + def _print_Import(self, expr): if expr.ignore: From 59ba041ecafe8354b8f7fec0658ad2a519125227 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Thu, 2 May 2024 12:51:33 +0100 Subject: [PATCH 036/139] Fix: Codacy problem. --- pyccel/codegen/printing/ccode.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 20a898b60a..e9d488fb62 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -936,8 +936,8 @@ def _print_PyccelPow(self, expr): e = self._print(e if e.dtype.primitive_type is PrimitiveFloatingPointType() else NumpyFloat(e)) code = 'pow({}, {})'.format(b, e) return self._cast_to(expr, expr.dtype).format(code) - - + + def _print_Import(self, expr): if expr.ignore: return '' From a2f58567f18ca93352da7eec69827126b49a3d49 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Thu, 2 May 2024 12:54:49 +0100 Subject: [PATCH 037/139] Fix: Codacy problem. --- pyccel/codegen/printing/ccode.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index e9d488fb62..e465cfa2e7 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -1185,7 +1185,6 @@ def find_in_dtype_registry(self, dtype): dtype = dtype.element_type._name key = cointainer_type + dtype source = 'stc/'+ cointainer_type + dtype - self.add_import(Import(source, Module(dtype, (), ()))) return key else: From face8519b77ee7a265f3b181ea18f42e4e2e4bbb Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Mon, 6 May 2024 10:24:31 +0100 Subject: [PATCH 038/139] revert to previous changes --- pyccel/codegen/printing/ccode.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index d957cf8e97..e465cfa2e7 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -825,10 +825,6 @@ def _print_Module(self, expr): self.exit_scope() return code - def _print_PythonList(self, expr): - vec_declare = 'vec_' + expr.dtype._name - return vec_declare - def _print_Break(self, expr): return 'break;\n' From 7adc8010bad98de9066cc2bb76e27952c73aad2c Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Mon, 6 May 2024 20:01:34 +0100 Subject: [PATCH 039/139] set the appropriate datatype for the STC container & use STC Vector methods to initialize and fill a vector --- pyccel/codegen/printing/ccode.py | 34 +++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index e465cfa2e7..56573415e4 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -302,7 +302,7 @@ def __init__(self, filename, prefix_module = None): errors.set_target(filename) - super().__init__() + super().__init__() self.prefix_module = prefix_module self._additional_imports = {'stdlib':c_imports['stdlib']} self._additional_code = '' @@ -952,7 +952,8 @@ def _print_Import(self, expr): if expr.target: dtype = expr.target.pop().name if source.startswith('stc/'): - import_file,_ = source.split('_') + import_file, *_ = source.split('_') + _ = '_'.join(_) dtype_macro = dtype.upper() _,container_type = import_file.split("/") if container_type in import_stc: @@ -1181,11 +1182,11 @@ def find_in_dtype_registry(self, dtype): key = (primitive_type, dtype.precision) elif isinstance(dtype, (HomogeneousSetType, HomogeneousListType)): - cointainer_type = 'hset_' if dtype._name == 'set' else 'vec_' - dtype = dtype.element_type._name - key = cointainer_type + dtype - source = 'stc/'+ cointainer_type + dtype - self.add_import(Import(source, Module(dtype, (), ()))) + container_type = 'hset_' if dtype._name == 'set' else 'vec_' + vec_dtype = self.find_in_dtype_registry(dtype.element_type) + key = container_type + vec_dtype + source = 'stc/'+ container_type + vec_dtype + self.add_import(Import(source, Module(vec_dtype, (), ()))) return key else: key = dtype @@ -1552,6 +1553,8 @@ def _print_PyccelArrayShapeElement(self, expr): def _print_Allocate(self, expr): free_code = '' variable = expr.variable + if isinstance(variable.class_type, (HomogeneousListType, HomogeneousSetType)): + return '' if variable.rank > 0: #free the array if its already allocated and checking if its not null if the status is unknown if (expr.status == 'unknown'): @@ -1990,6 +1993,21 @@ def _print_FunctionCall(self, expr): else: return call_code + def list_to_vector(self, expr): + """ + Print the initialization of a python assignment using STC init() method + """ + vec_dtype = self.find_in_dtype_registry(expr.current_user_node.lhs.dtype) + if (len(expr.args) == 0): + return f'vec_{vec_dtype}_init()' + + list_var = self._print(expr.current_user_node.lhs) + init = f'vec_{vec_dtype}_with_capacity({len(expr.args)});\n' + keyraw = '[' + ', '.join([self._print(a) for a in expr.args]) + ']' + emplace = f'vec_{vec_dtype}_emplace_n({list_var}, 0, {keyraw}, {len(expr.args)});\n' + + return init+emplace + def _print_Constant(self, expr): """ Convert a Python expression with a math constant call to C function call @@ -2153,6 +2171,8 @@ def _print_Assign(self, expr): return prefix_code+self.copy_NumpyArray_Data(expr) if isinstance(rhs, (NumpyFull)): return prefix_code+self.arrayFill(expr) + if isinstance(rhs, PythonList): + return prefix_code+self.list_to_vector(rhs) lhs = self._print(expr.lhs) rhs = self._print(expr.rhs) return prefix_code+'{} = {};\n'.format(lhs, rhs) From 3270d838891db3e03b68ddd3af591615e2cdcdaa Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Tue, 7 May 2024 11:04:45 +0100 Subject: [PATCH 040/139] use of maxsplit argument to optimize splitting --- pyccel/codegen/printing/ccode.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 56573415e4..d0b4fbea27 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -952,8 +952,7 @@ def _print_Import(self, expr): if expr.target: dtype = expr.target.pop().name if source.startswith('stc/'): - import_file, *_ = source.split('_') - _ = '_'.join(_) + import_file, _ = source.split('_', 1) dtype_macro = dtype.upper() _,container_type = import_file.split("/") if container_type in import_stc: From 3e2e7f226696b05cf51e23ed79951900346819a4 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Tue, 7 May 2024 16:30:27 +0100 Subject: [PATCH 041/139] fix: set the right import filename --- pyccel/codegen/printing/ccode.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index d0b4fbea27..bc268b0161 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -952,9 +952,8 @@ def _print_Import(self, expr): if expr.target: dtype = expr.target.pop().name if source.startswith('stc/'): - import_file, _ = source.split('_', 1) dtype_macro = dtype.upper() - _,container_type = import_file.split("/") + _,container_type = source.split("/") if container_type in import_stc: class_type_macro = import_stc[container_type] additional_defines = '#define i_use_cmp\n' if class_type_macro == 'VEC' else '' @@ -962,7 +961,7 @@ def _print_Import(self, expr): f'#define _{class_type_macro}_{dtype_macro}', f'#define i_key {dtype}', additional_defines, - f'#include "{import_file}.h"', + f'#include "{source}.h"', f'#endif\n')) # Get with a default value is not used here as it is @@ -1184,7 +1183,7 @@ def find_in_dtype_registry(self, dtype): container_type = 'hset_' if dtype._name == 'set' else 'vec_' vec_dtype = self.find_in_dtype_registry(dtype.element_type) key = container_type + vec_dtype - source = 'stc/'+ container_type + vec_dtype + source = 'stc/'+ container_type[:-1] self.add_import(Import(source, Module(vec_dtype, (), ()))) return key else: From 78fb75a73d21ce0b588e07f5a796bf9348b32b29 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 10 May 2024 11:32:37 +0100 Subject: [PATCH 042/139] make pyccel.extension module --- pyccel/extensions/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 pyccel/extensions/__init__.py diff --git a/pyccel/extensions/__init__.py b/pyccel/extensions/__init__.py new file mode 100644 index 0000000000..e69de29bb2 From 1729f8a0c0495d429623a97531d6296d0ae8043c Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 10 May 2024 11:33:53 +0100 Subject: [PATCH 043/139] prototype of treating external libraries --- pyccel/codegen/pipeline.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pyccel/codegen/pipeline.py b/pyccel/codegen/pipeline.py index efff153aad..30de2446cd 100644 --- a/pyccel/codegen/pipeline.py +++ b/pyccel/codegen/pipeline.py @@ -21,6 +21,7 @@ from pyccel.codegen.utilities import recompile_object from pyccel.codegen.utilities import copy_internal_library from pyccel.codegen.utilities import internal_libs +from pyccel.codegen.utilities import external_libs from pyccel.codegen.python_wrapper import create_shared_library from pyccel.naming import name_clash_checkers from pyccel.utilities.stage import PyccelStage @@ -334,6 +335,16 @@ def handle_error(stage): mod_obj.add_dependencies(stdlib) + + # Iterate over the external_libs list and determine if the printer + # requires an internal lib to be included. + for lib_name, (src_folder, external) in external_libs.items(): + if lib_name in codegen.get_printer_imports(): + + lib_dest_path = copy_internal_library(src_folder, pyccel_dirpath) + + + if convert_only: # Change working directory back to starting point os.chdir(base_dirpath) From 042fbbf0cf7aa3be4fb2d3a005081604454c9d81 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 10 May 2024 11:35:21 +0100 Subject: [PATCH 044/139] prototype of treating external libraries: copying STC to the destination path --- pyccel/codegen/utilities.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/pyccel/codegen/utilities.py b/pyccel/codegen/utilities.py index 190044b5f0..96c12c9a37 100644 --- a/pyccel/codegen/utilities.py +++ b/pyccel/codegen/utilities.py @@ -12,17 +12,25 @@ import shutil from filelock import FileLock import pyccel.stdlib as stdlib_folder +import pyccel.extensions as ext_folder from .compiling.basic import CompileObj # get path to pyccel/stdlib/lib_name stdlib_path = os.path.dirname(stdlib_folder.__file__) +# get path to pyccel/extensions/lib_name +ext_path = os.path.dirname(ext_folder.__file__) + __all__ = ['copy_internal_library','recompile_object'] #============================================================================== language_extension = {'fortran':'f90', 'c':'c', 'python':'py'} +#============================================================================== +# map external libraries to their folders inside pyccel/extensions +external_libs = {"stc/vec" : ("stc", "stc/vec.h")} + #============================================================================== # map internal libraries to their folders inside pyccel/stdlib and their compile objects # The compile object folder will be in the pyccel dirpath @@ -101,8 +109,12 @@ def copy_internal_library(lib_folder, pyccel_dirpath, extra_files = None): str The location that the files were copied to. """ - # get lib path (stdlib_path/lib_name) - lib_path = os.path.join(stdlib_path, lib_folder) + # get lib path (stdlib_path/lib_name or ext_path/lib_name) + if lib_folder == "stc": + lib_path = os.path.join(ext_path, "STC", "include", lib_folder) + else: + lib_path = os.path.join(stdlib_path, lib_folder) + # remove library folder to avoid missing files and copy # new one from pyccel stdlib lib_dest_path = os.path.join(pyccel_dirpath, lib_folder) From c89043d0f569197b500cab0b9e5bda76e306774a Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 10 May 2024 11:36:14 +0100 Subject: [PATCH 045/139] print the init assignement of the vector --- pyccel/codegen/printing/ccode.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 024fd869cc..d999f528c3 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -1994,7 +1994,7 @@ def _print_FunctionCall(self, expr): else: return call_code - def list_to_vector(self, expr): + def list_to_vector(self, expr, lhs): """ Print the initialization of a python assignment using STC init() method """ @@ -2003,7 +2003,7 @@ def list_to_vector(self, expr): return f'vec_{vec_dtype}_init()' list_var = self._print(expr.current_user_node.lhs) - init = f'vec_{vec_dtype}_with_capacity({len(expr.args)});\n' + init = f'{lhs} = vec_{vec_dtype}_with_capacity({len(expr.args)});\n' keyraw = '[' + ', '.join([self._print(a) for a in expr.args]) + ']' emplace = f'vec_{vec_dtype}_emplace_n({list_var}, 0, {keyraw}, {len(expr.args)});\n' @@ -2172,9 +2172,9 @@ def _print_Assign(self, expr): return prefix_code+self.copy_NumpyArray_Data(expr) if isinstance(rhs, (NumpyFull)): return prefix_code+self.arrayFill(expr) - if isinstance(rhs, PythonList): - return prefix_code+self.list_to_vector(rhs) lhs = self._print(expr.lhs) + if isinstance(rhs, PythonList): + return prefix_code+self.list_to_vector(rhs, lhs) rhs = self._print(expr.rhs) return prefix_code+'{} = {};\n'.format(lhs, rhs) From 52b5e7e14c643b615f0d19a41082ec164346a160 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Wed, 15 May 2024 11:05:23 +0100 Subject: [PATCH 046/139] Use of c_init prototype --- pyccel/codegen/printing/ccode.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index d999f528c3..dbc174646f 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -2002,10 +2002,11 @@ def list_to_vector(self, expr, lhs): if (len(expr.args) == 0): return f'vec_{vec_dtype}_init()' + # c_init(hset_str, {"This", "is", "the", "story"}); list_var = self._print(expr.current_user_node.lhs) - init = f'{lhs} = vec_{vec_dtype}_with_capacity({len(expr.args)});\n' - keyraw = '[' + ', '.join([self._print(a) for a in expr.args]) + ']' - emplace = f'vec_{vec_dtype}_emplace_n({list_var}, 0, {keyraw}, {len(expr.args)});\n' + # init = f'{lhs} = vec_{vec_dtype}_with_capacity({len(expr.args)});\n' + keyraw = '{' + ', '.join([self._print(a) for a in expr.args]) + '}' + init = f'c_init({list_var}, {keyraw})' return init+emplace From b84f1f1a1730eaab3c94b1ec8a761f6c395ba23e Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Wed, 15 May 2024 14:53:09 +0100 Subject: [PATCH 047/139] fix printing of c_init --- pyccel/codegen/printing/ccode.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index dbc174646f..5aeb6257a6 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -1994,7 +1994,7 @@ def _print_FunctionCall(self, expr): else: return call_code - def list_to_vector(self, expr, lhs): + def list_to_vector(self, expr, list_var): """ Print the initialization of a python assignment using STC init() method """ @@ -2002,13 +2002,10 @@ def list_to_vector(self, expr, lhs): if (len(expr.args) == 0): return f'vec_{vec_dtype}_init()' - # c_init(hset_str, {"This", "is", "the", "story"}); - list_var = self._print(expr.current_user_node.lhs) - # init = f'{lhs} = vec_{vec_dtype}_with_capacity({len(expr.args)});\n' keyraw = '{' + ', '.join([self._print(a) for a in expr.args]) + '}' - init = f'c_init({list_var}, {keyraw})' + init = f'{list_var} = c_init(vec_{vec_dtype}, {keyraw});\n' - return init+emplace + return init def _print_Constant(self, expr): """ Convert a Python expression with a math constant call to C From f4125ada06af886dbffaf2782c0057ff00f0d543 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Wed, 15 May 2024 15:25:20 +0100 Subject: [PATCH 048/139] fix name conflict in importing external library --- pyccel/codegen/pipeline.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyccel/codegen/pipeline.py b/pyccel/codegen/pipeline.py index 30de2446cd..4c98e965a7 100644 --- a/pyccel/codegen/pipeline.py +++ b/pyccel/codegen/pipeline.py @@ -338,10 +338,10 @@ def handle_error(stage): # Iterate over the external_libs list and determine if the printer # requires an internal lib to be included. - for lib_name, (src_folder, external) in external_libs.items(): - if lib_name in codegen.get_printer_imports(): + for ext_lib_name, (ext_src_folder, external) in external_libs.items(): + if ext_lib_name in codegen.get_printer_imports(): - lib_dest_path = copy_internal_library(src_folder, pyccel_dirpath) + lib_dest_path = copy_internal_library(ext_src_folder, pyccel_dirpath) From c29f1707bf050e02a42dffc88282a78c863e1e6a Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Wed, 15 May 2024 15:56:10 +0100 Subject: [PATCH 049/139] Fix Codacy Problem. --- pyccel/codegen/pipeline.py | 2 +- test.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 test.py diff --git a/pyccel/codegen/pipeline.py b/pyccel/codegen/pipeline.py index 4c98e965a7..221ceca808 100644 --- a/pyccel/codegen/pipeline.py +++ b/pyccel/codegen/pipeline.py @@ -343,7 +343,7 @@ def handle_error(stage): lib_dest_path = copy_internal_library(ext_src_folder, pyccel_dirpath) - + if convert_only: # Change working directory back to starting point diff --git a/test.py b/test.py new file mode 100644 index 0000000000..41e9994195 --- /dev/null +++ b/test.py @@ -0,0 +1,2 @@ +def ll (): + a : list[int] = [1,2,3] \ No newline at end of file From 948be19728e68fec977f2932b728b68e0b7c1eee Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Wed, 15 May 2024 16:54:43 +0100 Subject: [PATCH 050/139] Rename list_to_vector to init_lists_or_sets to declare both of them with c_init . --- pyccel/ast/utilities.py | 4 ++-- pyccel/codegen/printing/ccode.py | 15 ++++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/pyccel/ast/utilities.py b/pyccel/ast/utilities.py index 3aeaa25395..1e6c0422ab 100644 --- a/pyccel/ast/utilities.py +++ b/pyccel/ast/utilities.py @@ -17,7 +17,7 @@ Concatenate, Module, PyccelFunctionDef) from .builtins import (builtin_functions_dict, - PythonRange, PythonList, PythonTuple) + PythonRange, PythonList, PythonTuple, PythonSet) from .cmathext import cmath_mod from .datatypes import HomogeneousTupleType, PythonNativeInt from .internals import PyccelFunction, Slice @@ -409,7 +409,7 @@ def collect_loops(block, indices, new_index, language_has_vectors = False, resul if result is None: result = [] current_level = 0 - array_creator_types = (Allocate, PythonList, PythonTuple, Concatenate, Duplicate) + array_creator_types = (Allocate, PythonList, PythonTuple, Concatenate, Duplicate, PythonSet) is_function_call = lambda f: ((isinstance(f, FunctionCall) and not f.funcdef.is_elemental) or (isinstance(f, PyccelFunction) and not f.is_elemental and not hasattr(f, '__getitem__') and not isinstance(f, (NumpyTranspose)))) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 5aeb6257a6..4148141918 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -11,7 +11,7 @@ from pyccel.ast.builtins import PythonRange, PythonComplex from pyccel.ast.builtins import PythonPrint, PythonType -from pyccel.ast.builtins import PythonList, PythonTuple +from pyccel.ast.builtins import PythonList, PythonTuple, PythonSet from pyccel.ast.core import Declare, For, CodeBlock from pyccel.ast.core import FuncAddressDeclare, FunctionCall, FunctionCallArgument @@ -1994,16 +1994,17 @@ def _print_FunctionCall(self, expr): else: return call_code - def list_to_vector(self, expr, list_var): + def init_lists_or_sets(self, expr, list_var): """ Print the initialization of a python assignment using STC init() method """ - vec_dtype = self.find_in_dtype_registry(expr.current_user_node.lhs.dtype) + dtype = self.find_in_dtype_registry(expr.current_user_node.lhs.dtype) + container_type = "hset_"if isinstance(expr.class_type, HomogeneousSetType) else "vec_" if (len(expr.args) == 0): - return f'vec_{vec_dtype}_init()' + return f'{container_type}{dtype}_init()' keyraw = '{' + ', '.join([self._print(a) for a in expr.args]) + '}' - init = f'{list_var} = c_init(vec_{vec_dtype}, {keyraw});\n' + init = f'{list_var} = c_init({container_type}{dtype}, {keyraw});\n' return init @@ -2171,8 +2172,8 @@ def _print_Assign(self, expr): if isinstance(rhs, (NumpyFull)): return prefix_code+self.arrayFill(expr) lhs = self._print(expr.lhs) - if isinstance(rhs, PythonList): - return prefix_code+self.list_to_vector(rhs, lhs) + if isinstance(rhs, (PythonList, PythonSet)): + return prefix_code+self.init_lists_or_sets(rhs, lhs) rhs = self._print(expr.rhs) return prefix_code+'{} = {};\n'.format(lhs, rhs) From 4e2bf033a27cdf88c36800601cc2ede8c2d58759 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Wed, 15 May 2024 17:05:37 +0100 Subject: [PATCH 051/139] Fix printing in case there are no arguments. --- pyccel/codegen/printing/ccode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 4148141918..ce38b09cf2 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -2001,7 +2001,7 @@ def init_lists_or_sets(self, expr, list_var): dtype = self.find_in_dtype_registry(expr.current_user_node.lhs.dtype) container_type = "hset_"if isinstance(expr.class_type, HomogeneousSetType) else "vec_" if (len(expr.args) == 0): - return f'{container_type}{dtype}_init()' + return f'{list_var} = c_init({container_type}{dtype}, {"{}"});\n' keyraw = '{' + ', '.join([self._print(a) for a in expr.args]) + '}' init = f'{list_var} = c_init({container_type}{dtype}, {keyraw});\n' From d08f8cd05f2bc9d17f3093bab327daaa77b37d17 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Thu, 16 May 2024 09:43:55 +0100 Subject: [PATCH 052/139] Delete test file. --- test.py | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 test.py diff --git a/test.py b/test.py deleted file mode 100644 index 41e9994195..0000000000 --- a/test.py +++ /dev/null @@ -1,2 +0,0 @@ -def ll (): - a : list[int] = [1,2,3] \ No newline at end of file From 51cdaf2beba325c78862b32b50908ec1b27bf0f0 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Thu, 16 May 2024 15:36:30 +0100 Subject: [PATCH 053/139] Bad Merge --- pyccel/codegen/printing/ccode.py | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 0af280670f..567741daf8 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -2008,27 +2008,6 @@ def init_lists_or_sets(self, expr, list_var): return init - def _print_Constant(self, expr): - """ Convert a Python expression with a math constant call to C - function call - - Parameters - ---------- - expr : Pyccel ast node - Python expression with a Math constant - - Returns - ------- - string - String represent the value of the constant - - Example - ------- - math.pi ==> 3.14159265358979 - - """ - val = LiteralFloat(expr.value) - return self._print(val) def _print_Return(self, expr): code = '' From ee8c9bb688b48f12b47729745e11610a337831f6 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Thu, 16 May 2024 15:39:19 +0100 Subject: [PATCH 054/139] Remove a empty lines. --- pyccel/codegen/printing/ccode.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 567741daf8..16362e2ce6 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -2008,7 +2008,6 @@ def init_lists_or_sets(self, expr, list_var): return init - def _print_Return(self, expr): code = '' args = [ObjectAddress(a) if isinstance(a, Variable) and self.is_c_pointer(a) else a for a in expr.expr] From ef381205dcd76f68cae256b77dda1e967979c3f2 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Thu, 16 May 2024 15:39:21 +0100 Subject: [PATCH 055/139] Remove a empty lines. --- pyccel/codegen/pipeline.py | 2 -- pyccel/codegen/printing/ccode.py | 1 - 2 files changed, 3 deletions(-) diff --git a/pyccel/codegen/pipeline.py b/pyccel/codegen/pipeline.py index 221ceca808..0e6e07b8de 100644 --- a/pyccel/codegen/pipeline.py +++ b/pyccel/codegen/pipeline.py @@ -343,8 +343,6 @@ def handle_error(stage): lib_dest_path = copy_internal_library(ext_src_folder, pyccel_dirpath) - - if convert_only: # Change working directory back to starting point os.chdir(base_dirpath) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 16362e2ce6..99d4688b6f 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -940,7 +940,6 @@ def _print_PyccelPow(self, expr): code = 'pow({}, {})'.format(b, e) return self._cast_to(expr, expr.dtype).format(code) - def _print_Import(self, expr): if expr.ignore: return '' From 64aeff618a096ec9db9c7f61518b12831cab09ce Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 17 May 2024 11:59:52 +0100 Subject: [PATCH 056/139] import hset STC header file --- pyccel/codegen/utilities.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyccel/codegen/utilities.py b/pyccel/codegen/utilities.py index 96c12c9a37..4938532ace 100644 --- a/pyccel/codegen/utilities.py +++ b/pyccel/codegen/utilities.py @@ -29,7 +29,8 @@ #============================================================================== # map external libraries to their folders inside pyccel/extensions -external_libs = {"stc/vec" : ("stc", "stc/vec.h")} +external_libs = {"stc/vec" : ("stc", "stc/vec.h"), + "stc/hset" : ("stc", "stc/hvec.h")} #============================================================================== # map internal libraries to their folders inside pyccel/stdlib and their compile objects From 9b528bf34be1516216b7e945a88d9da16cb91297 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Fri, 17 May 2024 13:08:31 +0100 Subject: [PATCH 057/139] Deprecate unused line. --- pyccel/parser/semantic.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyccel/parser/semantic.py b/pyccel/parser/semantic.py index c952cd2092..c5a9b63086 100644 --- a/pyccel/parser/semantic.py +++ b/pyccel/parser/semantic.py @@ -2312,7 +2312,6 @@ def _visit_CodeBlock(self, expr): if len(line) != 1: errors.report(f"Variable {line[0]} cannot have multiple types", severity='error', symbol=line[0]) - ls.extend(line) # ---------------------------- End of if block ------------------------------------------ else: ls.append(line) From f843b054bf72b4c6dc07b7a2a455e0c676c10fe5 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Fri, 17 May 2024 13:09:00 +0100 Subject: [PATCH 058/139] Add test --- .../test_epyccel_variable_annotations.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/epyccel/test_epyccel_variable_annotations.py b/tests/epyccel/test_epyccel_variable_annotations.py index 5927f58373..552a049a73 100644 --- a/tests/epyccel/test_epyccel_variable_annotations.py +++ b/tests/epyccel/test_epyccel_variable_annotations.py @@ -166,3 +166,20 @@ def homogeneous_tuple_annotation(): assert epyc_homogeneous_tuple_annotation() == homogeneous_tuple_annotation() assert isinstance(epyc_homogeneous_tuple_annotation(), type(homogeneous_tuple_annotation())) + +@pytest.mark.parametrize( 'language', [ + pytest.param("c", marks = pytest.mark.c), + pytest.param("fortran", marks = [ + pytest.mark.skip(reason="append() not implemented in fortran"), + pytest.mark.fortran]), + pytest.param("python", marks = pytest.mark.python) + ] +) + +def test_homogeneous_set_annotation_int(language): + def homogeneous_set_annotation (): + a : set[int] + a = {1, 2, 3, 4} + epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=language) + assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation() + assert isinstance(epyc_homogeneous_set_annotation(), type(homogeneous_set_annotation())) \ No newline at end of file From 0bc5bff42f13d56c93f0f9bd8ce0715d3df0b984 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 17 May 2024 13:25:45 +0100 Subject: [PATCH 059/139] unused external field --- pyccel/codegen/pipeline.py | 2 +- pyccel/codegen/utilities.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pyccel/codegen/pipeline.py b/pyccel/codegen/pipeline.py index 0e6e07b8de..f336d9f006 100644 --- a/pyccel/codegen/pipeline.py +++ b/pyccel/codegen/pipeline.py @@ -338,7 +338,7 @@ def handle_error(stage): # Iterate over the external_libs list and determine if the printer # requires an internal lib to be included. - for ext_lib_name, (ext_src_folder, external) in external_libs.items(): + for ext_lib_name, ext_src_folder in external_libs.items(): if ext_lib_name in codegen.get_printer_imports(): lib_dest_path = copy_internal_library(ext_src_folder, pyccel_dirpath) diff --git a/pyccel/codegen/utilities.py b/pyccel/codegen/utilities.py index 4938532ace..565c31f0c1 100644 --- a/pyccel/codegen/utilities.py +++ b/pyccel/codegen/utilities.py @@ -29,8 +29,8 @@ #============================================================================== # map external libraries to their folders inside pyccel/extensions -external_libs = {"stc/vec" : ("stc", "stc/vec.h"), - "stc/hset" : ("stc", "stc/hvec.h")} +external_libs = {"stc/vec" : "stc", + "stc/hset" : "stc",} #============================================================================== # map internal libraries to their folders inside pyccel/stdlib and their compile objects From a4c1727bb82719dfd503048e0c6feb1e75ff1358 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 17 May 2024 15:27:58 +0100 Subject: [PATCH 060/139] revert to old changes --- pyccel/codegen/printing/ccode.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 99d4688b6f..4882fc22b8 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -2353,6 +2353,9 @@ def _print_Constant(self, expr): if expr == math_constants['inf']: self.add_import(c_imports['math']) return 'HUGE_VAL' + elif expr == math_constants['nan']: + self.add_import(c_imports['math']) + return 'NAN' elif expr == math_constants['pi']: self.add_import(c_imports['math']) return 'M_PI' @@ -2360,7 +2363,8 @@ def _print_Constant(self, expr): self.add_import(c_imports['math']) return 'M_E' else: - raise NotImplementedError("Constant not implemented") + cast_func = DtypePrecisionToCastFunction[expr.dtype] + return self._print(cast_func(expr.value)) def _print_Variable(self, expr): if self.is_c_pointer(expr): From 8127301ff2f5b0c5c81ae0f30ea45617a8035577 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 17 May 2024 15:31:51 +0100 Subject: [PATCH 061/139] update the reason to skip test for fortran --- tests/epyccel/test_epyccel_variable_annotations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/epyccel/test_epyccel_variable_annotations.py b/tests/epyccel/test_epyccel_variable_annotations.py index 552a049a73..ae9aaf41e1 100644 --- a/tests/epyccel/test_epyccel_variable_annotations.py +++ b/tests/epyccel/test_epyccel_variable_annotations.py @@ -170,7 +170,7 @@ def homogeneous_tuple_annotation(): @pytest.mark.parametrize( 'language', [ pytest.param("c", marks = pytest.mark.c), pytest.param("fortran", marks = [ - pytest.mark.skip(reason="append() not implemented in fortran"), + pytest.mark.skip(reason="Variable declaration not implemented in fortran"), pytest.mark.fortran]), pytest.param("python", marks = pytest.mark.python) ] From e87dbf113f01d210f72bcc5679bddff399985988 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 17 May 2024 15:36:33 +0100 Subject: [PATCH 062/139] disable unused var --- tests/epyccel/test_epyccel_variable_annotations.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/epyccel/test_epyccel_variable_annotations.py b/tests/epyccel/test_epyccel_variable_annotations.py index ae9aaf41e1..57ac0c2f1b 100644 --- a/tests/epyccel/test_epyccel_variable_annotations.py +++ b/tests/epyccel/test_epyccel_variable_annotations.py @@ -178,8 +178,8 @@ def homogeneous_tuple_annotation(): def test_homogeneous_set_annotation_int(language): def homogeneous_set_annotation (): - a : set[int] + a : set[int] #pylint: disable=unused-variable a = {1, 2, 3, 4} epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=language) assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation() - assert isinstance(epyc_homogeneous_set_annotation(), type(homogeneous_set_annotation())) \ No newline at end of file + assert isinstance(epyc_homogeneous_set_annotation(), type(homogeneous_set_annotation())) From cab1cc97aa568dcdde40ed16590f78881787cc61 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 17 May 2024 15:43:11 +0100 Subject: [PATCH 063/139] chore: revert to old changes --- pyccel/codegen/printing/ccode.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 4882fc22b8..f4b3f3ec3a 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -2366,6 +2366,7 @@ def _print_Constant(self, expr): cast_func = DtypePrecisionToCastFunction[expr.dtype] return self._print(cast_func(expr.value)) + def _print_Variable(self, expr): if self.is_c_pointer(expr): return '(*{0})'.format(expr.name) From 0576da7138afccbc5f99f177a082dabbea2ac512 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 17 May 2024 17:01:20 +0100 Subject: [PATCH 064/139] feat: tests for different datatypes in list and set declarations, int and float are passing in STC, bool and complex need some fixing --- .../test_epyccel_variable_annotations.py | 72 ++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/tests/epyccel/test_epyccel_variable_annotations.py b/tests/epyccel/test_epyccel_variable_annotations.py index 57ac0c2f1b..371bfacde8 100644 --- a/tests/epyccel/test_epyccel_variable_annotations.py +++ b/tests/epyccel/test_epyccel_variable_annotations.py @@ -10,6 +10,14 @@ from pyccel.errors.errors import PyccelSemanticError, Errors from pyccel.decorators import allow_negative_index, stack_array +def parametrize_languages(): + return pytest.mark.parametrize('language', [ + pytest.param("c", marks=pytest.mark.c), + pytest.param("fortran", marks=[ + pytest.mark.skip(reason="Variable declaration not implemented in fortran"), + pytest.mark.fortran]), + pytest.param("python", marks=pytest.mark.python) + ]) def test_local_type_annotation(language): def local_type_annotation(): @@ -175,7 +183,6 @@ def homogeneous_tuple_annotation(): pytest.param("python", marks = pytest.mark.python) ] ) - def test_homogeneous_set_annotation_int(language): def homogeneous_set_annotation (): a : set[int] #pylint: disable=unused-variable @@ -183,3 +190,66 @@ def homogeneous_set_annotation (): epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=language) assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation() assert isinstance(epyc_homogeneous_set_annotation(), type(homogeneous_set_annotation())) + +@parametrize_languages() +def test_homogeneous_set_annotation_float(language): + def homogeneous_set_annotation (): + a : set[float] #pylint: disable=unused-variable + a = {1.5, 2.5, 3.3, 4.3} + epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=language) + assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation() + assert isinstance(epyc_homogeneous_set_annotation(), type(homogeneous_set_annotation())) + +@parametrize_languages() +def test_homogeneous_set_annotation_bool(language): + def homogeneous_set_annotation (): + a : set[bool] #pylint: disable=unused-variable + a = {False, True, True, False} + epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=language) + assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation() + assert isinstance(epyc_homogeneous_set_annotation(), type(homogeneous_set_annotation())) + +@parametrize_languages() +def test_homogeneous_set_annotation_complex(language): + def homogeneous_set_annotation(): + a: set[complex] # pylint: disable=unused-variable + a = {1+1j, 2+2j, 3+3j, 4+4j} + epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=language) + assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation() + assert isinstance(epyc_homogeneous_set_annotation(), type(homogeneous_set_annotation())) + +@parametrize_languages() +def test_homogeneous_list_annotation_int(language): + def homogeneous_list_annotation(): + a: list[int] # pylint: disable=unused-variable + a = [1, 2, 3, 4] + epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=language) + assert epyc_homogeneous_list_annotation() == homogeneous_list_annotation() + assert isinstance(epyc_homogeneous_list_annotation(), type(homogeneous_list_annotation())) + +@parametrize_languages() +def test_homogeneous_list_annotation_float(language): + def homogeneous_list_annotation(): + a: list[float] # pylint: disable=unused-variable + a = [1.1, 2.2, 3.3, 4.4] + epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=language) + assert epyc_homogeneous_list_annotation() == homogeneous_list_annotation() + assert isinstance(epyc_homogeneous_list_annotation(), type(homogeneous_list_annotation())) + +@parametrize_languages() +def test_homogeneous_list_annotation_bool(language): + def homogeneous_list_annotation(): + a: list[bool] # pylint: disable=unused-variable + a = [False, True, True, False] + epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=language) + assert epyc_homogeneous_list_annotation() == homogeneous_list_annotation() + assert isinstance(epyc_homogeneous_list_annotation(), type(homogeneous_list_annotation())) + +@parametrize_languages() +def test_homogeneous_list_annotation_complex(language): + def homogeneous_list_annotation(): + a: list[complex] # pylint: disable=unused-variable + a = [1+1j, 2+2j, 3+3j, 4+4j] + epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=language) + assert epyc_homogeneous_list_annotation() == homogeneous_list_annotation() + assert isinstance(epyc_homogeneous_list_annotation(), type(homogeneous_list_annotation())) From e557d45e6bf06165d37cb0ff3300ae78aa27473c Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 17 May 2024 17:07:59 +0100 Subject: [PATCH 065/139] set can't have duplicates --- tests/epyccel/test_epyccel_variable_annotations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/epyccel/test_epyccel_variable_annotations.py b/tests/epyccel/test_epyccel_variable_annotations.py index 371bfacde8..eaa99273ba 100644 --- a/tests/epyccel/test_epyccel_variable_annotations.py +++ b/tests/epyccel/test_epyccel_variable_annotations.py @@ -204,7 +204,7 @@ def homogeneous_set_annotation (): def test_homogeneous_set_annotation_bool(language): def homogeneous_set_annotation (): a : set[bool] #pylint: disable=unused-variable - a = {False, True, True, False} + a = {False, True} epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=language) assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation() assert isinstance(epyc_homogeneous_set_annotation(), type(homogeneous_set_annotation())) From a6b47044a34bf865273659ceedcab3dc2aba73a6 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Tue, 21 May 2024 18:52:45 +0100 Subject: [PATCH 066/139] ignore pylint warning for using duplicate in set test --- tests/epyccel/test_epyccel_variable_annotations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/epyccel/test_epyccel_variable_annotations.py b/tests/epyccel/test_epyccel_variable_annotations.py index eaa99273ba..c8d3e8e5f6 100644 --- a/tests/epyccel/test_epyccel_variable_annotations.py +++ b/tests/epyccel/test_epyccel_variable_annotations.py @@ -204,7 +204,7 @@ def homogeneous_set_annotation (): def test_homogeneous_set_annotation_bool(language): def homogeneous_set_annotation (): a : set[bool] #pylint: disable=unused-variable - a = {False, True} + a = {False, True, False, True} #pylint: disable=error-code epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=language) assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation() assert isinstance(epyc_homogeneous_set_annotation(), type(homogeneous_set_annotation())) From e910c600489501d9d37594a3ef93b305f3bed4ae Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Tue, 21 May 2024 19:01:38 +0100 Subject: [PATCH 067/139] feat: use of i_type macro => The i_type macro is used to construct the full container type name. This is done by replacing any spaces in the datatype with underscores, as a sort of convention to preserve the readability of the container type --- pyccel/codegen/printing/ccode.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index f4b3f3ec3a..9cdf9d90d0 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -954,15 +954,15 @@ def _print_Import(self, expr): if expr.target: dtype = expr.target.pop().name if source.startswith('stc/'): - dtype_macro = dtype.upper() + dtype_macro = dtype.upper().replace(" ", "_") _,container_type = source.split("/") if container_type in import_stc: class_type_macro = import_stc[container_type] - additional_defines = '#define i_use_cmp\n' if class_type_macro == 'VEC' else '' + i_type_arg = f"{container_type}_{dtype.replace(' ', '_')}" return '\n'.join((f'#ifndef _{class_type_macro}_{dtype_macro}', f'#define _{class_type_macro}_{dtype_macro}', + f'#define i_type {i_type_arg}', f'#define i_key {dtype}', - additional_defines, f'#include "{source}.h"', f'#endif\n')) @@ -1184,10 +1184,10 @@ def find_in_dtype_registry(self, dtype): elif isinstance(dtype, (HomogeneousSetType, HomogeneousListType)): container_type = 'hset_' if dtype._name == 'set' else 'vec_' vec_dtype = self.find_in_dtype_registry(dtype.element_type) - key = container_type + vec_dtype + i_type = container_type + vec_dtype.replace(' ', '_') source = 'stc/'+ container_type[:-1] self.add_import(Import(source, Module(vec_dtype, (), ()))) - return key + return i_type else: key = dtype @@ -1997,7 +1997,7 @@ def init_lists_or_sets(self, expr, list_var): """ Print the initialization of a python assignment using STC init() method """ - dtype = self.find_in_dtype_registry(expr.current_user_node.lhs.dtype) + dtype = self.find_in_dtype_registry(expr.current_user_node.lhs.dtype).replace(" ", "_") container_type = "hset_"if isinstance(expr.class_type, HomogeneousSetType) else "vec_" if (len(expr.args) == 0): return f'{list_var} = c_init({container_type}{dtype},{"{}"});\n' From 4c7f8ec6edea8c9e606dccb0b6745738dcb12144 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 24 May 2024 11:15:28 +0100 Subject: [PATCH 068/139] fix: silent pylint warning to test duplicate value in set --- tests/epyccel/test_epyccel_variable_annotations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/epyccel/test_epyccel_variable_annotations.py b/tests/epyccel/test_epyccel_variable_annotations.py index c8d3e8e5f6..5a2e08eb4d 100644 --- a/tests/epyccel/test_epyccel_variable_annotations.py +++ b/tests/epyccel/test_epyccel_variable_annotations.py @@ -204,7 +204,7 @@ def homogeneous_set_annotation (): def test_homogeneous_set_annotation_bool(language): def homogeneous_set_annotation (): a : set[bool] #pylint: disable=unused-variable - a = {False, True, False, True} #pylint: disable=error-code + a = {False, True, False, True} #pylint: disable=duplicate-value epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=language) assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation() assert isinstance(epyc_homogeneous_set_annotation(), type(homogeneous_set_annotation())) From dd2af8bbb1182601840c775ba46131cfa440b084 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 24 May 2024 11:19:42 +0100 Subject: [PATCH 069/139] fix comment: check in an "external lib" is needed --- pyccel/codegen/pipeline.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyccel/codegen/pipeline.py b/pyccel/codegen/pipeline.py index f336d9f006..724a929289 100644 --- a/pyccel/codegen/pipeline.py +++ b/pyccel/codegen/pipeline.py @@ -337,7 +337,7 @@ def handle_error(stage): # Iterate over the external_libs list and determine if the printer - # requires an internal lib to be included. + # requires an external lib to be included. for ext_lib_name, ext_src_folder in external_libs.items(): if ext_lib_name in codegen.get_printer_imports(): From 283018fff9ed423426e8741a153290a957c8d6dd Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 24 May 2024 11:56:40 +0100 Subject: [PATCH 070/139] fix: specify an encoding for open() --- pyccel/codegen/codegen.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyccel/codegen/codegen.py b/pyccel/codegen/codegen.py index 98f59fc731..daf4559df4 100644 --- a/pyccel/codegen/codegen.py +++ b/pyccel/codegen/codegen.py @@ -218,14 +218,14 @@ def export(self, filename): # print module code = self._printer.doprint(self.ast) - with open(filename, 'w') as f: + with open(filename, 'w', encoding="utf-8") as f: for line in code: f.write(line) # print module header if header_ext is not None: code = self._printer.doprint(ModuleHeader(self.ast)) - with open(header_filename, 'w') as f: + with open(header_filename, 'w', encoding="utf-8") as f: for line in code: f.write(line) From b8b1b2af3e8942c64bde436fa48f5e3e201c5824 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 24 May 2024 12:02:56 +0100 Subject: [PATCH 071/139] fix: indentation and use of get() for dictionaries --- pyccel/codegen/printing/ccode.py | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 9cdf9d90d0..dc77103a2e 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -952,19 +952,18 @@ def _print_Import(self, expr): else: source = self._print(source) if expr.target: - dtype = expr.target.pop().name - if source.startswith('stc/'): - dtype_macro = dtype.upper().replace(" ", "_") - _,container_type = source.split("/") - if container_type in import_stc: - class_type_macro = import_stc[container_type] - i_type_arg = f"{container_type}_{dtype.replace(' ', '_')}" - return '\n'.join((f'#ifndef _{class_type_macro}_{dtype_macro}', - f'#define _{class_type_macro}_{dtype_macro}', - f'#define i_type {i_type_arg}', - f'#define i_key {dtype}', - f'#include "{source}.h"', - f'#endif\n')) + dtype = expr.target.pop().name + if source.startswith('stc/'): + dtype_macro = dtype.upper().replace(" ", "_") + _,container_type = source.split("/") + class_type_macro = import_stc.get(container_type) + i_type_arg = f"{container_type}_{dtype.replace(' ', '_')}" + return '\n'.join((f'#ifndef _{class_type_macro}_{dtype_macro}', + f'#define _{class_type_macro}_{dtype_macro}', + f'#define i_type {i_type_arg}', + f'#define i_key {dtype}', + f'#include "{source}.h"', + '#endif\n')) # Get with a default value is not used here as it is # slower and on most occasions the import will not be in the From aa539e77720f836b78747a277db445228de7fd69 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 24 May 2024 12:21:20 +0100 Subject: [PATCH 072/139] fix: use property decorator to access protected member _name --- pyccel/ast/datatypes.py | 10 ++++++++++ pyccel/codegen/printing/ccode.py | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/pyccel/ast/datatypes.py b/pyccel/ast/datatypes.py index 8d3dfb79ee..475946794a 100644 --- a/pyccel/ast/datatypes.py +++ b/pyccel/ast/datatypes.py @@ -488,6 +488,16 @@ class HomogeneousContainerType(ContainerType): This is the case for objects such as arrays, lists, etc. """ __slots__ = () + _name = None + + @property + def name(self): + """ + Get the name of the container. + + Get the name of the container. + """ + return self._name @property def datatype(self): diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index dc77103a2e..aa3f786628 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -1181,7 +1181,7 @@ def find_in_dtype_registry(self, dtype): key = (primitive_type, dtype.precision) elif isinstance(dtype, (HomogeneousSetType, HomogeneousListType)): - container_type = 'hset_' if dtype._name == 'set' else 'vec_' + container_type = 'hset_' if dtype.name == 'set' else 'vec_' vec_dtype = self.find_in_dtype_registry(dtype.element_type) i_type = container_type + vec_dtype.replace(' ', '_') source = 'stc/'+ container_type[:-1] From 9b53a28d2e8e123e66934687a31543a826908f74 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 24 May 2024 12:54:52 +0100 Subject: [PATCH 073/139] fix: docstring for the init method --- pyccel/codegen/printing/ccode.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index aa3f786628..e076d6d758 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -1992,17 +1992,32 @@ def _print_FunctionCall(self, expr): else: return call_code - def init_lists_or_sets(self, expr, list_var): + def init_lists_or_sets(self, expr, container_var): """ - Print the initialization of a python assignment using STC init() method + Prints the initialization of an STC vector in C. + + This method generates and prints the C code for initializing a vector using the STC `init()` method. + + Parameters + ---------- + expr : TypedAstNode + The object representing the container being printed (e.g., PythonList, PythonSet). + + container_var : str + The variable name to which the container is being assigned. + + Returns + ------- + str + The generated C code for the container initialization. """ dtype = self.find_in_dtype_registry(expr.current_user_node.lhs.dtype).replace(" ", "_") container_type = "hset_"if isinstance(expr.class_type, HomogeneousSetType) else "vec_" if (len(expr.args) == 0): - return f'{list_var} = c_init({container_type}{dtype},{"{}"});\n' + return f'{container_var} = c_init({container_type}{dtype},{"{}"});\n' keyraw = '{' + ', '.join([self._print(a) for a in expr.args]) + '}' - init = f'{list_var} = c_init({container_type}{dtype}, {keyraw});\n' + init = f'{container_var} = c_init({container_type}{dtype}, {keyraw});\n' return init From b16a96771b86c42bc533ae2d7d8f8dde89e50a86 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 24 May 2024 12:59:32 +0100 Subject: [PATCH 074/139] fix: unsubscriptable-object pylint error --- .../epyccel/test_epyccel_variable_annotations.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/epyccel/test_epyccel_variable_annotations.py b/tests/epyccel/test_epyccel_variable_annotations.py index 5a2e08eb4d..91862f393f 100644 --- a/tests/epyccel/test_epyccel_variable_annotations.py +++ b/tests/epyccel/test_epyccel_variable_annotations.py @@ -185,7 +185,7 @@ def homogeneous_tuple_annotation(): ) def test_homogeneous_set_annotation_int(language): def homogeneous_set_annotation (): - a : set[int] #pylint: disable=unused-variable + a : 'set[int]' #pylint: disable=unused-variable a = {1, 2, 3, 4} epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=language) assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation() @@ -194,7 +194,7 @@ def homogeneous_set_annotation (): @parametrize_languages() def test_homogeneous_set_annotation_float(language): def homogeneous_set_annotation (): - a : set[float] #pylint: disable=unused-variable + a : 'set[float]' #pylint: disable=unused-variable a = {1.5, 2.5, 3.3, 4.3} epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=language) assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation() @@ -203,7 +203,7 @@ def homogeneous_set_annotation (): @parametrize_languages() def test_homogeneous_set_annotation_bool(language): def homogeneous_set_annotation (): - a : set[bool] #pylint: disable=unused-variable + a : 'set[bool]' #pylint: disable=unused-variable a = {False, True, False, True} #pylint: disable=duplicate-value epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=language) assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation() @@ -212,7 +212,7 @@ def homogeneous_set_annotation (): @parametrize_languages() def test_homogeneous_set_annotation_complex(language): def homogeneous_set_annotation(): - a: set[complex] # pylint: disable=unused-variable + a: 'set[complex]' # pylint: disable=unused-variable a = {1+1j, 2+2j, 3+3j, 4+4j} epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=language) assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation() @@ -221,7 +221,7 @@ def homogeneous_set_annotation(): @parametrize_languages() def test_homogeneous_list_annotation_int(language): def homogeneous_list_annotation(): - a: list[int] # pylint: disable=unused-variable + a: 'list[int]' # pylint: disable=unused-variable a = [1, 2, 3, 4] epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=language) assert epyc_homogeneous_list_annotation() == homogeneous_list_annotation() @@ -230,7 +230,7 @@ def homogeneous_list_annotation(): @parametrize_languages() def test_homogeneous_list_annotation_float(language): def homogeneous_list_annotation(): - a: list[float] # pylint: disable=unused-variable + a: 'list[float]' # pylint: disable=unused-variable a = [1.1, 2.2, 3.3, 4.4] epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=language) assert epyc_homogeneous_list_annotation() == homogeneous_list_annotation() @@ -239,7 +239,7 @@ def homogeneous_list_annotation(): @parametrize_languages() def test_homogeneous_list_annotation_bool(language): def homogeneous_list_annotation(): - a: list[bool] # pylint: disable=unused-variable + a: 'list[bool]' # pylint: disable=unused-variable a = [False, True, True, False] epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=language) assert epyc_homogeneous_list_annotation() == homogeneous_list_annotation() @@ -248,7 +248,7 @@ def homogeneous_list_annotation(): @parametrize_languages() def test_homogeneous_list_annotation_complex(language): def homogeneous_list_annotation(): - a: list[complex] # pylint: disable=unused-variable + a: 'list[complex]' # pylint: disable=unused-variable a = [1+1j, 2+2j, 3+3j, 4+4j] epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=language) assert epyc_homogeneous_list_annotation() == homogeneous_list_annotation() From ab30ea0fca61f42cc75d7004e9576f154d1011fd Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 24 May 2024 13:13:00 +0100 Subject: [PATCH 075/139] fix doc --- pyccel/codegen/printing/ccode.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index e076d6d758..7e18255c19 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -1994,9 +1994,9 @@ def _print_FunctionCall(self, expr): def init_lists_or_sets(self, expr, container_var): """ - Prints the initialization of an STC vector in C. + Generate the initialization of an STC container in C. - This method generates and prints the C code for initializing a vector using the STC `init()` method. + This method generates and prints the C code for initializing a container using the STC `init()` method. Parameters ---------- From 64249cacc7bf7f038fa831099d2a47ba751b9af0 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Fri, 24 May 2024 20:34:08 +0100 Subject: [PATCH 076/139] Fix Error in Print Module Header for classes --- pyccel/codegen/codegen.py | 12 ++++++++++-- pyccel/codegen/printing/ccode.py | 6 ++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/pyccel/codegen/codegen.py b/pyccel/codegen/codegen.py index daf4559df4..cd12370e12 100644 --- a/pyccel/codegen/codegen.py +++ b/pyccel/codegen/codegen.py @@ -216,14 +216,22 @@ def export(self, filename): header_filename = f'{filename}.{header_ext}' filename = f'{filename}.{ext}' + check = set() + # print module header + if header_ext is not None: + code = self._printer.doprint(ModuleHeader(self.ast)) + with open(header_filename, 'w', encoding="utf-8") as f: + for line in code: + check.add(line) + f.write(line) + # print module code = self._printer.doprint(self.ast) with open(filename, 'w', encoding="utf-8") as f: for line in code: f.write(line) - # print module header - if header_ext is not None: + if header_ext is not None and self.ast: code = self._printer.doprint(ModuleHeader(self.ast)) with open(header_filename, 'w', encoding="utf-8") as f: for line in code: diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 7e18255c19..47c937a9be 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -779,12 +779,14 @@ def _print_ModuleHeader(self, expr): class_scope = classDef.scope for method in classDef.methods: if not method.is_inline: - class_scope.rename_function(method, f"{classDef.name}__{method.name.lstrip('__')}") + if method.name.startswith(classDef.name) == False: + class_scope.rename_function(method, f"{classDef.name}__{method.name.lstrip('__')}") funcs += f"{self.function_signature(method)};\n" for interface in classDef.interfaces: for func in interface.functions: if not func.is_inline: - class_scope.rename_function(func, f"{classDef.name}__{func.name.lstrip('__')}") + if method.name.startswith(classDef.name) == False: + class_scope.rename_function(func, f"{classDef.name}__{func.name.lstrip('__')}") funcs += f"{self.function_signature(func)};\n" classes += "};\n" funcs += '\n'.join(f"{self.function_signature(f)};" for f in expr.module.funcs if not f.is_inline) From b05a6699e6bb7d189055bdc4987788d11da4fa49 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Mon, 27 May 2024 12:45:43 +0100 Subject: [PATCH 077/139] The function is renamed in the _Print_Module instead of _Print_ModuleHeader. --- pyccel/codegen/codegen.py | 12 ++---------- pyccel/codegen/printing/ccode.py | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/pyccel/codegen/codegen.py b/pyccel/codegen/codegen.py index cd12370e12..daf4559df4 100644 --- a/pyccel/codegen/codegen.py +++ b/pyccel/codegen/codegen.py @@ -216,22 +216,14 @@ def export(self, filename): header_filename = f'{filename}.{header_ext}' filename = f'{filename}.{ext}' - check = set() - # print module header - if header_ext is not None: - code = self._printer.doprint(ModuleHeader(self.ast)) - with open(header_filename, 'w', encoding="utf-8") as f: - for line in code: - check.add(line) - f.write(line) - # print module code = self._printer.doprint(self.ast) with open(filename, 'w', encoding="utf-8") as f: for line in code: f.write(line) - if header_ext is not None and self.ast: + # print module header + if header_ext is not None: code = self._printer.doprint(ModuleHeader(self.ast)) with open(header_filename, 'w', encoding="utf-8") as f: for line in code: diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 47c937a9be..4e915fea94 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -776,18 +776,11 @@ def _print_ModuleHeader(self, expr): classes += self._print(classDef.docstring) classes += f"struct {classDef.name} {{\n" classes += ''.join(self._print(Declare(var)) for var in classDef.attributes) - class_scope = classDef.scope for method in classDef.methods: - if not method.is_inline: - if method.name.startswith(classDef.name) == False: - class_scope.rename_function(method, f"{classDef.name}__{method.name.lstrip('__')}") funcs += f"{self.function_signature(method)};\n" for interface in classDef.interfaces: for func in interface.functions: - if not func.is_inline: - if method.name.startswith(classDef.name) == False: - class_scope.rename_function(func, f"{classDef.name}__{func.name.lstrip('__')}") - funcs += f"{self.function_signature(func)};\n" + funcs += f"{self.function_signature(func)};\n" classes += "};\n" funcs += '\n'.join(f"{self.function_signature(f)};" for f in expr.module.funcs if not f.is_inline) @@ -811,6 +804,15 @@ def _print_ModuleHeader(self, expr): def _print_Module(self, expr): self.set_scope(expr.scope) self._current_module = expr + for classDef in expr.classes: + class_scope = classDef.scope + for method in classDef.methods: + if not method.is_inline: + class_scope.rename_function(method, f"{classDef.name}__{method.name.lstrip('__')}") + for interface in classDef.interfaces: + for func in interface.functions: + if not func.is_inline: + class_scope.rename_function(func, f"{classDef.name}__{func.name.lstrip('__')}") body = ''.join(self._print(i) for i in expr.body) global_variables = ''.join([self._print(d) for d in expr.declarations]) From 4a5aa9c3e13d2a4f8420387b29aa831ab4fe9469 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Tue, 28 May 2024 15:33:11 +0100 Subject: [PATCH 078/139] feat: print the deallocation of a STC container using container_X_drop() method --- pyccel/codegen/printing/ccode.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 4e915fea94..3b00e4f49d 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -1592,6 +1592,11 @@ def _print_Allocate(self, expr): raise NotImplementedError(f"Allocate not implemented for {variable}") def _print_Deallocate(self, expr): + if isinstance(expr.variable.class_type, (HomogeneousListType, HomogeneousSetType)): + variable_address = self._print(ObjectAddress(expr.variable)) + dtype = self.find_in_dtype_registry(expr.variable.dtype).replace(" ", "_") + container_type = "hset_"if isinstance(expr.variable.class_type, HomogeneousSetType) else "vec_" + return f'{container_type}{dtype}_drop({variable_address});\n' if isinstance(expr.variable, InhomogeneousTupleVariable): return ''.join(self._print(Deallocate(v)) for v in expr.variable) variable_address = self._print(ObjectAddress(expr.variable)) From 9dc7d46eea66679cbe47d15d770af19950024826 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Tue, 28 May 2024 15:51:56 +0100 Subject: [PATCH 079/139] feat: test list and set declarations without type annotations --- .../epyccel/test_epyccel_variable_annotations.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/epyccel/test_epyccel_variable_annotations.py b/tests/epyccel/test_epyccel_variable_annotations.py index 91862f393f..494cafe25b 100644 --- a/tests/epyccel/test_epyccel_variable_annotations.py +++ b/tests/epyccel/test_epyccel_variable_annotations.py @@ -191,6 +191,13 @@ def homogeneous_set_annotation (): assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation() assert isinstance(epyc_homogeneous_set_annotation(), type(homogeneous_set_annotation())) +def test_homogeneous_set_without_annotation(language): + def homogeneous_set(): + a = {1, 2, 3, 4} #pylint: disable=unused-variable + epyc_homogeneous_set = epyccel(homogeneous_set, language=language) + assert epyc_homogeneous_set() == homogeneous_set() + assert isinstance(epyc_homogeneous_set(), type(homogeneous_set())) + @parametrize_languages() def test_homogeneous_set_annotation_float(language): def homogeneous_set_annotation (): @@ -227,6 +234,14 @@ def homogeneous_list_annotation(): assert epyc_homogeneous_list_annotation() == homogeneous_list_annotation() assert isinstance(epyc_homogeneous_list_annotation(), type(homogeneous_list_annotation())) +@parametrize_languages() +def test_homogeneous_list_without_annotation(language): + def homogeneous_list(): + a = [1, 2, 3, 4] # pylint: disable=unused-variable + epyc_homogeneous_list = epyccel(homogeneous_list, language=language) + assert epyc_homogeneous_list() == homogeneous_list() + assert isinstance(epyc_homogeneous_list(), type(homogeneous_list())) + @parametrize_languages() def test_homogeneous_list_annotation_float(language): def homogeneous_list_annotation(): From a3fe0450967d5fb078b1db3a99be39456e584400 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Wed, 29 May 2024 12:24:59 +0100 Subject: [PATCH 080/139] Make some tests as xfail because C does not support list indexing yet. --- tests/epyccel/test_functionals.py | 14 ++++++++++++ tests/epyccel/test_loops.py | 36 +++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/tests/epyccel/test_functionals.py b/tests/epyccel/test_functionals.py index f30c7d2279..29a67fe5d4 100644 --- a/tests/epyccel/test_functionals.py +++ b/tests/epyccel/test_functionals.py @@ -1,10 +1,24 @@ # pylint: disable=missing-function-docstring, missing-module-docstring from numpy.random import randint from numpy import equal +import pytest + from pyccel import epyccel from modules import functionals +@pytest.fixture( params=[ + pytest.param("fortran", marks = pytest.mark.fortran), + pytest.param("c", marks = [ + pytest.mark.xfail(reason="C does not support list indexing yet."), + pytest.mark.c]), + pytest.param("python", marks = pytest.mark.python) + ], + scope = "module" +) +def language(request): + return request.param + def compare_epyccel(f, language, *args): f2 = epyccel(f, language=language) out1 = f(*args) diff --git a/tests/epyccel/test_loops.py b/tests/epyccel/test_loops.py index 3b24578f3f..50bfa34176 100644 --- a/tests/epyccel/test_loops.py +++ b/tests/epyccel/test_loops.py @@ -77,6 +77,15 @@ def test_double_loop_on_2d_array_F(language): f2( y ) assert np.array_equal( x, y ) +@pytest.mark.parametrize( 'language', ( + pytest.param("fortran", marks = pytest.mark.fortran), + pytest.param("c", marks = [ + pytest.mark.xfail(reason="C does not support list indexing yet."), + pytest.mark.c] + ), + pytest.param("python", marks = pytest.mark.python) + ) +) def test_product_loop_on_2d_array_C(language): f1 = loops.product_loop_on_2d_array_C @@ -89,6 +98,15 @@ def test_product_loop_on_2d_array_C(language): f2( y ) assert np.array_equal( x, y ) +@pytest.mark.parametrize( 'language', ( + pytest.param("fortran", marks = pytest.mark.fortran), + pytest.param("c", marks = [ + pytest.mark.xfail(reason="C does not support list indexing yet."), + pytest.mark.c] + ), + pytest.param("python", marks = pytest.mark.python) + ) +) def test_product_loop_on_2d_array_F(language): f1 = loops.product_loop_on_2d_array_F @@ -101,6 +119,15 @@ def test_product_loop_on_2d_array_F(language): f2( y ) assert np.array_equal( x, y ) +@pytest.mark.parametrize( 'language', ( + pytest.param("fortran", marks = pytest.mark.fortran), + pytest.param("c", marks = [ + pytest.mark.xfail(reason="C does not support list indexing yet."), + pytest.mark.c] + ), + pytest.param("python", marks = pytest.mark.python) + ) +) def test_product_loop(language): f1 = loops.product_loop @@ -150,6 +177,15 @@ def test_enumerate_on_1d_array_with_start(language): assert np.array_equal( f1(z, 5), f2(z, 5) ) assert np.array_equal( f1(z,-2), f2(z,-2) ) +@pytest.mark.parametrize( 'language', ( + pytest.param("fortran", marks = pytest.mark.fortran), + pytest.param("c", marks = [ + pytest.mark.xfail(reason="C does not support list indexing yet."), + pytest.mark.c] + ), + pytest.param("python", marks = pytest.mark.python) + ) +) def test_zip_prod(language): f1 = loops.zip_prod From 8174549b80c64dfe7e555ef888b8922c47445402 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Wed, 29 May 2024 12:27:37 +0100 Subject: [PATCH 081/139] Make some tests as xfail because C does not support list indexing yet. --- pyccel/codegen/printing/ccode.py | 35 ++++++++++++++------------------ 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 4e915fea94..5909907ff3 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -25,7 +25,7 @@ from pyccel.ast.operators import PyccelAssociativeParenthesis, PyccelMod from pyccel.ast.operators import PyccelUnarySub, IfTernaryOperator -from pyccel.ast.datatypes import PythonNativeInt, PythonNativeBool, VoidType +from pyccel.ast.datatypes import PythonNativeInt, PythonNativeBool, VoidType, GenericType from pyccel.ast.datatypes import TupleType, FixedSizeNumericType from pyccel.ast.datatypes import CustomDataType, StringType, HomogeneousTupleType, HomogeneousListType, HomogeneousSetType from pyccel.ast.datatypes import PrimitiveBooleanType, PrimitiveIntegerType, PrimitiveFloatingPointType, PrimitiveComplexType @@ -958,15 +958,14 @@ def _print_Import(self, expr): if expr.target: dtype = expr.target.pop().name if source.startswith('stc/'): - dtype_macro = dtype.upper().replace(" ", "_") _,container_type = source.split("/") - class_type_macro = import_stc.get(container_type) - i_type_arg = f"{container_type}_{dtype.replace(' ', '_')}" - return '\n'.join((f'#ifndef _{class_type_macro}_{dtype_macro}', - f'#define _{class_type_macro}_{dtype_macro}', - f'#define i_type {i_type_arg}', - f'#define i_key {dtype}', - f'#include "{source}.h"', + container = container_type.split("_") + index = len(container[0]) + 1 + return '\n'.join((f'#ifndef _{container_type.upper()}', + f'#define _{container_type.upper()}', + f'#define i_type {container_type}', + f'#define i_key {container_type[index:]}', + f'#include "{_ + "/" +container[0]}.h"', '#endif\n')) # Get with a default value is not used here as it is @@ -1186,10 +1185,10 @@ def find_in_dtype_registry(self, dtype): key = (primitive_type, dtype.precision) elif isinstance(dtype, (HomogeneousSetType, HomogeneousListType)): container_type = 'hset_' if dtype.name == 'set' else 'vec_' - vec_dtype = self.find_in_dtype_registry(dtype.element_type) + if not isinstance(dtype.element_type, GenericType): + vec_dtype = self.find_in_dtype_registry(dtype.element_type) i_type = container_type + vec_dtype.replace(' ', '_') - source = 'stc/'+ container_type[:-1] - self.add_import(Import(source, Module(vec_dtype, (), ()))) + self.add_import(Import('stc/' + i_type, Module('stc/' + i_type, (), ()))) return i_type else: key = dtype @@ -1325,7 +1324,6 @@ def _print_Declare(self, expr): static = 'static ' if expr.static else '' declaration = f'{static}{external}{declaration_type} {variable}{init};\n' - return preface + declaration def function_signature(self, expr, print_arg_names = True): @@ -2015,14 +2013,10 @@ def init_lists_or_sets(self, expr, container_var): str The generated C code for the container initialization. """ - dtype = self.find_in_dtype_registry(expr.current_user_node.lhs.dtype).replace(" ", "_") - container_type = "hset_"if isinstance(expr.class_type, HomogeneousSetType) else "vec_" - if (len(expr.args) == 0): - return f'{container_var} = c_init({container_type}{dtype},{"{}"});\n' + dtype = self.find_in_dtype_registry(container_var.lhs.class_type) keyraw = '{' + ', '.join([self._print(a) for a in expr.args]) + '}' - init = f'{container_var} = c_init({container_type}{dtype}, {keyraw});\n' - + init = f'{container_var.lhs.name} = c_init({dtype}, {keyraw});\n' return init def _print_Return(self, expr): @@ -2158,6 +2152,7 @@ def _print_Assign(self, expr): prefix_code = '' lhs = expr.lhs rhs = expr.rhs + if isinstance(rhs, FunctionCall) and isinstance(rhs.class_type, TupleType): self._temporary_args = [ObjectAddress(a) for a in lhs] return prefix_code+'{};\n'.format(self._print(rhs)) @@ -2168,7 +2163,7 @@ def _print_Assign(self, expr): return prefix_code+self.arrayFill(expr) lhs = self._print(expr.lhs) if isinstance(rhs, (PythonList, PythonSet)): - return prefix_code+self.init_lists_or_sets(rhs, lhs) + return prefix_code+self.init_lists_or_sets(rhs, expr) rhs = self._print(expr.rhs) return prefix_code+'{} = {};\n'.format(lhs, rhs) From f8132d4f20507c984bf19e51fcd94c8e91044aa4 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Wed, 29 May 2024 12:40:15 +0100 Subject: [PATCH 082/139] Add related issue in xfail comments. --- tests/epyccel/test_functionals.py | 2 +- tests/epyccel/test_loops.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/epyccel/test_functionals.py b/tests/epyccel/test_functionals.py index 29a67fe5d4..01e54521e0 100644 --- a/tests/epyccel/test_functionals.py +++ b/tests/epyccel/test_functionals.py @@ -10,7 +10,7 @@ @pytest.fixture( params=[ pytest.param("fortran", marks = pytest.mark.fortran), pytest.param("c", marks = [ - pytest.mark.xfail(reason="C does not support list indexing yet."), + pytest.mark.xfail(reason="C does not support list indexing yet, related issue #1876"), pytest.mark.c]), pytest.param("python", marks = pytest.mark.python) ], diff --git a/tests/epyccel/test_loops.py b/tests/epyccel/test_loops.py index 50bfa34176..a1176010e9 100644 --- a/tests/epyccel/test_loops.py +++ b/tests/epyccel/test_loops.py @@ -80,7 +80,7 @@ def test_double_loop_on_2d_array_F(language): @pytest.mark.parametrize( 'language', ( pytest.param("fortran", marks = pytest.mark.fortran), pytest.param("c", marks = [ - pytest.mark.xfail(reason="C does not support list indexing yet."), + pytest.mark.xfail(reason="C does not support list indexing yet, related issue #1876"), pytest.mark.c] ), pytest.param("python", marks = pytest.mark.python) @@ -101,7 +101,7 @@ def test_product_loop_on_2d_array_C(language): @pytest.mark.parametrize( 'language', ( pytest.param("fortran", marks = pytest.mark.fortran), pytest.param("c", marks = [ - pytest.mark.xfail(reason="C does not support list indexing yet."), + pytest.mark.xfail(reason="C does not support list indexing yet, related issue #1876"), pytest.mark.c] ), pytest.param("python", marks = pytest.mark.python) @@ -122,7 +122,7 @@ def test_product_loop_on_2d_array_F(language): @pytest.mark.parametrize( 'language', ( pytest.param("fortran", marks = pytest.mark.fortran), pytest.param("c", marks = [ - pytest.mark.xfail(reason="C does not support list indexing yet."), + pytest.mark.xfail(reason="C does not support list indexing yet, related issue #1876"), pytest.mark.c] ), pytest.param("python", marks = pytest.mark.python) @@ -180,7 +180,7 @@ def test_enumerate_on_1d_array_with_start(language): @pytest.mark.parametrize( 'language', ( pytest.param("fortran", marks = pytest.mark.fortran), pytest.param("c", marks = [ - pytest.mark.xfail(reason="C does not support list indexing yet."), + pytest.mark.xfail(reason="C does not support list indexing yet, related issue #1876"), pytest.mark.c] ), pytest.param("python", marks = pytest.mark.python) From 3dc4d5cdd6624e2535e6104714cac616b6493aa3 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Wed, 29 May 2024 12:44:25 +0100 Subject: [PATCH 083/139] correct the path for STC. --- pyccel/codegen/printing/ccode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index ecc1bc3ed5..3e6f434229 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -965,7 +965,7 @@ def _print_Import(self, expr): f'#define _{container_type.upper()}', f'#define i_type {container_type}', f'#define i_key {container_type[index:]}', - f'#include "{_ + "/" +container[0]}.h"', + f'#include "{"extensions/STC/include/"+ _ + "/" +container[0]}.h"', '#endif\n')) # Get with a default value is not used here as it is From 863a1a16980db31c83ea7c5f14483ae9169c0b71 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Wed, 29 May 2024 15:20:43 +0100 Subject: [PATCH 084/139] Fix import STC folder. --- pyccel/codegen/pipeline.py | 9 ++++----- pyccel/codegen/printing/ccode.py | 2 +- pyccel/codegen/utilities.py | 4 ---- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/pyccel/codegen/pipeline.py b/pyccel/codegen/pipeline.py index 724a929289..d4f523eca3 100644 --- a/pyccel/codegen/pipeline.py +++ b/pyccel/codegen/pipeline.py @@ -21,7 +21,6 @@ from pyccel.codegen.utilities import recompile_object from pyccel.codegen.utilities import copy_internal_library from pyccel.codegen.utilities import internal_libs -from pyccel.codegen.utilities import external_libs from pyccel.codegen.python_wrapper import create_shared_library from pyccel.naming import name_clash_checkers from pyccel.utilities.stage import PyccelStage @@ -338,10 +337,10 @@ def handle_error(stage): # Iterate over the external_libs list and determine if the printer # requires an external lib to be included. - for ext_lib_name, ext_src_folder in external_libs.items(): - if ext_lib_name in codegen.get_printer_imports(): - - lib_dest_path = copy_internal_library(ext_src_folder, pyccel_dirpath) + + result = [key for key in codegen.get_printer_imports() if key.startswith('stc')] + if result[0]: + lib_dest_path = copy_internal_library('stc', pyccel_dirpath) if convert_only: # Change working directory back to starting point diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 3e6f434229..ecc1bc3ed5 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -965,7 +965,7 @@ def _print_Import(self, expr): f'#define _{container_type.upper()}', f'#define i_type {container_type}', f'#define i_key {container_type[index:]}', - f'#include "{"extensions/STC/include/"+ _ + "/" +container[0]}.h"', + f'#include "{_ + "/" +container[0]}.h"', '#endif\n')) # Get with a default value is not used here as it is diff --git a/pyccel/codegen/utilities.py b/pyccel/codegen/utilities.py index 565c31f0c1..3cb8417fee 100644 --- a/pyccel/codegen/utilities.py +++ b/pyccel/codegen/utilities.py @@ -27,10 +27,6 @@ #============================================================================== language_extension = {'fortran':'f90', 'c':'c', 'python':'py'} -#============================================================================== -# map external libraries to their folders inside pyccel/extensions -external_libs = {"stc/vec" : "stc", - "stc/hset" : "stc",} #============================================================================== # map internal libraries to their folders inside pyccel/stdlib and their compile objects From 3ff31255755c303883395bbb64bf388ab750a89e Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Wed, 29 May 2024 15:28:16 +0100 Subject: [PATCH 085/139] update changelog. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 65b410038a..f20f8246d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,7 @@ All notable changes to this project will be documented in this file. - #1844 : Add line numbers and code to errors from built-in function calls. - \[INTERNALS\] Added `container_rank` property to `ast.datatypes.PyccelType` objects. - \[DEVELOPER\] Added an improved traceback to the developer-mode errors for errors in function calls. - +- #1847 : Support `list()` and `set()` declarations in c. ### Fixed - #1720 : Fix Undefined Variable error when the function definition is after the variable declaration. From 038bb39d19f0ee9b05215b7389367b3b1e021de4 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Wed, 29 May 2024 16:13:19 +0100 Subject: [PATCH 086/139] update comment of copying external library --- pyccel/codegen/pipeline.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pyccel/codegen/pipeline.py b/pyccel/codegen/pipeline.py index d4f523eca3..40489c89d4 100644 --- a/pyccel/codegen/pipeline.py +++ b/pyccel/codegen/pipeline.py @@ -335,9 +335,7 @@ def handle_error(stage): mod_obj.add_dependencies(stdlib) - # Iterate over the external_libs list and determine if the printer - # requires an external lib to be included. - + # Check if the printer requires an external lib to be included. result = [key for key in codegen.get_printer_imports() if key.startswith('stc')] if result[0]: lib_dest_path = copy_internal_library('stc', pyccel_dirpath) From ba24ebc74356f06657cac166c3306f18d0fbd977 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Wed, 29 May 2024 17:04:47 +0100 Subject: [PATCH 087/139] add or delete empty lines --- pyccel/codegen/printing/ccode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index ecc1bc3ed5..9fcb98294b 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -1324,6 +1324,7 @@ def _print_Declare(self, expr): static = 'static ' if expr.static else '' declaration = f'{static}{external}{declaration_type} {variable}{init};\n' + return preface + declaration def function_signature(self, expr, print_arg_names = True): @@ -2157,7 +2158,6 @@ def _print_Assign(self, expr): prefix_code = '' lhs = expr.lhs rhs = expr.rhs - if isinstance(rhs, FunctionCall) and isinstance(rhs.class_type, TupleType): self._temporary_args = [ObjectAddress(a) for a in lhs] return prefix_code+'{};\n'.format(self._print(rhs)) From bf4fb3433903a13c211e4389c1de4c118491cfe6 Mon Sep 17 00:00:00 2001 From: mustapha-belbiad Date: Thu, 30 May 2024 09:45:21 +0100 Subject: [PATCH 088/139] Fix import of STC --- pyccel/codegen/pipeline.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyccel/codegen/pipeline.py b/pyccel/codegen/pipeline.py index d4f523eca3..00a35602d3 100644 --- a/pyccel/codegen/pipeline.py +++ b/pyccel/codegen/pipeline.py @@ -338,8 +338,7 @@ def handle_error(stage): # Iterate over the external_libs list and determine if the printer # requires an external lib to be included. - result = [key for key in codegen.get_printer_imports() if key.startswith('stc')] - if result[0]: + if [key for key in codegen.get_printer_imports() if key.startswith('stc')] : lib_dest_path = copy_internal_library('stc', pyccel_dirpath) if convert_only: From b162d9df0ceb0c7adc4786b5f509e52ead695fbc Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Thu, 30 May 2024 11:52:33 +0100 Subject: [PATCH 089/139] fix: add decorator to skip fortran tests --- tests/epyccel/test_epyccel_variable_annotations.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/epyccel/test_epyccel_variable_annotations.py b/tests/epyccel/test_epyccel_variable_annotations.py index 494cafe25b..46ddf46366 100644 --- a/tests/epyccel/test_epyccel_variable_annotations.py +++ b/tests/epyccel/test_epyccel_variable_annotations.py @@ -191,6 +191,7 @@ def homogeneous_set_annotation (): assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation() assert isinstance(epyc_homogeneous_set_annotation(), type(homogeneous_set_annotation())) +@parametrize_languages() def test_homogeneous_set_without_annotation(language): def homogeneous_set(): a = {1, 2, 3, 4} #pylint: disable=unused-variable From 2e788a5f242735cd2d79096acb61f66f652fc9d9 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Thu, 30 May 2024 11:53:35 +0100 Subject: [PATCH 090/139] fix: construct the right macros --- pyccel/codegen/printing/ccode.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 9fcb98294b..6984a93566 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -956,16 +956,14 @@ def _print_Import(self, expr): else: source = self._print(source) if expr.target: - dtype = expr.target.pop().name if source.startswith('stc/'): - _,container_type = source.split("/") + stc_name, container_type, container_key = source.split("/") container = container_type.split("_") - index = len(container[0]) + 1 return '\n'.join((f'#ifndef _{container_type.upper()}', f'#define _{container_type.upper()}', f'#define i_type {container_type}', - f'#define i_key {container_type[index:]}', - f'#include "{_ + "/" +container[0]}.h"', + f'#define i_key {container_key}', + f'#include "{stc_name + "/" + container[0]}.h"', '#endif\n')) # Get with a default value is not used here as it is @@ -1188,7 +1186,7 @@ def find_in_dtype_registry(self, dtype): if not isinstance(dtype.element_type, GenericType): vec_dtype = self.find_in_dtype_registry(dtype.element_type) i_type = container_type + vec_dtype.replace(' ', '_') - self.add_import(Import('stc/' + i_type, Module('stc/' + i_type, (), ()))) + self.add_import(Import('stc/' + i_type + "/" + vec_dtype, Module('stc/' + i_type, (), ()))) return i_type else: key = dtype From 86841335c2d75914313b9a4ad3b334ae9adad34e Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Thu, 30 May 2024 12:13:06 +0100 Subject: [PATCH 091/139] fix: get the right container type to construct the drop() method --- pyccel/codegen/printing/ccode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 6984a93566..2873655a46 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -1591,7 +1591,7 @@ def _print_Allocate(self, expr): def _print_Deallocate(self, expr): if isinstance(expr.variable.class_type, (HomogeneousListType, HomogeneousSetType)): variable_address = self._print(ObjectAddress(expr.variable)) - dtype = self.find_in_dtype_registry(expr.variable.dtype).replace(" ", "_") + dtype = self.find_in_dtype_registry(expr.variable.class_type.element_type).replace(" ", "_") container_type = "hset_"if isinstance(expr.variable.class_type, HomogeneousSetType) else "vec_" return f'{container_type}{dtype}_drop({variable_address});\n' if isinstance(expr.variable, InhomogeneousTupleVariable): From 27de41d6b03ba3a2b49df8b6bbdd18f0b1f20a6c Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Thu, 30 May 2024 12:13:37 +0100 Subject: [PATCH 092/139] feat: test a list of embedded complex --- tests/epyccel/test_epyccel_variable_annotations.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/epyccel/test_epyccel_variable_annotations.py b/tests/epyccel/test_epyccel_variable_annotations.py index 46ddf46366..3c57eacc5f 100644 --- a/tests/epyccel/test_epyccel_variable_annotations.py +++ b/tests/epyccel/test_epyccel_variable_annotations.py @@ -269,3 +269,12 @@ def homogeneous_list_annotation(): epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=language) assert epyc_homogeneous_list_annotation() == homogeneous_list_annotation() assert isinstance(epyc_homogeneous_list_annotation(), type(homogeneous_list_annotation())) + +@parametrize_languages() +def test_homogeneous_list_annotation_embedded_complex(language): + def homogeneous_list_annotation(): + a : 'list[complex]' = [1j, 2j] + b = [a] # pylint: disable=unused-variable + epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=language) + assert epyc_homogeneous_list_annotation() == homogeneous_list_annotation() + assert isinstance(epyc_homogeneous_list_annotation(), type(homogeneous_list_annotation())) From 311150cd079f624c56755f403e016be1e4b07f57 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Mon, 3 Jun 2024 14:48:33 +0100 Subject: [PATCH 093/139] fix: list indexing tests marked as xfail for C language --- tests/epyccel/test_arrays.py | 10 +++++++++- tests/epyccel/test_epyccel_modules.py | 10 ++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/epyccel/test_arrays.py b/tests/epyccel/test_arrays.py index fdac39bbad..209972187b 100644 --- a/tests/epyccel/test_arrays.py +++ b/tests/epyccel/test_arrays.py @@ -4027,7 +4027,15 @@ def test_array_float_nested_C_array_initialization_3(language): #============================================================================== # NUMPY SUM #============================================================================== - +@pytest.mark.parametrize( 'language', ( + pytest.param("fortran", marks = pytest.mark.fortran), + pytest.param("c", marks = [ + pytest.mark.xfail(reason="List indexing is not yet supported in C"), + pytest.mark.c] + ), + pytest.param("python", marks = pytest.mark.python) + ) +) def test_arr_bool_sum(language): f1 = arrays.arr_bool_sum f2 = epyccel(f1, language = language) diff --git a/tests/epyccel/test_epyccel_modules.py b/tests/epyccel/test_epyccel_modules.py index 445e8dc457..2241c8aea8 100644 --- a/tests/epyccel/test_epyccel_modules.py +++ b/tests/epyccel/test_epyccel_modules.py @@ -1,4 +1,5 @@ # pylint: disable=missing-function-docstring, missing-module-docstring +import pytest import numpy as np from pyccel import epyccel @@ -129,6 +130,15 @@ def test_module_6(language): assert mod_att == modnew_att assert type(mod_att) is type(modnew_att) +@pytest.mark.parametrize( 'language', ( + pytest.param("fortran", marks = pytest.mark.fortran), + pytest.param("c", marks = [ + pytest.mark.xfail(reason="List indexing is not yet supported in C"), + pytest.mark.c] + ), + pytest.param("python", marks = pytest.mark.python) + ) +) def test_module_7(language): import modules.array_consts as mod From 60afc9f0143a9596aecf9b51800f1ca54d083370 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Mon, 3 Jun 2024 18:16:46 +0100 Subject: [PATCH 094/139] fix: get the right python name for the import --- pyccel/codegen/printing/ccode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 2873655a46..d4c36a9cd9 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -818,7 +818,7 @@ def _print_Module(self, expr): global_variables = ''.join([self._print(d) for d in expr.declarations]) # Print imports last to be sure that all additional_imports have been collected - imports = Import(expr.name, Module(expr.name,(),())) + imports = Import(self.scope.get_python_name(expr.name), Module(expr.name,(),())) imports = self._print(imports) code = ('{imports}\n' From c47d4599b84ebe3c6a859f95eddf9ac84eac87be Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Tue, 4 Jun 2024 15:13:52 +0100 Subject: [PATCH 095/139] fix: rename the imported files --- pyccel/codegen/printing/ccode.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index d4c36a9cd9..8d7148fcdc 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -800,10 +800,24 @@ def _print_ModuleHeader(self, expr): {classes}\n \ {funcs}\n \ #endif // {name}_H\n") + + def rename_imported_methods(self, expr): + if expr.source_module and expr.source_module is not self._current_module: + for classDef in expr.source_module.classes: + class_scope = classDef.scope + for method in classDef.methods: + if not method.is_inline: + class_scope.rename_function(method, f"{classDef.name}__{method.name.lstrip('__')}") + for interface in classDef.interfaces: + for func in interface.functions: + if not func.is_inline: + class_scope.rename_function(func, f"{classDef.name}__{func.name.lstrip('__')}") def _print_Module(self, expr): self.set_scope(expr.scope) self._current_module = expr + for item in expr.imports: + self.rename_imported_methods(item) for classDef in expr.classes: class_scope = classDef.scope for method in classDef.methods: @@ -972,16 +986,6 @@ def _print_Import(self, expr): if source in import_dict: # pylint: disable=consider-using-get source = import_dict[source] - if expr.source_module and expr.source_module is not self._current_module: - for classDef in expr.source_module.classes: - class_scope = classDef.scope - for method in classDef.methods: - if not method.is_inline: - class_scope.rename_function(method, f"{classDef.name}__{method.name.lstrip('__')}") - for interface in classDef.interfaces: - for func in interface.functions: - if not func.is_inline: - class_scope.rename_function(func, f"{classDef.name}__{func.name.lstrip('__')}") if source is None: return '' From 8ddba14448a38511654908f7bb169c97a2d9e41d Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Tue, 4 Jun 2024 15:57:24 +0100 Subject: [PATCH 096/139] chore: fix trailing whitespaces and empty lines --- pyccel/codegen/pipeline.py | 1 - pyccel/codegen/printing/ccode.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pyccel/codegen/pipeline.py b/pyccel/codegen/pipeline.py index 00a35602d3..305f0a9fba 100644 --- a/pyccel/codegen/pipeline.py +++ b/pyccel/codegen/pipeline.py @@ -337,7 +337,6 @@ def handle_error(stage): # Iterate over the external_libs list and determine if the printer # requires an external lib to be included. - if [key for key in codegen.get_printer_imports() if key.startswith('stc')] : lib_dest_path = copy_internal_library('stc', pyccel_dirpath) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 8d7148fcdc..e3683b84c4 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -800,7 +800,7 @@ def _print_ModuleHeader(self, expr): {classes}\n \ {funcs}\n \ #endif // {name}_H\n") - + def rename_imported_methods(self, expr): if expr.source_module and expr.source_module is not self._current_module: for classDef in expr.source_module.classes: From 700f254dba27d5496e5a9719b122e6b6a12162e0 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Tue, 4 Jun 2024 18:25:19 +0100 Subject: [PATCH 097/139] fix: Lists wrapping issues --- .../codegen/wrapper/fortran_to_c_wrapper.py | 5 +++- tests/epyccel/test_epyccel_modules.py | 27 +++++++++++-------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/pyccel/codegen/wrapper/fortran_to_c_wrapper.py b/pyccel/codegen/wrapper/fortran_to_c_wrapper.py index 6bea034128..c27f6dbe1c 100644 --- a/pyccel/codegen/wrapper/fortran_to_c_wrapper.py +++ b/pyccel/codegen/wrapper/fortran_to_c_wrapper.py @@ -22,6 +22,7 @@ from pyccel.ast.literals import LiteralInteger, Nil, LiteralTrue from pyccel.ast.operators import PyccelIsNot, PyccelMul from pyccel.ast.variable import Variable, IndexedElement, DottedVariable +from pyccel.ast.numpyext import NumpyNDArrayType from pyccel.parser.scope import Scope from .wrapper import Wrapper @@ -451,7 +452,7 @@ def _wrap_Variable(self, expr): """ if isinstance(expr.class_type, FixedSizeNumericType): return expr.clone(expr.name, new_class = BindCVariable) - else: + elif isinstance(expr.class_type, NumpyNDArrayType): scope = self.scope func_name = scope.get_new_name('bind_c_'+expr.name.lower()) func_scope = scope.new_child_scope(func_name) @@ -483,6 +484,8 @@ def _wrap_Variable(self, expr): original_function = expr) return expr.clone(expr.name, new_class = BindCArrayVariable, wrapper_function = func, original_variable = expr) + else: + raise NotImplementedError("Lists cannot be wrapped yet") def _wrap_DottedVariable(self, expr): """ diff --git a/tests/epyccel/test_epyccel_modules.py b/tests/epyccel/test_epyccel_modules.py index 2241c8aea8..b4cca5abaf 100644 --- a/tests/epyccel/test_epyccel_modules.py +++ b/tests/epyccel/test_epyccel_modules.py @@ -130,15 +130,6 @@ def test_module_6(language): assert mod_att == modnew_att assert type(mod_att) is type(modnew_att) -@pytest.mark.parametrize( 'language', ( - pytest.param("fortran", marks = pytest.mark.fortran), - pytest.param("c", marks = [ - pytest.mark.xfail(reason="List indexing is not yet supported in C"), - pytest.mark.c] - ), - pytest.param("python", marks = pytest.mark.python) - ) -) def test_module_7(language): import modules.array_consts as mod @@ -151,8 +142,6 @@ def test_module_7(language): assert np.array_equal(mod_att, modnew_att) assert mod_att.dtype == modnew_att.dtype - assert np.array_equal(mod.F, modnew.F) - modnew.update_a() mod.update_a() @@ -181,6 +170,22 @@ def test_module_7(language): mod.reset_c() mod.reset_e() +@pytest.mark.parametrize( 'language', ( + pytest.param("fortran", marks = pytest.mark.fortran), + pytest.param("c", marks = [ + pytest.mark.xfail(reason="List indexing is not yet supported in C"), + pytest.mark.c] + ), + pytest.param("python", marks = pytest.mark.python) + ) +) +def test_module_8(language): + import modules.array_consts as mod + + modnew = epyccel(mod, language=language) + + assert np.array_equal(mod.F, modnew.F) + def test_awkward_names(language): import modules.awkward_names as mod From c7d76e82338d1550d4d4095f1b0adbdf8c96573e Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Tue, 4 Jun 2024 18:50:33 +0100 Subject: [PATCH 098/139] fix: comprehension list test in a different module --- tests/epyccel/modules/array_consts.py | 1 - tests/epyccel/modules/list_comprehension.py | 3 +++ tests/epyccel/test_epyccel_modules.py | 7 +++++-- 3 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 tests/epyccel/modules/list_comprehension.py diff --git a/tests/epyccel/modules/array_consts.py b/tests/epyccel/modules/array_consts.py index 157b9e6549..8e38031f57 100644 --- a/tests/epyccel/modules/array_consts.py +++ b/tests/epyccel/modules/array_consts.py @@ -6,7 +6,6 @@ c = np.zeros((2,3), dtype=np.int32) d = np.array([1+2j, 3+4j]) e = np.empty((2,3,4)) -F = [False for _ in range(5)] def update_a(): a[:] = a+1 diff --git a/tests/epyccel/modules/list_comprehension.py b/tests/epyccel/modules/list_comprehension.py new file mode 100644 index 0000000000..7f85accec0 --- /dev/null +++ b/tests/epyccel/modules/list_comprehension.py @@ -0,0 +1,3 @@ +# pylint: disable=missing-function-docstring, missing-module-docstring + +F = [False for _ in range(5)] \ No newline at end of file diff --git a/tests/epyccel/test_epyccel_modules.py b/tests/epyccel/test_epyccel_modules.py index b4cca5abaf..74049bd172 100644 --- a/tests/epyccel/test_epyccel_modules.py +++ b/tests/epyccel/test_epyccel_modules.py @@ -171,7 +171,10 @@ def test_module_7(language): mod.reset_e() @pytest.mark.parametrize( 'language', ( - pytest.param("fortran", marks = pytest.mark.fortran), + pytest.param("fortran", marks = [ + pytest.mark.xfail(reason="List wrapper is not implemented yet."), + pytest.mark.fortran] + ), pytest.param("c", marks = [ pytest.mark.xfail(reason="List indexing is not yet supported in C"), pytest.mark.c] @@ -180,7 +183,7 @@ def test_module_7(language): ) ) def test_module_8(language): - import modules.array_consts as mod + import modules.list_comprehension as mod modnew = epyccel(mod, language=language) From 55d03e634f20fb35f60dd50c0848471f036234ef Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Tue, 4 Jun 2024 23:23:05 +0100 Subject: [PATCH 099/139] chore: add docstring for rename_imported_methods function --- pyccel/codegen/printing/ccode.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index e3683b84c4..9f5bc981e9 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -802,7 +802,19 @@ def _print_ModuleHeader(self, expr): #endif // {name}_H\n") def rename_imported_methods(self, expr): - if expr.source_module and expr.source_module is not self._current_module: + """ + Rename Imported Methods. + + This function is responsible for renaming methods of classes from + the imported modules, ensuring that the names are correct + by prefixing them with their class names. + + Parameters + ---------- + expr : Import + The import found in the module being renamed. + """ + if expr.source_module and expr.source_module is not self._current_module: for classDef in expr.source_module.classes: class_scope = classDef.scope for method in classDef.methods: From 1c2a51a5efc97eec5e5df4291babfc51b749049e Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Tue, 4 Jun 2024 23:24:22 +0100 Subject: [PATCH 100/139] trailing whitespace --- pyccel/codegen/printing/ccode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 9f5bc981e9..cce66ce539 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -830,7 +830,7 @@ def _print_Module(self, expr): self._current_module = expr for item in expr.imports: self.rename_imported_methods(item) - for classDef in expr.classes: + for classDef in expr.classes: class_scope = classDef.scope for method in classDef.methods: if not method.is_inline: From 758de515081ba7f6b2291ef6363793256834fbaa Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Tue, 4 Jun 2024 23:25:54 +0100 Subject: [PATCH 101/139] final newline --- tests/epyccel/modules/list_comprehension.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/epyccel/modules/list_comprehension.py b/tests/epyccel/modules/list_comprehension.py index 7f85accec0..5ae972da9a 100644 --- a/tests/epyccel/modules/list_comprehension.py +++ b/tests/epyccel/modules/list_comprehension.py @@ -1,3 +1,4 @@ # pylint: disable=missing-function-docstring, missing-module-docstring -F = [False for _ in range(5)] \ No newline at end of file +F = [False for _ in range(5)] + From 98967292141cfa853b1b8ea5c4dec35334210dc9 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Wed, 5 Jun 2024 17:15:31 +0100 Subject: [PATCH 102/139] enhance: map external libs to their path to avoid static lookup --- pyccel/codegen/pipeline.py | 7 +++++-- pyccel/codegen/utilities.py | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/pyccel/codegen/pipeline.py b/pyccel/codegen/pipeline.py index 305f0a9fba..c0f8634e03 100644 --- a/pyccel/codegen/pipeline.py +++ b/pyccel/codegen/pipeline.py @@ -21,6 +21,7 @@ from pyccel.codegen.utilities import recompile_object from pyccel.codegen.utilities import copy_internal_library from pyccel.codegen.utilities import internal_libs +from pyccel.codegen.utilities import external_libs from pyccel.codegen.python_wrapper import create_shared_library from pyccel.naming import name_clash_checkers from pyccel.utilities.stage import PyccelStage @@ -337,8 +338,10 @@ def handle_error(stage): # Iterate over the external_libs list and determine if the printer # requires an external lib to be included. - if [key for key in codegen.get_printer_imports() if key.startswith('stc')] : - lib_dest_path = copy_internal_library('stc', pyccel_dirpath) + for key in codegen.get_printer_imports(): + lib_name = key.split("/", 1)[0] + if lib_name in external_libs: + lib_dest_path = copy_internal_library(lib_name, pyccel_dirpath) if convert_only: # Change working directory back to starting point diff --git a/pyccel/codegen/utilities.py b/pyccel/codegen/utilities.py index 3cb8417fee..ceffc483e3 100644 --- a/pyccel/codegen/utilities.py +++ b/pyccel/codegen/utilities.py @@ -27,6 +27,9 @@ #============================================================================== language_extension = {'fortran':'f90', 'c':'c', 'python':'py'} +#============================================================================== +# map external libraries inside pyccel/extensions with their path +external_libs = {"stc" : "STC/include"} #============================================================================== # map internal libraries to their folders inside pyccel/stdlib and their compile objects @@ -107,8 +110,8 @@ def copy_internal_library(lib_folder, pyccel_dirpath, extra_files = None): The location that the files were copied to. """ # get lib path (stdlib_path/lib_name or ext_path/lib_name) - if lib_folder == "stc": - lib_path = os.path.join(ext_path, "STC", "include", lib_folder) + if lib_folder in external_libs: + lib_path = os.path.join(ext_path, external_libs[lib_folder], lib_folder) else: lib_path = os.path.join(stdlib_path, lib_folder) From e4c4f3ad7d567b8beb0c147c28f2a04b7f3ba34f Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Wed, 5 Jun 2024 17:18:50 +0100 Subject: [PATCH 103/139] deprecated: import_stc map is no longer used --- pyccel/codegen/printing/ccode.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index cce66ce539..c17d5ddf23 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -225,10 +225,6 @@ import_dict = {'omp_lib' : 'omp' } -import_stc = {'hset' : 'SET', - 'vec' : 'VEC' - } - c_imports = {n : Import(n, Module(n, (), ())) for n in ['stdlib', 'math', From 296ca4e2ad0d07effc7402f327d7087e964b1224 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Wed, 5 Jun 2024 17:39:53 +0100 Subject: [PATCH 104/139] update wrapper error message --- pyccel/codegen/wrapper/fortran_to_c_wrapper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyccel/codegen/wrapper/fortran_to_c_wrapper.py b/pyccel/codegen/wrapper/fortran_to_c_wrapper.py index c27f6dbe1c..b042c8aa9d 100644 --- a/pyccel/codegen/wrapper/fortran_to_c_wrapper.py +++ b/pyccel/codegen/wrapper/fortran_to_c_wrapper.py @@ -485,7 +485,7 @@ def _wrap_Variable(self, expr): return expr.clone(expr.name, new_class = BindCArrayVariable, wrapper_function = func, original_variable = expr) else: - raise NotImplementedError("Lists cannot be wrapped yet") + raise NotImplementedError("Containers cannot be wrapped yet") def _wrap_DottedVariable(self, expr): """ From 378ade635b72a58c302931e7c76ddc2f16d4f3c6 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Wed, 5 Jun 2024 17:42:21 +0100 Subject: [PATCH 105/139] test case for list comprehensions will start in alphabetic order --- tests/epyccel/modules/list_comprehension.py | 2 +- tests/epyccel/test_epyccel_modules.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/epyccel/modules/list_comprehension.py b/tests/epyccel/modules/list_comprehension.py index 5ae972da9a..13585fb048 100644 --- a/tests/epyccel/modules/list_comprehension.py +++ b/tests/epyccel/modules/list_comprehension.py @@ -1,4 +1,4 @@ # pylint: disable=missing-function-docstring, missing-module-docstring -F = [False for _ in range(5)] +A = [False for _ in range(5)] diff --git a/tests/epyccel/test_epyccel_modules.py b/tests/epyccel/test_epyccel_modules.py index 74049bd172..9c2c9226a1 100644 --- a/tests/epyccel/test_epyccel_modules.py +++ b/tests/epyccel/test_epyccel_modules.py @@ -187,7 +187,7 @@ def test_module_8(language): modnew = epyccel(mod, language=language) - assert np.array_equal(mod.F, modnew.F) + assert np.array_equal(mod.A, modnew.A) def test_awkward_names(language): import modules.awkward_names as mod From 749d5e524ccfb0319f0372cbe3d9cd7404eae994 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Thu, 6 Jun 2024 11:50:38 +0100 Subject: [PATCH 106/139] rename function that initializes stc containers --- pyccel/codegen/printing/ccode.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index c17d5ddf23..d75f57ece4 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -2010,7 +2010,7 @@ def _print_FunctionCall(self, expr): else: return call_code - def init_lists_or_sets(self, expr, container_var): + def init_stc_container(self, expr, container_var): """ Generate the initialization of an STC container in C. @@ -2178,7 +2178,7 @@ def _print_Assign(self, expr): return prefix_code+self.arrayFill(expr) lhs = self._print(expr.lhs) if isinstance(rhs, (PythonList, PythonSet)): - return prefix_code+self.init_lists_or_sets(rhs, expr) + return prefix_code+self.init_stc_container(rhs, expr) rhs = self._print(expr.rhs) return prefix_code+'{} = {};\n'.format(lhs, rhs) From 4196bcdf994a6bb756c8c27ba40788155b41f96f Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Thu, 6 Jun 2024 12:43:48 +0100 Subject: [PATCH 107/139] fix: raise an error from the codegen stage to handle the generic assignment case --- pyccel/codegen/printing/ccode.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index d75f57ece4..aec8746e6f 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -1195,8 +1195,7 @@ def find_in_dtype_registry(self, dtype): key = (primitive_type, dtype.precision) elif isinstance(dtype, (HomogeneousSetType, HomogeneousListType)): container_type = 'hset_' if dtype.name == 'set' else 'vec_' - if not isinstance(dtype.element_type, GenericType): - vec_dtype = self.find_in_dtype_registry(dtype.element_type) + vec_dtype = self.find_in_dtype_registry(dtype.element_type) i_type = container_type + vec_dtype.replace(' ', '_') self.add_import(Import('stc/' + i_type + "/" + vec_dtype, Module('stc/' + i_type, (), ()))) return i_type From 941703584992ce6d99ca196ee146ef23b29e7065 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Thu, 6 Jun 2024 18:01:22 +0100 Subject: [PATCH 108/139] fix: separate between ndarrays and the rest of the containers --- pyccel/codegen/printing/ccode.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index aec8746e6f..fd440fafa3 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -1274,14 +1274,15 @@ def get_declare_type(self, expr): rank = expr.rank if rank > 0: - if expr.is_ndarray or isinstance(expr.class_type, HomogeneousContainerType): - if expr.rank > 15: + if isinstance(class_type, NumpyNDArrayType): + if rank > 15: errors.report(UNSUPPORTED_ARRAY_RANK, symbol=expr, severity='fatal') - if isinstance(expr.class_type, (HomogeneousSetType, HomogeneousListType)): - dtype = self.find_in_dtype_registry(expr.class_type) return dtype self.add_import(c_imports['ndarrays']) dtype = 't_ndarray' + elif isinstance(class_type, (HomogeneousSetType, HomogeneousListType)): + dtype = self.find_in_dtype_registry(expr.class_type) + return dtype else: errors.report(PYCCEL_RESTRICTION_TODO+' (rank>0)', symbol=expr, severity='fatal') elif not isinstance(class_type, CustomDataType): From c7d984cc6fc3ffbb26a030a3e7562eb212872497 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Thu, 6 Jun 2024 18:17:02 +0100 Subject: [PATCH 109/139] fix: update error message in wrapper --- pyccel/codegen/wrapper/fortran_to_c_wrapper.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyccel/codegen/wrapper/fortran_to_c_wrapper.py b/pyccel/codegen/wrapper/fortran_to_c_wrapper.py index b042c8aa9d..e2eb760d9d 100644 --- a/pyccel/codegen/wrapper/fortran_to_c_wrapper.py +++ b/pyccel/codegen/wrapper/fortran_to_c_wrapper.py @@ -485,8 +485,7 @@ def _wrap_Variable(self, expr): return expr.clone(expr.name, new_class = BindCArrayVariable, wrapper_function = func, original_variable = expr) else: - raise NotImplementedError("Containers cannot be wrapped yet") - + raise NotImplementedError(f"Objects of type {expr.class_type} cannot be wrapped yet") def _wrap_DottedVariable(self, expr): """ Create all objects necessary to expose a class attribute to C. From 32cbe9660d35bb49f558bfae31982315fbd4f8d0 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Thu, 6 Jun 2024 18:20:18 +0100 Subject: [PATCH 110/139] fix: update error message in wrapper --- pyccel/codegen/wrapper/fortran_to_c_wrapper.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyccel/codegen/wrapper/fortran_to_c_wrapper.py b/pyccel/codegen/wrapper/fortran_to_c_wrapper.py index b042c8aa9d..e2eb760d9d 100644 --- a/pyccel/codegen/wrapper/fortran_to_c_wrapper.py +++ b/pyccel/codegen/wrapper/fortran_to_c_wrapper.py @@ -485,8 +485,7 @@ def _wrap_Variable(self, expr): return expr.clone(expr.name, new_class = BindCArrayVariable, wrapper_function = func, original_variable = expr) else: - raise NotImplementedError("Containers cannot be wrapped yet") - + raise NotImplementedError(f"Objects of type {expr.class_type} cannot be wrapped yet") def _wrap_DottedVariable(self, expr): """ Create all objects necessary to expose a class attribute to C. From 9872a5b3c8f24ec251ca34db38b8355bef29af4a Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Thu, 6 Jun 2024 18:20:58 +0100 Subject: [PATCH 111/139] fix: update error message in wrapper --- pyccel/codegen/wrapper/fortran_to_c_wrapper.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pyccel/codegen/wrapper/fortran_to_c_wrapper.py b/pyccel/codegen/wrapper/fortran_to_c_wrapper.py index e2eb760d9d..e0e1ccd7df 100644 --- a/pyccel/codegen/wrapper/fortran_to_c_wrapper.py +++ b/pyccel/codegen/wrapper/fortran_to_c_wrapper.py @@ -486,6 +486,7 @@ def _wrap_Variable(self, expr): original_variable = expr) else: raise NotImplementedError(f"Objects of type {expr.class_type} cannot be wrapped yet") + def _wrap_DottedVariable(self, expr): """ Create all objects necessary to expose a class attribute to C. From 674da248f4a75a0847b88d71a5a8513304ef1c57 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 7 Jun 2024 12:13:32 +0100 Subject: [PATCH 112/139] update changelog --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f20f8246d7..8998a0eb01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,9 @@ All notable changes to this project will be documented in this file. - #1844 : Add line numbers and code to errors from built-in function calls. - \[INTERNALS\] Added `container_rank` property to `ast.datatypes.PyccelType` objects. - \[DEVELOPER\] Added an improved traceback to the developer-mode errors for errors in function calls. -- #1847 : Support `list()` and `set()` declarations in c. +- #1655 : \[LISTS\] Support variable declarations in C +- #1659 : \[SETS\] Support variable declarations in C + ### Fixed - #1720 : Fix Undefined Variable error when the function definition is after the variable declaration. From c865d8effdfb8026e976709a10d9249c60120848 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 7 Jun 2024 13:07:57 +0100 Subject: [PATCH 113/139] avoid code duplication by grouping the renaming proccess of class methods in a separate function --- pyccel/codegen/printing/ccode.py | 60 ++++++++++++++------------------ 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index fd440fafa3..18135ba91a 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -645,6 +645,29 @@ def _handle_inline_func_call(self, expr): return code + def rename_imported_methods(self, expr): + """ + Rename class methods from user-defined imports. + + This function is responsible for renaming methods of classes from + the imported modules, ensuring that the names are correct + by prefixing them with their class names. + + Parameters + ---------- + expr : Tuple of ClassDef objects + The ClassDef objects found in the module being renamed. + """ + for classDef in expr: + class_scope = classDef.scope + for method in classDef.methods: + if not method.is_inline: + class_scope.rename_function(method, f"{classDef.name}__{method.name.lstrip('__')}") + for interface in classDef.interfaces: + for func in interface.functions: + if not func.is_inline: + class_scope.rename_function(func, f"{classDef.name}__{func.name.lstrip('__')}") + # ============ Elements ============ # def _print_PythonAbs(self, expr): @@ -797,44 +820,13 @@ def _print_ModuleHeader(self, expr): {funcs}\n \ #endif // {name}_H\n") - def rename_imported_methods(self, expr): - """ - Rename Imported Methods. - - This function is responsible for renaming methods of classes from - the imported modules, ensuring that the names are correct - by prefixing them with their class names. - - Parameters - ---------- - expr : Import - The import found in the module being renamed. - """ - if expr.source_module and expr.source_module is not self._current_module: - for classDef in expr.source_module.classes: - class_scope = classDef.scope - for method in classDef.methods: - if not method.is_inline: - class_scope.rename_function(method, f"{classDef.name}__{method.name.lstrip('__')}") - for interface in classDef.interfaces: - for func in interface.functions: - if not func.is_inline: - class_scope.rename_function(func, f"{classDef.name}__{func.name.lstrip('__')}") - def _print_Module(self, expr): self.set_scope(expr.scope) self._current_module = expr for item in expr.imports: - self.rename_imported_methods(item) - for classDef in expr.classes: - class_scope = classDef.scope - for method in classDef.methods: - if not method.is_inline: - class_scope.rename_function(method, f"{classDef.name}__{method.name.lstrip('__')}") - for interface in classDef.interfaces: - for func in interface.functions: - if not func.is_inline: - class_scope.rename_function(func, f"{classDef.name}__{func.name.lstrip('__')}") + if item.source_module and item.source_module is not self._current_module: + self.rename_imported_methods(item.source_module.classes) + self.rename_imported_methods(expr.classes) body = ''.join(self._print(i) for i in expr.body) global_variables = ''.join([self._print(d) for d in expr.declarations]) From d0c218b344206f673c1a4977a25b9b16d806d227 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 7 Jun 2024 15:27:46 +0100 Subject: [PATCH 114/139] getter property to retrieve the name of a pyccel type --- pyccel/ast/datatypes.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pyccel/ast/datatypes.py b/pyccel/ast/datatypes.py index 475946794a..0eb7f94d52 100644 --- a/pyccel/ast/datatypes.py +++ b/pyccel/ast/datatypes.py @@ -149,6 +149,16 @@ class PyccelType: is expected when calling a bitwise comparison operator on objects of these types. """ __slots__ = () + _name = None + + @property + def name(self): + """ + Get the name of the pyccel type. + + Get the name of the pyccel type. + """ + return self._name def __init__(self): #pylint: disable=useless-parent-delegation # This __init__ function is required so the ArgumentSingleton can @@ -488,16 +498,6 @@ class HomogeneousContainerType(ContainerType): This is the case for objects such as arrays, lists, etc. """ __slots__ = () - _name = None - - @property - def name(self): - """ - Get the name of the container. - - Get the name of the container. - """ - return self._name @property def datatype(self): From 1e988678f8492fd1644c474e3e00752bed29dd39 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 7 Jun 2024 15:32:56 +0100 Subject: [PATCH 115/139] fix bad indentation --- pyccel/codegen/printing/ccode.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 18135ba91a..2c4f54ba94 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -660,13 +660,13 @@ def rename_imported_methods(self, expr): """ for classDef in expr: class_scope = classDef.scope - for method in classDef.methods: - if not method.is_inline: - class_scope.rename_function(method, f"{classDef.name}__{method.name.lstrip('__')}") - for interface in classDef.interfaces: - for func in interface.functions: - if not func.is_inline: - class_scope.rename_function(func, f"{classDef.name}__{func.name.lstrip('__')}") + for method in classDef.methods: + if not method.is_inline: + class_scope.rename_function(method, f"{classDef.name}__{method.name.lstrip('__')}") + for interface in classDef.interfaces: + for func in interface.functions: + if not func.is_inline: + class_scope.rename_function(func, f"{classDef.name}__{func.name.lstrip('__')}") # ============ Elements ============ # From 3765e6bfd2f42030cc39869a0ee343afc8913578 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 7 Jun 2024 15:39:57 +0100 Subject: [PATCH 116/139] update issue description in changelog --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8998a0eb01..a5cdb7e463 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,10 +19,10 @@ All notable changes to this project will be documented in this file. - #1787 : Ensure `STC` is installed with Pyccel. - #1656 : Ensure `gFTL` is installed with Pyccel. - #1844 : Add line numbers and code to errors from built-in function calls. +- #1655 : Add the appropriate C language equivalent for declaring a Python `list` container using the `STC` library. +- #1659 : Add the appropriate C language equivalent for declaring a Python `set` container using the `STC` library. - \[INTERNALS\] Added `container_rank` property to `ast.datatypes.PyccelType` objects. - \[DEVELOPER\] Added an improved traceback to the developer-mode errors for errors in function calls. -- #1655 : \[LISTS\] Support variable declarations in C -- #1659 : \[SETS\] Support variable declarations in C ### Fixed From 262e3036e7bd48596c9f291dd0982c6d31615a0c Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 7 Jun 2024 15:46:32 +0100 Subject: [PATCH 117/139] element_type instead of vec_dtype --- pyccel/codegen/printing/ccode.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 2c4f54ba94..93f572caf0 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -1187,9 +1187,9 @@ def find_in_dtype_registry(self, dtype): key = (primitive_type, dtype.precision) elif isinstance(dtype, (HomogeneousSetType, HomogeneousListType)): container_type = 'hset_' if dtype.name == 'set' else 'vec_' - vec_dtype = self.find_in_dtype_registry(dtype.element_type) - i_type = container_type + vec_dtype.replace(' ', '_') - self.add_import(Import('stc/' + i_type + "/" + vec_dtype, Module('stc/' + i_type, (), ()))) + element_type = self.find_in_dtype_registry(dtype.element_type) + i_type = container_type + element_type.replace(' ', '_') + self.add_import(Import('stc/' + i_type + "/" + element_type, Module('stc/' + i_type, (), ()))) return i_type else: key = dtype From cc73b94c306a4196c448739af85245460364d550 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 7 Jun 2024 15:50:23 +0100 Subject: [PATCH 118/139] use of f-string --- pyccel/codegen/printing/ccode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 93f572caf0..8e77f9eb3a 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -1189,7 +1189,7 @@ def find_in_dtype_registry(self, dtype): container_type = 'hset_' if dtype.name == 'set' else 'vec_' element_type = self.find_in_dtype_registry(dtype.element_type) i_type = container_type + element_type.replace(' ', '_') - self.add_import(Import('stc/' + i_type + "/" + element_type, Module('stc/' + i_type, (), ()))) + self.add_import(Import(f'stc/{i_type}/{element_type}', Module(f'stc/{i_type}', (), ()))) return i_type else: key = dtype From 8defc5825cca506717b7774377d960fb8067e661 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 7 Jun 2024 17:14:36 +0100 Subject: [PATCH 119/139] can't return dtype after fatal error --- pyccel/codegen/printing/ccode.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 8e77f9eb3a..344f6b7271 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -1269,7 +1269,6 @@ def get_declare_type(self, expr): if isinstance(class_type, NumpyNDArrayType): if rank > 15: errors.report(UNSUPPORTED_ARRAY_RANK, symbol=expr, severity='fatal') - return dtype self.add_import(c_imports['ndarrays']) dtype = 't_ndarray' elif isinstance(class_type, (HomogeneousSetType, HomogeneousListType)): From e620bc4552e3560084f6115b353e6919a959d655 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 7 Jun 2024 18:09:17 +0100 Subject: [PATCH 120/139] generalize the use of find_in_type_registry --- pyccel/codegen/printing/ccode.py | 63 +++++++++++++++++++------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 344f6b7271..c386fed4cd 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -403,7 +403,7 @@ def copy_NumpyArray_Data(self, expr): order = lhs.order lhs_dtype = lhs.dtype - declare_dtype = self.find_in_dtype_registry(lhs_dtype) + declare_dtype = self.find_in_type_registry(lhs_dtype) if isinstance(lhs.class_type, NumpyNDArrayType): #set dtype to the C struct types dtype = self.find_in_ndarray_type_registry(lhs_dtype) @@ -496,7 +496,7 @@ def arrayFill(self, expr): rhs = expr.rhs lhs = expr.lhs code_init = '' - declare_dtype = self.find_in_dtype_registry(rhs.dtype) + declare_dtype = self.find_in_type_registry(rhs.dtype) if rhs.fill_value is not None: if isinstance(rhs.fill_value, Literal): @@ -524,7 +524,7 @@ def _init_stack_array(self, expr): String containing the rhs of the initialization of a stack array. """ var = expr - dtype = self.find_in_dtype_registry(var.dtype) + dtype = self.find_in_type_registry(var.dtype) if isinstance(var.class_type, NumpyNDArrayType): np_dtype = self.find_in_ndarray_type_registry(var.dtype) elif isinstance(var.class_type, HomogeneousContainerType): @@ -534,7 +534,7 @@ def _init_stack_array(self, expr): shape = ", ".join(self._print(i) for i in var.alloc_shape) tot_shape = self._print(functools.reduce( lambda x,y: PyccelMul(x,y,simplify=True), var.alloc_shape)) - declare_dtype = self.find_in_dtype_registry(NumpyInt64Type()) + declare_dtype = self.find_in_type_registry(NumpyInt64Type()) dummy_array_name = self.scope.get_new_name('array_dummy') buffer_array = "{dtype} {name}[{size}];\n".format( @@ -730,13 +730,13 @@ def _print_SysExit(self, expr): def _print_PythonFloat(self, expr): value = self._print(expr.arg) - type_name = self.find_in_dtype_registry(expr.dtype) + type_name = self.find_in_type_registry(expr.dtype) return '({0})({1})'.format(type_name, value) def _print_PythonInt(self, expr): self.add_import(c_imports['stdint']) value = self._print(expr.arg) - type_name = self.find_in_dtype_registry(expr.dtype) + type_name = self.find_in_type_registry(expr.dtype) return '({0})({1})'.format(type_name, value) def _print_PythonBool(self, expr): @@ -770,7 +770,7 @@ def _print_PythonComplex(self, expr): else: value = self._print(PyccelAssociativeParenthesis(PyccelAdd(expr.real, PyccelMul(expr.imag, LiteralImaginaryUnit())))) - type_name = self.find_in_dtype_registry(expr.dtype) + type_name = self.find_in_type_registry(expr.dtype) return '({0})({1})'.format(type_name, value) def _print_LiteralImaginaryUnit(self, expr): @@ -1156,28 +1156,38 @@ def formatted_args_to_printf(args_format, args, end): code += formatted_args_to_printf(args_format, args, end) return code - def find_in_dtype_registry(self, dtype): + def find_in_type_registry(self, dtype): """ - Find the corresponding C dtype in the dtype_registry. + Find the corresponding C dtype in the dtype_registry or the STC container type. - Find the corresponding C dtype in the dtype_registry. - Raise PYCCEL_RESTRICTION_TODO if not found. + This function searches for the corresponding C data type in the `dtype_registry`. + If the provided dtype is a container (like `HomogeneousSetType` or + `HomogeneousListType`), it identifies the scalar type of the container and returns + the appropriate type for the `STC` container. + It raises a `PYCCEL_RESTRICTION_TODO` error if the dtype is not found in the registry. Parameters ---------- - dtype : DataType - The data type of the expression. + dtype : DataType or ContainerType + The data type of the expression. This can be a fixed-size numeric type, + a primitive type, or a container type. Returns ------- str - The code which declares the datatype in C. + The code which declares the data type in C or the corresponding `STC` container + type. + + Raises + ------ + PYCCEL_RESTRICTION_TODO + If the dtype is not found in the dtype_registry. """ if isinstance(dtype, FixedSizeNumericType): primitive_type = dtype.primitive_type if isinstance(primitive_type, PrimitiveComplexType): self.add_import(c_imports['complex']) - return f'{self.find_in_dtype_registry(dtype.element_type)} complex' + return f'{self.find_in_type_registry(dtype.element_type)} complex' elif isinstance(primitive_type, PrimitiveIntegerType): self.add_import(c_imports['stdint']) elif isinstance(dtype, PythonNativeBool): @@ -1187,7 +1197,7 @@ def find_in_dtype_registry(self, dtype): key = (primitive_type, dtype.precision) elif isinstance(dtype, (HomogeneousSetType, HomogeneousListType)): container_type = 'hset_' if dtype.name == 'set' else 'vec_' - element_type = self.find_in_dtype_registry(dtype.element_type) + element_type = self.find_in_type_registry(dtype.element_type) i_type = container_type + element_type.replace(' ', '_') self.add_import(Import(f'stc/{i_type}/{element_type}', Module(f'stc/{i_type}', (), ()))) return i_type @@ -1201,6 +1211,7 @@ def find_in_dtype_registry(self, dtype): symbol = dtype, severity='fatal') + def find_in_ndarray_type_registry(self, dtype): """ Find the descriptor for the datatype in the ndarray_type_registry. @@ -1272,12 +1283,12 @@ def get_declare_type(self, expr): self.add_import(c_imports['ndarrays']) dtype = 't_ndarray' elif isinstance(class_type, (HomogeneousSetType, HomogeneousListType)): - dtype = self.find_in_dtype_registry(expr.class_type) + dtype = self.find_in_type_registry(expr.class_type) return dtype else: errors.report(PYCCEL_RESTRICTION_TODO+' (rank>0)', symbol=expr, severity='fatal') elif not isinstance(class_type, CustomDataType): - dtype = self.find_in_dtype_registry(expr.dtype) + dtype = self.find_in_type_registry(expr.dtype) else: dtype = self._print(expr.class_type) @@ -1361,11 +1372,11 @@ def function_signature(self, expr, print_arg_names = True): if n_results == 1: ret_type = self.get_declare_type(result_vars[0]) elif n_results > 1: - ret_type = self.find_in_dtype_registry(PythonNativeInt()) + ret_type = self.find_in_type_registry(PythonNativeInt()) arg_vars.extend(result_vars) self._additional_args.append(result_vars) # Ensure correct result for is_c_pointer else: - ret_type = self.find_in_dtype_registry(VoidType()) + ret_type = self.find_in_type_registry(VoidType()) name = expr.name if not arg_vars: @@ -1463,7 +1474,7 @@ def _cast_to(self, expr, dtype): after using this function. """ if expr.dtype != dtype: - cast=self.find_in_dtype_registry(dtype) + cast=self.find_in_type_registry(dtype) return '({}){{}}'.format(cast) return '{}' @@ -1575,7 +1586,7 @@ def _print_Allocate(self, expr): dtype = self.find_in_ndarray_type_registry(numpy_precision_map[(variable.dtype.primitive_type, variable.dtype.precision)]) else: raise NotImplementedError(f"Don't know how to index {variable.class_type} type") - shape_dtype = self.find_in_dtype_registry(NumpyInt64Type()) + shape_dtype = self.find_in_type_registry(NumpyInt64Type()) shape_Assign = "("+ shape_dtype +"[]){" + shape + "}" is_view = 'false' if variable.on_heap else 'true' order = "order_f" if expr.order == "F" else "order_c" @@ -1594,7 +1605,7 @@ def _print_Allocate(self, expr): def _print_Deallocate(self, expr): if isinstance(expr.variable.class_type, (HomogeneousListType, HomogeneousSetType)): variable_address = self._print(ObjectAddress(expr.variable)) - dtype = self.find_in_dtype_registry(expr.variable.class_type.element_type).replace(" ", "_") + dtype = self.find_in_type_registry(expr.variable.class_type.element_type).replace(" ", "_") container_type = "hset_"if isinstance(expr.variable.class_type, HomogeneousSetType) else "vec_" return f'{container_type}{dtype}_drop({variable_address});\n' if isinstance(expr.variable, InhomogeneousTupleVariable): @@ -1767,7 +1778,7 @@ def _print_MathFunctionBase(self, expr): args.append(self._print(arg)) code_args = ', '.join(args) if expr.dtype.primitive_type is PrimitiveIntegerType(): - cast_type = self.find_in_dtype_registry(expr.dtype) + cast_type = self.find_in_type_registry(expr.dtype) return f'({cast_type}){func_name}({code_args})' return f'{func_name}({code_args})' @@ -2021,7 +2032,7 @@ def init_stc_container(self, expr, container_var): The generated C code for the container initialization. """ - dtype = self.find_in_dtype_registry(container_var.lhs.class_type) + dtype = self.find_in_type_registry(container_var.lhs.class_type) keyraw = '{' + ', '.join([self._print(a) for a in expr.args]) + '}' init = f'{container_var.lhs.name} = c_init({dtype}, {keyraw});\n' return init @@ -2104,7 +2115,7 @@ def _print_PyccelFloorDiv(self, expr): code = ' / '.join(self._print(a if a.dtype.primitive_type is PrimitiveFloatingPointType() else NumpyFloat(a)) for a in expr.args) if (need_to_cast): - cast_type = self.find_in_dtype_registry(expr.dtype) + cast_type = self.find_in_type_registry(expr.dtype) return "({})floor({})".format(cast_type, code) return "floor({})".format(code) From 6d07beb104be5119e1efbe0bd6988fc3a2e1c423 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 7 Jun 2024 18:12:07 +0100 Subject: [PATCH 121/139] retrieve the correct stc container type for deallocation --- pyccel/codegen/printing/ccode.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index c386fed4cd..4c41fc7d73 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -1605,9 +1605,8 @@ def _print_Allocate(self, expr): def _print_Deallocate(self, expr): if isinstance(expr.variable.class_type, (HomogeneousListType, HomogeneousSetType)): variable_address = self._print(ObjectAddress(expr.variable)) - dtype = self.find_in_type_registry(expr.variable.class_type.element_type).replace(" ", "_") - container_type = "hset_"if isinstance(expr.variable.class_type, HomogeneousSetType) else "vec_" - return f'{container_type}{dtype}_drop({variable_address});\n' + container_type = self.find_in_type_registry(expr.variable.class_type) + return f'{container_type}_drop({variable_address});\n' if isinstance(expr.variable, InhomogeneousTupleVariable): return ''.join(self._print(Deallocate(v)) for v in expr.variable) variable_address = self._print(ObjectAddress(expr.variable)) From f9a7fb0c614fbe942b702149910043a43676e1f9 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 7 Jun 2024 18:20:11 +0100 Subject: [PATCH 122/139] using a generator expression instead of a list comprehension inside the join function to avoid unnecessary memory allocation --- pyccel/codegen/printing/ccode.py | 50 ++++++++++++++++---------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 4c41fc7d73..8c586d2ad7 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -645,6 +645,31 @@ def _handle_inline_func_call(self, expr): return code + def init_stc_container(self, expr, container_var): + """ + Generate the initialization of an STC container in C. + + This method generates and prints the C code for initializing a container using the STC `init()` method. + + Parameters + ---------- + expr : TypedAstNode + The object representing the container being printed (e.g., PythonList, PythonSet). + + container_var : str + The variable name to which the container is being assigned. + + Returns + ------- + str + The generated C code for the container initialization. + """ + + dtype = self.find_in_type_registry(container_var.lhs.class_type) + keyraw = '{' + ', '.join(self._print(a) for a in expr.args) + '}' + init = f'{container_var.lhs.name} = c_init({dtype}, {keyraw});\n' + return init + def rename_imported_methods(self, expr): """ Rename class methods from user-defined imports. @@ -2011,31 +2036,6 @@ def _print_FunctionCall(self, expr): else: return call_code - def init_stc_container(self, expr, container_var): - """ - Generate the initialization of an STC container in C. - - This method generates and prints the C code for initializing a container using the STC `init()` method. - - Parameters - ---------- - expr : TypedAstNode - The object representing the container being printed (e.g., PythonList, PythonSet). - - container_var : str - The variable name to which the container is being assigned. - - Returns - ------- - str - The generated C code for the container initialization. - """ - - dtype = self.find_in_type_registry(container_var.lhs.class_type) - keyraw = '{' + ', '.join([self._print(a) for a in expr.args]) + '}' - init = f'{container_var.lhs.name} = c_init({dtype}, {keyraw});\n' - return init - def _print_Return(self, expr): code = '' args = [ObjectAddress(a) if isinstance(a, Variable) and self.is_c_pointer(a) else a for a in expr.expr] From 16b721cd1158ba4f64b8050ce3a49d6d3cfb03ef Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 7 Jun 2024 19:19:34 +0100 Subject: [PATCH 123/139] fix: PythonSet removed from builtin_functions_dict --- pyccel/ast/builtins.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pyccel/ast/builtins.py b/pyccel/ast/builtins.py index 1f03d4b39b..1df3a2f92a 100644 --- a/pyccel/ast/builtins.py +++ b/pyccel/ast/builtins.py @@ -1262,7 +1262,6 @@ def print_string(self): 'min' : PythonMin, 'not' : PyccelNot, 'map' : PythonMap, - 'set' : PythonSet, 'str' : LiteralString, 'type' : PythonType, 'tuple' : PythonTupleFunction, From 38d214c4ea66a9a06b29bb66979c9f8ac116a853 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 7 Jun 2024 20:28:26 +0100 Subject: [PATCH 124/139] fix: use of __eq__ method to compare list and set objects --- pyccel/ast/datatypes.py | 19 +++++++++++++++++++ pyccel/parser/semantic.py | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/pyccel/ast/datatypes.py b/pyccel/ast/datatypes.py index 0eb7f94d52..4490f41392 100644 --- a/pyccel/ast/datatypes.py +++ b/pyccel/ast/datatypes.py @@ -442,6 +442,12 @@ class GenericType(FixedSizeType): @lru_cache def __add__(self, other): return other + + def __eq__(self, other): + return True + + def __hash__(self): + return hash(self.__class__) class SymbolicType(FixedSizeType): """ @@ -754,6 +760,13 @@ def __init__(self, element_type): self._element_type = element_type self._order = 'C' if (element_type.order == 'C' or element_type.rank == 1) else None super().__init__() + + def __eq__(self, other): + return isinstance(other, self.__class__) and self._element_type == other._element_type \ + and self._order == other._order + + def __hash__(self): + return hash((self.__class__, self._element_type, self._order)) class HomogeneousSetType(HomogeneousContainerType, metaclass = ArgumentSingleton): """ @@ -776,6 +789,12 @@ def __init__(self, element_type): assert isinstance(element_type, PyccelType) self._element_type = element_type super().__init__() + + def __eq__(self, other): + return isinstance(other, self.__class__) and self._element_type == other._element_type + + def __hash__(self): + return hash((self.__class__, self._element_type)) #============================================================================== diff --git a/pyccel/parser/semantic.py b/pyccel/parser/semantic.py index b550d85d41..e125a04600 100644 --- a/pyccel/parser/semantic.py +++ b/pyccel/parser/semantic.py @@ -1621,7 +1621,7 @@ def _ensure_inferred_type_matches_existing(self, class_type, d_var, var, is_auga # to remove memory leaks new_expressions.append(Deallocate(var)) - elif class_type != var.class_type and not isinstance(class_type.datatype, GenericType): + elif class_type != var.class_type: if is_augassign: tmp_result = PyccelAdd(var, rhs) result_type = tmp_result.class_type From 4bb4b5d1a02bfa682ee73217dbafb390f9f5a5d3 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 7 Jun 2024 20:33:01 +0100 Subject: [PATCH 125/139] chore: trailing whitespace --- pyccel/ast/datatypes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyccel/ast/datatypes.py b/pyccel/ast/datatypes.py index 4490f41392..8b2361ff00 100644 --- a/pyccel/ast/datatypes.py +++ b/pyccel/ast/datatypes.py @@ -442,7 +442,7 @@ class GenericType(FixedSizeType): @lru_cache def __add__(self, other): return other - + def __eq__(self, other): return True From 9f130af854d7e10e94a0ef630918aef2cbaddf5d Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 7 Jun 2024 20:33:58 +0100 Subject: [PATCH 126/139] chore: trailing whitespace --- pyccel/ast/datatypes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyccel/ast/datatypes.py b/pyccel/ast/datatypes.py index 8b2361ff00..88f9857e98 100644 --- a/pyccel/ast/datatypes.py +++ b/pyccel/ast/datatypes.py @@ -760,7 +760,7 @@ def __init__(self, element_type): self._element_type = element_type self._order = 'C' if (element_type.order == 'C' or element_type.rank == 1) else None super().__init__() - + def __eq__(self, other): return isinstance(other, self.__class__) and self._element_type == other._element_type \ and self._order == other._order From b8bcfdc1bbbb973a8e5f39cebb5148d729bc85bb Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 7 Jun 2024 20:46:03 +0100 Subject: [PATCH 127/139] chore: trailing whitespace --- pyccel/ast/datatypes.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyccel/ast/datatypes.py b/pyccel/ast/datatypes.py index 88f9857e98..b39df74103 100644 --- a/pyccel/ast/datatypes.py +++ b/pyccel/ast/datatypes.py @@ -760,10 +760,10 @@ def __init__(self, element_type): self._element_type = element_type self._order = 'C' if (element_type.order == 'C' or element_type.rank == 1) else None super().__init__() - + def __eq__(self, other): return isinstance(other, self.__class__) and self._element_type == other._element_type \ - and self._order == other._order + and self._order == other._order def __hash__(self): return hash((self.__class__, self._element_type, self._order)) @@ -789,7 +789,7 @@ def __init__(self, element_type): assert isinstance(element_type, PyccelType) self._element_type = element_type super().__init__() - + def __eq__(self, other): return isinstance(other, self.__class__) and self._element_type == other._element_type From 48eddce08d7c38ad658f6c6040f38b37e9601731 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 7 Jun 2024 22:04:44 +0100 Subject: [PATCH 128/139] chore: trailing whitespace --- pyccel/ast/datatypes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyccel/ast/datatypes.py b/pyccel/ast/datatypes.py index b39df74103..56e6754708 100644 --- a/pyccel/ast/datatypes.py +++ b/pyccel/ast/datatypes.py @@ -760,10 +760,10 @@ def __init__(self, element_type): self._element_type = element_type self._order = 'C' if (element_type.order == 'C' or element_type.rank == 1) else None super().__init__() - + def __eq__(self, other): return isinstance(other, self.__class__) and self._element_type == other._element_type \ - and self._order == other._order + and self._order == other._order def __hash__(self): return hash((self.__class__, self._element_type, self._order)) From f3b368b983e387834e4863df0597199befb38f83 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Fri, 7 Jun 2024 23:31:19 +0100 Subject: [PATCH 129/139] fix: lists and sets are not restricted to a rank of 15 --- pyccel/codegen/printing/ccode.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 8c586d2ad7..5f84b031bb 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -1302,14 +1302,14 @@ def get_declare_type(self, expr): rank = expr.rank if rank > 0: - if isinstance(class_type, NumpyNDArrayType): - if rank > 15: + if isinstance(expr.class_type, (HomogeneousSetType, HomogeneousListType)): + dtype = self.find_in_type_registry(expr.class_type) + return dtype + if expr.is_ndarray or isinstance(expr.class_type, HomogeneousContainerType): + if expr.rank > 15: errors.report(UNSUPPORTED_ARRAY_RANK, symbol=expr, severity='fatal') self.add_import(c_imports['ndarrays']) dtype = 't_ndarray' - elif isinstance(class_type, (HomogeneousSetType, HomogeneousListType)): - dtype = self.find_in_type_registry(expr.class_type) - return dtype else: errors.report(PYCCEL_RESTRICTION_TODO+' (rank>0)', symbol=expr, severity='fatal') elif not isinstance(class_type, CustomDataType): From 1134b8e52e17fcc75c1c4123d5820f685ff9c167 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Mon, 10 Jun 2024 12:22:46 +0100 Subject: [PATCH 130/139] fix: check on supported containers only, to not conflict Dict and Cuda containers with Ndarrays in the future --- pyccel/codegen/printing/ccode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 5f84b031bb..19f9a90b34 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -1305,7 +1305,7 @@ def get_declare_type(self, expr): if isinstance(expr.class_type, (HomogeneousSetType, HomogeneousListType)): dtype = self.find_in_type_registry(expr.class_type) return dtype - if expr.is_ndarray or isinstance(expr.class_type, HomogeneousContainerType): + if isinstance(expr.class_type,(HomogeneousTupleType, NumpyNDArrayType)): if expr.rank > 15: errors.report(UNSUPPORTED_ARRAY_RANK, symbol=expr, severity='fatal') self.add_import(c_imports['ndarrays']) From cd22d9552fa7c174faa97aaba068fe8ff2acd247 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Mon, 10 Jun 2024 15:30:47 +0100 Subject: [PATCH 131/139] fix: add related issues to xfail, and update tests fixtures --- tests/epyccel/test_arrays.py | 2 +- tests/epyccel/test_epyccel_modules.py | 4 +- .../test_epyccel_variable_annotations.py | 79 ++++++++----------- 3 files changed, 35 insertions(+), 50 deletions(-) diff --git a/tests/epyccel/test_arrays.py b/tests/epyccel/test_arrays.py index 209972187b..59ddb650ab 100644 --- a/tests/epyccel/test_arrays.py +++ b/tests/epyccel/test_arrays.py @@ -4030,7 +4030,7 @@ def test_array_float_nested_C_array_initialization_3(language): @pytest.mark.parametrize( 'language', ( pytest.param("fortran", marks = pytest.mark.fortran), pytest.param("c", marks = [ - pytest.mark.xfail(reason="List indexing is not yet supported in C"), + pytest.mark.xfail(reason="List indexing is not yet supported in C, related issue #1876"), pytest.mark.c] ), pytest.param("python", marks = pytest.mark.python) diff --git a/tests/epyccel/test_epyccel_modules.py b/tests/epyccel/test_epyccel_modules.py index 9c2c9226a1..46cd9d5b75 100644 --- a/tests/epyccel/test_epyccel_modules.py +++ b/tests/epyccel/test_epyccel_modules.py @@ -172,11 +172,11 @@ def test_module_7(language): @pytest.mark.parametrize( 'language', ( pytest.param("fortran", marks = [ - pytest.mark.xfail(reason="List wrapper is not implemented yet."), + pytest.mark.xfail(reason="List wrapper is not implemented yet, related issue #1911"), pytest.mark.fortran] ), pytest.param("c", marks = [ - pytest.mark.xfail(reason="List indexing is not yet supported in C"), + ppytest.mark.xfail(reason="List indexing is not yet supported in C, related issue #1876"), pytest.mark.c] ), pytest.param("python", marks = pytest.mark.python) diff --git a/tests/epyccel/test_epyccel_variable_annotations.py b/tests/epyccel/test_epyccel_variable_annotations.py index 3c57eacc5f..06b745caa8 100644 --- a/tests/epyccel/test_epyccel_variable_annotations.py +++ b/tests/epyccel/test_epyccel_variable_annotations.py @@ -10,14 +10,17 @@ from pyccel.errors.errors import PyccelSemanticError, Errors from pyccel.decorators import allow_negative_index, stack_array -def parametrize_languages(): - return pytest.mark.parametrize('language', [ - pytest.param("c", marks=pytest.mark.c), - pytest.param("fortran", marks=[ - pytest.mark.skip(reason="Variable declaration not implemented in fortran"), +@pytest.fixture( params=[ + pytest.param("c", marks = pytest.mark.c), + pytest.param("fortran", marks = [ + pytest.mark.xfail(reason="Variable declaration not implemented in fortran, related issues #1657 1658"), pytest.mark.fortran]), - pytest.param("python", marks=pytest.mark.python) - ]) + pytest.param("python", marks = pytest.mark.python) + ], + scope = "module" +) +def stc_language(request): + return request.param def test_local_type_annotation(language): def local_type_annotation(): @@ -175,106 +178,88 @@ def homogeneous_tuple_annotation(): assert epyc_homogeneous_tuple_annotation() == homogeneous_tuple_annotation() assert isinstance(epyc_homogeneous_tuple_annotation(), type(homogeneous_tuple_annotation())) -@pytest.mark.parametrize( 'language', [ - pytest.param("c", marks = pytest.mark.c), - pytest.param("fortran", marks = [ - pytest.mark.skip(reason="Variable declaration not implemented in fortran"), - pytest.mark.fortran]), - pytest.param("python", marks = pytest.mark.python) - ] -) -def test_homogeneous_set_annotation_int(language): +def test_homogeneous_set_annotation_int(stc_language): def homogeneous_set_annotation (): a : 'set[int]' #pylint: disable=unused-variable a = {1, 2, 3, 4} - epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=language) + epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=stc_language) assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation() assert isinstance(epyc_homogeneous_set_annotation(), type(homogeneous_set_annotation())) -@parametrize_languages() -def test_homogeneous_set_without_annotation(language): +def test_homogeneous_set_without_annotation(stc_language): def homogeneous_set(): a = {1, 2, 3, 4} #pylint: disable=unused-variable - epyc_homogeneous_set = epyccel(homogeneous_set, language=language) + epyc_homogeneous_set = epyccel(homogeneous_set, language=stc_language) assert epyc_homogeneous_set() == homogeneous_set() assert isinstance(epyc_homogeneous_set(), type(homogeneous_set())) -@parametrize_languages() -def test_homogeneous_set_annotation_float(language): +def test_homogeneous_set_annotation_float(stc_language): def homogeneous_set_annotation (): a : 'set[float]' #pylint: disable=unused-variable a = {1.5, 2.5, 3.3, 4.3} - epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=language) + epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=stc_language) assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation() assert isinstance(epyc_homogeneous_set_annotation(), type(homogeneous_set_annotation())) -@parametrize_languages() -def test_homogeneous_set_annotation_bool(language): +def test_homogeneous_set_annotation_bool(stc_language): def homogeneous_set_annotation (): a : 'set[bool]' #pylint: disable=unused-variable a = {False, True, False, True} #pylint: disable=duplicate-value - epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=language) + epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=stc_language) assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation() assert isinstance(epyc_homogeneous_set_annotation(), type(homogeneous_set_annotation())) -@parametrize_languages() -def test_homogeneous_set_annotation_complex(language): +def test_homogeneous_set_annotation_complex(stc_language): def homogeneous_set_annotation(): a: 'set[complex]' # pylint: disable=unused-variable a = {1+1j, 2+2j, 3+3j, 4+4j} - epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=language) + epyc_homogeneous_set_annotation = epyccel(homogeneous_set_annotation, language=stc_language) assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation() assert isinstance(epyc_homogeneous_set_annotation(), type(homogeneous_set_annotation())) -@parametrize_languages() -def test_homogeneous_list_annotation_int(language): +def test_homogeneous_list_annotation_int(stc_language): def homogeneous_list_annotation(): a: 'list[int]' # pylint: disable=unused-variable a = [1, 2, 3, 4] - epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=language) + epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=stc_language) assert epyc_homogeneous_list_annotation() == homogeneous_list_annotation() assert isinstance(epyc_homogeneous_list_annotation(), type(homogeneous_list_annotation())) -@parametrize_languages() -def test_homogeneous_list_without_annotation(language): +def test_homogeneous_list_without_annotation(stc_language): def homogeneous_list(): a = [1, 2, 3, 4] # pylint: disable=unused-variable - epyc_homogeneous_list = epyccel(homogeneous_list, language=language) + epyc_homogeneous_list = epyccel(homogeneous_list, language=stc_language) assert epyc_homogeneous_list() == homogeneous_list() assert isinstance(epyc_homogeneous_list(), type(homogeneous_list())) -@parametrize_languages() -def test_homogeneous_list_annotation_float(language): +def test_homogeneous_list_annotation_float(stc_language): def homogeneous_list_annotation(): a: 'list[float]' # pylint: disable=unused-variable a = [1.1, 2.2, 3.3, 4.4] - epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=language) + epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=stc_language) assert epyc_homogeneous_list_annotation() == homogeneous_list_annotation() assert isinstance(epyc_homogeneous_list_annotation(), type(homogeneous_list_annotation())) -@parametrize_languages() -def test_homogeneous_list_annotation_bool(language): +def test_homogeneous_list_annotation_bool(stc_language): def homogeneous_list_annotation(): a: 'list[bool]' # pylint: disable=unused-variable a = [False, True, True, False] - epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=language) + epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=stc_language) assert epyc_homogeneous_list_annotation() == homogeneous_list_annotation() assert isinstance(epyc_homogeneous_list_annotation(), type(homogeneous_list_annotation())) -@parametrize_languages() -def test_homogeneous_list_annotation_complex(language): +def test_homogeneous_list_annotation_complex(stc_language): def homogeneous_list_annotation(): a: 'list[complex]' # pylint: disable=unused-variable a = [1+1j, 2+2j, 3+3j, 4+4j] - epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=language) + epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=stc_language) assert epyc_homogeneous_list_annotation() == homogeneous_list_annotation() assert isinstance(epyc_homogeneous_list_annotation(), type(homogeneous_list_annotation())) -@parametrize_languages() -def test_homogeneous_list_annotation_embedded_complex(language): +def test_homogeneous_list_annotation_embedded_complex(stc_language): def homogeneous_list_annotation(): a : 'list[complex]' = [1j, 2j] b = [a] # pylint: disable=unused-variable - epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=language) + epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=stc_language) assert epyc_homogeneous_list_annotation() == homogeneous_list_annotation() assert isinstance(epyc_homogeneous_list_annotation(), type(homogeneous_list_annotation())) From d0d055a2b42cfbbd92375c8dff66e882d6841810 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Mon, 10 Jun 2024 15:49:24 +0100 Subject: [PATCH 132/139] fix: typo in test --- tests/epyccel/test_epyccel_modules.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/epyccel/test_epyccel_modules.py b/tests/epyccel/test_epyccel_modules.py index 46cd9d5b75..ad8ae0bd75 100644 --- a/tests/epyccel/test_epyccel_modules.py +++ b/tests/epyccel/test_epyccel_modules.py @@ -176,7 +176,7 @@ def test_module_7(language): pytest.mark.fortran] ), pytest.param("c", marks = [ - ppytest.mark.xfail(reason="List indexing is not yet supported in C, related issue #1876"), + pytest.mark.xfail(reason="List indexing is not yet supported in C, related issue #1876"), pytest.mark.c] ), pytest.param("python", marks = pytest.mark.python) From 211d99a741671337a6aaa0ecd4eea982b40f73d1 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Mon, 10 Jun 2024 16:32:00 +0100 Subject: [PATCH 133/139] fix: pylint issues --- pyccel/codegen/printing/ccode.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 19f9a90b34..76dce3b101 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -25,7 +25,7 @@ from pyccel.ast.operators import PyccelAssociativeParenthesis, PyccelMod from pyccel.ast.operators import PyccelUnarySub, IfTernaryOperator -from pyccel.ast.datatypes import PythonNativeInt, PythonNativeBool, VoidType, GenericType +from pyccel.ast.datatypes import PythonNativeInt, PythonNativeBool, VoidType from pyccel.ast.datatypes import TupleType, FixedSizeNumericType from pyccel.ast.datatypes import CustomDataType, StringType, HomogeneousTupleType, HomogeneousListType, HomogeneousSetType from pyccel.ast.datatypes import PrimitiveBooleanType, PrimitiveIntegerType, PrimitiveFloatingPointType, PrimitiveComplexType @@ -1303,8 +1303,8 @@ def get_declare_type(self, expr): if rank > 0: if isinstance(expr.class_type, (HomogeneousSetType, HomogeneousListType)): - dtype = self.find_in_type_registry(expr.class_type) - return dtype + dtype = self.find_in_type_registry(expr.class_type) + return dtype if isinstance(expr.class_type,(HomogeneousTupleType, NumpyNDArrayType)): if expr.rank > 15: errors.report(UNSUPPORTED_ARRAY_RANK, symbol=expr, severity='fatal') From 7d253d1347e758556687177cf3707b90ff6856f8 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Mon, 10 Jun 2024 16:32:39 +0100 Subject: [PATCH 134/139] feat: test declaring an empty annotated list --- tests/epyccel/test_epyccel_variable_annotations.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/epyccel/test_epyccel_variable_annotations.py b/tests/epyccel/test_epyccel_variable_annotations.py index 06b745caa8..c8710a59da 100644 --- a/tests/epyccel/test_epyccel_variable_annotations.py +++ b/tests/epyccel/test_epyccel_variable_annotations.py @@ -217,6 +217,14 @@ def homogeneous_set_annotation(): assert epyc_homogeneous_set_annotation() == homogeneous_set_annotation() assert isinstance(epyc_homogeneous_set_annotation(), type(homogeneous_set_annotation())) +def test_homogeneous_empty_list_annotation_int(stc_language): + def homogeneous_list_annotation(): + a: 'list[int]' # pylint: disable=unused-variable + a = [] + epyc_homogeneous_list_annotation = epyccel(homogeneous_list_annotation, language=stc_language) + assert epyc_homogeneous_list_annotation() == homogeneous_list_annotation() + assert isinstance(epyc_homogeneous_list_annotation(), type(homogeneous_list_annotation())) + def test_homogeneous_list_annotation_int(stc_language): def homogeneous_list_annotation(): a: 'list[int]' # pylint: disable=unused-variable From 59e39e8bcaf07e66951693ba9cb17d668be0a071 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Mon, 10 Jun 2024 17:53:48 +0100 Subject: [PATCH 135/139] chore: duplicate import --- pyccel/parser/semantic.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyccel/parser/semantic.py b/pyccel/parser/semantic.py index e125a04600..0bb1a7c0b1 100644 --- a/pyccel/parser/semantic.py +++ b/pyccel/parser/semantic.py @@ -61,10 +61,10 @@ from pyccel.ast.class_defs import NumpyArrayClass, TupleClass, get_cls_base from pyccel.ast.datatypes import CustomDataType, PyccelType, TupleType, VoidType, GenericType -from pyccel.ast.datatypes import PrimitiveIntegerType, HomogeneousListType, StringType, SymbolicType, HomogeneousSetType +from pyccel.ast.datatypes import PrimitiveIntegerType, StringType, SymbolicType from pyccel.ast.datatypes import PythonNativeBool, PythonNativeInt, PythonNativeFloat from pyccel.ast.datatypes import DataTypeFactory, PrimitiveFloatingPointType -from pyccel.ast.datatypes import InhomogeneousTupleType, HomogeneousTupleType, HomogeneousSetType +from pyccel.ast.datatypes import InhomogeneousTupleType, HomogeneousTupleType, HomogeneousSetType, HomogeneousListType from pyccel.ast.datatypes import PrimitiveComplexType, FixedSizeNumericType from pyccel.ast.functionalexpr import FunctionalSum, FunctionalMax, FunctionalMin, GeneratorComprehension, FunctionalFor From 8b4fa11b2c6dce02e30c77cef4d60da0d58e9315 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Tue, 11 Jun 2024 13:15:49 +0100 Subject: [PATCH 136/139] update docs --- pyccel/codegen/printing/ccode.py | 69 ++++++++++++++++---------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 76dce3b101..23b36a4230 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -403,7 +403,7 @@ def copy_NumpyArray_Data(self, expr): order = lhs.order lhs_dtype = lhs.dtype - declare_dtype = self.find_in_type_registry(lhs_dtype) + declare_dtype = self.get_c_type(lhs_dtype) if isinstance(lhs.class_type, NumpyNDArrayType): #set dtype to the C struct types dtype = self.find_in_ndarray_type_registry(lhs_dtype) @@ -496,7 +496,7 @@ def arrayFill(self, expr): rhs = expr.rhs lhs = expr.lhs code_init = '' - declare_dtype = self.find_in_type_registry(rhs.dtype) + declare_dtype = self.get_c_type(rhs.dtype) if rhs.fill_value is not None: if isinstance(rhs.fill_value, Literal): @@ -524,7 +524,7 @@ def _init_stack_array(self, expr): String containing the rhs of the initialization of a stack array. """ var = expr - dtype = self.find_in_type_registry(var.dtype) + dtype = self.get_c_type(var.dtype) if isinstance(var.class_type, NumpyNDArrayType): np_dtype = self.find_in_ndarray_type_registry(var.dtype) elif isinstance(var.class_type, HomogeneousContainerType): @@ -534,7 +534,7 @@ def _init_stack_array(self, expr): shape = ", ".join(self._print(i) for i in var.alloc_shape) tot_shape = self._print(functools.reduce( lambda x,y: PyccelMul(x,y,simplify=True), var.alloc_shape)) - declare_dtype = self.find_in_type_registry(NumpyInt64Type()) + declare_dtype = self.get_c_type(NumpyInt64Type()) dummy_array_name = self.scope.get_new_name('array_dummy') buffer_array = "{dtype} {name}[{size}];\n".format( @@ -645,19 +645,20 @@ def _handle_inline_func_call(self, expr): return code - def init_stc_container(self, expr, container_var): + def init_stc_container(self, expr, assignment_var): """ Generate the initialization of an STC container in C. - This method generates and prints the C code for initializing a container using the STC `init()` method. + This method generates and prints the C code for initializing a container using the STC `c_init()` method. Parameters ---------- expr : TypedAstNode The object representing the container being printed (e.g., PythonList, PythonSet). - container_var : str - The variable name to which the container is being assigned. + assignment_var : Assign + The assignment node where the Python container (rhs) is being initialized + and saved into a variable (lhs). Returns ------- @@ -665,9 +666,9 @@ def init_stc_container(self, expr, container_var): The generated C code for the container initialization. """ - dtype = self.find_in_type_registry(container_var.lhs.class_type) + dtype = self.get_c_type(assignment_var.lhs.class_type) keyraw = '{' + ', '.join(self._print(a) for a in expr.args) + '}' - init = f'{container_var.lhs.name} = c_init({dtype}, {keyraw});\n' + init = f'{assignment_var.lhs.name} = c_init({dtype}, {keyraw});\n' return init def rename_imported_methods(self, expr): @@ -680,7 +681,7 @@ def rename_imported_methods(self, expr): Parameters ---------- - expr : Tuple of ClassDef objects + expr : iterable[ClassDef] The ClassDef objects found in the module being renamed. """ for classDef in expr: @@ -755,13 +756,13 @@ def _print_SysExit(self, expr): def _print_PythonFloat(self, expr): value = self._print(expr.arg) - type_name = self.find_in_type_registry(expr.dtype) + type_name = self.get_c_type(expr.dtype) return '({0})({1})'.format(type_name, value) def _print_PythonInt(self, expr): self.add_import(c_imports['stdint']) value = self._print(expr.arg) - type_name = self.find_in_type_registry(expr.dtype) + type_name = self.get_c_type(expr.dtype) return '({0})({1})'.format(type_name, value) def _print_PythonBool(self, expr): @@ -795,7 +796,7 @@ def _print_PythonComplex(self, expr): else: value = self._print(PyccelAssociativeParenthesis(PyccelAdd(expr.real, PyccelMul(expr.imag, LiteralImaginaryUnit())))) - type_name = self.find_in_type_registry(expr.dtype) + type_name = self.get_c_type(expr.dtype) return '({0})({1})'.format(type_name, value) def _print_LiteralImaginaryUnit(self, expr): @@ -1181,19 +1182,20 @@ def formatted_args_to_printf(args_format, args, end): code += formatted_args_to_printf(args_format, args, end) return code - def find_in_type_registry(self, dtype): + def get_c_type(self, dtype): """ - Find the corresponding C dtype in the dtype_registry or the STC container type. + Find the corresponding C type of the PyccelType. - This function searches for the corresponding C data type in the `dtype_registry`. - If the provided dtype is a container (like `HomogeneousSetType` or - `HomogeneousListType`), it identifies the scalar type of the container and returns - the appropriate type for the `STC` container. - It raises a `PYCCEL_RESTRICTION_TODO` error if the dtype is not found in the registry. + For scalar types, this function searches for the corresponding C data type + in the `dtype_registry`. If the provided type is a container (like + `HomogeneousSetType` or `HomogeneousListType`), it recursively identifies + the type of an element of the container and uses it to calculate the + appropriate type for the `STC` container. + A `PYCCEL_RESTRICTION_TODO` error is raised if the dtype is not found in the registry. Parameters ---------- - dtype : DataType or ContainerType + dtype : PyccelType The data type of the expression. This can be a fixed-size numeric type, a primitive type, or a container type. @@ -1212,7 +1214,7 @@ def find_in_type_registry(self, dtype): primitive_type = dtype.primitive_type if isinstance(primitive_type, PrimitiveComplexType): self.add_import(c_imports['complex']) - return f'{self.find_in_type_registry(dtype.element_type)} complex' + return f'{self.get_c_type(dtype.element_type)} complex' elif isinstance(primitive_type, PrimitiveIntegerType): self.add_import(c_imports['stdint']) elif isinstance(dtype, PythonNativeBool): @@ -1222,7 +1224,7 @@ def find_in_type_registry(self, dtype): key = (primitive_type, dtype.precision) elif isinstance(dtype, (HomogeneousSetType, HomogeneousListType)): container_type = 'hset_' if dtype.name == 'set' else 'vec_' - element_type = self.find_in_type_registry(dtype.element_type) + element_type = self.get_c_type(dtype.element_type) i_type = container_type + element_type.replace(' ', '_') self.add_import(Import(f'stc/{i_type}/{element_type}', Module(f'stc/{i_type}', (), ()))) return i_type @@ -1236,7 +1238,6 @@ def find_in_type_registry(self, dtype): symbol = dtype, severity='fatal') - def find_in_ndarray_type_registry(self, dtype): """ Find the descriptor for the datatype in the ndarray_type_registry. @@ -1303,7 +1304,7 @@ def get_declare_type(self, expr): if rank > 0: if isinstance(expr.class_type, (HomogeneousSetType, HomogeneousListType)): - dtype = self.find_in_type_registry(expr.class_type) + dtype = self.get_c_type(expr.class_type) return dtype if isinstance(expr.class_type,(HomogeneousTupleType, NumpyNDArrayType)): if expr.rank > 15: @@ -1313,7 +1314,7 @@ def get_declare_type(self, expr): else: errors.report(PYCCEL_RESTRICTION_TODO+' (rank>0)', symbol=expr, severity='fatal') elif not isinstance(class_type, CustomDataType): - dtype = self.find_in_type_registry(expr.dtype) + dtype = self.get_c_type(expr.dtype) else: dtype = self._print(expr.class_type) @@ -1397,11 +1398,11 @@ def function_signature(self, expr, print_arg_names = True): if n_results == 1: ret_type = self.get_declare_type(result_vars[0]) elif n_results > 1: - ret_type = self.find_in_type_registry(PythonNativeInt()) + ret_type = self.get_c_type(PythonNativeInt()) arg_vars.extend(result_vars) self._additional_args.append(result_vars) # Ensure correct result for is_c_pointer else: - ret_type = self.find_in_type_registry(VoidType()) + ret_type = self.get_c_type(VoidType()) name = expr.name if not arg_vars: @@ -1499,7 +1500,7 @@ def _cast_to(self, expr, dtype): after using this function. """ if expr.dtype != dtype: - cast=self.find_in_type_registry(dtype) + cast=self.get_c_type(dtype) return '({}){{}}'.format(cast) return '{}' @@ -1611,7 +1612,7 @@ def _print_Allocate(self, expr): dtype = self.find_in_ndarray_type_registry(numpy_precision_map[(variable.dtype.primitive_type, variable.dtype.precision)]) else: raise NotImplementedError(f"Don't know how to index {variable.class_type} type") - shape_dtype = self.find_in_type_registry(NumpyInt64Type()) + shape_dtype = self.get_c_type(NumpyInt64Type()) shape_Assign = "("+ shape_dtype +"[]){" + shape + "}" is_view = 'false' if variable.on_heap else 'true' order = "order_f" if expr.order == "F" else "order_c" @@ -1630,7 +1631,7 @@ def _print_Allocate(self, expr): def _print_Deallocate(self, expr): if isinstance(expr.variable.class_type, (HomogeneousListType, HomogeneousSetType)): variable_address = self._print(ObjectAddress(expr.variable)) - container_type = self.find_in_type_registry(expr.variable.class_type) + container_type = self.get_c_type(expr.variable.class_type) return f'{container_type}_drop({variable_address});\n' if isinstance(expr.variable, InhomogeneousTupleVariable): return ''.join(self._print(Deallocate(v)) for v in expr.variable) @@ -1802,7 +1803,7 @@ def _print_MathFunctionBase(self, expr): args.append(self._print(arg)) code_args = ', '.join(args) if expr.dtype.primitive_type is PrimitiveIntegerType(): - cast_type = self.find_in_type_registry(expr.dtype) + cast_type = self.get_c_type(expr.dtype) return f'({cast_type}){func_name}({code_args})' return f'{func_name}({code_args})' @@ -2114,7 +2115,7 @@ def _print_PyccelFloorDiv(self, expr): code = ' / '.join(self._print(a if a.dtype.primitive_type is PrimitiveFloatingPointType() else NumpyFloat(a)) for a in expr.args) if (need_to_cast): - cast_type = self.find_in_type_registry(expr.dtype) + cast_type = self.get_c_type(expr.dtype) return "({})floor({})".format(cast_type, code) return "floor({})".format(code) From 4992779c9c11524fdb9495a0db9fc8d5e3287bfa Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Tue, 11 Jun 2024 13:19:26 +0100 Subject: [PATCH 137/139] expr.target is unused --- pyccel/codegen/printing/ccode.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 23b36a4230..4bdf0b9cfc 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -995,16 +995,15 @@ def _print_Import(self, expr): source = source.name[-1] else: source = self._print(source) - if expr.target: - if source.startswith('stc/'): - stc_name, container_type, container_key = source.split("/") - container = container_type.split("_") - return '\n'.join((f'#ifndef _{container_type.upper()}', - f'#define _{container_type.upper()}', - f'#define i_type {container_type}', - f'#define i_key {container_key}', - f'#include "{stc_name + "/" + container[0]}.h"', - '#endif\n')) + if source.startswith('stc/'): + stc_name, container_type, container_key = source.split("/") + container = container_type.split("_") + return '\n'.join((f'#ifndef _{container_type.upper()}', + f'#define _{container_type.upper()}', + f'#define i_type {container_type}', + f'#define i_key {container_key}', + f'#include "{stc_name + "/" + container[0]}.h"', + '#endif\n')) # Get with a default value is not used here as it is # slower and on most occasions the import will not be in the From 5c72144c6a07a1f8cd40885d15e1da677993abc0 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Tue, 11 Jun 2024 13:24:12 +0100 Subject: [PATCH 138/139] use of print to retrieve the container name --- pyccel/codegen/printing/ccode.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 4bdf0b9cfc..111ee34440 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -668,7 +668,8 @@ def init_stc_container(self, expr, assignment_var): dtype = self.get_c_type(assignment_var.lhs.class_type) keyraw = '{' + ', '.join(self._print(a) for a in expr.args) + '}' - init = f'{assignment_var.lhs.name} = c_init({dtype}, {keyraw});\n' + container_name = self._print(assignment_var.lhs) + init = f'{container_name} = c_init({dtype}, {keyraw});\n' return init def rename_imported_methods(self, expr): From c381e60cad0b9cc554ac36c1a170f2b796f011e5 Mon Sep 17 00:00:00 2001 From: Farouk-Echaref Date: Tue, 11 Jun 2024 14:30:08 +0100 Subject: [PATCH 139/139] update error docstring --- pyccel/codegen/printing/ccode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py index 111ee34440..a39a442a83 100644 --- a/pyccel/codegen/printing/ccode.py +++ b/pyccel/codegen/printing/ccode.py @@ -1207,7 +1207,7 @@ def get_c_type(self, dtype): Raises ------ - PYCCEL_RESTRICTION_TODO + PyccelCodegenError If the dtype is not found in the dtype_registry. """ if isinstance(dtype, FixedSizeNumericType):