From 29a8d2b9ce22ca792f39cce35ccb02fe4916e44e Mon Sep 17 00:00:00 2001
From: George Marchment <georgemarchment@yahoo.fr>
Date: Mon, 10 Feb 2025 16:13:22 +0100
Subject: [PATCH] Runs on all the test workflows

---
 src/block.py       |  59 +++++++++++-
 src/call.py        |  41 +++++++--
 src/condition.py   |   5 +-
 src/executor.py    |  41 ++++++---
 src/operation.py   |  97 +++++++++++---------
 src/outils.py      |  11 ++-
 src/root.py        | 221 +++++++++++++++++++++++++++++++++++++++------
 src/subworkflow.py |  36 ++++++--
 8 files changed, 399 insertions(+), 112 deletions(-)

diff --git a/src/block.py b/src/block.py
index 8fc620b..c58d05d 100644
--- a/src/block.py
+++ b/src/block.py
@@ -13,14 +13,67 @@ class Block(Root):
     def get_type(self):
         return "Root"
 
-    def get_channels(self):
-        return self.channels+self.origin.get_channels()
+    def same_condition(self, block):
+        return self.condition.same_condition(block.condition)
+
+    def get_blocks_with_same_conditions(self, condition):
+        tab = self.origin.get_blocks_with_same_conditions(self)
+        return tab
+
+    #def get_channels(self):
+    #    blocks_with_same_condition = self.get_blocks_with_same_conditions(self.condition)
+    #    channels_in_other_blocks = []
+    #    for b in blocks_with_same_condition:
+    #        channels_in_other_blocks+=b.channels
+    #    return self.channels+self.origin.get_channels()+channels_in_other_blocks
     
+    #This method returns all the executors of a block and the block above it
+    #As well as the executors with the same condition on the same level
     def get_executors(self):
-        return self.executors+self.origin.get_executors()
+        blocks_with_same_condition = self.get_blocks_with_same_conditions(self.condition)
+        executors_in_other_blocks = []
+        for b in blocks_with_same_condition:
+            executors_in_other_blocks+=b.executors
+        return self.executors+self.origin.get_executors()+executors_in_other_blocks
     
     def get_structure(self, dico):
         return super().get_structure(dico)
+    
+
+    #This method returns all the executors inside a block
+    def get_above_executors_rec(self, dico = {}):
+        for e in self.executors:
+            dico[e] = ''
+        self.origin.get_above_executors_rec(dico)
+
+    def get_above_executors(self, dico = {}):
+        self.origin.get_above_executors_rec(dico)
+        return list(dico.keys())
+        
+
+    def get_calls_above_level(self):
+        tab = []
+        for e in self.get_above_executors():
+            if(e.get_type()=="Call"):
+                tab.append(e)
+            elif(e.get_type()=="Operation"):
+                for o in e.get_origins():
+                    if(o.get_type()=="Call"):
+                        tab.append(o)
+        return tab
+
+    #############
+    # CHANNELS
+    #############
+    def get_channels_above_level_rec(self, dico = {}):
+        for c in self.channels:
+            dico[c] = ''
+        self.origin.get_channel_from_name_above_level_rec(dico)
+        
+    def get_channels_above_level(self, dico = {}):
+        dico = {}
+        self.origin.get_channels_above_level_rec(dico)
+        return list(dico.keys())
 
     #def check_in_channels(self, channel):
     #    for c in self.get_channels():
diff --git a/src/call.py b/src/call.py
index abdd3ba..7d47860 100644
--- a/src/call.py
+++ b/src/call.py
@@ -26,6 +26,17 @@ class Call(Executor):
         #It's important this is last
         #self.condition = Condition(self)
         
+    #This method returns all the calls inside a call eg p1(p2(), p3()) returns [p1(p2(), p3()), p2(), p3()]
+    def get_all_calls(self):
+        tab = []
+        tab.append(self)
+        for param in self.parameters:
+            if(param.get_type()=="Operation"):
+                for o in param.get_origins():
+                    if(o.get_type()=="Call"):
+                        tab+=o.get_all_calls()
+        return tab
+
 
     def add_to_emits(self, emitted):
         self.emits.append(emitted)
@@ -138,16 +149,26 @@ class Call(Executor):
                 #Case it's a channel
                 if(re.fullmatch(constant.WORD, param) and not analysed_param):
                 #if(re.fullmatch(constant.WORD, param) and not analysed_param or param in ['[]'] or param[:7]=="params."):
-                    from .channel import Channel
-                    channel = Channel(name=param, origin=self.origin)
-                    if(not self.origin.check_in_channels(channel)):
+                    
+                    channels = self.origin.get_channels_from_name_same_level(param)
+                    if(channels==[]):
+                        channels = self.origin.get_channels_from_name_inside_level(param)
+                    if(channels==[]):
+                        channels = self.origin.get_channels_from_name_above_level(param)
+                    if(channels==[]):
+                        from .channel import Channel
+                        channel = Channel(name=param, origin=self.origin)
                         self.origin.add_channel(channel)
-                    else:
-                        channel = self.origin.get_channel_from_name(param)
-                    #TODO -> check this
-                    channel.add_sink(self)
-                    self.parameters.append(channel)
+                        channels = [channel]
+                    from .operation import Operation
+                    ope = Operation(param, self)
+                    for channel in channels:
+                        channel.add_sink(self)
+                        ope.add_element_origins(channel)
+                    self.parameters.append(ope)
                     analysed_param = True
+                    
+                    
                 else:
                     from .executor import Executor
                     executor = Executor(param, self)
@@ -399,7 +420,7 @@ class Call(Executor):
                 if(self.get_duplicate_status()):
                     temp = subworkflow
                     subworkflow = subworkflow.copy()
-                    subworkflow.set_alias(subworkflow.get_alias())
+                    subworkflow.set_alias(temp.get_alias())
                 subworkflow.initialise()
                 self.first_element_called = subworkflow
                 self.origin.add_element_to_elements_being_called(subworkflow)
@@ -429,7 +450,7 @@ class Call(Executor):
         file.write("  "*(tab+1)+"* Called "+str(self.get_called())+"\n")
         file.write("  "*(tab+1)+"* Code : "+ str(self.get_code())+"\n")
         file.write("  "*(tab+1)+"* Parameters"+"\n")
-        for p in  self.parameters:
+        for p in self.parameters:
             file.write("  "*(tab+3)+p.get_code()+f" '{p.get_type()}'"+"\n")
         file.write("\n")
 
diff --git a/src/condition.py b/src/condition.py
index f081c01..243cca0 100644
--- a/src/condition.py
+++ b/src/condition.py
@@ -4,6 +4,9 @@ from .outils import extract_conditions
 class Condition:
     def __init__(self, origin, condition):
         self.origin = origin
-        self.condition = condition
+        self.value = condition
         #self.initialise()
 
+    def same_condition(self, condition):
+        return self.value == condition.value
+
diff --git a/src/executor.py b/src/executor.py
index 845b5ca..c7ada07 100644
--- a/src/executor.py
+++ b/src/executor.py
@@ -204,22 +204,35 @@ class Executor(Nextflow_Building_Blocks):
             return Call(self.get_code(), self.origin)
     
 
-    #Method which returns the call which calls the element called 
-    def get_call_by_name(self, name):
-        #This is an old comment:
-        #We get the calls that have already been analysed or which are currently being analysed
-        #for example "p(a.out)" -> the call for 'a' may not have been analysed yet
-        #In that case when calling "get_calls" -> we don't want to reanalyse the "p(a.out)"
-        
+    #Method which returns the calls which call the element called 
+    def get_calls_by_name(self, name):
+        tab = []
         if(self.origin.get_type() in ['Root', 'Block']):
-            for c in self.origin.get_calls():
-                #c.initialise()#Don't need to analyse the call cause the element called is already analysed when the call is created
-                if(c.first_element_called.get_alias()==name):
-                    return c
-            return None
-        
+            for call in self.origin.get_calls_same_level():
+                #call.initialise()
+                for c in call.get_all_calls():
+                    if(c.first_element_called.get_alias()==name):
+                        tab.append(c)
+                #if(c.first_element_called.get_alias()==name):
+                #    tab.append(c)
+            #Here it is important that BioFlow-Insight is not a Nextflow verificator
+            #Here i'm checking the call inside the block
+            if(len(tab)==0):
+                for call in self.origin.get_calls_inside_level():
+                    #call.initialise()
+                    for c in call.get_all_calls():
+                        if(c.first_element_called.get_alias()==name):
+                            tab.append(c)
+            if(len(tab)==0):
+                for call in self.origin.get_calls_above_level():
+                    #call.initialise()
+                    for c in call.get_all_calls():
+                        if(c.first_element_called.get_alias()==name):
+                            tab.append(c)
+            return tab
+
         else:
-            return self.origin.get_call_by_name(name)
+            return self.origin.get_calls_by_name(name)
 
 
 
diff --git a/src/operation.py b/src/operation.py
index b5add76..6bdd6d3 100644
--- a/src/operation.py
+++ b/src/operation.py
@@ -85,17 +85,31 @@ class Operation(Executor):
         #Check that the name is not the list of illegal words
         #and Check that the thing extarcted is not WorkflowNameFile like 'WorkflowHgtseq' in nf-core/hgtseq
         if(name not in constant.ERROR_WORDS_ORIGINS):# and name.lower()!=f"workflow{self.get_name_file().lower()}"):
-            channel = Channel(name=name, origin=self.origin)
+            #channel = Channel(name=name, origin=self.origin)
             if(self.origin.get_type()!="Subworkflow"):
-                if(not self.origin.check_in_channels(channel)):
-                        self.origin.add_channel(channel)
-                else:
-                    channel = self.origin.get_channel_from_name(name)
+                #First check that the channel is not defined at the same level
+                channels = self.origin.get_channels_from_name_same_level(name)
+                #Then check that the channel is defined in the below level
+                if(channels==[]):
+                    channels = self.origin.get_channels_from_name_inside_level(name)
+                #Finally check if the channels is defined above
+                if(channels==[]):
+                    channels = self.origin.get_channels_from_name_above_level(name)
+                #If it still doesn't exist -> we create it 
+                if(channels==[]):
+                    channel = Channel(name=name, origin=self.origin)
+                    self.origin.add_channel(channel)
+                    channels = [channel]
+
             else:
+                channel = Channel(name=name, origin=self.origin)
                 self.origin.takes_channels.append(channel)
-            self.origins.append(channel)
-            #channel.initialise()
-            channel.add_sink(self)
+                channels = [channel]
+            
+            for channel in channels:
+                self.origins.append(channel)
+                #channel.initialise()
+                channel.add_sink(self)
         
 
 
@@ -117,37 +131,21 @@ class Operation(Executor):
                 if( splited[-1] in constant.LIST_OPERATORS):
                     full_code = '.'.join(splited[:-1])
             if(name_called not in IGNORE_NAMES):
-                call = self.get_call_by_name(name_called)
-                #process = self.get_process_from_name(name_called)
-                #subworkflow = self.get_subworkflow_from_name(name_called)
-                #
-                #if(process!=None and subworkflow!=None):
-                #    raise Exception(f"Problem in get_element -> {name_called} exists as process and subworkflow")
-                ##Case subworkflow
-                #if(process==None and subworkflow!=None):
-                #    emitted = Emitted(name=full_code, origin=self.origin, emitted_by=subworkflow)
-                #    emitted.set_emits(name_emitted)
-                ##Case Process
-                #if(process!=None and subworkflow==None):
-                #    emitted = Emitted(name=full_code, origin=self.origin, emitted_by=process)
-                #    #TODO -> analyse the outputs of the process
-                #
-                #if(process==None and subworkflow==None):
-                #    if(name_called[:5]=="Call_"):
-                #        name_called = self.calls[name_called].get_code()
-                #    raise BioFlowInsightError(f"The call for '{name_called}' coudn't be found, before its use in the operation '{self.get_code(get_OG=True)}'{self.get_string_line(self.get_code(get_OG=True))}. Either because the call wasn't made before the operation or that the element it is calling doesn't exist.", num =8, origin=self)
-
-                if(call!=None):
-                    emitted = Emitted(name=full_code, origin=self.origin, emitted_by=call)
-                    emitted.set_emits(name_emitted)
+                calls = self.get_calls_by_name(name_called)
+
+                if(calls!=[]):
+                    for call in calls:
+                        emitted = Emitted(name=full_code, origin=self.origin, emitted_by=call)
+                        emitted.set_emits(name_emitted)
+                        emitted.add_sink(self)
+                        self.origins.append(emitted)
                 else:
                     if(name_called[:5]=="Call_"):
                         name_called = self.calls[name_called].get_code()
-                        raise BioFlowInsightError(f"The call for '{name_called}' coudn't be found, before its use in the operation '{self.get_code(get_OG=True)}'{self.get_string_line(self.get_code(get_OG=True))}. Either because the call wasn't made before the operation or that the element it is calling doesn't exist.", num =8, origin=self)
+                    raise BioFlowInsightError(f"The call for '{name_called}' coudn't be found, before its use in the operation '{self.get_code(get_OG=True)}'{self.get_string_line(self.get_code(get_OG=True))}. Either because the call wasn't made before the operation or that the element it is calling doesn't exist.", num =8, origin=self)
                     
 
-                emitted.add_sink(self)
-                self.origins.append(emitted)
+                
 
     #This methods checks if the input is an emit and adds it if it's the case, it also returns T/F if it's an emit
     def check_is_emit(self, name):
@@ -195,17 +193,28 @@ class Operation(Executor):
             raise Exception("This shoudn't happen! -> a call is taking a value")
         
         else:
-            print("here")
-            channel = Channel(name=name, origin=self.origin)
-            print(self.get_code(), name, self.get_file_address())
-            if(not self.origin.check_in_channels(channel)):
-                self.origin.add_channel(channel)
+            
+            origin = None
+            #Case the emited thing is an operation -> of type 'ch = existing_channel' 
+            if(self.origin.get_type()=="Subworkflow"):
+                origin = self.origin.root
             else:
-                channel = self.origin.get_channel_from_name(name)
-
-            self.gives.append(channel)
-            #channel.initialise()
-            channel.add_source(self)
+                origin = self.origin
+
+            channels = origin.get_channels_from_name_same_level(name)
+            if(channels==[]):
+                channels = origin.get_channels_from_name_inside_level(name)
+            if(channels==[]):
+                channels = origin.get_channels_from_name_above_level(name)
+            if(channels==[]):
+                channel = Channel(name=name, origin=self.origin)
+                origin.add_channel(channel)
+                channels = [channel]
+
+            for channel in channels:
+                self.gives.append(channel)
+                #channel.initialise()
+                channel.add_source(self)
 
     def add_origin(self, name):
         name = name.strip()
diff --git a/src/outils.py b/src/outils.py
index 84da880..f1bb04f 100644
--- a/src/outils.py
+++ b/src/outils.py
@@ -922,6 +922,7 @@ def is_git_directory(path = '.'):
 def extract_conditions(code):
 
     conditions_dico = {}
+    index_condition = 0
 
     start = 0
 
@@ -997,7 +998,8 @@ def extract_conditions(code):
                         conditions.append(condition)
                         end = extract_curly(code, match.span(0)[1]+start)#Here we nedd to add the start index since we're only working on a subpart of code 
                         start_inside, end_inside = match.span(0)[1]+start, end-1
-                        conditions_dico[condition] = (start_inside, end_inside)
+                        conditions_dico[f"{condition}$$__$${index_condition}"] = (start_inside, end_inside)
+                        index_condition+=1
                         #conditions_dico = adding_inside(conditions_dico, code, start_inside, end_inside)
                     break
                 searching_for_else = True
@@ -1016,7 +1018,8 @@ def extract_conditions(code):
                             start_else+=end
                             end_else = extract_curly(code, end_else+end)
                             start_inside, end_inside = match.span(0)[1]+end, end_else-1
-                            conditions_dico[condition] = (start_inside, end_inside)
+                            conditions_dico[f"{condition}$$__$${index_condition}"] = (start_inside, end_inside)
+                            index_condition+=1
                             #conditions_dico = adding_inside(conditions_dico, code, start_inside, end_inside)
                             break
                         #CASE of "else"
@@ -1026,7 +1029,9 @@ def extract_conditions(code):
                                 start_else+=end
                                 end_else = extract_curly(code, end_else+end)
                                 start_inside, end_inside = match.span(0)[1]+end, end_else-1
-                                conditions_dico[' && '.join(["!({})".format(v) for v in conditions])] = (start_inside, end_inside)
+                                condition = ' && '.join(["!({})".format(v) for v in conditions])
+                                conditions_dico[f"{condition}$$__$${index_condition}"] = (start_inside, end_inside)
+                                index_condition+=1
                                 #conditions_dico = adding_inside(conditions_dico, code, start_inside, end_inside)
 
                                 break
diff --git a/src/root.py b/src/root.py
index 24f7a31..2e585d7 100644
--- a/src/root.py
+++ b/src/root.py
@@ -19,43 +19,179 @@ class Root(Nextflow_Building_Blocks):
         self.elements_being_called = []
         self.channels = subworkflow_inputs
     
+
+    #############
+    #  GENERAL
+    #############
     def get_type(self):
         return "Root"
     
+    def get_blocks(self):
+        return self.blocks
+
     def add_element_to_elements_being_called(self, element):
         self.elements_being_called.append(element)
 
-    def check_in_channels(self, channel):
-        for c in self.get_channels():
-            if(c.equal(channel)):
-                return True
-        return False
+    def get_blocks_with_same_conditions(self, searching_block):
+        tab = []
+        for block in self.blocks:
+            if(block != searching_block):
+                if(block.same_condition(searching_block)):
+                    tab.append(block)
+        return tab
+
+
+    #############
+    # CHANNELS
+    #############
+
+    def get_channels_from_name_same_level(self, name):
+        tab = []
+        for c in self.channels:
+            if(c.get_name()==name):
+                tab.append(c)
+        return tab
+    
+    def get_channels_above_level(self):
+        return []
     
-    def get_channels(self):
-        return self.channels
-
-    def add_channel(self, channel):
-        if(not self.check_in_channels(channel)):
-            self.channels.append(channel)
-        else:
-            raise Exception("This shoudn't happen!")
+    def get_channels_above_level_rec(self, dico = {}):
+        for c in self.channels:
+            dico[c] = ''
+
+    def get_channels_from_name_above_level(self, name):
+        tab = []
+        for c in self.get_channels_above_level():
+            if(c.get_name()==name):
+                tab.append(c)
+        return tab
         
-    def get_channel_from_name(self, name):
-        for c in self.get_channels():
-            if(name == c.get_name()):
-                return c
-        #raise Exception(f"{name} is not in the list of channels")
-        return None
+    def get_channels_inside_level_rec(self, dico = {}):
+        for c in self.channels:
+            dico[c] = ''
+        for b in self.blocks:
+            b.get_channels_inside_level_rec(dico)
+    
+    def get_channels_inside_level(self):
+        dico = {}
+        for b in self.blocks:
+            b.get_channels_inside_level_rec(dico)
+        return list(dico.keys())
+    
+    def get_channels_from_name_inside_level(self, name):
+        tab = []
+        for c in self.get_channels_inside_level():
+            if(c.get_name()==name):
+                tab.append(c)
+        return tab
+
+
+
+
+
+    #def check_in_channels(self, channel):
+    #    for c in self.get_channels():
+    #        if(c.equal(channel)):
+    #            return True
+    #    for b in self.blocks:
+    #        if(b.check_in_channels(channel)):
+    #            return True
+    #    return False
     
-    def get_executors(self):
+
+    def add_channel(self, channel):        
+        self.channels.append(channel)
+
+        
+    #def get_channel_from_name(self, name):
+    #    for c in self.get_channels():
+    #        if(name == c.get_name()):
+    #            return c
+    #    return None
+    #    #tab = []
+    #    #for b in self.blocks:
+    #    #    channels = b.get_channel_from_name(name)
+    #    #    tab+=channels
+    #    #raise Exception(f"{name} is not in the list of channels")
+        
+    
+
+    #############
+    # EXECUTORS
+    #############
+    def get_executors_same_level(self):
         return self.executors
+    
+    def get_above_executors(self):
+        return []
+
+    def get_above_executors_rec(self, dico = {}):
+        for e in self.executors:
+            dico[e] = ''
+    
+    #This method returns all the executors inside a block
+    def get_inside_executors_rec(self, dico = {}):
+        for e in self.executors:
+            dico[e] = ''
+        for b in self.blocks:
+            b.get_inside_executors_rec(dico)
+    
+    def get_inside_executors(self):
+        dico = {}
+        for b in self.blocks:
+            b.get_inside_executors_rec(dico)
+        return list(dico.keys())
+
+    #def get_calls(self):
+    #    tab = []
+    #    for c in self.get_executors():
+    #        if(c.get_type()=="Call"):
+    #            tab.append(c)
+    #        elif(c.get_type()=="Operation"):
+    #            for o in c.get_origins():
+    #                if(o.get_type()=="Call"):
+    #                    tab.append(o)
+    #    return tab
+    
+    #############
+    #   CALLS
+    #############
 
-    def get_calls(self):
+    def get_calls_same_level(self):
         tab = []
-        for c in self.get_executors():
+        for c in self.executors:
             if(c.get_type()=="Call"):
                 tab.append(c)
+            elif(c.get_type()=="Operation"):
+                for o in c.get_origins():
+                    if(o.get_type()=="Call"):
+                        tab.append(o)
+        return tab
+    
+    def get_calls_above_level(self):
+        return []
+    
+    #This method returns all the calls inside a block
+    def get_calls_inside_level(self):
+        tab = []
+        executors = self.get_inside_executors()
+        for e in executors:
+            if(e.get_type()=="Call"):
+                tab.append(e)
+            elif(e.get_type()=="Operation"):
+                for o in e.get_origins():
+                    if(o.get_type()=="Call"):
+                        tab.append(o)
         return tab
+    
+
+
+
+    
+    
+    
+    
+    
 
     
     def initialise(self):
@@ -69,18 +205,49 @@ class Root(Nextflow_Building_Blocks):
         for c in conditions:
             from .block import Block
             body = code[conditions[c][0]:conditions[c][1]]
-            block = Block(code=body, origin=self, condition=c, modules_defined=self.modules_defined, existing_channels = self.channels)
+            c = c.split("$$__$$")[0]
+            import copy
+            block = Block(code=body, origin=self, condition=c, modules_defined=self.modules_defined, existing_channels = copy.copy(self.channels))
             self.blocks.append(block)
 
 
         self.extract_executors()
 
+        #TODO i need to sort the execution order out
+        position_2_thing_2_analyse = {}
         for block in self.blocks:
-            block.initialise()
-
-        #Analyse Executors
+            pos = code.find(block.get_code())
+            print(block.get_code())
+            print()
+            if(pos!=-1):
+                position_2_thing_2_analyse[pos] = block
+                code = code.replace(block.get_code(), "a"*len(block.get_code()), 1)
+            else:
+                raise Exception("This shouldn't happen")
         for e in self.executors:
-            e.initialise()
+            pos = code.find(e.get_code())
+            if(pos!=-1):
+                position_2_thing_2_analyse[pos] = e
+                code = code.replace(e.get_code(), "a"*len(e.get_code()))
+            else:
+                raise Exception("This shouldn't happen")
+            
+        sorted_position_2_thing_2_analyse = dict(sorted(position_2_thing_2_analyse.items()))
+        print(sorted_position_2_thing_2_analyse)
+        for key in sorted_position_2_thing_2_analyse:
+            element = sorted_position_2_thing_2_analyse[key]
+            element.initialise()
+
+
+        #for block in self.blocks:
+        #    print("block",code.find(block.get_code()))
+        #    #TODO -> this would be the place you put the verification of the conditions
+        #    block.initialise()
+        #
+        ##Analyse Executors
+        #for e in self.executors:
+        #    print(code.find(e.get_code()))
+        #    e.initialise()
 
         #Initialise each subworkflow being called
         #for sub in self.elements_being_called:
diff --git a/src/subworkflow.py b/src/subworkflow.py
index 07fb61e..432719d 100644
--- a/src/subworkflow.py
+++ b/src/subworkflow.py
@@ -43,12 +43,25 @@ class Subworkflow(Main):
         sub.called_by = []
         return sub
     
-    def get_call_by_name(self, name):
-        for c in self.root.get_calls():
-            #c.initialise()#Don't need to analyse the call cause the element called is already analysed when the call is created
-            if(c.first_element_called.get_alias()==name):
-                return c
-        return None
+    #TODO make sure this is uptodate
+    def get_calls_by_name(self, name):            
+        tab = []
+        for call in self.root.get_calls_same_level():
+            #call.initialise()
+            for c in call.get_all_calls():
+                if(c.first_element_called.get_alias()==name):
+                    tab.append(c)
+
+
+        #Here it is important that BioFlow-Insight is not a Nextflow verificator
+        #Here i'm checking the call inside the block
+        if(len(tab)!=0):
+            for c in self.root.get_calls_inside_level():
+                #call.initialise()
+                for c in call.get_all_calls():
+                    if(c.first_element_called.get_alias()==name):
+                        tab.append(c)
+        return tab
         
 
     def add_to_emits(self, emit):
@@ -193,12 +206,15 @@ class Subworkflow(Main):
             for i in range(len(code)):
                 code[i] = code[i].strip()
                 if(code[i]!=""):
-                    channel = self.root.get_channel_from_name(code[i])
-                    if(channel!=None):
+                    channels = self.root.get_channels_from_name_same_level(code[i])
+                    if(channels==[]):
+                        channels = self.root.get_channels_from_name_inside_level(code[i])
+                    if(channels!=[]):
                         ope = Operation(code=f"emit: {code[i]}", origin=self)
                         ope.set_as_artificial()
-                        ope.add_element_origins(channel)
-                        channel.add_sink(ope)
+                        for channel in channels:
+                            ope.add_element_origins(channel)
+                            channel.add_sink(ope)
                         tab.append(ope)
                         
                     else:
-- 
GitLab