PLCGenerator.py
changeset 1310 3d7fa2257b24
parent 1298 f034fb2b1aab
child 1315 ff14a66bbd12
equal deleted inserted replaced
1309:85ce56758900 1310:3d7fa2257b24
    72     bx, by = int(b.getx()), int(b.gety())
    72     bx, by = int(b.getx()), int(b.gety())
    73     if abs(ay - by) < 10:
    73     if abs(ay - by) < 10:
    74         return cmp(ax, bx)
    74         return cmp(ax, bx)
    75     else:
    75     else:
    76         return cmp(ay, by)
    76         return cmp(ay, by)
       
    77 
       
    78 # Helper for emulate join on element list
       
    79 def JoinList(separator, mylist):
       
    80     if len(mylist) > 0 :
       
    81         return reduce(lambda x, y: x + separator + y, mylist)
       
    82     else :
       
    83         return mylist
    77 
    84 
    78 #-------------------------------------------------------------------------------
    85 #-------------------------------------------------------------------------------
    79 #                  Specific exception for PLC generating errors
    86 #                  Specific exception for PLC generating errors
    80 #-------------------------------------------------------------------------------
    87 #-------------------------------------------------------------------------------
    81 
    88 
   622                     if vartype_content.getLocalTag() == "derived":
   629                     if vartype_content.getLocalTag() == "derived":
   623                         var_type = vartype_content.getname()
   630                         var_type = vartype_content.getname()
   624                         blocktype = self.GetBlockType(var_type)
   631                         blocktype = self.GetBlockType(var_type)
   625                         if blocktype is not None:
   632                         if blocktype is not None:
   626                             self.ParentGenerator.GeneratePouProgram(var_type)
   633                             self.ParentGenerator.GeneratePouProgram(var_type)
   627                             if body_type in ["FBD", "LD", "SFC"]:
   634                             variables.append((var_type, var.getname(), None, None))
   628                                 block = pou.getinstanceByName(var.getname())
       
   629                             else:
       
   630                                 block = None
       
   631                             for variable in blocktype["initialise"](var_type, var.getname(), block):
       
   632                                 if variable[2] is not None:
       
   633                                     located.append(variable)
       
   634                                 else:
       
   635                                     variables.append(variable)
       
   636                         else:
   635                         else:
   637                             self.ParentGenerator.GenerateDataType(var_type)
   636                             self.ParentGenerator.GenerateDataType(var_type)
   638                             initial = var.getinitialValue()
   637                             initial = var.getinitialValue()
   639                             if initial:
   638                             if initial is not None:
   640                                 initial_value = initial.getvalue()
   639                                 initial_value = initial.getvalue()
   641                             else:
   640                             else:
   642                                 initial_value = None
   641                                 initial_value = None
   643                             address = var.getaddress()
   642                             address = var.getaddress()
   644                             if address is not None:
   643                             if address is not None:
   646                             else:
   645                             else:
   647                                 variables.append((vartype_content.getname(), var.getname(), None, initial_value))
   646                                 variables.append((vartype_content.getname(), var.getname(), None, initial_value))
   648                     else:
   647                     else:
   649                         var_type = var.gettypeAsText()
   648                         var_type = var.gettypeAsText()
   650                         initial = var.getinitialValue()
   649                         initial = var.getinitialValue()
   651                         if initial:
   650                         if initial is not None:
   652                             initial_value = initial.getvalue()
   651                             initial_value = initial.getvalue()
   653                         else:
   652                         else:
   654                             initial_value = None
   653                             initial_value = None
   655                         address = var.getaddress()
   654                         address = var.getaddress()
   656                         if address is not None:
   655                         if address is not None:
   933                     if block_infos is None:
   932                     if block_infos is None:
   934                         block_infos = self.GetBlockType(block_type)
   933                         block_infos = self.GetBlockType(block_type)
   935                     if block_infos is None:
   934                     if block_infos is None:
   936                         raise PLCGenException, _("Undefined block type \"%s\" in \"%s\" POU")%(block_type, self.Name)
   935                         raise PLCGenException, _("Undefined block type \"%s\" in \"%s\" POU")%(block_type, self.Name)
   937                     try:
   936                     try:
   938                         block_infos["generate"](self, instance, block_infos, body, None)
   937                         self.GenerateBlock(instance, block_infos, body, None)
   939                     except ValueError, e:
   938                     except ValueError, e:
   940                         raise PLCGenException, e.message
   939                         raise PLCGenException, e.message
   941                 elif isinstance(instance, ConnectorClass):
   940                 elif isinstance(instance, ConnectorClass):
   942                     connector = instance.getname()
   941                     connector = instance.getname()
   943                     if self.ComputedConnectors.get(connector, None):
   942                     if self.ComputedConnectors.get(connector, None):
   981         for num in uncomputed_index:
   980         for num in uncomputed_index:
   982             factorized_paths.append(paths[num])
   981             factorized_paths.append(paths[num])
   983         factorized_paths.sort()
   982         factorized_paths.sort()
   984         return factorized_paths
   983         return factorized_paths
   985 
   984 
       
   985     def GenerateBlock(self, block, block_infos, body, link, order=False, to_inout=False):
       
   986         body_type = body.getcontent().getLocalTag()
       
   987         name = block.getinstanceName()
       
   988         type = block.gettypeName()
       
   989         executionOrderId = block.getexecutionOrderId()
       
   990         input_variables = block.inputVariables.getvariable()
       
   991         output_variables = block.outputVariables.getvariable()
       
   992         inout_variables = {}
       
   993         for input_variable in input_variables:
       
   994             for output_variable in output_variables:
       
   995                 if input_variable.getformalParameter() == output_variable.getformalParameter():
       
   996                     inout_variables[input_variable.getformalParameter()] = ""
       
   997         input_names = [input[0] for input in block_infos["inputs"]]
       
   998         output_names = [output[0] for output in block_infos["outputs"]]
       
   999         if block_infos["type"] == "function":
       
  1000             if not self.ComputedBlocks.get(block, False) and not order:
       
  1001                 self.ComputedBlocks[block] = True
       
  1002                 connected_vars = []
       
  1003                 if not block_infos["extensible"]:
       
  1004                     input_connected = dict([("EN", None)] + 
       
  1005                                            [(input_name, None) for input_name in input_names])
       
  1006                     for variable in input_variables:
       
  1007                         parameter = variable.getformalParameter()
       
  1008                         if input_connected.has_key(parameter):
       
  1009                             input_connected[parameter] = variable
       
  1010                     if input_connected["EN"] is None:
       
  1011                         input_connected.pop("EN")
       
  1012                         input_parameters = input_names
       
  1013                     else:
       
  1014                         input_parameters = ["EN"] + input_names
       
  1015                 else:
       
  1016                     input_connected = dict([(variable.getformalParameter(), variable)
       
  1017                                             for variable in input_variables])
       
  1018                     input_parameters = [variable.getformalParameter()
       
  1019                                         for variable in input_variables]
       
  1020                 one_input_connected = False
       
  1021                 all_input_connected = True
       
  1022                 for i, parameter in enumerate(input_parameters):
       
  1023                     variable = input_connected.get(parameter)
       
  1024                     if variable is not None:
       
  1025                         input_info = (self.TagName, "block", block.getlocalId(), "input", i)
       
  1026                         connections = variable.connectionPointIn.getconnections()
       
  1027                         if connections is not None:
       
  1028                             if parameter != "EN":
       
  1029                                 one_input_connected = True
       
  1030                             if inout_variables.has_key(parameter):
       
  1031                                 expression = self.ComputeExpression(body, connections, executionOrderId > 0, True)
       
  1032                                 if expression is not None:
       
  1033                                     inout_variables[parameter] = value
       
  1034                             else:
       
  1035                                 expression = self.ComputeExpression(body, connections, executionOrderId > 0)
       
  1036                             if expression is not None:
       
  1037                                 connected_vars.append(([(parameter, input_info), (" := ", ())],
       
  1038                                                        self.ExtractModifier(variable, expression, input_info)))
       
  1039                         else:
       
  1040                             all_input_connected = False
       
  1041                     else:
       
  1042                         all_input_connected = False
       
  1043                 if len(output_variables) > 1 or not all_input_connected:
       
  1044                     vars = [name + value for name, value in connected_vars]
       
  1045                 else:
       
  1046                     vars = [value for name, value in connected_vars]
       
  1047                 if one_input_connected:
       
  1048                     for i, variable in enumerate(output_variables):
       
  1049                         parameter = variable.getformalParameter()
       
  1050                         if not inout_variables.has_key(parameter) and parameter in output_names + ["", "ENO"]:
       
  1051                             if variable.getformalParameter() == "":
       
  1052                                 variable_name = "%s%d"%(type, block.getlocalId())
       
  1053                             else:
       
  1054                                 variable_name = "%s%d_%s"%(type, block.getlocalId(), parameter)
       
  1055                             if self.Interface[-1][0] != "VAR" or self.Interface[-1][1] is not None or self.Interface[-1][2]:
       
  1056                                 self.Interface.append(("VAR", None, False, []))
       
  1057                             if variable.connectionPointOut in self.ConnectionTypes:
       
  1058                                 self.Interface[-1][3].append((self.ConnectionTypes[variable.connectionPointOut], variable_name, None, None))
       
  1059                             else:
       
  1060                                 self.Interface[-1][3].append(("ANY", variable_name, None, None))
       
  1061                             if len(output_variables) > 1 and parameter not in ["", "OUT"]:
       
  1062                                 vars.append([(parameter, (self.TagName, "block", block.getlocalId(), "output", i)), 
       
  1063                                              (" => %s"%variable_name, ())])
       
  1064                             else:
       
  1065                                 output_info = (self.TagName, "block", block.getlocalId(), "output", i)
       
  1066                                 output_name = variable_name
       
  1067                     self.Program += [(self.CurrentIndent, ()),
       
  1068                                      (output_name, output_info),
       
  1069                                      (" := ", ()),
       
  1070                                      (type, (self.TagName, "block", block.getlocalId(), "type")),
       
  1071                                      ("(", ())]
       
  1072                     self.Program += JoinList([(", ", ())], vars)
       
  1073                     self.Program += [(");\n", ())]
       
  1074                 else:
       
  1075                     self.Warnings.append(_("\"%s\" function cancelled in \"%s\" POU: No input connected")%(type, self.TagName.split("::")[-1]))
       
  1076         elif block_infos["type"] == "functionBlock":
       
  1077             if not self.ComputedBlocks.get(block, False) and not order:
       
  1078                 self.ComputedBlocks[block] = True
       
  1079                 vars = []
       
  1080                 offset_idx = 0
       
  1081                 for variable in input_variables:
       
  1082                     parameter = variable.getformalParameter()
       
  1083                     if parameter in input_names or parameter == "EN":
       
  1084                         if parameter == "EN":
       
  1085                             input_idx = 0
       
  1086                             offset_idx = 1
       
  1087                         else:
       
  1088                             input_idx = offset_idx + input_names.index(parameter)
       
  1089                         input_info = (self.TagName, "block", block.getlocalId(), "input", input_idx)
       
  1090                         connections = variable.connectionPointIn.getconnections()
       
  1091                         if connections is not None:
       
  1092                             expression = self.ComputeExpression(body, connections, executionOrderId > 0, inout_variables.has_key(parameter))
       
  1093                             if expression is not None:
       
  1094                                 vars.append([(parameter, input_info),
       
  1095                                              (" := ", ())] + self.ExtractModifier(variable, expression, input_info))
       
  1096                 self.Program += [(self.CurrentIndent, ()), 
       
  1097                                  (name, (self.TagName, "block", block.getlocalId(), "name")),
       
  1098                                  ("(", ())]
       
  1099                 self.Program += JoinList([(", ", ())], vars)
       
  1100                 self.Program += [(");\n", ())]
       
  1101         
       
  1102         if link is not None:
       
  1103             connectionPoint = link.getposition()[-1]
       
  1104             output_parameter = link.getformalParameter()
       
  1105         else:
       
  1106             connectionPoint = None
       
  1107             output_parameter = None
       
  1108         
       
  1109         output_variable = None
       
  1110         output_idx = 0
       
  1111         if output_parameter is not None:
       
  1112             if output_parameter in output_names or output_parameter == "ENO":
       
  1113                 for variable in output_variables:
       
  1114                     if variable.getformalParameter() == output_parameter:
       
  1115                         output_variable = variable
       
  1116                         if output_parameter != "ENO":
       
  1117                             output_idx = output_names.index(output_parameter)
       
  1118         else:
       
  1119             for i, variable in enumerate(output_variables):
       
  1120                 blockPointx, blockPointy = variable.connectionPointOut.getrelPositionXY()
       
  1121                 if (connectionPoint is None or 
       
  1122                     block.getx() + blockPointx == connectionPoint.getx() and 
       
  1123                     block.gety() + blockPointy == connectionPoint.gety()):
       
  1124                     output_variable = variable
       
  1125                     output_parameter = variable.getformalParameter()
       
  1126                     output_idx = i
       
  1127         
       
  1128         if output_variable is not None:
       
  1129             if block_infos["type"] == "function":
       
  1130                 output_info = (self.TagName, "block", block.getlocalId(), "output", output_idx)
       
  1131                 if inout_variables.has_key(output_parameter):
       
  1132                     output_value = inout_variables[output_parameter]
       
  1133                 else:
       
  1134                     if output_parameter == "":
       
  1135                         output_name = "%s%d"%(type, block.getlocalId())
       
  1136                     else:
       
  1137                         output_name = "%s%d_%s"%(type, block.getlocalId(), output_parameter)
       
  1138                     output_value = [(output_name, output_info)]
       
  1139                 return self.ExtractModifier(output_variable, output_value, output_info)
       
  1140             
       
  1141             if block_infos["type"] == "functionBlock":
       
  1142                 output_info = (self.TagName, "block", block.getlocalId(), "output", output_idx)
       
  1143                 output_name = self.ExtractModifier(output_variable, [("%s.%s"%(name, output_parameter), output_info)], output_info)
       
  1144                 if to_inout:
       
  1145                     variable_name = "%s_%s"%(name, output_parameter)
       
  1146                     if not self.IsAlreadyDefined(variable_name):
       
  1147                         if self.Interface[-1][0] != "VAR" or self.Interface[-1][1] is not None or self.Interface[-1][2]:
       
  1148                             self.Interface.append(("VAR", None, False, []))
       
  1149                         if variable.connectionPointOut in self.ConnectionTypes:
       
  1150                             self.Interface[-1][3].append(
       
  1151                                 (self.ConnectionTypes[output_variable.connectionPointOut], variable_name, None, None))
       
  1152                         else:
       
  1153                             self.Interface[-1][3].append(("ANY", variable_name, None, None))
       
  1154                         self.Program += [(self.CurrentIndent, ()),
       
  1155                                          ("%s := "%variable_name, ())]
       
  1156                         self.Program += output_name
       
  1157                         self.Program += [(";\n", ())]
       
  1158                     return [(variable_name, ())]
       
  1159                 return output_name 
       
  1160         if link is not None:
       
  1161             if output_parameter is None:
       
  1162                 output_parameter = ""
       
  1163             if name:
       
  1164                 blockname = "%s(%s)" % (name, type)
       
  1165             else:
       
  1166                 blockname = type
       
  1167             raise ValueError, _("No output %s variable found in block %s in POU %s. Connection must be broken")  % \
       
  1168                               (output_parameter, blockname, self.Name)
       
  1169 
   986     def GeneratePaths(self, connections, body, order = False, to_inout = False):
  1170     def GeneratePaths(self, connections, body, order = False, to_inout = False):
   987         paths = []
  1171         paths = []
   988         for connection in connections:
  1172         for connection in connections:
   989             localId = connection.getrefLocalId()
  1173             localId = connection.getrefLocalId()
   990             next = body.getcontentInstance(localId)
  1174             next = body.getcontentInstance(localId)
   999                 if block_infos is None:
  1183                 if block_infos is None:
  1000                     block_infos = self.GetBlockType(block_type)
  1184                     block_infos = self.GetBlockType(block_type)
  1001                 if block_infos is None:
  1185                 if block_infos is None:
  1002                     raise PLCGenException, _("Undefined block type \"%s\" in \"%s\" POU")%(block_type, self.Name)
  1186                     raise PLCGenException, _("Undefined block type \"%s\" in \"%s\" POU")%(block_type, self.Name)
  1003                 try:
  1187                 try:
  1004                     paths.append(str(block_infos["generate"](self, next, block_infos, body, connection, order, to_inout)))
  1188                     paths.append(str(self.GenerateBlock(next, block_infos, body, connection, order, to_inout)))
  1005                 except ValueError, e:
  1189                 except ValueError, e:
  1006                     raise PLCGenException, e.message
  1190                     raise PLCGenException, e.message
  1007             elif isinstance(next, ContinuationClass):
  1191             elif isinstance(next, ContinuationClass):
  1008                 name = next.getname()
  1192                 name = next.getname()
  1009                 computed_value = self.ComputedConnectors.get(name, None)
  1193                 computed_value = self.ComputedConnectors.get(name, None)
  1396         self.ComputeConnectionTypes(pou)
  1580         self.ComputeConnectionTypes(pou)
  1397         self.ComputeProgram(pou)
  1581         self.ComputeProgram(pou)
  1398         
  1582         
  1399         program = [("%s "%self.Type, ()),
  1583         program = [("%s "%self.Type, ()),
  1400                    (self.Name, (self.TagName, "name"))]
  1584                    (self.Name, (self.TagName, "name"))]
  1401         if self.ReturnType:
  1585         if self.ReturnType is not None:
  1402             program += [(" : ", ()),
  1586             program += [(" : ", ()),
  1403                         (self.ReturnType, (self.TagName, "return"))]
  1587                         (self.ReturnType, (self.TagName, "return"))]
  1404         program += [("\n", ())]
  1588         program += [("\n", ())]
  1405         if len(self.Interface) == 0:
  1589         if len(self.Interface) == 0:
  1406             raise PLCGenException, _("No variable defined in \"%s\" POU")%self.Name
  1590             raise PLCGenException, _("No variable defined in \"%s\" POU")%self.Name