Fixed declaration and ST code gen for IEC function that return derivated types
authorEdouard Tisserant
Thu, 12 Jun 2014 17:50:30 +0200
changeset 1418 c97dc5281419
parent 1417 374238039643
child 1419 d6adca8b6697
Fixed declaration and ST code gen for IEC function that return derivated types
PLCControler.py
PLCGenerator.py
--- a/PLCControler.py	Wed Jun 11 19:01:17 2014 +0200
+++ b/PLCControler.py	Thu Jun 12 17:50:30 2014 +0200
@@ -1467,7 +1467,7 @@
                 else:
                     derived_type = PLCOpenParser.CreateElement("derived", "dataType")
                     derived_type.setname(return_type)
-                    return_type.setcontent(derived_type)
+                    return_type_obj.setcontent(derived_type)
 
     def UpdateProjectUsedPous(self, old_name, new_name):
         if self.Project is not None:
--- a/PLCGenerator.py	Wed Jun 11 19:01:17 2014 +0200
+++ b/PLCGenerator.py	Thu Jun 12 17:50:30 2014 +0200
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 
 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor
-#based on the plcopen standard. 
+#based on the plcopen standard.
 #
 #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
 #
@@ -27,14 +27,14 @@
 from types import *
 import re
 
-# Dictionary associating PLCOpen variable categories to the corresponding 
+# Dictionary associating PLCOpen variable categories to the corresponding
 # IEC 61131-3 variable categories
-varTypeNames = {"localVars" : "VAR", "tempVars" : "VAR_TEMP", "inputVars" : "VAR_INPUT", 
+varTypeNames = {"localVars" : "VAR", "tempVars" : "VAR_TEMP", "inputVars" : "VAR_INPUT",
                 "outputVars" : "VAR_OUTPUT", "inOutVars" : "VAR_IN_OUT", "externalVars" : "VAR_EXTERNAL",
                 "globalVars" : "VAR_GLOBAL", "accessVars" : "VAR_ACCESS"}
 
 
-# Dictionary associating PLCOpen POU categories to the corresponding 
+# Dictionary associating PLCOpen POU categories to the corresponding
 # IEC 61131-3 POU categories
 pouTypeNames = {"function" : "FUNCTION", "functionBlock" : "FUNCTION_BLOCK", "program" : "PROGRAM"}
 
@@ -125,16 +125,16 @@
         if not self.DatatypeComputed.get(datatype_name, True):
             # If not mark data type as computed
             self.DatatypeComputed[datatype_name] = True
-            
+
             # Getting datatype model from project
             datatype = self.Project.getdataType(datatype_name)
             tagname = self.Controler.ComputeDataTypeName(datatype.getname())
-            datatype_def = [("  ", ()), 
+            datatype_def = [("  ", ()),
                             (datatype.getname(), (tagname, "name")),
                             (" : ", ())]
             basetype_content = datatype.baseType.getcontent()
             basetype_content_type = basetype_content.getLocalTag()
-            # Data type derived directly from a user defined type 
+            # Data type derived directly from a user defined type
             if basetype_content_type == "derived":
                 basetype_name = basetype_content.getname()
                 self.GenerateDataType(basetype_name)
@@ -143,11 +143,11 @@
             elif basetype_content_type in ["subrangeSigned", "subrangeUnsigned"]:
                 base_type = basetype_content.baseType.getcontent()
                 base_type_type = base_type.getLocalTag()
-                # Subrange derived directly from a user defined type 
+                # Subrange derived directly from a user defined type
                 if base_type_type == "derived":
                     basetype_name = base_type_type.getname()
                     self.GenerateDataType(basetype_name)
-                # Subrange derived directly from an elementary type 
+                # Subrange derived directly from an elementary type
                 else:
                     basetype_name = base_type_type
                 min_value = basetype_content.range.getlower()
@@ -162,7 +162,7 @@
             elif basetype_content_type == "enum":
                 values = [[(value.getname(), (tagname, "value", i))]
                           for i, value in enumerate(
-                              basetype_content.xpath("ppx:values/ppx:value", 
+                              basetype_content.xpath("ppx:values/ppx:value",
                                   namespaces=PLCOpenParser.NSMAP))]
                 datatype_def += [("(", ())]
                 datatype_def += JoinList([(", ", ())], values)
@@ -171,16 +171,16 @@
             elif basetype_content_type == "array":
                 base_type = basetype_content.baseType.getcontent()
                 base_type_type = base_type.getLocalTag()
-                # Array derived directly from a user defined type 
+                # Array derived directly from a user defined type
                 if base_type_type == "derived":
                     basetype_name = base_type.getname()
                     self.GenerateDataType(basetype_name)
-                # Array derived directly from an elementary type 
+                # Array derived directly from an elementary type
                 else:
                     basetype_name = base_type_type.upper()
                 dimensions = [[("%s"%dimension.getlower(), (tagname, "range", i, "lower")),
                                ("..", ()),
-                               ("%s"%dimension.getupper(), (tagname, "range", i, "upper"))] 
+                               ("%s"%dimension.getupper(), (tagname, "range", i, "upper"))]
                               for i, dimension in enumerate(basetype_content.getdimension())]
                 datatype_def += [("ARRAY [", ())]
                 datatype_def += JoinList([(",", ())], dimensions)
@@ -192,24 +192,24 @@
                 for i, element in enumerate(basetype_content.getvariable()):
                     element_type = element.type.getcontent()
                     element_type_type = element_type.getLocalTag()
-                    # Structure element derived directly from a user defined type 
+                    # Structure element derived directly from a user defined type
                     if element_type_type == "derived":
                         elementtype_name = element_type.getname()
                         self.GenerateDataType(elementtype_name)
                     elif element_type_type == "array":
                         base_type = element_type.baseType.getcontent()
                         base_type_type = base_type.getLocalTag()
-                        # Array derived directly from a user defined type 
+                        # Array derived directly from a user defined type
                         if base_type_type == "derived":
                             basetype_name = base_type.getname()
                             self.GenerateDataType(basetype_name)
-                        # Array derived directly from an elementary type 
+                        # Array derived directly from an elementary type
                         else:
                             basetype_name = base_type_type.upper()
                         dimensions = ["%s..%s" % (dimension.getlower(), dimension.getupper())
                                       for dimension in element_type.getdimension()]
                         elementtype_name = "ARRAY [%s] OF %s" % (",".join(dimensions), basetype_name)
-                    # Structure element derived directly from an elementary type 
+                    # Structure element derived directly from an elementary type
                     else:
                         elementtype_name = element_type_type.upper()
                     element_text = [("\n    ", ()),
@@ -224,7 +224,7 @@
                 datatype_def += [("STRUCT", ())]
                 datatype_def += JoinList([("", ())], elements)
                 datatype_def += [("\n  END_STRUCT", ())]
-            # Data type derived directly from a elementary type 
+            # Data type derived directly from a elementary type
             else:
                 datatype_def += [(basetype_content_type.upper(), (tagname, "base"))]
             # Data type has an initial value
@@ -240,7 +240,7 @@
         if not self.PouComputed.get(pou_name, True):
             # If not mark POU as computed
             self.PouComputed[pou_name] = True
-            
+
             # Getting POU model from project
             pou = self.Project.getpou(pou_name)
             pou_type = pou.getpouType()
@@ -252,14 +252,14 @@
                 self.Program += program
             else:
                 raise PLCGenException, _("Undefined pou type \"%s\"")%pou_type
-    
+
     # Generate a POU defined and used in text
     def GeneratePouProgramInText(self, text):
         for pou_name in self.PouComputed.keys():
             model = re.compile("(?:^|[^0-9^A-Z])%s(?:$|[^0-9^A-Z])"%pou_name.upper())
             if model.search(text) is not None:
                 self.GeneratePouProgram(pou_name)
-    
+
     # Generate a configuration from its model
     def GenerateConfiguration(self, configuration):
         tagname = self.Controler.ComputeConfigurationName(configuration.getname())
@@ -267,20 +267,20 @@
                   (configuration.getname(), (tagname, "name")),
                   ("\n", ())]
         var_number = 0
-        
+
         varlists = [(varlist, varlist.getvariable()[:]) for varlist in configuration.getglobalVars()]
-        
+
         extra_variables = self.Controler.GetConfigurationExtraVariables()
         extra_global_vars = None
         if len(extra_variables) > 0 and len(varlists) == 0:
             extra_global_vars = PLCOpenParser.CreateElement("globalVars", "interface")
             configuration.setglobalVars([extra_global_vars])
             varlists = [(extra_global_vars, [])]
-            
+
         for variable in extra_variables:
             varlists[-1][0].appendvariable(variable)
             varlists[-1][1].append(variable)
-            
+
         # Generate any global variable in configuration
         for varlist, varlist_variables in varlists:
             variable_type = errorVarTypes.get("VAR_GLOBAL", "var_local")
@@ -301,7 +301,7 @@
                     self.GenerateDataType(var_type)
                 else:
                     var_type = var.gettypeAsText()
-                
+
                 config += [("    ", ()),
                            (var.getname(), (tagname, variable_type, var_number, "name")),
                            (" ", ())]
@@ -321,19 +321,19 @@
                 config += [(";\n", ())]
                 var_number += 1
             config += [("  END_VAR\n", ())]
-        
+
         if extra_global_vars is not None:
             configuration.remove(extra_global_vars)
         else:
             for variable in extra_variables:
                 varlists[-1][0].remove(variable)
-        
+
         # Generate any resource in the configuration
         for resource in configuration.getresource():
             config += self.GenerateResource(resource, configuration.getname())
         config += [("END_CONFIGURATION\n", ())]
         return config
-    
+
     # Generate a resource from its model
     def GenerateResource(self, resource, config_name):
         tagname = self.Controler.ComputeConfigurationResourceName(config_name, resource.getname())
@@ -361,7 +361,7 @@
                     self.GenerateDataType(var_type)
                 else:
                     var_type = var.gettypeAsText()
-                
+
                 resrce += [("      ", ()),
                            (var.getname(), (tagname, variable_type, var_number, "name")),
                            (" ", ())]
@@ -413,7 +413,7 @@
 ##                    resrce += [("%dms"%(interval.microsecond / 1000), (tagname, "task", task_number, "interval", "millisecond"))]
 ##                resrce += [(",", ())]
             # Priority argument
-            resrce += [("PRIORITY := ", ()), 
+            resrce += [("PRIORITY := ", ()),
                        ("%d"%task.getpriority(), (tagname, "task", task_number, "priority")),
                        (");\n", ())]
             task_number += 1
@@ -439,16 +439,16 @@
             instance_number += 1
         resrce += [("  END_RESOURCE\n", ())]
         return resrce
-    
+
     # Generate the entire program for current project
-    def GenerateProgram(self):        
+    def GenerateProgram(self):
         # Find all data types defined
         for datatype in self.Project.getdataTypes():
             self.DatatypeComputed[datatype.getname()] = False
         # Find all data types defined
         for pou in self.Project.getpous():
             self.PouComputed[pou.getname()] = False
-        # Generate data type declaration structure if there is at least one data 
+        # Generate data type declaration structure if there is at least one data
         # type defined
         if len(self.DatatypeComputed) > 0:
             self.Program += [("TYPE\n", ())]
@@ -462,7 +462,7 @@
         # Generate every configurations defined
         for config in self.Project.getconfigurations():
             self.Program += self.GenerateConfiguration(config)
-    
+
     # Return generated program
     def GetGeneratedProgram(self):
         return self.Program
@@ -481,18 +481,18 @@
 [ContactClass, CoilClass, LeftPowerRailClass, RightPowerRailClass] = [
     PLCOpenParser.GetElementClass(instance_name, "ldObjects")
     for instance_name in ["contact", "coil", "leftPowerRail", "rightPowerRail"]]
-[StepClass, TransitionClass, JumpStepClass, 
+[StepClass, TransitionClass, JumpStepClass,
  SelectionConvergenceClass, SelectionDivergenceClass,
  SimultaneousConvergenceClass, SimultaneousDivergenceClass] = [
     PLCOpenParser.GetElementClass(instance_name, "sfcObjects")
-    for instance_name in ["step", "transition", "jumpStep", 
+    for instance_name in ["step", "transition", "jumpStep",
         "selectionConvergence", "selectionDivergence",
         "simultaneousConvergence", "simultaneousDivergence"]]
 TransitionObjClass = PLCOpenParser.GetElementClass("transition", "transitions")
 ActionObjClass = PLCOpenParser.GetElementClass("action", "actions")
 
 class PouProgramGenerator:
-    
+
     # Create a new POU program generator
     def __init__(self, parent, name, type, errors, warnings):
         # Keep Reference to the parent generator
@@ -514,22 +514,22 @@
         self.Program = []
         self.Errors = errors
         self.Warnings = warnings
-    
+
     def GetBlockType(self, type, inputs=None):
         return self.ParentGenerator.Controler.GetBlockType(type, inputs)
-    
+
     def IndentLeft(self):
         if len(self.CurrentIndent) >= 2:
             self.CurrentIndent = self.CurrentIndent[:-2]
-    
+
     def IndentRight(self):
         self.CurrentIndent += "  "
-    
+
     # Generator of unique ID for inline actions
     def GetActionNumber(self):
         self.ActionNumber += 1
         return self.ActionNumber
-    
+
     # Test if a variable has already been defined
     def IsAlreadyDefined(self, name):
         for list_type, option, located, vars in self.Interface:
@@ -537,7 +537,7 @@
                 if name == var_name:
                     return True
         return False
-    
+
     # Return the type of a variable defined in interface
     def GetVariableType(self, name):
         parts = name.split('.')
@@ -569,18 +569,18 @@
                                 current_type = element["Type"]
                                 break
         return current_type
-    
+
     # Return connectors linked by a connection to the given connector
     def GetConnectedConnector(self, connector, body):
         links = connector.getconnections()
         if links is not None and len(links) == 1:
             return self.GetLinkedConnector(links[0], body)
-        return None        
+        return None
 
     def GetLinkedConnector(self, link, body):
         parameter = link.getformalParameter()
         instance = body.getcontentInstance(link.getrefLocalId())
-        if isinstance(instance, (InVariableClass, InOutVariableClass, 
+        if isinstance(instance, (InVariableClass, InOutVariableClass,
              ContinuationClass, ContactClass, CoilClass)):
             return instance.connectionPointOut
         elif isinstance(instance, BlockClass):
@@ -610,13 +610,13 @@
                     if point.x == powerrailposition.x + relposition[0] and point.y == powerrailposition.y + relposition[1]:
                         return outputconnection
         return None
-        
+
     def ExtractRelatedConnections(self, connection):
         for i, related in enumerate(self.RelatedConnections):
             if connection in related:
                 return self.RelatedConnections.pop(i)
         return [connection]
-    
+
     def ComputeInterface(self, pou):
         interface = pou.getinterface()
         if interface is not None:
@@ -626,7 +626,7 @@
             body_content = body.getcontent()
             body_type = body_content.getLocalTag()
             if self.Type == "FUNCTION":
-                returntype_content = interface.getreturnType().getcontent()
+                returntype_content = interface.getreturnType()[0]
                 returntype_content_type = returntype_content.getLocalTag()
                 if returntype_content_type == "derived":
                     self.ReturnType = returntype_content.getname()
@@ -680,7 +680,7 @@
                     self.Interface.append((varTypeNames[varlist_type], option, False, variables))
                 if len(located) > 0:
                     self.Interface.append((varTypeNames[varlist_type], option, True, located))
-    
+
     LITERAL_TYPES = {
         "T": "TIME",
         "D": "DATE",
@@ -699,11 +699,11 @@
         if body_type in ["FBD", "LD", "SFC"]:
             undefined_blocks = []
             for instance in body.getcontentInstances():
-                if isinstance(instance, (InVariableClass, OutVariableClass, 
+                if isinstance(instance, (InVariableClass, OutVariableClass,
                                          InOutVariableClass)):
                     expression = instance.getexpression()
                     var_type = self.GetVariableType(expression)
-                    if (isinstance(pou, TransitionObjClass) 
+                    if (isinstance(pou, TransitionObjClass)
                         and expression == pou.getname()):
                         var_type = "BOOL"
                     elif (not isinstance(pou, (TransitionObjClass, ActionObjClass)) and
@@ -718,7 +718,7 @@
                         parts = expression.split("#")
                         if len(parts) > 1:
                             literal_prefix = parts[0].upper()
-                            var_type = self.LITERAL_TYPES.get(literal_prefix, 
+                            var_type = self.LITERAL_TYPES.get(literal_prefix,
                                                               literal_prefix)
                         elif expression.startswith("'"):
                             var_type = "STRING"
@@ -822,7 +822,7 @@
                     self.TagName = self.ParentGenerator.Controler.ComputePouTransitionName(self.Name, transition.getname())
                     self.ComputeConnectionTypes(transition)
                 self.TagName = previous_tagname
-                
+
     def ComputeBlockInputTypes(self, instance, block_infos, body):
         undefined = {}
         for variable in instance.outputVariables.getvariable():
@@ -883,7 +883,7 @@
         if body_type in ["IL","ST"]:
             text = body_content.getanyText()
             self.ParentGenerator.GeneratePouProgramInText(text.upper())
-            self.Program = [(ReIndentText(text, len(self.CurrentIndent)), 
+            self.Program = [(ReIndentText(text, len(self.CurrentIndent)),
                             (self.TagName, "body", len(self.CurrentIndent)))]
         elif body_type == "SFC":
             self.IndentRight()
@@ -966,7 +966,7 @@
                             self.Program += [(self.CurrentIndent, ())]
                             self.Program += [(instance.getvariable(), coil_info + ("reference",))]
                             self.Program += [(" := ", ())] + expression + [(";\n", ())]
-                        
+
     def FactorizePaths(self, paths):
         same_paths = {}
         uncomputed_index = range(len(paths))
@@ -984,7 +984,7 @@
             if len(elements) > 1:
                 elements_paths = self.FactorizePaths([path for path, num in elements])
                 if len(elements_paths) > 1:
-                    factorized_paths.append([tuple(elements_paths)] + eval(same_path))        
+                    factorized_paths.append([tuple(elements_paths)] + eval(same_path))
                 else:
                     factorized_paths.append(elements_paths + eval(same_path))
                 for path, num in elements:
@@ -1013,7 +1013,7 @@
                 self.ComputedBlocks[block] = True
                 connected_vars = []
                 if not block_infos["extensible"]:
-                    input_connected = dict([("EN", None)] + 
+                    input_connected = dict([("EN", None)] +
                                            [(input_name, None) for input_name in input_names])
                     for variable in input_variables:
                         parameter = variable.getformalParameter()
@@ -1071,7 +1071,7 @@
                             else:
                                 self.Interface[-1][3].append(("ANY", variable_name, None, None))
                             if len(output_variables) > 1 and parameter not in ["", "OUT"]:
-                                vars.append([(parameter, (self.TagName, "block", block.getlocalId(), "output", i)), 
+                                vars.append([(parameter, (self.TagName, "block", block.getlocalId(), "output", i)),
                                              (" => %s"%variable_name, ())])
                             else:
                                 output_info = (self.TagName, "block", block.getlocalId(), "output", i)
@@ -1105,19 +1105,19 @@
                             if expression is not None:
                                 vars.append([(parameter, input_info),
                                              (" := ", ())] + self.ExtractModifier(variable, expression, input_info))
-                self.Program += [(self.CurrentIndent, ()), 
+                self.Program += [(self.CurrentIndent, ()),
                                  (name, (self.TagName, "block", block.getlocalId(), "name")),
                                  ("(", ())]
                 self.Program += JoinList([(", ", ())], vars)
                 self.Program += [(");\n", ())]
-        
+
         if link is not None:
             connectionPoint = link.getposition()[-1]
             output_parameter = link.getformalParameter()
         else:
             connectionPoint = None
             output_parameter = None
-        
+
         output_variable = None
         output_idx = 0
         if output_parameter is not None:
@@ -1130,13 +1130,13 @@
         else:
             for i, variable in enumerate(output_variables):
                 blockPointx, blockPointy = variable.connectionPointOut.getrelPositionXY()
-                if (connectionPoint is None or 
-                    block.getx() + blockPointx == connectionPoint.getx() and 
+                if (connectionPoint is None or
+                    block.getx() + blockPointx == connectionPoint.getx() and
                     block.gety() + blockPointy == connectionPoint.gety()):
                     output_variable = variable
                     output_parameter = variable.getformalParameter()
                     output_idx = i
-        
+
         if output_variable is not None:
             if block_infos["type"] == "function":
                 output_info = (self.TagName, "block", block.getlocalId(), "output", output_idx)
@@ -1149,7 +1149,7 @@
                         output_name = "%s%d_%s"%(type, block.getlocalId(), output_parameter)
                     output_value = [(output_name, output_info)]
                 return self.ExtractModifier(output_variable, output_value, output_info)
-            
+
             if block_infos["type"] == "functionBlock":
                 output_info = (self.TagName, "block", block.getlocalId(), "output", output_idx)
                 output_name = self.ExtractModifier(output_variable, [("%s.%s"%(name, output_parameter), output_info)], output_info)
@@ -1168,7 +1168,7 @@
                         self.Program += output_name
                         self.Program += [(";\n", ())]
                     return [(variable_name, ())]
-                return output_name 
+                return output_name
         if link is not None:
             if output_parameter is None:
                 output_parameter = ""
@@ -1291,7 +1291,7 @@
             elif edge == "falling":
                 return self.AddTrigger("F_TRIG", expression, var_info + ("falling",))
         return expression
-    
+
     def AddTrigger(self, edge, expression, var_info):
         if self.Interface[-1][0] != "VAR" or self.Interface[-1][1] is not None or self.Interface[-1][2]:
             self.Interface.append(("VAR", None, False, []))
@@ -1301,11 +1301,11 @@
             i += 1
             name = "%s%d"%(edge, i)
         self.Interface[-1][3].append((edge, name, None, None))
-        self.Program += [(self.CurrentIndent, ()), (name, var_info), ("(CLK := ", ())] 
+        self.Program += [(self.CurrentIndent, ()), (name, var_info), ("(CLK := ", ())]
         self.Program += expression
         self.Program += [(");\n", ())]
         return [("%s.Q"%name, var_info)]
-    
+
     def ExtractDivergenceInput(self, divergence, pou):
         connectionPointIn = divergence.getconnectionPointIn()
         if connectionPointIn is not None:
@@ -1335,9 +1335,9 @@
         if step_name not in self.SFCNetworks["Steps"].keys():
             if step.getinitialStep():
                 self.InitialSteps.append(step_name)
-            step_infos = {"id" : step.getlocalId(), 
-                          "initial" : step.getinitialStep(), 
-                          "transitions" : [], 
+            step_infos = {"id" : step.getlocalId(),
+                          "initial" : step.getinitialStep(),
+                          "transitions" : [],
                           "actions" : []}
             self.SFCNetworks["Steps"][step_name] = step_infos
             if step.connectionPointIn is not None:
@@ -1365,7 +1365,7 @@
                     if instance in self.SFCNetworks["Transitions"].keys():
                         target_info = (self.TagName, "transition", instance.getlocalId(), "to", step_infos["id"])
                         self.SFCNetworks["Transitions"][instance]["to"].append([(step_name, target_info)])
-    
+
     def GenerateSFCJump(self, jump, pou):
         jump_target = jump.gettargetName()
         if jump.connectionPointIn is not None:
@@ -1393,7 +1393,7 @@
                 if instance in self.SFCNetworks["Transitions"].keys():
                     target_info = (self.TagName, "jump", jump.getlocalId(), "target")
                     self.SFCNetworks["Transitions"][instance]["to"].append([(jump_target, target_info)])
-    
+
     def GenerateSFCStepActions(self, actionBlock, pou):
         connections = actionBlock.connectionPointIn.getconnections()
         if connections is not None and len(connections) == 1:
@@ -1407,8 +1407,8 @@
             if step_name in self.SFCNetworks["Steps"].keys():
                 actions = actionBlock.getactions()
                 for i, action in enumerate(actions):
-                    action_infos = {"id" : actionBlock.getlocalId(), 
-                                    "qualifier" : action["qualifier"], 
+                    action_infos = {"id" : actionBlock.getlocalId(),
+                                    "qualifier" : action["qualifier"],
                                     "content" : action["value"],
                                     "num" : i}
                     if "duration" in action:
@@ -1419,12 +1419,12 @@
                         self.GenerateSFCAction(action["value"], pou)
                     else:
                         action_name = "%s_INLINE%d"%(step_name.upper(), self.GetActionNumber())
-                        self.SFCNetworks["Actions"][action_name] = ([(self.CurrentIndent, ()), 
+                        self.SFCNetworks["Actions"][action_name] = ([(self.CurrentIndent, ()),
                             (action["value"], (self.TagName, "action_block", action_infos["id"], "action", i, "inline")),
                             ("\n", ())], ())
                         action_infos["content"] = action_name
                     self.SFCNetworks["Steps"][step_name]["actions"].append(action_infos)
-    
+
     def GenerateSFCAction(self, action_name, pou):
         if action_name not in self.SFCNetworks["Actions"].keys():
             actionContent = pou.getaction(action_name)
@@ -1435,7 +1435,7 @@
                 self.SFCNetworks["Actions"][action_name] = (self.Program, (self.TagName, "name"))
                 self.Program = []
                 self.TagName = previous_tagname
-    
+
     def GenerateSFCTransition(self, transition, pou):
         if transition not in self.SFCNetworks["Transitions"].keys():
             steps = []
@@ -1457,9 +1457,9 @@
                             steps.extend(self.ExtractConvergenceInputs(step, pou))
                 elif isinstance(instance, SimultaneousConvergenceClass):
                     steps.extend(self.ExtractConvergenceInputs(instance, pou))
-            transition_infos = {"id" : transition.getlocalId(), 
-                                "priority": transition.getpriority(), 
-                                "from": [], 
+            transition_infos = {"id" : transition.getlocalId(),
+                                "priority": transition.getpriority(),
+                                "from": [],
                                 "to" : [],
                                 "content": []}
             self.SFCNetworks["Transitions"][transition] = transition_infos
@@ -1546,7 +1546,7 @@
                 self.ComputeSFCAction(action)
             for transition in step_infos["transitions"]:
                 self.ComputeSFCTransition(transition)
-                
+
     def ComputeSFCAction(self, action_name):
         if action_name in self.SFCNetworks["Actions"].keys():
             action_content, action_info = self.SFCNetworks["Actions"].pop(action_name)
@@ -1555,7 +1555,7 @@
                              (":\n", ())]
             self.Program += action_content
             self.Program += [("%sEND_ACTION\n\n"%self.CurrentIndent, ())]
-    
+
     def ComputeSFCTransition(self, transition):
         if transition in self.SFCNetworks["Transitions"].keys():
             transition_infos = self.SFCNetworks["Transitions"].pop(transition)
@@ -1586,12 +1586,12 @@
             self.Program += [("%sEND_TRANSITION\n\n"%self.CurrentIndent, ())]
             for [(step_name, step_infos)] in transition_infos["to"]:
                 self.ComputeSFCStep(step_name)
-    
+
     def GenerateProgram(self, pou):
         self.ComputeInterface(pou)
         self.ComputeConnectionTypes(pou)
         self.ComputeProgram(pou)
-        
+
         program = [("%s "%self.Type, ()),
                    (self.Name, (self.TagName, "name"))]
         if self.ReturnType is not None: