PLCGenerator.py
changeset 1765 ccf59c1f0b45
parent 1763 bcc07ff2362c
child 1766 c1e5b9f19483
equal deleted inserted replaced
1764:d5df428640ff 1765:ccf59c1f0b45
   252                 # Create a POU program generator
   252                 # Create a POU program generator
   253                 pou_program = PouProgramGenerator(self, pou.getname(), pouTypeNames[pou_type], self.Errors, self.Warnings)
   253                 pou_program = PouProgramGenerator(self, pou.getname(), pouTypeNames[pou_type], self.Errors, self.Warnings)
   254                 program = pou_program.GenerateProgram(pou)
   254                 program = pou_program.GenerateProgram(pou)
   255                 self.Program += program
   255                 self.Program += program
   256             else:
   256             else:
   257                 raise PLCGenException, _("Undefined pou type \"%s\"") % pou_type
   257                 raise PLCGenException(_("Undefined pou type \"%s\"") % pou_type)
   258 
   258 
   259     # Generate a POU defined and used in text
   259     # Generate a POU defined and used in text
   260     def GeneratePouProgramInText(self, text):
   260     def GeneratePouProgramInText(self, text):
   261         for pou_name in self.PouComputed.keys():
   261         for pou_name in self.PouComputed.keys():
   262             model = re.compile("(?:^|[^0-9^A-Z])%s(?:$|[^0-9^A-Z])" % pou_name.upper())
   262             model = re.compile("(?:^|[^0-9^A-Z])%s(?:$|[^0-9^A-Z])" % pou_name.upper())
   395             args = []
   395             args = []
   396             single = task.getsingle()
   396             single = task.getsingle()
   397             # Single argument if exists
   397             # Single argument if exists
   398             if single is not None:
   398             if single is not None:
   399                 if len(single) == 0:
   399                 if len(single) == 0:
   400                     msg = _("Source signal has to be defined for single task '{a1}' in resource '{a2}.{a3}'.").\
   400                     raise PLCGenException(
   401                           format(a1=task.getname(), a2=config_name, a3=resource.getname())
   401                         _("Source signal has to be defined for single task '{a1}' in resource '{a2}.{a3}'.").
   402                     raise PLCGenException, msg
   402                         format(a1=task.getname(), a2=config_name, a3=resource.getname()))
   403 
   403 
   404                 if single[0] == '[' and single[-1] == ']':
   404                 if single[0] == '[' and single[-1] == ']':
   405                     SNGLKW = "MULTI"
   405                     SNGLKW = "MULTI"
   406                 else:
   406                 else:
   407                     SNGLKW = "SINGLE"
   407                     SNGLKW = "SINGLE"
   773                     content = instance.getconditionContent()
   773                     content = instance.getconditionContent()
   774                     if content["type"] == "connection":
   774                     if content["type"] == "connection":
   775                         self.ConnectionTypes[content["value"]] = "BOOL"
   775                         self.ConnectionTypes[content["value"]] = "BOOL"
   776                         connections = content["value"].getconnections()
   776                         connections = content["value"].getconnections()
   777                         if not connections:
   777                         if not connections:
   778                             raise PLCGenException, _("SFC transition in POU \"%s\" must be connected.") % self.Name
   778                             raise PLCGenException(
       
   779                                 _("SFC transition in POU \"%s\" must be connected.") % self.Name)
       
   780 
   779                         for link in connections:
   781                         for link in connections:
   780                             connected = self.GetLinkedConnector(link, body)
   782                             connected = self.GetLinkedConnector(link, body)
   781                             if connected is not None and not connected in self.ConnectionTypes:
   783                             if connected is not None and not connected in self.ConnectionTypes:
   782                                 for related in self.ExtractRelatedConnections(connected):
   784                                 for related in self.ExtractRelatedConnections(connected):
   783                                     self.ConnectionTypes[related] = "BOOL"
   785                                     self.ConnectionTypes[related] = "BOOL"
   786                     connector = None
   788                     connector = None
   787                     var_type = "ANY"
   789                     var_type = "ANY"
   788                     for element in body.getcontentInstances():
   790                     for element in body.getcontentInstances():
   789                         if isinstance(element, ConnectorClass) and element.getname() == name:
   791                         if isinstance(element, ConnectorClass) and element.getname() == name:
   790                             if connector is not None:
   792                             if connector is not None:
   791                                 msg = _("More than one connector found corresponding to \"{a1}\" continuation in \"{a2}\" POU").format(a1=name, a2=self.Name)
   793                                 raise PLCGenException(
   792                                 raise PLCGenException, msg
   794                                     _("More than one connector found corresponding to \"{a1}\" continuation in \"{a2}\" POU").
       
   795                                     format(a1=name, a2=self.Name))
   793                             connector = element
   796                             connector = element
   794                     if connector is not None:
   797                     if connector is not None:
   795                         undefined = [instance.connectionPointOut, connector.connectionPointIn]
   798                         undefined = [instance.connectionPointOut, connector.connectionPointIn]
   796                         connected = self.GetConnectedConnector(connector.connectionPointIn, body)
   799                         connected = self.GetConnectedConnector(connector.connectionPointIn, body)
   797                         if connected is not None:
   800                         if connected is not None:
   806                             self.RelatedConnections.append(related)
   809                             self.RelatedConnections.append(related)
   807                         else:
   810                         else:
   808                             for connection in related:
   811                             for connection in related:
   809                                 self.ConnectionTypes[connection] = var_type
   812                                 self.ConnectionTypes[connection] = var_type
   810                     else:
   813                     else:
   811                         msg = _("No connector found corresponding to \"{a1}\" continuation in \"{a2}\" POU").format(a1=name, a2=self.Name)
   814                         raise PLCGenException(
   812                         raise PLCGenException, msg
   815                             _("No connector found corresponding to \"{a1}\" continuation in \"{a2}\" POU").
       
   816                             format(a1=name, a2=self.Name))
       
   817 
   813                 elif isinstance(instance, BlockClass):
   818                 elif isinstance(instance, BlockClass):
   814                     block_infos = self.GetBlockType(instance.gettypeName(), "undefined")
   819                     block_infos = self.GetBlockType(instance.gettypeName(), "undefined")
   815                     if block_infos is not None:
   820                     if block_infos is not None:
   816                         self.ComputeBlockInputTypes(instance, block_infos, body)
   821                         self.ComputeBlockInputTypes(instance, block_infos, body)
   817                     else:
   822                     else:
   829             for instance in undefined_blocks:
   834             for instance in undefined_blocks:
   830                 block_infos = self.GetBlockType(instance.gettypeName(), tuple([self.ConnectionTypes.get(variable.connectionPointIn, "ANY") for variable in instance.inputVariables.getvariable() if variable.getformalParameter() != "EN"]))
   835                 block_infos = self.GetBlockType(instance.gettypeName(), tuple([self.ConnectionTypes.get(variable.connectionPointIn, "ANY") for variable in instance.inputVariables.getvariable() if variable.getformalParameter() != "EN"]))
   831                 if block_infos is not None:
   836                 if block_infos is not None:
   832                     self.ComputeBlockInputTypes(instance, block_infos, body)
   837                     self.ComputeBlockInputTypes(instance, block_infos, body)
   833                 else:
   838                 else:
   834                     raise PLCGenException, _("No informations found for \"%s\" block") % (instance.gettypeName())
   839                     raise PLCGenException(
       
   840                         _("No informations found for \"%s\" block") % (instance.gettypeName()))
   835             if body_type == "SFC":
   841             if body_type == "SFC":
   836                 previous_tagname = self.TagName
   842                 previous_tagname = self.TagName
   837                 for action in pou.getactionList():
   843                 for action in pou.getactionList():
   838                     self.TagName = self.ParentGenerator.Controler.ComputePouActionName(self.Name, action.getname())
   844                     self.TagName = self.ParentGenerator.Controler.ComputePouActionName(self.Name, action.getname())
   839                     self.ComputeConnectionTypes(action)
   845                     self.ComputeConnectionTypes(action)
   961                     self.ParentGenerator.GeneratePouProgram(block_type)
   967                     self.ParentGenerator.GeneratePouProgram(block_type)
   962                     block_infos = self.GetBlockType(block_type, tuple([self.ConnectionTypes.get(variable.connectionPointIn, "ANY") for variable in instance.inputVariables.getvariable() if variable.getformalParameter() != "EN"]))
   968                     block_infos = self.GetBlockType(block_type, tuple([self.ConnectionTypes.get(variable.connectionPointIn, "ANY") for variable in instance.inputVariables.getvariable() if variable.getformalParameter() != "EN"]))
   963                     if block_infos is None:
   969                     if block_infos is None:
   964                         block_infos = self.GetBlockType(block_type)
   970                         block_infos = self.GetBlockType(block_type)
   965                     if block_infos is None:
   971                     if block_infos is None:
   966                         raise PLCGenException, _("Undefined block type \"{a1}\" in \"{a2}\" POU").format(a1=block_type, a2=self.Name)
   972                         raise PLCGenException(
       
   973                             _("Undefined block type \"{a1}\" in \"{a2}\" POU").
       
   974                             format(a1=block_type, a2=self.Name))
   967                     try:
   975                     try:
   968                         self.GenerateBlock(instance, block_infos, body, None)
   976                         self.GenerateBlock(instance, block_infos, body, None)
   969                     except ValueError, e:
   977                     except ValueError, e:
   970                         raise PLCGenException, e.message
   978                         raise PLCGenException(e.message)
   971                 elif isinstance(instance, ConnectorClass):
   979                 elif isinstance(instance, ConnectorClass):
   972                     connector = instance.getname()
   980                     connector = instance.getname()
   973                     if self.ComputedConnectors.get(connector, None):
   981                     if self.ComputedConnectors.get(connector, None):
   974                         continue
   982                         continue
   975                     expression = self.ComputeExpression(body, instance.connectionPointIn.getconnections())
   983                     expression = self.ComputeExpression(body, instance.connectionPointIn.getconnections())
  1194                 output_parameter = ""
  1202                 output_parameter = ""
  1195             if name:
  1203             if name:
  1196                 blockname = "{a1}({a2})".format(a1=name, a2=type)
  1204                 blockname = "{a1}({a2})".format(a1=name, a2=type)
  1197             else:
  1205             else:
  1198                 blockname = type
  1206                 blockname = type
  1199             msg = _("No output {a1} variable found in block {a2} in POU {a3}. Connection must be broken").\
  1207             raise ValueError(
  1200                               format(a1=output_parameter, a2=blockname, a3=self.Name)
  1208                 _("No output {a1} variable found in block {a2} in POU {a3}. Connection must be broken").
  1201             raise ValueError, msg
  1209                 format(a1=output_parameter, a2=blockname, a3=self.Name))
  1202 
  1210 
  1203     def GeneratePaths(self, connections, body, order=False, to_inout=False):
  1211     def GeneratePaths(self, connections, body, order=False, to_inout=False):
  1204         paths = []
  1212         paths = []
  1205         for connection in connections:
  1213         for connection in connections:
  1206             localId = connection.getrefLocalId()
  1214             localId = connection.getrefLocalId()
  1214                 self.ParentGenerator.GeneratePouProgram(block_type)
  1222                 self.ParentGenerator.GeneratePouProgram(block_type)
  1215                 block_infos = self.GetBlockType(block_type, tuple([self.ConnectionTypes.get(variable.connectionPointIn, "ANY") for variable in next.inputVariables.getvariable() if variable.getformalParameter() != "EN"]))
  1223                 block_infos = self.GetBlockType(block_type, tuple([self.ConnectionTypes.get(variable.connectionPointIn, "ANY") for variable in next.inputVariables.getvariable() if variable.getformalParameter() != "EN"]))
  1216                 if block_infos is None:
  1224                 if block_infos is None:
  1217                     block_infos = self.GetBlockType(block_type)
  1225                     block_infos = self.GetBlockType(block_type)
  1218                 if block_infos is None:
  1226                 if block_infos is None:
  1219                     msg = _("Undefined block type \"{a1}\" in \"{a2}\" POU").format(a1=block_type, a2=self.Name)
  1227                     raise PLCGenException(
  1220                     raise PLCGenException, msg
  1228                         _("Undefined block type \"{a1}\" in \"{a2}\" POU").
       
  1229                         format(a1=block_type, a2=self.Name))
  1221                 try:
  1230                 try:
  1222                     paths.append(str(self.GenerateBlock(next, block_infos, body, connection, order, to_inout)))
  1231                     paths.append(str(self.GenerateBlock(next, block_infos, body, connection, order, to_inout)))
  1223                 except ValueError, e:
  1232                 except ValueError, e:
  1224                     raise PLCGenException, e.message
  1233                     raise PLCGenException(e.message)
  1225             elif isinstance(next, ContinuationClass):
  1234             elif isinstance(next, ContinuationClass):
  1226                 name = next.getname()
  1235                 name = next.getname()
  1227                 computed_value = self.ComputedConnectors.get(name, None)
  1236                 computed_value = self.ComputedConnectors.get(name, None)
  1228                 if computed_value is not None:
  1237                 if computed_value is not None:
  1229                     paths.append(str(computed_value))
  1238                     paths.append(str(computed_value))
  1230                 else:
  1239                 else:
  1231                     connector = None
  1240                     connector = None
  1232                     for instance in body.getcontentInstances():
  1241                     for instance in body.getcontentInstances():
  1233                         if isinstance(instance, ConnectorClass) and instance.getname() == name:
  1242                         if isinstance(instance, ConnectorClass) and instance.getname() == name:
  1234                             if connector is not None:
  1243                             if connector is not None:
  1235                                 msg = _("More than one connector found corresponding to \"{a1}\" continuation in \"{a2}\" POU").format(a1=name, a2=self.Name)
  1244                                 raise PLCGenException(
  1236                                 raise PLCGenException, msg
  1245                                     _("More than one connector found corresponding to \"{a1}\" continuation in \"{a2}\" POU").
       
  1246                                     format(a1=name, a2=self.Name))
  1237                             connector = instance
  1247                             connector = instance
  1238                     if connector is not None:
  1248                     if connector is not None:
  1239                         connections = connector.connectionPointIn.getconnections()
  1249                         connections = connector.connectionPointIn.getconnections()
  1240                         if connections is not None:
  1250                         if connections is not None:
  1241                             expression = self.ComputeExpression(body, connections, order)
  1251                             expression = self.ComputeExpression(body, connections, order)
  1242                             if expression is not None:
  1252                             if expression is not None:
  1243                                 self.ComputedConnectors[name] = expression
  1253                                 self.ComputedConnectors[name] = expression
  1244                                 paths.append(str(expression))
  1254                                 paths.append(str(expression))
  1245                     else:
  1255                     else:
  1246                         msg = _("No connector found corresponding to \"{a1}\" continuation in \"{a2}\" POU").format(a1=name, a2=self.Name)
  1256                         raise PLCGenException(
  1247                         raise PLCGenException, msg
  1257                             _("No connector found corresponding to \"{a1}\" continuation in \"{a2}\" POU").
       
  1258                             format(a1=name, a2=self.Name))
  1248             elif isinstance(next, ContactClass):
  1259             elif isinstance(next, ContactClass):
  1249                 contact_info = (self.TagName, "contact", next.getlocalId())
  1260                 contact_info = (self.TagName, "contact", next.getlocalId())
  1250                 variable = str(self.ExtractModifier(next, [(next.getvariable(), contact_info + ("reference",))], contact_info))
  1261                 variable = str(self.ExtractModifier(next, [(next.getvariable(), contact_info + ("reference",))], contact_info))
  1251                 result = self.GeneratePaths(next.connectionPointIn.getconnections(), body, order)
  1262                 result = self.GeneratePaths(next.connectionPointIn.getconnections(), body, order)
  1252                 if len(result) > 1:
  1263                 if len(result) > 1:
  1392 
  1403 
  1393     def GenerateSFCJump(self, jump, pou):
  1404     def GenerateSFCJump(self, jump, pou):
  1394         jump_target = jump.gettargetName()
  1405         jump_target = jump.gettargetName()
  1395         if not pou.hasstep(jump_target):
  1406         if not pou.hasstep(jump_target):
  1396             pname = pou.getname()
  1407             pname = pou.getname()
  1397             msg = _("SFC jump in pou \"{a1}\" refers to non-existent SFC step \"{a2}\"").format(a1=pname, a2=jump_target)
  1408             raise PLCGenException(
  1398             raise PLCGenException, msg
  1409                 _("SFC jump in pou \"{a1}\" refers to non-existent SFC step \"{a2}\"").
       
  1410                 format(a1=pname, a2=jump_target))
       
  1411 
  1399         if jump.connectionPointIn is not None:
  1412         if jump.connectionPointIn is not None:
  1400             instances = []
  1413             instances = []
  1401             connections = jump.connectionPointIn.getconnections()
  1414             connections = jump.connectionPointIn.getconnections()
  1402             if connections is not None and len(connections) == 1:
  1415             if connections is not None and len(connections) == 1:
  1403                 instanceLocalId = connections[0].getrefLocalId()
  1416                 instanceLocalId = connections[0].getrefLocalId()
  1518                                 if expression is not None:
  1531                                 if expression is not None:
  1519                                     transition_infos["content"] = [("\n%s:= " % self.CurrentIndent, ())] + expression + [(";\n", ())]
  1532                                     transition_infos["content"] = [("\n%s:= " % self.CurrentIndent, ())] + expression + [(";\n", ())]
  1520                                     self.SFCComputedBlocks += self.Program
  1533                                     self.SFCComputedBlocks += self.Program
  1521                                     self.Program = []
  1534                                     self.Program = []
  1522                     if not "content" in transition_infos:
  1535                     if not "content" in transition_infos:
  1523                         raise PLCGenException, _("Transition \"%s\" body must contain an output variable or coil referring to its name") % transitionValues["value"]
  1536                         raise PLCGenException(
       
  1537                             _("Transition \"%s\" body must contain an output variable or coil referring to its name")
       
  1538                             % transitionValues["value"])
  1524                 self.TagName = previous_tagname
  1539                 self.TagName = previous_tagname
  1525             elif transitionValues["type"] == "connection":
  1540             elif transitionValues["type"] == "connection":
  1526                 body = pou.getbody()
  1541                 body = pou.getbody()
  1527                 if isinstance(body, ListType):
  1542                 if isinstance(body, ListType):
  1528                     body = body[0]
  1543                     body = body[0]
  1598                 self.Program += JoinList([(", ", ())], transition_infos["from"])
  1613                 self.Program += JoinList([(", ", ())], transition_infos["from"])
  1599                 self.Program += [(")", ())]
  1614                 self.Program += [(")", ())]
  1600             elif len(transition_infos["from"]) == 1:
  1615             elif len(transition_infos["from"]) == 1:
  1601                 self.Program += transition_infos["from"][0]
  1616                 self.Program += transition_infos["from"][0]
  1602             else:
  1617             else:
  1603                 msg = _("Transition with content \"{a1}\" not connected to a previous step in \"{a2}\" POU").\
  1618                 raise PLCGenException(
  1604                       format(a1=transition_infos["content"], a2=self.Name)
  1619                     _("Transition with content \"{a1}\" not connected to a previous step in \"{a2}\" POU").
  1605                 raise PLCGenException, msg
  1620                     format(a1=transition_infos["content"], a2=self.Name))
  1606             self.Program += [(" TO ", ())]
  1621             self.Program += [(" TO ", ())]
  1607             if len(transition_infos["to"]) > 1:
  1622             if len(transition_infos["to"]) > 1:
  1608                 self.Program += [("(", ())]
  1623                 self.Program += [("(", ())]
  1609                 self.Program += JoinList([(", ", ())], transition_infos["to"])
  1624                 self.Program += JoinList([(", ", ())], transition_infos["to"])
  1610                 self.Program += [(")", ())]
  1625                 self.Program += [(")", ())]
  1611             elif len(transition_infos["to"]) == 1:
  1626             elif len(transition_infos["to"]) == 1:
  1612                 self.Program += transition_infos["to"][0]
  1627                 self.Program += transition_infos["to"][0]
  1613             else:
  1628             else:
  1614                 msg = _("Transition with content \"{a1}\" not connected to a next step in \"{a2}\" POU").\
  1629                 raise PLCGenException(
  1615                       format(a1=transition_infos["content"], a2=self.Name)
  1630                     _("Transition with content \"{a1}\" not connected to a next step in \"{a2}\" POU").
  1616                 raise PLCGenException, msg
  1631                     format(a1=transition_infos["content"], a2=self.Name))
  1617             self.Program += transition_infos["content"]
  1632             self.Program += transition_infos["content"]
  1618             self.Program += [("%sEND_TRANSITION\n\n" % self.CurrentIndent, ())]
  1633             self.Program += [("%sEND_TRANSITION\n\n" % self.CurrentIndent, ())]
  1619             for [(step_name, step_infos)] in transition_infos["to"]:
  1634             for [(step_name, step_infos)] in transition_infos["to"]:
  1620                 self.ComputeSFCStep(step_name)
  1635                 self.ComputeSFCStep(step_name)
  1621 
  1636 
  1629         if self.ReturnType is not None:
  1644         if self.ReturnType is not None:
  1630             program += [(" : ", ()),
  1645             program += [(" : ", ()),
  1631                         (self.ReturnType, (self.TagName, "return"))]
  1646                         (self.ReturnType, (self.TagName, "return"))]
  1632         program += [("\n", ())]
  1647         program += [("\n", ())]
  1633         if len(self.Interface) == 0:
  1648         if len(self.Interface) == 0:
  1634             raise PLCGenException, _("No variable defined in \"%s\" POU") % self.Name
  1649             raise PLCGenException(_("No variable defined in \"%s\" POU") % self.Name)
  1635         if len(self.Program) == 0:
  1650         if len(self.Program) == 0:
  1636             raise PLCGenException, _("No body defined in \"%s\" POU") % self.Name
  1651             raise PLCGenException(_("No body defined in \"%s\" POU") % self.Name)
  1637         var_number = 0
  1652         var_number = 0
  1638         for list_type, option, located, variables in self.Interface:
  1653         for list_type, option, located, variables in self.Interface:
  1639             variable_type = errorVarTypes.get(list_type, "var_local")
  1654             variable_type = errorVarTypes.get(list_type, "var_local")
  1640             program += [("  %s" % list_type, ())]
  1655             program += [("  %s" % list_type, ())]
  1641             if option is not None:
  1656             if option is not None: