Adding support for cancelling code generation of function with no input connected
--- a/PLCControler.py Mon Jan 19 17:07:03 2009 +0100
+++ b/PLCControler.py Mon Jan 19 17:08:17 2009 +0100
@@ -499,9 +499,11 @@
return False
def GenerateProgram(self, filepath=None):
+ errors = []
+ warnings = []
if self.Project is not None:
try:
- self.ProgramChunks = GenerateCurrentProgram(self, self.Project)
+ self.ProgramChunks = GenerateCurrentProgram(self, self.Project, errors, warnings)
self.NextCompiledProject = self.Copy(self.Project)
program_text = "".join([item[0] for item in self.ProgramChunks])
if filepath is not None:
@@ -509,12 +511,12 @@
programfile.write(program_text)
programfile.close()
self.ProgramFilePath = filepath
- return None
- else:
- return program_text
+ return program_text, errors, warnings
except PLCGenException, e:
- return e.message
- return "No project opened"
+ errors.append(e.message)
+ else:
+ errors.append("No project opened")
+ return "", errors, warnings
def ProgramTransferred(self):
self.CurrentCompiledProject = self.NextCompiledProject
--- a/PLCGenerator.py Mon Jan 19 17:07:03 2009 +0100
+++ b/PLCGenerator.py Mon Jan 19 17:08:17 2009 +0100
@@ -86,7 +86,7 @@
class ProgramGenerator:
# Create a new PCL program generator
- def __init__(self, controler, project):
+ def __init__(self, controler, project, errors, warnings):
# Keep reference of the controler and project
self.Controler = controler
self.Project = project
@@ -94,6 +94,8 @@
self.Program = []
self.DatatypeComputed = {}
self.PouComputed = {}
+ self.Errors = errors
+ self.Warnings = warnings
# Compute value according to type given
def ComputeValue(self, value, var_type):
@@ -222,7 +224,7 @@
# Verify that POU type exists
if pou_type in pouTypeNames:
# Create a POU program generator
- pou_program = PouProgramGenerator(self, pou.getname(), pouTypeNames[pou_type])
+ pou_program = PouProgramGenerator(self, pou.getname(), pouTypeNames[pou_type], self.Errors, self.Warnings)
program = pou_program.GenerateProgram(pou)
self.Program += program
else:
@@ -420,7 +422,7 @@
class PouProgramGenerator:
# Create a new POU program generator
- def __init__(self, parent, name, type):
+ def __init__(self, parent, name, type, errors, warnings):
# Keep Reference to the parent generator
self.ParentGenerator = parent
self.Name = name
@@ -438,6 +440,8 @@
self.SFCComputedBlocks = []
self.ActionNumber = 0
self.Program = []
+ self.Errors = errors
+ self.Warnings = warnings
def GetBlockType(self, type):
return self.ParentGenerator.Controler.GetBlockType(type)
@@ -1208,8 +1212,8 @@
program += [("END_%s\n\n"%self.Type, ())]
return program
-def GenerateCurrentProgram(controler, project):
- generator = ProgramGenerator(controler, project)
+def GenerateCurrentProgram(controler, project, errors, warnings):
+ generator = ProgramGenerator(controler, project, errors, warnings)
generator.GenerateProgram()
return generator.GetGeneratedProgram()
--- a/PLCOpenEditor.py Mon Jan 19 17:07:03 2009 +0100
+++ b/PLCOpenEditor.py Mon Jan 19 17:08:17 2009 +0100
@@ -883,20 +883,23 @@
dialog = wx.FileDialog(self, "Choose a file", os.getcwd(), self.Controler.GetProgramFilePath(), "ST files (*.st)|*.st|All files|*.*", wx.SAVE|wx.CHANGE_DIR)
if dialog.ShowModal() == wx.ID_OK:
filepath = dialog.GetPath()
+ message_text = ""
+ header, icon = "Done", wx.ICON_INFORMATION
if os.path.isdir(os.path.dirname(filepath)):
- result = self.Controler.GenerateProgram(filepath)
- if result is not None:
- message = wx.MessageDialog(self, "Can't generate program to file %s :\n%s"%(filepath, result), "Error", wx.OK|wx.ICON_ERROR)
- message.ShowModal()
- message.Destroy()
+ program, errors, warnings = self.Controler.GenerateProgram(filepath)
+ message_text += "".join(["warning: %s\n" for warning in warnings])
+ if len(errors) > 0:
+ message_text += "".join(["error: %s\n" for warning in warnings])
+ message_text += "Can't generate program to file %s!"%filepath
+ header, icon = "Error", wx.ICON_ERROR
else:
- message = wx.MessageDialog(self, "Program was successfully generated!", "Done", wx.OK|wx.ICON_INFORMATION)
- message.ShowModal()
- message.Destroy()
+ message_text += "Program was successfully generated!"
else:
- message = wx.MessageDialog(self, "%s is not a valid folder!"%os.path.dirname(filepath), "Error", wx.OK|wx.ICON_ERROR)
- message.ShowModal()
- message.Destroy()
+ message_text += "%s is not a valid folder!"%os.path.dirname(filepath)
+ header, icon = "Error", wx.ICON_ERROR
+ message = wx.MessageDialog(self, message_text, header, wx.OK|icon)
+ message.ShowModal()
+ message.Destroy()
dialog.Destroy()
event.Skip()
--- a/generate_IEC_std.py Mon Jan 19 17:07:03 2009 +0100
+++ b/generate_IEC_std.py Mon Jan 19 17:08:17 2009 +0100
@@ -108,14 +108,14 @@
This tests are defined in search_expression_type.cc
"""
return {"ANY" : "",
- "ANY_BIT" : "if(search_expression_type->is_binary_type(%(paramname)s_type_symbol))",
- "ANY_NBIT" : "if(search_expression_type->is_nbinary_type(%(paramname)s_type_symbol))",
- "ANY_NUM" : "if(search_expression_type->is_num_type(%(paramname)s_type_symbol))",
- "ANY_REAL" : "if(search_expression_type->is_real_type(%(paramname)s_type_symbol))",
- "ANY_INT" : "if(search_expression_type->is_integer_type(%(paramname)s_type_symbol))"
+ "ANY_BIT" : "if(%(paramname)s_type_symbol == NULL || search_expression_type->is_binary_type(%(paramname)s_type_symbol))",
+ "ANY_NBIT" : "if(%(paramname)s_type_symbol == NULL || search_expression_type->is_nbinary_type(%(paramname)s_type_symbol))",
+ "ANY_NUM" : "if(%(paramname)s_type_symbol == NULL || search_expression_type->is_num_type(%(paramname)s_type_symbol))",
+ "ANY_REAL" : "if(%(paramname)s_type_symbol == NULL || search_expression_type->is_real_type(%(paramname)s_type_symbol))",
+ "ANY_INT" : "if(%(paramname)s_type_symbol == NULL || search_expression_type->is_integer_type(%(paramname)s_type_symbol))"
}.get(typename,
#"if (typeid(*last_type_symbol) == typeid(%(typename)s_type_name_c))")%{
- "if(search_expression_type->is_same_type(&search_constant_type_c::%(typename)s_type_name, last_type_symbol))")%{
+ "if(%(paramname)s_type_symbol == NULL || search_expression_type->is_same_type(&search_constant_type_c::%(typename)s_type_name, last_type_symbol))")%{
"paramname" : paramname, "typename": typename.lower()}
def recurse_and_indent(fdecls, indent, do_type_search_only = False, do_il = False):
@@ -151,12 +151,15 @@
identifier_c param_name("%(input_name)s");
/* Get the value from a foo(<param_name> = <param_value>) style call */
symbol_c *%(input_name)s_param_value = function_call_param_iterator.search(¶m_name);
+ symbol_c *%(input_name)s_type_symbol = NULL;
/* Get the value from a foo(<param_value>) style call */
if (%(input_name)s_param_value == NULL)
%(input_name)s_param_value = function_call_param_iterator.next();
- symbol_c *%(input_name)s_type_symbol = search_expression_type->get_type(%(input_name)s_param_value);
- last_type_symbol = last_type_symbol && search_expression_type->is_same_type(%(input_name)s_type_symbol, last_type_symbol) ? search_expression_type->common_type(%(input_name)s_type_symbol, last_type_symbol) : %(input_name)s_type_symbol ;
+ if (%(input_name)s_param_value != NULL) {
+ %(input_name)s_type_symbol = search_expression_type->get_type(%(input_name)s_param_value);
+ last_type_symbol = last_type_symbol && %(input_name)s_type_symbol && search_expression_type->is_same_type(%(input_name)s_type_symbol, last_type_symbol) ? search_expression_type->common_type(%(input_name)s_type_symbol, last_type_symbol) : %(input_name)s_type_symbol ;
+ }
"""%{"input_name":Paramname}
for ParamType,NextParamDecl in ParamTypes.iteritems():
@@ -188,13 +191,18 @@
res += "function_name = (symbol_c*)(new pragma_c(\"%s\"));\n"%code_gen[1]
if fdecl["extensible"]:
res += """
+if (nb_param < %(min_nb_param)d)
+ nb_param = %(min_nb_param)d;
char* nb_param_str = new char[10];
-sprintf(nb_param_str, "%d", nb_param);
+sprintf(nb_param_str, "%%d", nb_param);
ADD_PARAM_LIST((symbol_c*)(new integer_c((const char *)nb_param_str)), (symbol_c*)(new int_type_name_c()), function_param_iterator_c::direction_in)
-"""
+"""%{"min_nb_param" : len(fdecl["inputs"])}
for paramname,paramtype,unused in fdecl["inputs"]:
- res += "ADD_PARAM_LIST(%(input_name)s_param_value, %(input_name)s_type_symbol, function_param_iterator_c::direction_in)\n"%{"input_name" : paramname}
-
+ res += """
+if (%(input_name)s_type_symbol == NULL)
+ %(input_name)s_type_symbol = last_type_symbol;
+ADD_PARAM_LIST(%(input_name)s_param_value, %(input_name)s_type_symbol, function_param_iterator_c::direction_in)
+"""%{"input_name" : paramname}
if fdecl["extensible"]:
res += """
int base_num = %d;
--- a/plcopen/structures.py Mon Jan 19 17:07:03 2009 +0100
+++ b/plcopen/structures.py Mon Jan 19 17:08:17 2009 +0100
@@ -51,42 +51,48 @@
if not generator.ComputedBlocks.get(block, False) and not order:
generator.ComputedBlocks[block] = True
vars = []
+ one_input_connected = False
for i, variable in enumerate(block.inputVariables.getvariable()):
input_info = (generator.TagName, "block", block.getlocalId(), "input", i)
connections = variable.connectionPointIn.getconnections()
if connections is not None:
+ parameter = variable.getformalParameter()
+ if parameter != "EN":
+ one_input_connected = True
value = generator.ComputeExpression(body, connections, executionOrderId > 0)
if len(output_variables) > 1:
- parameter = variable.getformalParameter()
vars.append([(parameter, input_info),
(" := ", ())] + generator.ExtractModifier(variable, value, input_info))
else:
vars.append(generator.ExtractModifier(variable, value, input_info))
- for i, variable in enumerate(output_variables):
- parameter = variable.getformalParameter()
- if variable.getformalParameter() == "":
- variable_name = "%s%d"%(type, block.getlocalId())
- else:
- variable_name = "%s%d_%s"%(type, block.getlocalId(), parameter)
- if generator.Interface[-1][0] != "VAR" or generator.Interface[-1][1] or generator.Interface[-1][2] or generator.Interface[-1][3]:
- generator.Interface.append(("VAR", False, False, False, []))
- if variable.connectionPointOut in generator.ConnectionTypes:
- generator.Interface[-1][4].append((generator.ConnectionTypes[variable.connectionPointOut], variable_name, None, None))
- else:
- generator.Interface[-1][4].append(("ANY", variable_name, None, None))
- if len(output_variables) > 1 and parameter not in ["", "OUT"]:
- vars.append([(parameter, (generator.TagName, "block", block.getlocalId(), "output", i)),
- (" => %s"%variable_name, ())])
- else:
- output_info = (generator.TagName, "block", block.getlocalId(), "output", i)
- output_name = variable_name
- generator.Program += [(generator.CurrentIndent, ()),
- (output_name, output_info),
- (" := ", ()),
- (type, (generator.TagName, "block", block.getlocalId(), "type")),
- ("(", ())]
- generator.Program += JoinList([(", ", ())], vars)
- generator.Program += [(");\n", ())]
+ if one_input_connected:
+ for i, variable in enumerate(output_variables):
+ parameter = variable.getformalParameter()
+ if variable.getformalParameter() == "":
+ variable_name = "%s%d"%(type, block.getlocalId())
+ else:
+ variable_name = "%s%d_%s"%(type, block.getlocalId(), parameter)
+ if generator.Interface[-1][0] != "VAR" or generator.Interface[-1][1] or generator.Interface[-1][2] or generator.Interface[-1][3]:
+ generator.Interface.append(("VAR", False, False, False, []))
+ if variable.connectionPointOut in generator.ConnectionTypes:
+ generator.Interface[-1][4].append((generator.ConnectionTypes[variable.connectionPointOut], variable_name, None, None))
+ else:
+ generator.Interface[-1][4].append(("ANY", variable_name, None, None))
+ if len(output_variables) > 1 and parameter not in ["", "OUT"]:
+ vars.append([(parameter, (generator.TagName, "block", block.getlocalId(), "output", i)),
+ (" => %s"%variable_name, ())])
+ else:
+ output_info = (generator.TagName, "block", block.getlocalId(), "output", i)
+ output_name = variable_name
+ generator.Program += [(generator.CurrentIndent, ()),
+ (output_name, output_info),
+ (" := ", ()),
+ (type, (generator.TagName, "block", block.getlocalId(), "type")),
+ ("(", ())]
+ generator.Program += JoinList([(", ", ())], vars)
+ generator.Program += [(");\n", ())]
+ else:
+ generator.Warnings.append("\"%s\" function cancelled in \"%s\" POU: No input connected"%(type, generator.TagName.split("::")[-1]))
if link:
connectionPoint = link.getposition()[-1]
else: