# HG changeset patch # User lbessard # Date 1232381297 -3600 # Node ID fd1f6ae26d4fc59baa2d68eb21a3fd9304641c65 # Parent eecc53781498056a31e3cb25298c407d793af61e Adding support for cancelling code generation of function with no input connected diff -r eecc53781498 -r fd1f6ae26d4f PLCControler.py --- 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 diff -r eecc53781498 -r fd1f6ae26d4f PLCGenerator.py --- 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() diff -r eecc53781498 -r fd1f6ae26d4f PLCOpenEditor.py --- 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() diff -r eecc53781498 -r fd1f6ae26d4f generate_IEC_std.py --- 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( = ) 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() 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; diff -r eecc53781498 -r fd1f6ae26d4f plcopen/structures.py --- 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: