Repository: stfc/PSyclone (python)

Issue:
Schedule.debug_string() defaults to str() and FortranWriter raises an error on it.
`Schedule.debug_string()` defaults to `Node.debug_string()` which uses `DebugWriter` and defaults to `str()`.
`FortranWriter()(schedule)` raises a `VisitorError`.

Script:
```python

from psyclone.psyir.frontend.fortran import FortranReader
from psyclone.psyir.backend.fortran import FortranWriter
from psyclone.psyir.nodes import Schedule

reader = FortranReader()
writer = FortranWriter()

assignment_1 = "a = 1"
assignment_2 = "b = 2"

schedule = Schedule()
schedule.addchild(reader.psyir_from_statement(assignment_1))
schedule.addchild(reader.psyir_from_statement(assignment_2))
assert isinstance(schedule, Schedule)

print("Debug string of the Schedule:")
print(schedule.debug_string())

print("Fortran writer output:")
print(writer(schedule))
```

Output:
```bash
Debug string of the Schedule:
< Schedule:
Assignment[]
Reference[name:'a']Literal[value:'1', Scalar<INTEGER, UNDEFINED>]
Assignment[]
Reference[name:'b']Literal[value:'2', Scalar<INTEGER, UNDEFINED>]
End Schedule >

Fortran writer output:
Traceback (most recent call last):
  File "/home/julien/schedule_debug_string.py", line 20, in <module>
    print(writer(schedule))
          ^^^^^^^^^^^^^^^^
  File "/home/julien/miniconda3/lib/python3.12/site-packages/psyclone/psyir/backend/visitor.py", line 199, in __call__
    return self._visit(lowered_node)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/julien/miniconda3/lib/python3.12/site-packages/psyclone/psyir/backend/visitor.py", line 304, in _visit
    raise VisitorError(
psyclone.psyir.backend.visitor.VisitorError: Visitor Error: Unsupported node 'Schedule' found: method names attempted were ['schedule_node', 'scopingnode_node', 'node_node'].
```

In my opinion both should output:
```fortran
a = 1
b = 2
```

Pull request:
(Closes #2624) Add `FortranWriter().schedule_node()`.
Avoids defaulting to `str(schedule)` for `Schedule().debug_string()` and raising a `VisitorError` using `FortranWriter()(Schedule())`.

Patch:
diff --git a/changelog b/changelog
index c9f4885d5..2abfa78a0 100644
--- a/changelog
+++ b/changelog
@@ -317,6 +317,8 @@
 	119) PR #2775. Adds Call.get_callee() which matches the arguments of
 	a Call against the signature of potential callees.
 
+	120) PR #2628 for #2624. Improves debug_string output for Schedules.
+
 release 2.5.0 14th of February 2024
 
 	1) PR #2199 for #2189. Fix bugs with missing maps in enter data
diff --git a/src/psyclone/psyir/backend/fortran.py b/src/psyclone/psyir/backend/fortran.py
index e42e77dc9..743352628 100644
--- a/src/psyclone/psyir/backend/fortran.py
+++ b/src/psyclone/psyir/backend/fortran.py
@@ -1742,3 +1742,19 @@ class FortranWriter(LanguageWriter):
             result_list.append(self._visit(child))
         args = ", ".join(result_list)
         return f"{node.name}({args})"
+
+    def schedule_node(self, node):
+        '''
+        Translate the Schedule node into Fortran.
+
+        :param node: the PSyIR node to translate.
+        :type node: :py:class:`psyclone.psyir.nodes.Schedule`
+
+        :returns: the equivalent Fortran code.
+        :rtype: str
+
+        '''
+        result = ""
+        for child in node.children:
+            result += self._visit(child)
+        return result


Test patch:
diff --git a/src/psyclone/tests/psyir/backend/fortran_test.py b/src/psyclone/tests/psyir/backend/fortran_test.py
index 32c6b3807..d51fbfd52 100644
--- a/src/psyclone/tests/psyir/backend/fortran_test.py
+++ b/src/psyclone/tests/psyir/backend/fortran_test.py
@@ -2035,3 +2035,24 @@ def test_pointer_assignments(fortran_reader, fortran_writer):
     assert "a = 4" in code
     assert "b => a" in code
     assert "field(3,c)%pointer => b" in code
+
+
+def test_fw_schedule(fortran_reader, fortran_writer):
+    '''Test that the FortranWriter correctly handles a Schedule node.
+
+    '''
+    routine_header = ("subroutine foo()\n"
+                      "real :: a, b, c\n")
+    test_code = (
+        "a = b\n"
+        "b = c\n"
+        "call bar(a)\n"
+    )
+    routine_end = "end subroutine foo\n"
+    routine_code = routine_header + test_code + routine_end
+    schedule = Schedule()
+    routine = fortran_reader.psyir_from_source(routine_code).children[0]
+    for child in routine.children:
+        schedule.addchild(child.copy().detach())
+    result = fortran_writer(schedule)
+    assert result == test_code