# HG changeset patch # User Edouard Tisserant # Date 1375624512 -32400 # Node ID f3cfe1ff917e09a04ea99cf785434e75bd1e3e11 # Parent f427352f972752c60abd0ddd1002b7468053efcf More optimization attemps in type handling diff -r f427352f9727 -r f3cfe1ff917e PLCControler.py --- a/PLCControler.py Fri Aug 02 08:58:09 2013 +0900 +++ b/PLCControler.py Sun Aug 04 22:55:12 2013 +0900 @@ -210,7 +210,8 @@ self.NextCompiledProject = None self.CurrentCompiledProject = None self.ConfNodeTypes = [] - self.ProgramFilePath = "" + self.TotalTypesDict = StdBlckDct.copy() + self.TotalTypes = StdBlckLst[:] def GetQualifierTypes(self): return plcopen.QualifierList @@ -1534,25 +1535,34 @@ # Function that add a new confnode to the confnode list def AddConfNodeTypesList(self, typeslist): self.ConfNodeTypes.extend(typeslist) + addedcat = [{"name": _("%s POUs") % confnodetypes["name"], + "list": confnodetypes["types"].GetCustomBlockTypes()} + for confnodetypes in typeslist] + self.TotalTypes.extend(addedcat) + for cat in addedcat: + for desc in cat["list"]: + BlkLst = self.TotalTypesDict.setdefault(desc["name"],[]) + BlkLst.append((section["name"], desc)) # Function that clear the confnode list def ClearConfNodeTypes(self): - for i in xrange(len(self.ConfNodeTypes)): - self.ConfNodeTypes.pop(0) + self.ConfNodeTypes = [] + self.TotalTypesDict = StdBlckDct.copy() + self.TotalTypes = StdBlckLst[:] def GetConfNodeBlockTypes(self): return [{"name": _("%s POUs") % confnodetypes["name"], "list": confnodetypes["types"].GetCustomBlockTypes()} for confnodetypes in self.ConfNodeTypes] - def GetConfNodeDataTypes(self, exclude = "", only_locatables = False): + def GetConfNodeDataTypes(self, exclude = None, only_locatables = False): return [{"name": _("%s Data Types") % confnodetypes["name"], "list": [datatype["name"] for datatype in confnodetypes["types"].GetCustomDataTypes(exclude, only_locatables)]} for confnodetypes in self.ConfNodeTypes] - def GetConfNodeDataType(self, type): + def GetConfNodeDataType(self, typename): for confnodetype in self.ConfNodeTypes: - datatype = confnodetype["types"].getdataType(type) + datatype = confnodetype["types"].getdataType(typename) if datatype is not None: return datatype return None @@ -1592,61 +1602,59 @@ return global_vars # Function that returns the block definition associated to the block type given - def GetBlockType(self, type, inputs = None, debug = False): + def GetBlockType(self, typename, inputs = None, debug = False): result_blocktype = None - for category in BlockTypes + self.GetConfNodeBlockTypes(): - for blocktype in category["list"]: - if blocktype["name"] == type: - if inputs is not None and inputs != "undefined": - block_inputs = tuple([var_type for name, var_type, modifier in blocktype["inputs"]]) - if reduce(lambda x, y: x and y, map(lambda x: x[0] == "ANY" or self.IsOfType(*x), zip(inputs, block_inputs)), True): - return blocktype + for sectioname, blocktype in self.TotalTypesDict.get(typename,[]): + if inputs is not None and inputs != "undefined": + block_inputs = tuple([var_type for name, var_type, modifier in blocktype["inputs"]]) + if reduce(lambda x, y: x and y, map(lambda x: x[0] == "ANY" or self.IsOfType(*x), zip(inputs, block_inputs)), True): + return blocktype + else: + if result_blocktype is not None: + if inputs == "undefined": + return None else: - if result_blocktype is not None: - if inputs == "undefined": - return None - else: - result_blocktype["inputs"] = [(i[0], "ANY", i[2]) for i in result_blocktype["inputs"]] - result_blocktype["outputs"] = [(o[0], "ANY", o[2]) for o in result_blocktype["outputs"]] - return result_blocktype - result_blocktype = blocktype.copy() + result_blocktype["inputs"] = [(i[0], "ANY", i[2]) for i in result_blocktype["inputs"]] + result_blocktype["outputs"] = [(o[0], "ANY", o[2]) for o in result_blocktype["outputs"]] + return result_blocktype + result_blocktype = blocktype.copy() if result_blocktype is not None: return result_blocktype project = self.GetProject(debug) if project is not None: - return project.GetCustomBlockType(type, inputs) + return project.GetCustomBlockType(typename, inputs) return None # Return Block types checking for recursion def GetBlockTypes(self, tagname = "", debug = False): - type = None + typename = None words = tagname.split("::") - if self.Project: - name = "" + name = None + project = self.GetProject(debug) + if project is not None: + blocktypes = [] if words[0] in ["P","T","A"]: name = words[1] - type = self.GetPouType(name, debug) - if type == "function": - blocktypes = [] - for category in BlockTypes + self.GetConfNodeBlockTypes(): - cat = {"name" : category["name"], "list" : []} - for block in category["list"]: - if block["type"] == "function": - cat["list"].append(block) - if len(cat["list"]) > 0: - blocktypes.append(cat) - else: - blocktypes = [category for category in BlockTypes + self.GetConfNodeBlockTypes()] - project = self.GetProject(debug) - if project is not None: - blocktypes.append({"name" : USER_DEFINED_POUS, "list": project.GetCustomBlockTypes(name, type == "function" or words[0] == "T")}) - return blocktypes + typename = self.GetPouType(name, debug) + if typename == "function": + for category in self.TotalTypes: + cat = {"name" : category["name"], "list" : []} + for block in category["list"]: + if block["type"] == "function": + cat["list"].append(block) + if len(cat["list"]) > 0: + blocktypes.append(cat) + blocktypes.append({"name" : USER_DEFINED_POUS, + "list": project.GetCustomBlockTypes(name, + typename == "function" or words[0] == "T")}) + return blocktypes + return self.TotalTypes # Return Function Block types checking for recursion def GetFunctionBlockTypes(self, tagname = "", debug = False): blocktypes = [] - for category in BlockTypes + self.GetConfNodeBlockTypes(): - for block in category["list"]: + for blocks in self.TotalTypesDict.itervalues(): + for sectioname,block in blocks: if block["type"] == "functionBlock": blocktypes.append(block["name"]) project = self.GetProject(debug) @@ -1661,7 +1669,7 @@ # Return Block types checking for recursion def GetBlockResource(self, debug = False): blocktypes = [] - for category in BlockTypes[:-1]: + for category in StdBlckLst[:-1]: for blocktype in category["list"]: if blocktype["type"] == "program": blocktypes.append(blocktype["name"]) @@ -1677,8 +1685,8 @@ else: datatypes = [] project = self.GetProject(debug) - if project is not None: - name = "" + name = None + if project is not None: words = tagname.split("::") if words[0] in ["D"]: name = words[1] diff -r f427352f9727 -r f3cfe1ff917e plcopen/plcopen.py --- a/plcopen/plcopen.py Fri Aug 02 08:58:09 2013 +0900 +++ b/plcopen/plcopen.py Sun Aug 04 22:55:12 2013 +0900 @@ -26,7 +26,7 @@ from structures import * from types import * import os, re - +from collections import OrderedDict """ Dictionary that makes the relation between var names in plcopen and displayed values """ @@ -177,7 +177,7 @@ cls.CustomDataTypeRange = {} cls.CustomTypeHierarchy = {} cls.ElementUsingTree = {} - cls.CustomBlockTypes = [] + cls.CustomBlockTypes = OrderedDict() def setname(self, name): self.contentHeader.setname(name) @@ -443,7 +443,7 @@ # Update Block types with user-defined pou added def RefreshCustomBlockTypes(self): # Reset the tree of user-defined pou cross-use - self.CustomBlockTypes = [] + self.CustomBlockTypes = OrderedDict() for pou in self.getpous(): self.AddCustomBlockType(pou) setattr(cls, "RefreshCustomBlockTypes", RefreshCustomBlockTypes) @@ -497,7 +497,7 @@ block_infos["outputs"].append((var.getname(), var_type["name"], "none")) block_infos["usage"] = "\n (%s) => (%s)" % (", ".join(["%s:%s" % (input[1], input[0]) for input in block_infos["inputs"]]), ", ".join(["%s:%s" % (output[1], output[0]) for output in block_infos["outputs"]])) - self.CustomBlockTypes.append(block_infos) + self.CustomBlockTypes[pou_name]=block_infos setattr(cls, "AddCustomBlockType", AddCustomBlockType) def AddElementUsingTreeInstance(self, name, type_infos): @@ -633,14 +633,14 @@ setattr(cls, "GetEnumeratedDataTypeValues", GetEnumeratedDataTypeValues) # Function that returns the block definition associated to the block type given - def GetCustomBlockType(self, type, inputs = None): - for customblocktype in self.CustomBlockTypes: + def GetCustomBlockType(self, typename, inputs = None): + customblocktype = self.CustomBlockTypes.get(typename,None) + if customblocktype is not None: if inputs is not None and inputs != "undefined": customblock_inputs = tuple([var_type for name, var_type, modifier in customblocktype["inputs"]]) - same_inputs = inputs == customblock_inputs + if inputs == customblock_inputs: + return customblocktype else: - same_inputs = True - if customblocktype["name"] == type and same_inputs: return customblocktype return None setattr(cls, "GetCustomBlockType", GetCustomBlockType) @@ -648,32 +648,31 @@ # Return Block types checking for recursion def GetCustomBlockTypes(self, exclude = None, onlyfunctions = False): if exclude is not None: - return [customblocktype for customblocktype in self.CustomBlockTypes + return [customblocktype for name,customblocktype in self.CustomBlockTypes.iteritems() if (customblocktype["type"] != "program" - and customblocktype["name"] != exclude - and not self.ElementIsUsedBy(exclude, customblocktype["name"]) + and name != exclude + and not self.ElementIsUsedBy(exclude, name) and not (onlyfunctions and customblocktype["type"] != "function"))] - return [customblocktype for customblocktype in self.CustomBlockTypes + return [customblocktype for customblocktype in self.CustomBlockTypes.itervalues() if (customblocktype["type"] != "program" and not (onlyfunctions and customblocktype["type"] != "function"))] setattr(cls, "GetCustomBlockTypes", GetCustomBlockTypes) # Return Function Block types checking for recursion - def GetCustomFunctionBlockTypes(self, exclude = ""): - customblocktypes = [] - for customblocktype in self.CustomBlockTypes: - if customblocktype["type"] == "functionBlock" and customblocktype["name"] != exclude and not self.ElementIsUsedBy(exclude, customblocktype["name"]): - customblocktypes.append(customblocktype["name"]) - return customblocktypes + def GetCustomFunctionBlockTypes(self, exclude = None): + if exclude is not None: + return [customblocktype for name,customblocktype in self.CustomBlockTypes.iteritems() + if (customblocktype["type"] == "functionBlock" + and name != exclude + and not self.ElementIsUsedBy(exclude, name))] + return [customblocktype for customblocktype in self.CustomBlockTypes.itervalues() + if customblocktype["type"] == "functionBlock"] setattr(cls, "GetCustomFunctionBlockTypes", GetCustomFunctionBlockTypes) # Return Block types checking for recursion def GetCustomBlockResource(self): - customblocktypes = [] - for customblocktype in self.CustomBlockTypes: - if customblocktype["type"] == "program": - customblocktypes.append(customblocktype["name"]) - return customblocktypes + return [customblocktype for customblocktype in self.CustomBlockTypes.itervalues() + if customblocktype["type"] == "program"] setattr(cls, "GetCustomBlockResource", GetCustomBlockResource) # Return Data Types checking for recursion diff -r f427352f9727 -r f3cfe1ff917e plcopen/structures.py --- a/plcopen/structures.py Fri Aug 02 08:58:09 2013 +0900 +++ b/plcopen/structures.py Sun Aug 04 22:55:12 2013 +0900 @@ -250,7 +250,7 @@ - The default modifier which can be "none", "negated", "rising" or "falling" """ -BlockTypes = [{"name" : _("Standard function blocks"), "list": +StdBlckLst = [{"name" : _("Standard function blocks"), "list": [{"name" : "SR", "type" : "functionBlock", "extensible" : False, "inputs" : [("S1","BOOL","none"),("R","BOOL","none")], "outputs" : [("Q1","BOOL","none")], @@ -663,9 +663,12 @@ std_decl = get_standard_funtions(csv_file_to_table(open(os.path.join(os.path.split(__file__)[0],"iec_std.csv"))))#, True) -BlockTypes.extend(std_decl) - -for section in BlockTypes: +StdBlckLst.extend(std_decl) + +# Dictionary to speedup block type fetching by name +StdBlckDct = {} + +for section in StdBlckLst: for desc in section["list"]: words = desc["comment"].split('"') if len(words) > 1: @@ -676,7 +679,8 @@ " ) => (" + str([ " " + fctdecl[1]+":"+fctdecl[0] for fctdecl in desc["outputs"]]).strip("[]").replace("'",'') + " )") - + BlkLst = StdBlckDct.setdefault(desc["name"],[]) + BlkLst.append((section["name"], desc)) #------------------------------------------------------------------------------- # Languages Keywords @@ -687,7 +691,7 @@ POU_BLOCK_START_KEYWORDS = ["FUNCTION", "FUNCTION_BLOCK", "PROGRAM"] POU_BLOCK_END_KEYWORDS = ["END_FUNCTION", "END_FUNCTION_BLOCK", "END_PROGRAM"] POU_KEYWORDS = ["EN", "ENO", "F_EDGE", "R_EDGE"] + POU_BLOCK_START_KEYWORDS + POU_BLOCK_END_KEYWORDS -for category in BlockTypes: +for category in StdBlckLst: for block in category["list"]: if block["name"] not in POU_KEYWORDS: POU_KEYWORDS.append(block["name"])