# HG changeset patch # User lbessard # Date 1218551599 -7200 # Node ID c6fee379d446eac4908cee23316fd1931976a84a # Parent 6a2f7ddd2e50c76d032f544b106eb8f7b48954c0 Adding informations to program chunks to allow display of compiling errors from matiec diff -r 6a2f7ddd2e50 -r c6fee379d446 PLCGenerator.py --- a/PLCGenerator.py Tue Aug 12 16:30:39 2008 +0200 +++ b/PLCGenerator.py Tue Aug 12 16:33:19 2008 +0200 @@ -26,20 +26,20 @@ from plcopen.structures import * from types import * + +# Dictionary associating PLCOpen variable categories to the corresponding +# IEC 61131-3 variable categories 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 +# IEC 61131-3 POU categories pouTypeNames = {"function" : "FUNCTION", "functionBlock" : "FUNCTION_BLOCK", "program" : "PROGRAM"} -currentProject = None -currentProgram = "" -datatypeComputed = {} -pouComputed = {} - -class PLCGenException(Exception): - pass - + +# Helper function for reindenting text def ReIndentText(text, nb_spaces): compute = "" lines = text.splitlines() @@ -61,179 +61,338 @@ compute += "\n" return compute -def GenerateDataType(datatype_name): - if not datatypeComputed.get(datatype_name, True): - datatypeComputed[datatype_name] = True - global currentProject, currentProgram - datatype = currentProject.getdataType(datatype_name) - datatype_def = " %s :"%datatype.getname() - basetype_content = datatype.baseType.getcontent() - if basetype_content["name"] in ["string", "wstring"]: - datatype_def += " %s"%basetype_content["name"].upper() - elif basetype_content["name"] == "derived": - basetype_name = basetype_content["value"].getname() - GenerateDataType(basetype_name) - datatype_def += " %s"%basetype_name - elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned"]: - base_type = basetype_content["value"].baseType.getcontent() - if base_type["name"] == "derived": - basetype_name = base_type["value"].getname() + +#------------------------------------------------------------------------------- +# Specific exception for PLC generating errors +#------------------------------------------------------------------------------- + + +class PLCGenException(Exception): + pass + + +#------------------------------------------------------------------------------- +# Generator of PLC program +#------------------------------------------------------------------------------- + + +class ProgramGenerator: + + # Create a new PCL program generator + def __init__(self, controler, project): + # Keep reference of the controler and project + self.Controler = controler + self.Project = project + # Reset the internal variables used to generate PLC programs + self.Program = [] + self.DatatypeComputed = {} + self.PouComputed = {} + + # Compute value according to type given + def ComputeValue(self, value, var_type): + base_type = self.Controler.GetBaseType(var_type) + if base_type == "STRING": + return "'%s'"%value + elif base_type == "WSTRING": + return "\"%s\""%value + return value + + # Generate a data type from its name + def GenerateDataType(self, datatype_name): + # Verify that data type hasn't been generated yet + 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.getname(), (tagname, "name")), + (" : ", ())] + basetype_content = datatype.baseType.getcontent() + # Data type derived directly from a string type + if basetype_content["name"] in ["string", "wstring"]: + datatype_def += [(basetype_content["name"].upper(), (tagname, "base"))] + # Data type derived directly from a user defined type + elif basetype_content["name"] == "derived": + basetype_name = basetype_content["value"].getname() + self.GenerateDataType(basetype_name) + datatype_def += [(basetype_name, (tagname, "base"))] + # Data type is a subrange + elif basetype_content["name"] in ["subrangeSigned", "subrangeUnsigned"]: + base_type = basetype_content["value"].baseType.getcontent() + # Subrange derived directly from a user defined type + if base_type["name"] == "derived": + basetype_name = base_type["value"].getname() + self.GenerateDataType(basetype_name) + # Subrange derived directly from an elementary type + else: + basetype_name = base_type["name"] + min_value = basetype_content["value"].range.getlower() + max_value = basetype_content["value"].range.getupper() + datatype_def += [(basetype_name, (tagname, "base")), + (" (", ()), + ("%d"%min_value, (tagname, "lower")), + ("..", ()), + ("%d"%max_value, (tagname, "upper")), + (")",())] + # Data type is an enumerated type + elif basetype_content["name"] == "enum": + values = [[(value.getname(), (tagname, "value", i))] + for i, value in enumerate(basetype_content["value"].values.getvalue())] + datatype_def += [("(", ())] + datatype_def += JoinList([(", ", ())], values) + datatype_def += [(")", ())] + # Data type is an array + elif basetype_content["name"] == "array": + base_type = basetype_content["value"].baseType.getcontent() + # Array derived directly from a user defined type + if base_type["name"] == "derived": + basetype_name = base_type["value"].getname() + self.GenerateDataType(basetype_name) + # Array derived directly from a string type + elif base_type["name"] in ["string", "wstring"]: + basetype_name = base_type["name"].upper() + # Array derived directly from an elementary type + else: + basetype_name = base_type["name"] + dimensions = [[("%d"%dimension.getlower(), (tagname, "range", i, "lower")), + ("..", ()), + ("%d"%dimension.getupper(), (tagname, "range", i, "upper"))] + for i, dimension in enumerate(basetype_content["value"].getdimension())] + datatype_def += [("ARRAY [", ())] + datatype_def += JoinList([(",", ())], dimensions) + datatype_def += [("] OF " , ()), + (basetype_name, (tagname, "base"))] + # Data type derived directly from a elementary type else: - basetype_name = base_type["name"] - GenerateDataType(basetype_name) - min_value = basetype_content["value"].range.getlower() - max_value = basetype_content["value"].range.getupper() - datatype_def += " %s (%d..%d)"%(basetype_name, min_value, max_value) - elif basetype_content["name"] == "enum": - values = [] - for value in basetype_content["value"].values.getvalue(): - values.append(value.getname()) - datatype_def += " (%s)"%", ".join(values) - elif basetype_content["name"] == "array": - base_type = basetype_content["value"].baseType.getcontent() - if base_type["name"] == "derived": - basetype_name = base_type["value"].getname() - elif base_type["name"] in ["string", "wstring"]: - basetype_name = base_type["name"].upper() + datatype_def += [(basetype_content["name"], (tagname, "base"))] + # Data type has an initial value + if datatype.initialValue is not None: + datatype_def += [(" := ", ()), + (self.ComputeValue(datatype.initialValue.getvalue(), datatype_name), (tagname, "initial"))] + datatype_def += [(";\n", ())] + return datatype_def + + # Generate a POU from its name + def GeneratePouProgram(self, pou_name): + # Verify that POU hasn't been generated yet + 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() + # Verify that POU type exists + if pou_type in pouTypeNames: + # Create a POU program generator + pou_program = PouProgramGenerator(self, pou.getname(), pouTypeNames[pou_type]) + program = pou_program.GenerateProgram(pou) + self.Program += program else: - basetype_name = base_type["name"] - GenerateDataType(basetype_name) - dimensions = [] - for dimension in basetype_content["value"].getdimension(): - dimensions.append("%d..%d"%(dimension.getlower(), dimension.getupper())) - datatype_def += " ARRAY [%s] OF %s"%(",".join(dimensions), basetype_name) - else: - datatype_def += " %s"%basetype_content["name"] - if datatype.initialValue is not None: - datatype_def += " := %s"%str(datatype.initialValue.getvalue()) - currentProgram += "%s;\n"%datatype_def - -def GeneratePouProgram(pou_name): - if not pouComputed.get(pou_name, True): - pouComputed[pou_name] = True - global currentProject, currentProgram - pou = currentProject.getpou(pou_name) - pou_type = pou.getpouType() - if pou_type in pouTypeNames: - pou_program = PouProgram(pou.getname(), pouTypeNames[pou_type]) - else: - raise PLCGenException, "Undefined pou type \"%s\""%pou_type - pou_program.GenerateInterface(pou) - pou_program.GenerateConnectionTypes(pou) - pou_program.GenerateProgram(pou) - currentProgram += pou_program.GenerateSTProgram() - -def GenerateConfiguration(configuration): - config = "\nCONFIGURATION %s\n"%configuration.getname() - for varlist in configuration.getglobalVars(): - config += " VAR_GLOBAL" - if varlist.getretain(): - config += " RETAIN" - if varlist.getconstant(): - config += " CONSTANT" - config += "\n" - for var in varlist.getvariable(): - vartype_content = var.gettype().getcontent() - if vartype_content["name"] == "derived": - var_type = vartype_content["value"].getname() - elif vartype_content["name"] in ["string", "wstring"]: - var_type = vartype_content["name"].upper() - else: - var_type = vartype_content["name"] - config += " %s "%var.getname() - address = var.getaddress() - if address: - config += "AT %s "%address - config += ": %s"%var_type - initial = var.getinitialValue() - if initial: - value = str(initial.getvalue()) - value = {"TRUE":"0","FALSE":"1"}.get(value.upper(), value) - if var_type == "STRING": - config += " := '%s'"%value - elif var_type == "WSTRING": - config += " := \"%s\""%value + raise PLCGenException, "Undefined pou type \"%s\""%pou_type + + # Generate a configuration from its model + def GenerateConfiguration(self, configuration): + tagname = self.Controler.ComputeConfigurationName(configuration.getname()) + config = [("\nCONFIGURATION ", ()), + (configuration.getname(), (tagname, "name")), + ("\n", ())] + var_number = 0 + # Generate any global variable in configuration + for varlist in configuration.getglobalVars(): + # Generate variable block with modifier + config += [(" VAR_GLOBAL", ())] + if varlist.getretain(): + config += [(" RETAIN", (tagname, "variable", (var_number, var_number + len(varlist.getvariable())), "retain"))] + if varlist.getconstant(): + config += [(" CONSTANT", (tagname, "variable", (var_number, var_number + len(varlist.getvariable())), "constant"))] + config += [("\n", ())] + # Generate any variable of this block + for var in varlist.getvariable(): + vartype_content = var.gettype().getcontent() + # Variable type is a user data type + if vartype_content["name"] == "derived": + var_type = vartype_content["value"].getname() + # Variable type is a string type + elif vartype_content["name"] in ["string", "wstring"]: + var_type = vartype_content["name"].upper() + # Variable type is an elementary type else: - config += " := %s"%value - config += ";\n" - config += " END_VAR\n" - for resource in configuration.getresource(): - config += GenerateResource(resource) - config += "END_CONFIGURATION\n" - return config - -def GenerateResource(resource): - resrce = "\n RESOURCE %s ON BEREMIZ\n"%resource.getname() - for varlist in resource.getglobalVars(): - resrce += " VAR_GLOBAL" - if varlist.getretain(): - resrce += " RETAIN" - if varlist.getconstant(): - resrce += " CONSTANT" - resrce += "\n" - for var in varlist.getvariable(): - vartype_content = var.gettype().getcontent() - if vartype_content["name"] == "derived": - var_type = vartype_content["value"].getname() - elif vartype_content["name"] in ["string", "wstring"]: - var_type = vartype_content["name"].upper() - else: - var_type = vartype_content["name"] - resrce += " %s "%var.getname() - address = var.getaddress() - if address: - resrce += "AT %s "%address - resrce += ": %s"%var_type - initial = var.getinitialValue() - if initial: - value = str(initial.getvalue()) - value = {"TRUE":"0","FALSE":"1"}.get(value.upper(), value) - if var_type == "STRING": - resrce += " := '%s'"%value - elif var_type == "WSTRING": - resrce += " := \"%s\""%value + var_type = vartype_content["name"] + config += [(" ", ()), + (var.getname(), (tagname, "variable", var_number, "name")), + (" ", ())] + # Generate variable address if exists + address = var.getaddress() + if address: + config += [("AT ", ()), + (address, (tagename, "variable", var_number, "address")), + (" ", ())] + config += [(": ", ()), + (var_type, (tagename, "variable", var_number, "type"))] + # Generate variable initial value if exists + initial = var.getinitialValue() + if initial: + config += [(" := ", ()), + (self.ComputeValue(initial.getvalue(), var_type), (tagename, "variable", var_number, "initial"))] + config += [(";\n", ())] + var_number += 1 + config += [(" END_VAR\n", ())] + # 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()) + resrce = [("\n RESOURCE ", ()), + (resource.getname(), (tagname, "name")), + (" ON PLC\n", ())] + var_number = 0 + # Generate any global variable in configuration + for varlist in resource.getglobalVars(): + # Generate variable block with modifier + resrce += [(" VAR_GLOBAL", ())] + if varlist.getretain(): + resrce += [(" RETAIN", (tagname, "variable", (var_number, var_number + len(varlist.getvariable())), "retain"))] + if varlist.getconstant(): + resrce += [(" CONSTANT", (tagname, "variable", (var_number, var_number + len(varlist.getvariable())), "constant"))] + resrce += "\n" + # Generate any variable of this block + for var in varlist.getvariable(): + vartype_content = var.gettype().getcontent() + # Variable type is a user data type + if vartype_content["name"] == "derived": + var_type = vartype_content["value"].getname() + # Variable type is a string type + elif vartype_content["name"] in ["string", "wstring"]: + var_type = vartype_content["name"].upper() + # Variable type is an elementary type else: - resrce += " := %s"%value - resrce += ";\n" - resrce += " END_VAR\n" - tasks = resource.gettask() - for task in tasks: - resrce += " TASK %s("%task.getname() - args = [] - single = task.getsingle() - if single: - args.append("SINGLE := %s"%single) - interval = task.getinterval() - if interval: - text = "t#" - if interval.hour != 0: - text += "%dh"%interval.hour - if interval.minute != 0: - text += "%dm"%interval.minute - if interval.second != 0: - text += "%ds"%interval.second - if interval.microsecond != 0: - text += "%dms"%(interval.microsecond / 1000) - args.append("INTERVAL := %s"%text) - args.append("PRIORITY := %s"%str(task.getpriority())) - resrce += ",".join(args) + ");\n" - for task in tasks: - for instance in task.getpouInstance(): - resrce += " PROGRAM %s WITH %s : %s;\n"%(instance.getname(), task.getname(), instance.gettype()) - for instance in resource.getpouInstance(): - resrce += " PROGRAM %s : %s;\n"%(instance.getname(), instance.gettype()) - resrce += " END_RESOURCE\n" - return resrce - -""" -Module implementing methods for generating PLC programs in ST or IL -""" - -class PouProgram: - - def __init__(self, name, type): + var_type = vartype_content["name"] + resrce += [(" ", ()), + (var.getname(), (tagname, "variable", var_number, "name")), + (" ", ())] + address = var.getaddress() + # Generate variable address if exists + if address: + resrce += [("AT ", ()), + (address, (tagename, "variable", var_number, "address")), + (" ", ())] + resrce += [(": ", ()), + (var_type, (tagename, "variable", var_number, "type"))] + # Generate variable initial value if exists + initial = var.getinitialValue() + if initial: + resrce += [(" := ", ()), + (self.ComputeValue(initial.getvalue(), var_type), (tagename, "variable", var_number, "initial"))] + resrce += [(";\n", ())] + var_number += 1 + resrce += [(" END_VAR\n", ())] + # Generate any task in the resource + tasks = resource.gettask() + task_number = 0 + for task in tasks: + # Task declaration + resrce += [(" TASK ", ()), + (task.getname(), (tagname, "task", task_number, "name")), + ("(", ())] + args = [] + single = task.getsingle() + # Single argument if exists + if single: + resrce += [("SINGLE := ", ()), + (single, (tagname, "task", task_number, "single")), + (",", ())] + # Interval argument if exists + interval = task.getinterval() + if interval: + resrce += [("INTERVAL := t#", ())] + if interval.hour != 0: + resrce += [("%dh"%interval.hour, (tagname, "task", task_number, "interval", "hour"))] + if interval.minute != 0: + resrce += [("%dm"%interval.minute, (tagname, "task", task_number, "interval", "minute"))] + if interval.second != 0: + resrce += [("%ds"%interval.second, (tagname, "task", task_number, "interval", "second"))] + if interval.microsecond != 0: + resrce += [("%dms"%(interval.microsecond / 1000), (tagname, "task", task_number, "interval", "millisecond"))] + resrce += [(",", ())] + # Priority argument + resrce += [("PRIORITY := ", ()), + ("%d"%task.getpriority(), (tagname, "task", task_number, "priority")), + (");\n", ())] + task_number += 1 + instance_number = 0 + # Generate any program assign to each task + for task in tasks: + for instance in task.getpouInstance(): + resrce += [(" PROGRAM ", ()), + (instance.getname(), (tagname, "instance", instance_number, "name")), + (" WITH ", ()), + (task.getname(), (tagname, "instance", instance_number, "task")), + (" : ", ()), + (instance.gettype(), (tagname, "instance", instance_number, "type")), + (";\n", ())] + instance_number += 1 + # Generate any program assign to no task + for instance in resource.getpouInstance(): + resrce += [(" PROGRAM ", ()), + (instance.getname(), (tagname, "instance", instance_number, "name")), + (" : ", ()), + (instance.gettype(), (tagname, "instance", instance_number, "type")), + (";\n", ())] + instance_number += 1 + resrce += [(" END_RESOURCE\n", ())] + return resrce + + # Generate the entire program for current project + 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 + # type defined + if len(self.DatatypeComputed) > 0: + self.Program += [("TYPE\n", ())] + # Generate every data types defined + for datatype_name in self.DatatypeComputed.keys(): + self.Program += self.GenerateDataType(datatype_name) + self.Program += [("END_TYPE\n\n", ())] + # Generate every POUs defined + for pou_name in self.PouComputed.keys(): + self.GeneratePouProgram(pou_name) + # Generate every configurations defined + for config in self.Project.getconfigurations(): + self.Program += self.GenerateConfiguration(config) + + # Return generated program + def GetGeneratedProgram(self): + return self.Program + + +#------------------------------------------------------------------------------- +# Generator of POU programs +#------------------------------------------------------------------------------- + + +class PouProgramGenerator: + + # Create a new POU program generator + def __init__(self, parent, name, type): + # Keep Reference to the parent generator + self.ParentGenerator = parent self.Name = name self.Type = type + self.TagName = self.ParentGenerator.Controler.ComputePouName(name) + self.CurrentIndent = " " self.ReturnType = None self.Interface = [] self.InitialSteps = [] @@ -242,14 +401,26 @@ self.ConnectionTypes = {} self.RelatedConnections = [] self.SFCNetworks = {"Steps":{}, "Transitions":{}, "Actions":{}} - self.SFCComputedBlocks = "" + self.SFCComputedBlocks = [] self.ActionNumber = 0 - self.Program = "" - + self.Program = [] + + def GetBlockType(self, type): + return self.ParentGenerator.Controler.GetBlockType(type) + + 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, retain, constant, located, vars in self.Interface: for var_type, var_name, var_address, var_initial in vars: @@ -257,6 +428,7 @@ return True return False + # Return the type of a variable defined in interface def GetVariableType(self, name): for list_type, retain, constant, located, vars in self.Interface: for var_type, var_name, var_address, var_initial in vars: @@ -264,13 +436,14 @@ return var_type return None - def GetConnectedConnection(self, connection, body): - links = connection.getconnections() + # Return connectors linked by a connection to the given connector + def GetConnectedConnector(self, connector, body): + links = connector.getconnections() if links and len(links) == 1: - return self.GetLinkedConnection(links[0], body) - return None - - def GetLinkedConnection(self, link, body): + return self.GetLinkedConnector(links[0], body) + return None + + def GetLinkedConnector(self, link, body): parameter = link.getformalParameter() instance = body.getcontentInstance(link.getrefLocalId()) if isinstance(instance, (plcopen.fbdObjects_inVariable, plcopen.fbdObjects_inOutVariable, plcopen.commonObjects_continuation, plcopen.ldObjects_contact, plcopen.ldObjects_coil)): @@ -309,17 +482,19 @@ return self.RelatedConnections.pop(i) return [connection] - def GenerateInterface(self, pou): + def ComputeInterface(self, pou): interface = pou.getinterface() if interface is not None: body = pou.getbody() body_content = body.getcontent() if self.Type == "FUNCTION": returntype_content = interface.getreturnType().getcontent() - if returntype_content["value"] is None: + if returntype_content["name"] == "derived": + self.ReturnType = returntype_content["value"].getname() + elif returntype_content["name"] in ["string", "wstring"]: + self.ReturnType = returntype_content["name"].upper() + else: self.ReturnType = returntype_content["name"] - else: - self.ReturnType = returntype_content["value"].getname() for varlist in interface.getcontent(): variables = [] located = [] @@ -327,9 +502,9 @@ vartype_content = var.gettype().getcontent() if vartype_content["name"] == "derived": var_type = vartype_content["value"].getname() - GeneratePouProgram(var_type) - blocktype = GetBlockType(var_type) + blocktype = self.GetBlockType(var_type) if blocktype is not None: + self.ParentGenerator.GeneratePouProgram(var_type) if body_content["name"] in ["FBD", "LD", "SFC"]: block = pou.getinstanceByName(var.getname()) else: @@ -373,7 +548,7 @@ self.Interface.append((varTypeNames[varlist["name"]], varlist["value"].getretain(), varlist["value"].getconstant(), True, located)) - def GenerateConnectionTypes(self, pou): + def ComputeConnectionTypes(self, pou): body = pou.getbody() body_content = body.getcontent() body_type = body_content["name"] @@ -397,7 +572,7 @@ self.ConnectionTypes[connection] = var_type if isinstance(instance, (plcopen.fbdObjects_outVariable, plcopen.fbdObjects_inOutVariable)): self.ConnectionTypes[instance.connectionPointIn] = var_type - connected = self.GetConnectedConnection(instance.connectionPointIn, body) + connected = self.GetConnectedConnector(instance.connectionPointIn, body) if connected and connected not in self.ConnectionTypes: for connection in self.ExtractRelatedConnections(connected): self.ConnectionTypes[connection] = var_type @@ -405,7 +580,7 @@ for connection in self.ExtractRelatedConnections(instance.connectionPointOut): self.ConnectionTypes[connection] = "BOOL" self.ConnectionTypes[instance.connectionPointIn] = "BOOL" - connected = self.GetConnectedConnection(instance.connectionPointIn, body) + connected = self.GetConnectedConnector(instance.connectionPointIn, body) if connected and connected not in self.ConnectionTypes: for connection in self.ExtractRelatedConnections(connected): self.ConnectionTypes[connection] = "BOOL" @@ -416,19 +591,19 @@ elif isinstance(instance, plcopen.ldObjects_rightPowerRail): for connection in instance.getconnectionPointIn(): self.ConnectionTypes[connection] = "BOOL" - connected = self.GetConnectedConnection(connection, body) + connected = self.GetConnectedConnector(connection, body) if connected and connected not in self.ConnectionTypes: for connection in self.ExtractRelatedConnections(connected): self.ConnectionTypes[connection] = "BOOL" elif isinstance(instance, plcopen.sfcObjects_transition): content = instance.condition.getcontent() if content["name"] == "connection" and len(content["value"]) == 1: - connected = self.GetLinkedConnection(content["value"][0], body) + connected = self.GetLinkedConnector(content["value"][0], body) if connected and connected not in self.ConnectionTypes: for connection in self.ExtractRelatedConnections(connected): self.ConnectionTypes[connection] = "BOOL" elif isinstance(instance, plcopen.fbdObjects_block): - block_infos = GetBlockType(instance.gettypeName()) + block_infos = self.GetBlockType(instance.gettypeName()) undefined = {} for variable in instance.outputVariables.getvariable(): output_name = variable.getformalParameter() @@ -445,7 +620,7 @@ input_name = variable.getformalParameter() for iname, itype, iqualifier in block_infos["inputs"]: if input_name == iname: - connected = self.GetConnectedConnection(variable.connectionPointIn, body) + connected = self.GetConnectedConnector(variable.connectionPointIn, body) if itype.startswith("ANY"): if itype not in undefined: undefined[itype] = [] @@ -469,13 +644,34 @@ else: for connection in related: self.ConnectionTypes[connection] = var_type - - def GenerateProgram(self, pou): + + def GetNetworkType(self, connections, body): + network_type = "FBD" + for connection in connections: + localId = connection.getrefLocalId() + next = body.getcontentInstance(localId) + if isinstance(next, plcopen.ldObjects_leftPowerRail) or isinstance(next, plcopen.ldObjects_contact): + return "LD" + elif isinstance(next, plcopen.fbdObjects_block): + for variable in next.inputVariables.getvariable(): + result = self.GetNetworkType(variable.connectionPointIn.getconnections(), body) + if result != "FBD": + return result + elif isinstance(next, plcopen.fbdObjects_inVariable): + return "FBD" + elif isinstance(next, plcopen.fbdObjects_inOutVariable): + return self.GetNetworkType(next.connectionPointIn.getconnections(), body) + else: + return None + return "FBD" + + def ComputeProgram(self, pou): body = pou.getbody() body_content = body.getcontent() body_type = body_content["name"] if body_type in ["IL","ST"]: - self.Program = ReIndentText(body_content["value"].gettext(), 2) + self.Program = [(ReIndentText(body_content["value"].gettext(), len(self.CurrentIndent)), + (self.TagName, "body"))] elif body_type == "FBD": orderedInstances = [] otherInstances = {"outVariables" : [], "block" : [], "connector" : []} @@ -495,15 +691,18 @@ instances.extend(otherInstances["connector"] + otherInstances["outVariables"] + otherInstances["block"]) for instance in instances: if isinstance(instance, (plcopen.fbdObjects_outVariable, plcopen.fbdObjects_inOutVariable)): - var = instance.getexpression() connections = instance.connectionPointIn.getconnections() if connections and len(connections) == 1: expression = self.ComputeFBDExpression(body, connections[0]) - self.Program += " %s := %s;\n"%(var, expression) + self.Program += [(self.CurrentIndent, ()), + (instance.getexpression(), (self.TagName, "io_variable", instance.getlocalId(), "expression")), + (" := ", ())] + self.Program += expression + self.Program += [(";\n", ())] elif isinstance(instance, plcopen.fbdObjects_block): block_type = instance.gettypeName() - self.GeneratePouProgram(block_type) - block_infos = GetBlockType(block_type) + self.ParentGenerator.GeneratePouProgram(block_type) + block_infos = self.GetBlockType(block_type) block_infos["generate"](self, instance, body, None) elif isinstance(instance, plcopen.commonObjects_connector): connector = instance.getname() @@ -519,11 +718,14 @@ if len(paths) > 0: paths = tuple(paths) else: - paths = paths[0] - variable = self.ExtractModifier(instance, instance.getvariable()) + paths = paths[0] + coil_info = (self.TagName, "coil", instance.getlocalId()) + variable = self.ExtractModifier(instance, [(instance.getvariable(), coil_info + ("reference",))], coil_info) expression = self.ComputeLDExpression(paths, True) - self.Program += " %s := %s;\n"%(variable, expression) + self.Program += [(self.CurrentIndent, ())] + variable + self.Program += [(" := ", ())] + expression + [(";\n", ())] elif body_type == "SFC": + self.IndentRight() for instance in body.getcontentInstances(): if isinstance(instance, plcopen.sfcObjects_step): self.GenerateSFCStep(instance, pou) @@ -533,24 +735,25 @@ self.GenerateSFCTransition(instance, pou) elif isinstance(instance, plcopen.sfcObjects_jumpStep): self.GenerateSFCJump(instance, pou) - if len(self.InitialSteps) > 0 and self.SFCComputedBlocks != "": + if len(self.InitialSteps) > 0 and len(self.SFCComputedBlocks) > 0: action_name = "COMPUTE_FUNCTION_BLOCKS" action_infos = {"qualifier" : "S", "content" : action_name} self.SFCNetworks["Steps"][self.InitialSteps[0]]["actions"].append(action_infos) - self.SFCNetworks["Actions"][action_name] = ReIndentText(self.SFCComputedBlocks, 4) - self.Program = "" + self.SFCNetworks["Actions"][action_name] = (self.SFCComputedBlocks, ()) + self.Program = [] + self.IndentLeft() for initialstep in self.InitialSteps: self.ComputeSFCStep(initialstep) - + def ComputeFBDExpression(self, body, link, order = False): localid = link.getrefLocalId() instance = body.getcontentInstance(localid) if isinstance(instance, (plcopen.fbdObjects_inVariable, plcopen.fbdObjects_inOutVariable)): - return instance.getexpression() + return [(instance.getexpression(), (self.TagName, "io_variable", localid, "expression"))] elif isinstance(instance, plcopen.fbdObjects_block): block_type = instance.gettypeName() - self.GeneratePouProgram(block_type) - block_infos = GetBlockType(block_type) + self.ParentGenerator.GeneratePouProgram(block_type) + block_infos = self.GetBlockType(block_type) return block_infos["generate"](self, instance, body, link, order) elif isinstance(instance, plcopen.commonObjects_continuation): name = instance.getname() @@ -576,11 +779,12 @@ paths.append(None) elif isinstance(next, plcopen.fbdObjects_block): block_type = next.gettypeName() - self.GeneratePouProgram(block_type) - block_infos = GetBlockType(block_type) - paths.append(block_infos["generate"](self, next, body, connection)) + self.ParentGenerator.GeneratePouProgram(block_type) + block_infos = self.GetBlockType(block_type) + paths.append(str(block_infos["generate"](self, next, body, connection))) else: - variable = self.ExtractModifier(next, next.getvariable()) + contact_info = (self.TagName, "contact", next.getlocalId()) + variable = str(self.ExtractModifier(next, [(next.getvariable(), contact_info + ("reference",))], contact_info)) result = self.GenerateLDPaths(next.connectionPointIn.getconnections(), body) if len(result) > 1: paths.append([variable, tuple(result)]) @@ -592,25 +796,46 @@ paths.append(variable) return paths - def GetNetworkType(self, connections, body): - network_type = "FBD" - for connection in connections: - localId = connection.getrefLocalId() - next = body.getcontentInstance(localId) - if isinstance(next, plcopen.ldObjects_leftPowerRail) or isinstance(next, plcopen.ldObjects_contact): - return "LD" - elif isinstance(next, plcopen.fbdObjects_block): - for variable in next.inputVariables.getvariable(): - result = self.GetNetworkType(variable.connectionPointIn.getconnections(), body) - if result != "FBD": - return result - elif isinstance(next, plcopen.fbdObjects_inVariable): - return "FBD" - elif isinstance(next, plcopen.fbdObjects_inOutVariable): - return self.GetNetworkType(next.connectionPointIn.getconnections(), body) + def ComputeLDExpression(self, paths, first = False): + if type(paths) == TupleType: + if None in paths: + return [("TRUE", ())] else: - return None - return "FBD" + vars = [self.ComputeLDExpression(path) for path in paths] + if first: + return JoinList([(" OR ", ())], vars) + else: + return [("(", ())] + JoinList([(" OR ", ())], vars) + [(")", ())] + elif type(paths) == ListType: + vars = [self.ComputeLDExpression(path) for path in paths] + return JoinList([(" AND ", ())], vars) + else: + return eval(paths) + + def ExtractModifier(self, variable, expression, var_info): + if variable.getnegated(): + return [("NOT(", var_info + ("negated",))] + expression + [(")", ())] + else: + edge = variable.getedge() + if edge == "rising": + return self.AddTrigger("R_TRIG", expression, var_info + ("rising",)) + 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] or self.Interface[-1][2] or self.Interface[-1][3]: + self.Interface.append(("VAR", False, False, False, [])) + i = 1 + name = "%s%d"%(edge, i) + while self.IsAlreadyDefined(name): + i += 1 + name = "%s%d"%(edge, i) + self.Interface[-1][4].append((edge, name, None, None)) + 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() @@ -635,7 +860,10 @@ if step_name not in self.SFCNetworks["Steps"].keys(): if step.getinitialStep(): self.InitialSteps.append(step_name) - step_infos = {"initial" : step.getinitialStep(), "transitions" : [], "actions" : []} + step_infos = {"id" : step.getlocalId(), + "initial" : step.getinitialStep(), + "transitions" : [], + "actions" : []} if step.connectionPointIn: instances = [] connections = step.connectionPointIn.getconnections() @@ -656,7 +884,8 @@ for instance in instances: self.GenerateSFCTransition(instance, pou) if instance in self.SFCNetworks["Transitions"].keys(): - self.SFCNetworks["Transitions"][instance]["to"].append(step_name) + target_info = (self.TagName, "transition", instance.getlocalId(), "to", step_infos["id"]) + self.SFCNetworks["Transitions"][instance]["to"].append([(step_name, target_info)]) self.SFCNetworks["Steps"][step_name] = step_infos def GenerateSFCJump(self, jump, pou): @@ -681,7 +910,8 @@ for instance in instances: self.GenerateSFCTransition(instance, pou) if instance in self.SFCNetworks["Transitions"].keys(): - self.SFCNetworks["Transitions"][instance]["to"].append(jump_target) + 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() @@ -692,8 +922,11 @@ step_name = step.getname() if step_name in self.SFCNetworks["Steps"].keys(): actions = actionBlock.getactions() - for action in actions: - action_infos = {"qualifier" : action["qualifier"], "content" : action["value"]} + for i, action in enumerate(actions): + action_infos = {"id" : actionBlock.getlocalId(), + "qualifier" : action["qualifier"], + "content" : action["value"], + "num" : i} if "duration" in action: action_infos["duration"] = action["duration"] if "indicator" in action: @@ -702,7 +935,9 @@ self.GenerateSFCAction(action["value"], pou) else: action_name = "%s_INLINE%d"%(step_name.upper(), self.GetActionNumber()) - self.SFCNetworks["Actions"][action_name] = " %s\n"%action["value"] + 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) @@ -710,29 +945,12 @@ if action_name not in self.SFCNetworks["Actions"].keys(): actionContent = pou.getaction(action_name) if actionContent: - actionType = actionContent.getbodyType() - actionBody = actionContent.getbody() - if actionType in ["ST", "IL"]: - self.SFCNetworks["Actions"][action_name] = ReIndentText(actionContent.gettext(), 4) - elif actionType == "FBD": - for instance in actionBody.getcontentInstances(): - if isinstance(instance, plcopen.fbdObjects_outVariable): - var = instance.getexpression() - connections = instance.connectionPointIn.getconnections() - if connections and len(connections) == 1: - expression = self.ComputeFBDExpression(actionBody, connections[0]) - action_content = self.Program + " %s := %s;\n"%(var, expression) - self.Program = "" - self.SFCNetworks["Actions"][action_name] = ReIndentText(action_content, 4) - elif actionType == "LD": - for instance in actionbody.getcontentInstances(): - if isinstance(instance, plcopen.ldObjects_coil): - paths = self.GenerateLDPaths(instance.connectionPointIn.getconnections(), actionBody) - variable = self.ExtractModifier(instance, instance.getvariable()) - expression = self.ComputeLDExpression(paths, True) - action_content = self.Program + " %s := %s;\n"%(variable, expression) - self.Program = "" - self.SFCNetworks["Actions"][action_name] = ReIndentText(action_content, 4) + previous_tagname = self.TagName + self.TagName = self.ParentGenerator.Controler.ComputePouActionName(self.Name, action_name) + self.ComputeProgram(actionContent) + 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(): @@ -752,35 +970,45 @@ steps.extend(self.ExtractConvergenceInputs(step, pou)) elif isinstance(instance, plcopen.sfcObjects_simultaneousConvergence): steps.extend(self.ExtractConvergenceInputs(instance, pou)) - transition_infos = {"priority": transition.getpriority(), "from": [], "to" : []} + transition_infos = {"id" : transition.getlocalId(), + "priority": transition.getpriority(), + "from": [], + "to" : []} transitionValues = transition.getconditionContent() if transitionValues["type"] == "inline": - transition_infos["content"] = "\n := %s;\n"%transitionValues["value"] + transition_infos["content"] = [("\n%s:= "%self.CurrentIndent, ()), + (transitionValues["value"], (self.TagName, "transition", transition.getlocalId(), "inline")), + (";\n", ())] elif transitionValues["type"] == "reference": transitionContent = pou.gettransition(transitionValues["value"]) transitionType = transitionContent.getbodyType() transitionBody = transitionContent.getbody() + previous_tagname = self.TagName + self.TagName = self.ParentGenerator.Controler.ComputePouTransitionName(self.Name, transitionValues["value"]) if transitionType == "IL": - transition_infos["content"] = ":\n%s"%ReIndentText(transitionBody.gettext(), 4) + transition_infos["content"] = [(":\n", ()), + (ReIndentText(transitionBody.gettext(), len(self.CurrentIndent)), (self.TagName, "body"))] elif transitionType == "ST": - transition_infos["content"] = "\n%s"%ReIndentText(transitionBody.gettext(), 4) + transition_infos["content"] = [("\n", ()), + (ReIndentText(transitionBody.gettext(), len(self.CurrentIndent)), (self.TagName, "body"))] elif transitionType == "FBD": for instance in transitionBody.getcontentInstances(): if isinstance(instance, plcopen.fbdObjects_outVariable): connections = instance.connectionPointIn.getconnections() if connections and len(connections) == 1: expression = self.ComputeFBDExpression(transitionBody, connections[0]) - transition_infos["content"] = "\n := %s;\n"%expression + transition_infos["content"] = [("\n%s:= "%self.CurrentIndent, ())] + expression + [(";\n", ())] self.SFCComputedBlocks += self.Program - self.Program = "" + self.Program = [] elif transitionType == "LD": for instance in transitionBody.getcontentInstances(): if isinstance(instance, plcopen.ldObjects_coil): paths = self.GenerateLDPaths(instance.connectionPointIn.getconnections(), transitionBody) expression = self.ComputeLDExpression(paths, True) - transition_infos["content"] = "\n := %s;\n"%expression + transition_infos["content"] = [("\n%s:= "%self.CurrentIndent, ())] + expression + [(";\n", ())] self.SFCComputedBlocks += self.Program - self.Program = "" + self.Program = [] + self.TagName = previous_tagname elif transitionValues["type"] == "connection": body = pou.getbody() connections = transition.getconnections() @@ -790,39 +1018,49 @@ if len(connections) > 1 or network_type == "LD": paths = self.GenerateLDPaths(connections, body) expression = self.ComputeLDExpression(paths, True) - transition_infos["content"] = "\n := %s;\n"%expression - self.SFCComputedBlocks += self.Program - self.Program = "" else: expression = self.ComputeFBDExpression(body, connections[0]) - transition_infos["content"] = "\n := %s;\n"%expression - self.SFCComputedBlocks += self.Program - self.Program = "" + transition_infos["content"] = [("\n%s:= "%self.CurrentIndent, ())] + expression + [(";\n", ())] + self.SFCComputedBlocks += self.Program + self.Program = [] for step in steps: self.GenerateSFCStep(step, pou) step_name = step.getname() if step_name in self.SFCNetworks["Steps"].keys(): - transition_infos["from"].append(step_name) + transition_infos["from"].append([(step_name, (self.TagName, "transition", transition.getlocalId(), "from", step.getlocalId()))]) self.SFCNetworks["Steps"][step_name]["transitions"].append(transition) self.SFCNetworks["Transitions"][transition] = transition_infos def ComputeSFCStep(self, step_name): if step_name in self.SFCNetworks["Steps"].keys(): step_infos = self.SFCNetworks["Steps"].pop(step_name) + self.Program += [(self.CurrentIndent, ())] if step_infos["initial"]: - self.Program += " INITIAL_STEP %s:\n"%step_name - else: - self.Program += " STEP %s:\n"%step_name + self.Program += [("INITIAL_", ())] + self.Program += [("STEP ", ()), + (step_name, (self.TagName, "step", step_infos["id"], "name")), + (":\n", ())] actions = [] + self.IndentRight() for action_infos in step_infos["actions"]: + if action_infos.get("id", None) is not None: + action_info = (self.TagName, "action_block", action_infos["id"], "action", action_infos["num"]) + else: + action_info = () actions.append(action_infos["content"]) - self.Program += " %(content)s(%(qualifier)s"%action_infos + self.Program += [(self.CurrentIndent, ()), + (action_infos["content"], action_info + ("reference",)), + ("(", ()), + (action_infos["qualifier"], action_info + ("qualifier",))] if "duration" in action_infos: - self.Program += ", %(duration)s"%action_infos + self.Program += [(", ", ()), + (action_infos["duration"], action_info + ("duration",))] if "indicator" in action_infos: - self.Program += ", %(indicator)s"%action_infos - self.Program += ");\n" - self.Program += " END_STEP\n\n" + self.Program += [(", ", ()), + (action_infos["indicator"], action_info + ("indicator",))] + self.Program += [(");\n", ())] + self.IndentLeft() + self.Program += [("%sEND_STEP\n\n"%self.CurrentIndent, ())] for action in actions: self.ComputeSFCAction(action) for transition in step_infos["transitions"]: @@ -830,129 +1068,91 @@ def ComputeSFCAction(self, action_name): if action_name in self.SFCNetworks["Actions"].keys(): - action_content = self.SFCNetworks["Actions"].pop(action_name) - self.Program += " ACTION %s:\n%s END_ACTION\n\n"%(action_name, action_content) + action_content, action_info = self.SFCNetworks["Actions"].pop(action_name) + self.Program += [("%sACTION "%self.CurrentIndent, ()), + (action_name, action_info), + (" :\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) - self.Program += " TRANSITION" + self.Program += [("%sTRANSITION"%self.CurrentIndent, ())] if transition_infos["priority"] != None: - self.Program += " (PRIORITY := %d)"%transition_infos["priority"] - self.Program += " FROM " + self.Program += [(" (PRIORITY := ", ()), + ("%d"%transition_infos["priority"], (self.TagName, "transition", transition_infos["id"], "priority")), + (")", ())] + self.Program += [(" FROM ", ())] if len(transition_infos["from"]) > 1: - self.Program += "(%s)"%", ".join(transition_infos["from"]) + self.Program += [("(", ())] + self.Program += JoinList([(", ", ())], transition_infos["from"]) + self.Program += [(")", ())] elif len(transition_infos["from"]) == 1: - self.Program += "%s"%transition_infos["from"][0] + self.Program += transition_infos["from"][0] else: raise PLCGenException, "Transition with content \"%s\" not connected to a previous step in \"%s\" POU"%(transition_infos["content"], self.Name) - self.Program += " TO " + self.Program += [(" TO ", ())] if len(transition_infos["to"]) > 1: - self.Program += "(%s)"%", ".join(transition_infos["to"]) + self.Program += [("(", ())] + self.Program += JoinList([(", ", ())], transition_infos["to"]) + self.Program += [(")", ())] elif len(transition_infos["to"]) == 1: - self.Program += "%s"%transition_infos["to"][0] + self.Program += transition_infos["to"][0] else: raise PLCGenException, "Transition with content \"%s\" not connected to a next step in \"%s\" POU"%(transition_infos["content"], self.Name) self.Program += transition_infos["content"] - self.Program += " END_TRANSITION\n\n" - for step_name in transition_infos["to"]: + 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) - def ComputeLDExpression(self, paths, first = False): - if type(paths) == TupleType: - if None in paths: - return "TRUE" - else: - var = [self.ComputeLDExpression(path) for path in paths] - if first: - return " OR ".join(var) - else: - return "(%s)"%" OR ".join(var) - elif type(paths) == ListType: - var = [self.ComputeLDExpression(path) for path in paths] - return " AND ".join(var) - else: - return paths - - def ExtractModifier(self, variable, text): - if variable.getnegated(): - return "NOT(%s)"%text - else: - edge = variable.getedge() - if edge == "rising": - return self.AddTrigger("R_TRIG", text) - elif edge == "falling": - return self.AddTrigger("F_TRIG", text) - return text - - def AddTrigger(self, edge, text): - if self.Interface[-1][0] != "VAR" or self.Interface[-1][1] or self.Interface[-1][2] or self.Interface[-1][3]: - self.Interface.append(("VAR", False, False, False, [])) - i = 1 - name = "%s%d"%(edge, i) - while self.IsAlreadyDefined(name): - i += 1 - name = "%s%d"%(edge, i) - self.Interface[-1][4].append((edge, name, None, None)) - self.Program += " %s(CLK := %s);\n"%(name, text) - return "%s.Q"%name - - def GenerateSTProgram(self): + program = [("%s "%self.Type, ()), + (self.Name, (self.TagName, "name"))] if self.ReturnType: - program = "%s %s : %s\n"%(self.Type, self.Name, self.ReturnType) - else: - program = "%s %s\n"%(self.Type, self.Name) + program += [(" : ", ()), + (self.ReturnType, (self.TagName, "return"))] + program += [("\n", ())] if len(self.Interface) == 0: raise PLCGenException, "No variable defined in \"%s\" POU"%self.Name - if self.Program == "": + if len(self.Program) == 0 : raise PLCGenException, "No body defined in \"%s\" POU"%self.Name + var_number = 0 for list_type, retain, constant, located, variables in self.Interface: - program += " %s"%list_type + program += [(" %s"%list_type, ())] if retain: - program += " RETAIN" + program += [(" RETAIN", (self.TagName, "variable", (var_number, var_number + len(variables)), "retain"))] if constant: - program += " CONSTANT" - program += "\n" + program += [(" CONSTANT", (self.TagName, "variable", (var_number, var_number + len(variables)), "constant"))] + program += [("\n", ())] for var_type, var_name, var_address, var_initial in variables: - program += " " + program += [(" ", ())] if var_name: - program += "%s "%var_name + program += [(var_name, (self.TagName, "variable", var_number, "name")), + (" ", ())] if var_address != None: - program += "AT %s "%var_address - program += ": %s"%var_type + program += [("AT ", ()), + (var_address, (self.TagName, "variable", var_number, "address")), + (" ", ())] + program += [(": ", ()), + (var_type, (self.TagName, "variable", var_number, "type"))] if var_initial != None: - if var_type == "STRING": - program += " := '%s'"%var_initial - elif var_type == "WSTRING": - program += " := \"%s\""%var_initial - else: - program += " := %s"%var_initial - program += ";\n" - program += " END_VAR\n" - program += "\n" + program += [(" := ", ()), + (self.ComputeValue(var_initial, var_type), (self.TagName, "variable", var_number, "initial"))] + program += [(";\n", ())] + var_number += 1 + program += [(" END_VAR\n", ())] + program += [("\n", ())] program += self.Program - program += "END_%s\n\n"%self.Type + program += [("END_%s\n\n"%self.Type, ())] return program - def GeneratePouProgram(self, pou_name): - GeneratePouProgram(pou_name) - -def GenerateCurrentProgram(project): - global currentProject, currentProgram - currentProject = project - currentProgram = "" - for datatype in project.getdataTypes(): - datatypeComputed[datatype.getname()] = False - for pou in project.getpous(): - pouComputed[pou.getname()] = False - if len(datatypeComputed) > 0: - currentProgram += "TYPE\n" - for datatype_name in datatypeComputed.keys(): - GenerateDataType(datatype_name) - currentProgram += "END_TYPE\n\n" - for pou_name in pouComputed.keys(): - GeneratePouProgram(pou_name) - for config in project.getconfigurations(): - currentProgram += GenerateConfiguration(config) - return currentProgram - +def GenerateCurrentProgram(controler, project): + generator = ProgramGenerator(controler, project) + generator.GenerateProgram() + return generator.GetGeneratedProgram() +