Repository: pyccel/pyccel (python)

Issue:
[SETS] Add C support for `Discard`
### Test Code
Provide code which does not currently work but which should do when this issue is fixed:
```python
def foo():
    a = {1, 2, 3}
    a.discard(2)
```

### Proposed Solution
This feature should be implemented using the functionalities provided by STC


Pull request description:
Add C and Fortran support for remove/discard
Add C and Fortran support for set methods `remove`/`discard`. Fixes #1921

Blocked by #2102

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d650553a..a558cb6e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,8 +13,6 @@ All notable changes to this project will be documented in this file.
 -   #1700 : Add Python support for list method `sort()`.
 -   #1696 : Add Python support for list method `copy()`.
 -   #1693 : Add Python support for list method `remove()`.
--   #1750 : Add Python support for set method `remove()`.
--   #1743 : Add Python support for set method `discard()`.
 -   #1893 : Add Python support for set initialisation with `set()`.
 -   #1895 : Add Python support for dict initialisation with `{}`.
 -   #1895 : Add Python support for dict initialisation with `dict()`.
@@ -44,6 +42,8 @@ All notable changes to this project will be documented in this file.
 -   #1917 : Add C and Fortran support for set method `add()`.
 -   #1918 : Add support for set method `clear()`.
 -   #1918 : Add support for set method `copy()`.
+-   #1743 : Add support for set method `discard()`.
+-   #1750 : Add support for set method `remove()`.
 -   #1753 : Add support for set method `union()`.
 -   #1754 : Add support for set method `update()`.
 -   #1744 : Add support for set method `intersection()`.
diff --git a/docs/builtin-functions.md b/docs/builtin-functions.md
index 91f80467..189dd3b0 100644
--- a/docs/builtin-functions.md
+++ b/docs/builtin-functions.md
@@ -101,14 +101,14 @@ Python contains a limited number of builtin functions defined [here](https://doc
 | **`copy`** | **Yes** |
 | `difference` | No |
 | `difference_update` | No |
-| `discard` | Python-only |
-| `intersection` | **Yes** |
-| `intersection_update` | **Yes** |
+| **`discard`** | **Yes** |
+| **`intersection`** | **Yes** |
+| **`intersection_update`** | **Yes** |
 | `isdisjoint` | No |
 | `issubset` | No |
 | `issuperset` | No |
 | **`pop`** | **Yes** |
-| `remove` | Python-only |
+| **`remove`** | **Yes** |
 | `symmetric_difference` | No |
 | `symmetric_difference_update` | No |
 | **`union`** | **Yes** |
diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py
index db61df97..5d0854a9 100644
--- a/pyccel/codegen/printing/ccode.py
+++ b/pyccel/codegen/printing/ccode.py
@@ -2804,6 +2804,12 @@ class CCodePrinter(CodePrinter):
         return ''.join(f'{var_type}_intersection_update({set_var}, {self._print(ObjectAddress(a))});\n' \
                 for a in expr.args)
 
+    def _print_SetDiscard(self, expr):
+        var_type = self.get_c_type(expr.set_variable.class_type)
+        set_var = self._print(ObjectAddress(expr.set_variable))
+        arg_val = self._print(expr.args[0])
+        return f'{var_type}_erase({set_var}, {arg_val});\n'
+
     #=================== MACROS ==================
 
     def _print_MacroShape(self, expr):
diff --git a/pyccel/codegen/printing/fcode.py b/pyccel/codegen/printing/fcode.py
index 065ef709..26dc3572 100644
--- a/pyccel/codegen/printing/fcode.py
+++ b/pyccel/codegen/printing/fcode.py
@@ -1431,6 +1431,12 @@ class FCodePrinter(CodePrinter):
         return ''.join(f'call {type_name}_intersection_update({var_code}, {self._print(arg)})\n' \
                 for arg in expr.args)
 
+    def _print_SetDiscard(self, expr):
+        var = self._print(expr.set_variable)
+        val = self._print(expr.args[0])
+        success = self.scope.get_temporary_variable(PythonNativeInt())
+        return f'{success} = {var} % erase_value({val})\n'
+
     #========================== Numpy Elements ===============================#
 
     def _print_NumpySum(self, expr):


Test patch:
diff --git a/tests/epyccel/test_epyccel_sets.py b/tests/epyccel/test_epyccel_sets.py
index 65c45a89..5bf9ee65 100644
--- a/tests/epyccel/test_epyccel_sets.py
+++ b/tests/epyccel/test_epyccel_sets.py
@@ -119,62 +119,62 @@ def test_copy_complex(language):
     assert python_result[0] == pyccel_result[0]
     assert set(python_result[1:]) == set(pyccel_result[1:])
 
-def test_remove_complex(python_only_language):
+def test_remove_complex(language):
     def remove_complex():
         se = {1j, 3j, 8j}
         se.remove(3j)
         return se
-    epyccel_remove = epyccel(remove_complex, language = python_only_language)
+    epyccel_remove = epyccel(remove_complex, language = language)
     pyccel_result = epyccel_remove()
     python_result = remove_complex()
     assert python_result == pyccel_result
 
-def test_remove_int(python_only_language):
+def test_remove_int(language):
     def remove_int():
         se = {2, 4, 9}
         se.remove(4)
         return se
-    epyccel_remove = epyccel(remove_int, language = python_only_language)
+    epyccel_remove = epyccel(remove_int, language = language)
     pyccel_result = epyccel_remove()
     python_result = remove_int()
     assert python_result == pyccel_result
 
-def test_remove_float(python_only_language):
+def test_remove_float(language):
     def remove_float():
         se = {5.7, 2.4, 8.1}
         se.remove(8.1)
         return se
-    epyccel_remove = epyccel(remove_float, language = python_only_language)
+    epyccel_remove = epyccel(remove_float, language = language)
     pyccel_result = epyccel_remove()
     python_result = remove_float()
     assert python_result == pyccel_result
 
-def test_Discard_int(python_only_language):
+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 = python_only_language)
+    epyccel_remove = epyccel(Discard_int, language = language)
     pyccel_result = epyccel_remove()
     python_result = Discard_int()
     assert python_result == pyccel_result
 
-def test_Discard_complex(python_only_language):
+def test_Discard_complex(language):
     def Discard_complex():
         se = {2j, 5j, 3j, 7j}
         se.discard(5j)
         return se
-    epyccel_remove = epyccel(Discard_complex, language = python_only_language)
+    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(python_only_language):
+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 = python_only_language)
+    epyccel_remove = epyccel(Discard_wrong_arg, language = language)
     pyccel_result = epyccel_remove()
     python_result = Discard_wrong_arg()
     assert python_result == pyccel_result