Repository: pyccel/pyccel (python)

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


Pull request description:
[SET] Add c support for `add`
Add C and Fortran support for the `set` method `add`. Fixes #1917

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index efe1cc6b..3d04d0d3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -37,6 +37,7 @@ All notable changes to this project will be documented in this file.
 -   #1876 : Add C support for indexing lists.
 -   #1690 : Add C support for list method `pop()`.
 -   #1877 : Add C Support for set method `pop()`.
+-   #1917 : Add C and Fortran Support for set method `add()`.
 -   #1936 : Add missing C output for inline decorator example in documentation
 -   #1937 : Optimise `pyccel.ast.basic.PyccelAstNode.substitute` method.
 -   #1544 : Add support for `typing.TypeAlias`.
diff --git a/docs/builtin-functions.md b/docs/builtin-functions.md
index c22d25f6..9f3dcc1e 100644
--- a/docs/builtin-functions.md
+++ b/docs/builtin-functions.md
@@ -96,7 +96,7 @@ Python contains a limited number of builtin functions defined [here](https://doc
 
 | Method | Supported |
 |----------|-----------|
-| `add` | Python-only |
+| **`add`** | **Yes** |
 | `clear` | Python-only |
 | `copy` | Python-only |
 | `difference` | No |
diff --git a/pyccel/codegen/printing/ccode.py b/pyccel/codegen/printing/ccode.py
index e11e9d8e..60437513 100644
--- a/pyccel/codegen/printing/ccode.py
+++ b/pyccel/codegen/printing/ccode.py
@@ -2519,6 +2519,12 @@ class CCodePrinter(CodePrinter):
     def _print_EmptyNode(self, expr):
         return ''
 
+    def _print_SetAdd(self, expr):
+        var_type = self.get_declare_type(expr.set_variable)
+        set_var = self._print(ObjectAddress(expr.set_variable))
+        arg = self._print(expr.args[0])
+        return f'{var_type}_push({set_var}, {arg});\n'
+
     #=================== OMP ==================
 
     def _print_OmpAnnotatedComment(self, expr):
diff --git a/pyccel/codegen/printing/fcode.py b/pyccel/codegen/printing/fcode.py
index 585a6dae..706157a3 100644
--- a/pyccel/codegen/printing/fcode.py
+++ b/pyccel/codegen/printing/fcode.py
@@ -1243,7 +1243,12 @@ class FCodePrinter(CodePrinter):
         return f'call {target} % push_back({arg})\n'
 
 
+    #========================== Set Methods ================================#
 
+    def _print_SetAdd(self, expr):
+        var = self._print(expr.set_variable)
+        insert_obj = self._print(expr.args[0])
+        return f'call {var} % insert( {insert_obj} )\n'
 
     #========================== Numpy Elements ===============================#
 


Test patch:
diff --git a/tests/epyccel/test_epyccel_sets.py b/tests/epyccel/test_epyccel_sets.py
index b6056dd7..455fd1a3 100644
--- a/tests/epyccel/test_epyccel_sets.py
+++ b/tests/epyccel/test_epyccel_sets.py
@@ -16,33 +16,33 @@ from pyccel import epyccel
 def python_only_language(request):
     return request.param
 
-def test_add_literal_int(python_only_language) :
+def test_add_literal_int(language) :
     def add_int():
         a = {1,3,45}
         a.add(4)
-        return a
-    epyc_add_element = epyccel(add_int, language = python_only_language)
+        return len(a)
+    epyc_add_element = epyccel(add_int, language = language)
     pyccel_result = epyc_add_element()
     python_result = add_int()
     assert python_result == pyccel_result
 
-def test_add_literal_complex(python_only_language) :
+def test_add_literal_complex(language) :
     def add_complex():
         a = {6j,7j,8j}
         a.add(9j)
-        return a
-    epyc_add_element = epyccel(add_complex, language = python_only_language)
+        return len(a)
+    epyc_add_element = epyccel(add_complex, language = language)
     pyccel_result = epyc_add_element()
     python_result = add_complex()
     assert python_result == pyccel_result
 
-def test_add_variable_int(python_only_language):
+def test_add_variable_int(language):
     def add_element_range():
         a = {1, 2, 3}
         for i in range(50, 100):
             a.add(i)
-        return a
-    epyc_add_element = epyccel(add_element_range, language = python_only_language)
+        return len(a)
+    epyc_add_element = epyccel(add_element_range, language = language)
     pyccel_result = epyc_add_element()
     python_result = add_element_range()
     assert python_result == pyccel_result
@@ -335,51 +335,39 @@ def test_set_copy_from_arg2(python_only_language):
     assert isinstance(python_result, type(pyccel_result))
     assert python_result == pyccel_result
 
-@pytest.fixture( params=[
-        pytest.param("fortran", marks = [
-            pytest.mark.skip(reason="set methods not implemented in fortran"),
-            pytest.mark.fortran]),
-        pytest.param("c", marks =  pytest.mark.c),
-        pytest.param("python", marks = pytest.mark.python)
-    ],
-    scope = "module"
-)
-def language_without_fortran(request):
-    return request.param
-
-def test_Pop_int(language_without_fortran):
+def test_Pop_int(stc_language):
     def Pop_int():
         se = {2, 4, 9}
         el1 = se.pop()
         el2 = se.pop()
         el3 = se.pop()
         return el1, el2, el3
-    epyccel_remove = epyccel(Pop_int, language = language_without_fortran)
+    epyccel_remove = epyccel(Pop_int, language = stc_language)
     pyccel_result = set(epyccel_remove())
     python_result = set(Pop_int())
     assert python_result == pyccel_result
 
-def test_Pop_float(language_without_fortran):
+def test_Pop_float(stc_language):
     def Pop_float():
         se = {2.3 , 4.1, 9.5}
         el1 = se.pop()
         el2 = se.pop()
         el3 = se.pop()
         return el1, el2, el3
-    epyccel_remove = epyccel(Pop_float, language = language_without_fortran)
+    epyccel_remove = epyccel(Pop_float, language = stc_language)
     pyccel_result = set(epyccel_remove())
     python_result = set(Pop_float())
     assert python_result == pyccel_result
 
 
-def test_Pop_complex(language_without_fortran):
+def test_Pop_complex(stc_language):
     def Pop_complex():
         se = {4j , 1j, 7j}
         el1 = se.pop()
         el2 = se.pop()
         el3 = se.pop()
         return el1, el2, el3
-    epyccel_remove = epyccel(Pop_complex, language = language_without_fortran)
+    epyccel_remove = epyccel(Pop_complex, language = stc_language)
     pyccel_result = set(epyccel_remove())
     python_result = set(Pop_complex())
     assert python_result == pyccel_result