Fixed PLC code generator when interface of an already used POU has changed
authorLaurent Bessard
Tue, 14 May 2013 11:12:34 +0200
changeset 1134 1c7a4ad86aa1
parent 1133 d81d99fd1932
child 1135 519a21ddbc40
Fixed PLC code generator when interface of an already used POU has changed
PLCGenerator.py
plcopen/structures.py
--- a/PLCGenerator.py	Tue May 14 10:56:57 2013 +0200
+++ b/PLCGenerator.py	Tue May 14 11:12:34 2013 +0200
@@ -902,7 +902,10 @@
                         block_infos = self.GetBlockType(block_type)
                     if block_infos is None:
                         raise PLCGenException, _("Undefined block type \"%s\" in \"%s\" POU")%(block_type, self.Name)
-                    block_infos["generate"](self, instance, block_infos, body, None)
+                    try:
+                        block_infos["generate"](self, instance, block_infos, body, None)
+                    except ValueError, e:
+                        raise PLCGenException, e.message
                 elif isinstance(instance, plcopen.commonObjects_connector):
                     connector = instance.getname()
                     if self.ComputedConnectors.get(connector, None):
@@ -961,7 +964,10 @@
                     block_infos = self.GetBlockType(block_type)
                 if block_infos is None:
                     raise PLCGenException, _("Undefined block type \"%s\" in \"%s\" POU")%(block_type, self.Name)
-                paths.append(str(block_infos["generate"](self, next, block_infos, body, connection, order, to_inout)))
+                try:
+                    paths.append(str(block_infos["generate"](self, next, block_infos, body, connection, order, to_inout)))
+                except ValueError, e:
+                    raise PLCGenException, e.message
             elif isinstance(next, plcopen.commonObjects_continuation):
                 name = next.getname()
                 computed_value = self.ComputedConnectors.get(name, None)
--- a/plcopen/structures.py	Tue May 14 10:56:57 2013 +0200
+++ b/plcopen/structures.py	Tue May 14 11:12:34 2013 +0200
@@ -46,38 +46,59 @@
     name = block.getinstanceName()
     type = block.gettypeName()
     executionOrderId = block.getexecutionOrderId()
+    input_variables = block.inputVariables.getvariable()
+    output_variables = block.outputVariables.getvariable()
     inout_variables = {}
-    for input_variable in block.inputVariables.getvariable():
-        for output_variable in block.outputVariables.getvariable():
+    for input_variable in input_variables:
+        for output_variable in output_variables:
             if input_variable.getformalParameter() == output_variable.getformalParameter():
                 inout_variables[input_variable.getformalParameter()] = ""
+    input_names = [input[0] for input in block_infos["inputs"]]
+    output_names = [output[0] for output in block_infos["outputs"]]
     if block_infos["type"] == "function":
-        output_variables = block.outputVariables.getvariable()
         if not generator.ComputedBlocks.get(block, False) and not order:
             generator.ComputedBlocks[block] = True
-            vars = []
+            connected_vars = []
+            input_connected = dict([("EN", None)] + 
+                                   [(input_name, None) for input_name in input_names])
+            for variable in input_variables:
+                parameter = variable.getformalParameter()
+                if input_connected.has_key(parameter):
+                    input_connected[parameter] = variable
+            if input_connected["EN"] is None:
+                input_connected.pop("EN")
+                input_parameters = input_names
+            else:
+                input_parameters = ["EN"] + input_names
             one_input_connected = False
-            for i, variable in enumerate(block.inputVariables.getvariable()):
-                input_info = (generator.TagName, "block", block.getlocalId(), "input", i)
-                connections = variable.connectionPointIn.getconnections()
-                if connections is not None:
-                    parameter = variable.getformalParameter()
-                    if parameter != "EN":
-                        one_input_connected = True
-                    if inout_variables.has_key(parameter):
-                        value = generator.ComputeExpression(body, connections, executionOrderId > 0, True)
-                        inout_variables[parameter] = value
+            all_input_connected = True
+            for i, parameter in enumerate(input_parameters):
+                variable = input_connected.get(parameter)
+                if variable is not None:
+                    input_info = (generator.TagName, "block", block.getlocalId(), "input", i)
+                    connections = variable.connectionPointIn.getconnections()
+                    if connections is not None:
+                        if parameter != "EN":
+                            one_input_connected = True
+                        if inout_variables.has_key(parameter):
+                            value = generator.ComputeExpression(body, connections, executionOrderId > 0, True)
+                            inout_variables[parameter] = value
+                        else:
+                            value = generator.ComputeExpression(body, connections, executionOrderId > 0)
+                        connected_vars.append(([(parameter, input_info), (" := ", ())],
+                                               generator.ExtractModifier(variable, value, input_info)))
                     else:
-                        value = generator.ComputeExpression(body, connections, executionOrderId > 0)
-                    if len(output_variables) > 1:
-                        vars.append([(parameter, input_info),
-                                     (" := ", ())] + generator.ExtractModifier(variable, value, input_info))
-                    else:
-                        vars.append(generator.ExtractModifier(variable, value, input_info))
+                        all_input_connected = False
+                else:
+                    all_input_connected = False
+            if len(output_variables) > 1 or not all_input_connected:
+                vars = [name + value for name, value in connected_vars]
+            else:
+                vars = [value for name, value in connected_vars]
             if one_input_connected:
                 for i, variable in enumerate(output_variables):
                     parameter = variable.getformalParameter()
-                    if not inout_variables.has_key(parameter):
+                    if not inout_variables.has_key(parameter) and parameter in output_names + ["ENO"]:
                         if variable.getformalParameter() == "":
                             variable_name = "%s%d"%(type, block.getlocalId())
                         else:
@@ -103,67 +124,98 @@
                 generator.Program += [(");\n", ())]
             else:
                 generator.Warnings.append(_("\"%s\" function cancelled in \"%s\" POU: No input connected")%(type, generator.TagName.split("::")[-1]))
-        if link:
-            connectionPoint = link.getposition()[-1]
-        else:
-            connectionPoint = None
-        for i, variable in enumerate(output_variables):
-            blockPointx, blockPointy = variable.connectionPointOut.getrelPositionXY()
-            if not connectionPoint or block.getx() + blockPointx == connectionPoint.getx() and block.gety() + blockPointy == connectionPoint.gety():
-                output_info = (generator.TagName, "block", block.getlocalId(), "output", i)
-                parameter = variable.getformalParameter()
-                if inout_variables.has_key(parameter):
-                    output_value = inout_variables[parameter]
-                else:
-                    if parameter == "":
-                        output_name = "%s%d"%(type, block.getlocalId())
-                    else:
-                        output_name = "%s%d_%s"%(type, block.getlocalId(), parameter)
-                    output_value = [(output_name, output_info)]
-                return generator.ExtractModifier(variable, output_value, output_info)
     elif block_infos["type"] == "functionBlock":
         if not generator.ComputedBlocks.get(block, False) and not order:
             generator.ComputedBlocks[block] = True
             vars = []
-            for i, variable in enumerate(block.inputVariables.getvariable()):
-                input_info = (generator.TagName, "block", block.getlocalId(), "input", i)
-                connections = variable.connectionPointIn.getconnections()
-                if connections is not None:
-                    parameter = variable.getformalParameter()
-                    value = generator.ComputeExpression(body, connections, executionOrderId > 0, inout_variables.has_key(parameter))
-                    vars.append([(parameter, input_info),
-                                 (" := ", ())] + generator.ExtractModifier(variable, value, input_info))
+            offset_idx = 0
+            for variable in input_variables:
+                parameter = variable.getformalParameter()
+                if parameter in input_names or parameter == "EN":
+                    if parameter == "EN":
+                        input_idx = 0
+                        offset_idx = 1
+                    else:
+                        input_idx = offset_idx + input_names.index(parameter)
+                    input_info = (generator.TagName, "block", block.getlocalId(), "input", input_idx)
+                    connections = variable.connectionPointIn.getconnections()
+                    if connections is not None:
+                        value = generator.ComputeExpression(body, connections, executionOrderId > 0, inout_variables.has_key(parameter))
+                        vars.append([(parameter, input_info),
+                                     (" := ", ())] + generator.ExtractModifier(variable, value, input_info))
             generator.Program += [(generator.CurrentIndent, ()), 
                                   (name, (generator.TagName, "block", block.getlocalId(), "name")),
                                   ("(", ())]
             generator.Program += JoinList([(", ", ())], vars)
             generator.Program += [(");\n", ())]
-        if link:
-            connectionPoint = link.getposition()[-1]
+    
+    if link:
+        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:
+        if output_parameter in output_names or output_parameter == "ENO":
+            for variable in output_variables:
+                if variable.getformalParameter() == output_parameter:
+                    output_variable = variable
+                    if output_parameter != "ENO":
+                        output_idx = output_names.index(output_parameter)
+    else:
+        for i, variable in enumerate(output_variables):
+            blockPointx, blockPointy = variable.connectionPointOut.getrelPositionXY()
+            if (not connectionPoint 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 = (generator.TagName, "block", block.getlocalId(), "output", output_idx)
+            if inout_variables.has_key(output_parameter):
+                output_value = inout_variables[output_parameter]
+            else:
+                if output_parameter == "":
+                    output_name = "%s%d"%(type, block.getlocalId())
+                else:
+                    output_name = "%s%d_%s"%(type, block.getlocalId(), output_parameter)
+                output_value = [(output_name, output_info)]
+            return generator.ExtractModifier(output_variable, output_value, output_info)
+        
+        if block_infos["type"] == "functionBlock":
+            output_info = (generator.TagName, "block", block.getlocalId(), "output", output_idx)
+            output_name = generator.ExtractModifier(output_variable, [("%s.%s"%(name, output_parameter), output_info)], output_info)
+            if to_inout:
+                variable_name = "%s_%s"%(name, output_parameter)
+                if not generator.IsAlreadyDefined(variable_name):
+                    if generator.Interface[-1][0] != "VAR" or generator.Interface[-1][1] is not None or generator.Interface[-1][2]:
+                        generator.Interface.append(("VAR", None, False, []))
+                    if variable.connectionPointOut in generator.ConnectionTypes:
+                        generator.Interface[-1][3].append(
+                            (generator.ConnectionTypes[output_variable.connectionPointOut], variable_name, None, None))
+                    else:
+                        generator.Interface[-1][3].append(("ANY", variable_name, None, None))
+                    generator.Program += [(generator.CurrentIndent, ()),
+                                          ("%s := "%variable_name, ())]
+                    generator.Program += output_name
+                    generator.Program += [(";\n", ())]
+                return [(variable_name, ())]
+            return output_name 
+    if link is not None:
+        if output_parameter is None:
+            output_parameter = ""
+        if name:
+            blockname = "%s(%s)" % (name, type)
         else:
-            connectionPoint = None
-        for i, variable in enumerate(block.outputVariables.getvariable()):
-            blockPointx, blockPointy = variable.connectionPointOut.getrelPositionXY()
-            if not connectionPoint or block.getx() + blockPointx == connectionPoint.getx() and block.gety() + blockPointy == connectionPoint.gety():
-                output_info = (generator.TagName, "block", block.getlocalId(), "output", i)
-                output_name = generator.ExtractModifier(variable, [("%s.%s"%(name, variable.getformalParameter()), output_info)], output_info)
-                if to_inout:
-                    variable_name = "%s_%s"%(name, variable.getformalParameter())
-                    if not generator.IsAlreadyDefined(variable_name):
-                        if generator.Interface[-1][0] != "VAR" or generator.Interface[-1][1] is not None or generator.Interface[-1][2]:
-                            generator.Interface.append(("VAR", None, False, []))
-                        if variable.connectionPointOut in generator.ConnectionTypes:
-                            generator.Interface[-1][3].append((generator.ConnectionTypes[variable.connectionPointOut], variable_name, None, None))
-                        else:
-                            generator.Interface[-1][3].append(("ANY", variable_name, None, None))
-                        generator.Program += [(generator.CurrentIndent, ()),
-                                              ("%s := "%variable_name, ())]
-                        generator.Program += output_name
-                        generator.Program += [(";\n", ())]
-                    return [(variable_name, ())]
-                return output_name 
-    if link is not None:
-        raise ValueError, _("No output variable found")
+            blockname = type
+        raise ValueError, _("No output %s variable found in block %s in POU %s. Connection must be broken")  % \
+                          (output_parameter, blockname, generator.Name)
 
 def initialise_block(type, name, block = None):
     return [(type, name, None, None)]