From b3054538d81d217413dd4a14bbd5f743c1eca85c Mon Sep 17 00:00:00 2001
From: Tim Jammer <tim.jammer@tu-darmstadt.de>
Date: Mon, 5 Feb 2024 13:40:01 +0100
Subject: [PATCH] implemented List cases for managing list of Instructions (see
 !7)

---
 scripts/Infrastructure/InstructionBlock.py | 86 ++++++++++++++--------
 1 file changed, 55 insertions(+), 31 deletions(-)

diff --git a/scripts/Infrastructure/InstructionBlock.py b/scripts/Infrastructure/InstructionBlock.py
index a0119fa48..05b8a16b3 100644
--- a/scripts/Infrastructure/InstructionBlock.py
+++ b/scripts/Infrastructure/InstructionBlock.py
@@ -33,29 +33,35 @@ class InstructionBlock:
         assert not isinstance(name, int)
         self.name = name
 
-    # TODO test if op also can be a list of operations
     def register_operation(self, op: Instruction | typing.List[Instruction], kind: str | int = 'all'):
         """
         Registers an operation based on rank.
 
         Parameters:
-            - op: The operation to register.
+            - op: The operation (or list of Operations) to register.
             - kind: Rank to execute the operation ('all', 'not0', or integer).
                 - all: all Ranks execute this operation
                 - not0: all Ranks but the Root (rank 0) execute
                 - Or the integer of the rank that should execute
         """
         if kind == 'all':
-            self.operations['all'].append(op)
+            if isinstance(op, list):
+                self.operations['all'].extend(op)
+            else:
+                self.operations['all'].append(op)
         elif kind == 'not0':
-            self.operations['not0'].append(op)
+            if isinstance(op, list):
+                self.operations['not0'].extend(op)
+            else:
+                self.operations['not0'].append(op)
         else:
             as_int = int(kind)  # will Raise ValueError if not integer
             if as_int not in self.operations:
                 self.operations[as_int] = []
-            self.operations[as_int].append(op)
-
-    # TODO implement list part
+            if isinstance(op, list):
+                self.operations[as_int].extend(op)
+            else:
+                self.operations[as_int].append(op)
 
     def get_version(self) -> str:
         """
@@ -101,7 +107,7 @@ class InstructionBlock:
         Checks if the Block has an operation with the given index and kind
         Parameters:
             - kind ('all','not0' or integer): which ranks should execute the operation
-            - index (int): the index of the operation within the given kind
+            - index (int ): the index of the operation within the given kind
         Returns:
             boolean
         """
@@ -111,55 +117,73 @@ class InstructionBlock:
         except (KeyError, IndexError) as e:
             return False
 
-    def get_operation(self, kind: int | str = 'all', index: int = 0) -> Instruction | typing.List[Instruction]:
+    def get_operation(self, kind: int | str = 'all', index: str | int = 0) -> Instruction | typing.List[Instruction]:
         """
         Retrieve the operation registered. will Raise IndexError if not present
         Parameters:
             - kind ('all','not0' or integer): which ranks should execute the operation
-            - index (int): the index of the operation within the given kind
+            - index ('all' or int): the index of the operation within the given kind; 'all' means that the list of all operations for the kind is returned
         Returns:
             str: The operation specified by kind and index
         """
-        return self.operations[kind][index]
-
-    # todo implement list case
+        if index == 'all':
+            return self.operations[kind]
+        else:
+            as_int = int(index)  # will Raise ValueError if not integer
+            return self.operations[kind][as_int]
 
-    def replace_operation(self, op: Instruction | typing.List[Instruction], kind: str | int = 'all', index: int = 0):
+    def replace_operation(self, op: Instruction | typing.List[Instruction], kind: str | int = 'all',
+                          index: str | int = 0):
         """
         Replace the operation registered. will Raise IndexError if not present
         Parameters:
-            - op (str or MPICall) the new operation
+            - op the new operation or list of operations
             - kind ('all','not0' or integer): which ranks should execute the operation
-            - index (int): the index of the operation within the given kind
-        """
-        if len(self.operations[kind]) < index:
-            raise IndexError("Operation Not Found")
-        self.operations[kind][index] = op
-
-    # todo implement list caee
+            - index ('all' or int): the index of the operation within the given kind; 'all' means all operations will be replaced with the given list
+        Notes : if one wants to replace all operations one needs to provide a list
+        if one only wants to replace one operation: no list of operations is allowed
+        """
+        if index == 'all':
+            if not isinstance(op, list):
+                raise ValueError('Provide List for replacement')
+            self.operations[kind] = op
+        else:
+            as_int = int(index)  # will Raise ValueError if not integer
+            if not isinstance(op, Instruction):
+                raise ValueError('Provide Instruction')
+            if len(self.operations[kind]) < as_int:
+                raise IndexError("Operation Not Found")
+            self.operations[kind][as_int] = op
 
     def insert_operation(self, op: Instruction | typing.List[Instruction], kind: str | int = 'all',
                          before_index: int = 0):
         """
         Inserts an operation before the specified one. will Raise IndexError if not present
         Parameters:
-            - op (str or MPICall) the new operation
+            - op  the new operation or list of operations
             - kind ('all','not0' or integer): which ranks should execute the operation
             - index (int): the index of the operation within the given kind
         """
+        as_int = int(before_index)  # will Raise ValueError if not integer
         if len(self.operations[kind]) < before_index:
             raise IndexError("Operation Not Found")
-        self.operations[kind].insert(before_index, op)
-
-    # todo implement list caee
+        if isinstance(op, list):
+            self.operations[kind] = (
+                    self.operations[kind][0:before_index - 1] + op + self.operations[kind][before_index:])
+        else:
+            self.operations[kind].insert(before_index, op)
 
-    def remove_operation(self, kind: str | int = 'all', index: int = 0):
+    def remove_operation(self, kind: str | int = 'all', index: str | int = 0):
         """
         Removes the operation registered. will Raise IndexError if not present
         Parameters:
             - kind ('all','not0' or integer): which ranks should execute the operation
-            - index (int): the index of the operation within the given kind
+            - index ('all' or int): the index of the operation within the given kind
         """
-        if len(self.operations[kind]) < index:
-            raise IndexError("Operation Not Found")
-        del self.operations[kind][index]
+        if index == 'all':
+            self.operations[kind] = []
+        else:
+            as_int = int(index)  # will Raise ValueError if not integer
+            if len(self.operations[kind]) < index:
+                raise IndexError("Operation Not Found")
+            del self.operations[kind][index]
-- 
GitLab