plcopen/structures.py
changeset 1784 64beb9e9c749
parent 1782 5b6ad7a7fd9d
child 1828 396da88d7b5c
--- a/plcopen/structures.py	Mon Aug 21 20:17:19 2017 +0000
+++ b/plcopen/structures.py	Mon Aug 21 23:22:58 2017 +0300
@@ -22,17 +22,19 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
-import string, re
+import string
+import re
 from plcopen import LoadProject
 from collections import OrderedDict
 from definitions import *
 
 TypeHierarchy = dict(TypeHierarchy_list)
 
-"""
-returns true if the given data type is the same that "reference" meta-type or one of its types.
-"""
+
 def IsOfType(type, reference):
+    """
+    Returns true if the given data type is the same that "reference" meta-type or one of its types.
+    """
     if reference is None:
         return True
     elif type == reference:
@@ -43,12 +45,14 @@
             return IsOfType(parent_type, reference)
     return False
 
-"""
-returns list of all types that correspont to the ANY* meta type
-"""
+
 def GetSubTypes(type):
+    """
+    Returns list of all types that correspont to the ANY* meta type
+    """
     return [typename for typename, parenttype in TypeHierarchy.items() if not typename.startswith("ANY") and IsOfType(typename, type)]
 
+
 DataTypeRange = dict(DataTypeRange_list)
 
 """
@@ -67,76 +71,82 @@
     - The default modifier which can be "none", "negated", "rising" or "falling"
 """
 
-StdBlckLibs = {libname : LoadProject(tc6fname)[0]
-             for libname, tc6fname in StdTC6Libs}
-StdBlckLst = [{"name" : libname, "list":
+StdBlckLibs = {libname: LoadProject(tc6fname)[0]
+               for libname, tc6fname in StdTC6Libs}
+StdBlckLst = [{"name": libname, "list":
                [GetBlockInfos(pous) for pous in lib.getpous()]}
-             for libname, lib in StdBlckLibs.iteritems()]
-
-#-------------------------------------------------------------------------------
+              for libname, lib in StdBlckLibs.iteritems()]
+
+# -------------------------------------------------------------------------------
 #                             Test identifier
-#-------------------------------------------------------------------------------
+# -------------------------------------------------------------------------------
 
 IDENTIFIER_MODEL = re.compile(
     "(?:%(letter)s|_(?:%(letter)s|%(digit)s))(?:_?(?:%(letter)s|%(digit)s))*$" %
     {"letter": "[a-zA-Z]", "digit": "[0-9]"})
 
-# Test if identifier is valid
+
 def TestIdentifier(identifier):
-     return IDENTIFIER_MODEL.match(identifier) is not None
-
-#-------------------------------------------------------------------------------
+    """
+    Test if identifier is valid
+    """
+    return IDENTIFIER_MODEL.match(identifier) is not None
+
+# -------------------------------------------------------------------------------
 #                        Standard functions list generation
-#-------------------------------------------------------------------------------
-
-
-"""
-take a .csv file and translate it it a "csv_table"
-"""            
+# -------------------------------------------------------------------------------
+
+
 def csv_file_to_table(file):
-    return [ map(string.strip,line.split(';')) for line in file.xreadlines()]
-
-"""
-seek into the csv table to a section ( section_name match 1st field )
-return the matching row without first field
-"""
+    """
+    take a .csv file and translate it it a "csv_table"
+    """
+    return [map(string.strip, line.split(';')) for line in file.xreadlines()]
+
+
 def find_section(section_name, table):
+    """
+    seek into the csv table to a section ( section_name match 1st field )
+    return the matching row without first field
+    """
     fields = [None]
     while(fields[0] != section_name):
         fields = table.pop(0)
     return fields[1:]
 
-"""
-extract the standard functions standard parameter names and types...
-return a { ParameterName: Type, ...}
-"""
+
 def get_standard_funtions_input_variables(table):
+    """
+    extract the standard functions standard parameter names and types...
+    return a { ParameterName: Type, ...}
+    """
     variables = find_section("Standard_functions_variables_types", table)
     standard_funtions_input_variables = {}
-    fields = [True,True]
+    fields = [True, True]
     while(fields[1]):
         fields = table.pop(0)
-        variable_from_csv = dict([(champ, val) for champ, val in zip(variables, fields[1:]) if champ!=''])
+        variable_from_csv = dict([(champ, val) for champ, val in zip(variables, fields[1:]) if champ != ''])
         standard_funtions_input_variables[variable_from_csv['name']] = variable_from_csv['type']
     return standard_funtions_input_variables
-    
-"""
-translate .csv file input declaration into PLCOpenEditor interessting values
-in : "(ANY_NUM, ANY_NUM)" and { ParameterName: Type, ...}
-return [("IN1","ANY_NUM","none"),("IN2","ANY_NUM","none")] 
-"""
+
+
 def csv_input_translate(str_decl, variables, base):
-    decl = str_decl.replace('(','').replace(')','').replace(' ','').split(',')
+    """
+    translate .csv file input declaration into PLCOpenEditor interessting values
+    in : "(ANY_NUM, ANY_NUM)" and { ParameterName: Type, ...}
+    return [("IN1","ANY_NUM","none"),("IN2","ANY_NUM","none")]
+    """
+    decl = str_decl.replace('(', '').replace(')', '').replace(' ', '').split(',')
     params = []
-    
+
     len_of_not_predifined_variable = len([True for param_type in decl if param_type not in variables])
-    
+
     for param_type in decl:
         if param_type in variables.keys():
             param_name = param_type
             param_type = variables[param_type]
         elif len_of_not_predifined_variable > 1:
-            param_name = "IN%d"%base
+            param_name = "IN%d" % base
             base += 1
         else:
             param_name = "IN"
@@ -144,10 +154,11 @@
     return params
 
 
-"""
-Returns this kind of declaration for all standard functions
-
-            [{"name" : "Numerical", 'list': [   {   
+def get_standard_funtions(table):
+    """
+    Returns this kind of declaration for all standard functions
+
+            [{"name" : "Numerical", 'list': [   {
                 'baseinputnumber': 1,
                 'comment': 'Addition',
                 'extensible': True,
@@ -156,21 +167,20 @@
                 'name': 'ADD',
                 'outputs': [('OUT', 'ANY_NUM', 'none')],
                 'type': 'function'}, ...... ] },.....]
-"""
-def get_standard_funtions(table):
-    
+    """
+
     variables = get_standard_funtions_input_variables(table)
-    
-    fonctions = find_section("Standard_functions_type",table)
+
+    fonctions = find_section("Standard_functions_type", table)
 
     Standard_Functions_Decl = []
     Current_section = None
-    
+
     translate = {
-            "extensible" : lambda x: {"yes":True, "no":False}[x],
-            "inputs" : lambda x:csv_input_translate(x,variables,baseinputnumber),
-            "outputs":lambda x:[("OUT",x,"none")]}
-    
+            "extensible": lambda x: {"yes": True, "no": False}[x],
+            "inputs": lambda x: csv_input_translate(x, variables, baseinputnumber),
+            "outputs": lambda x: [("OUT", x, "none")]}
+
     for fields in table:
         if fields[1]:
             # If function section name given
@@ -180,82 +190,83 @@
                     section_name = words[1]
                 else:
                     section_name = fields[0]
-                Current_section = {"name" : section_name, "list" : []}
+                Current_section = {"name": section_name, "list": []}
                 Standard_Functions_Decl.append(Current_section)
                 Function_decl_list = []
             if Current_section:
                 Function_decl = dict([(champ, val) for champ, val in zip(fonctions, fields[1:]) if champ])
-                baseinputnumber = int(Function_decl.get("baseinputnumber",1))
+                baseinputnumber = int(Function_decl.get("baseinputnumber", 1))
                 Function_decl["baseinputnumber"] = baseinputnumber
                 for param, value in Function_decl.iteritems():
                     if param in translate:
                         Function_decl[param] = translate[param](value)
                 Function_decl["type"] = "function"
-                
-                if Function_decl["name"].startswith('*') or Function_decl["name"].endswith('*') :
+
+                if Function_decl["name"].startswith('*') or Function_decl["name"].endswith('*'):
                     input_ovrloading_types = GetSubTypes(Function_decl["inputs"][0][1])
                     output_types = GetSubTypes(Function_decl["outputs"][0][1])
                 else:
                     input_ovrloading_types = [None]
                     output_types = [None]
-                
+
                 funcdeclname_orig = Function_decl["name"]
                 funcdeclname = Function_decl["name"].strip('*_')
                 fdc = Function_decl["inputs"][:]
                 for intype in input_ovrloading_types:
-                    if intype != None:
+                    if intype is not None:
                         Function_decl["inputs"] = []
                         for decl_tpl in fdc:
                             if IsOfType(intype, decl_tpl[1]):
                                 Function_decl["inputs"] += [(decl_tpl[0], intype, decl_tpl[2])]
                             else:
                                 Function_decl["inputs"] += [(decl_tpl)]
-                            
+
                             if funcdeclname_orig.startswith('*'):
-                                funcdeclin = intype + '_' + funcdeclname 
+                                funcdeclin = intype + '_' + funcdeclname
                             else:
                                 funcdeclin = funcdeclname
                     else:
                         funcdeclin = funcdeclname
-                        
+
                     for outype in output_types:
-                        if outype != None:
+                        if outype is not None:
                             decl_tpl = Function_decl["outputs"][0]
-                            Function_decl["outputs"] = [ (decl_tpl[0] , outype,  decl_tpl[2])]
+                            Function_decl["outputs"] = [(decl_tpl[0], outype,  decl_tpl[2])]
                             if funcdeclname_orig.endswith('*'):
-                                funcdeclout =  funcdeclin + '_' + outype
+                                funcdeclout = funcdeclin + '_' + outype
                             else:
-                                funcdeclout =  funcdeclin
+                                funcdeclout = funcdeclin
                         else:
-                            funcdeclout =  funcdeclin
+                            funcdeclout = funcdeclin
                         Function_decl["name"] = funcdeclout
 
                         # apply filter given in "filter" column
                         filter_name = Function_decl["filter"]
                         store = True
-                        for (InTypes, OutTypes) in ANY_TO_ANY_FILTERS.get(filter_name,[]):
-                            outs = reduce(lambda a,b: a or b, 
-                                       map(lambda testtype : IsOfType(
-                                           Function_decl["outputs"][0][1],
-                                           testtype), OutTypes))
-                            inps = reduce(lambda a,b: a or b,
-                                       map(lambda testtype : IsOfType(
-                                           Function_decl["inputs"][0][1],
-                                           testtype), InTypes))
+                        for (InTypes, OutTypes) in ANY_TO_ANY_FILTERS.get(filter_name, []):
+                            outs = reduce(lambda a, b: a or b,
+                                          map(lambda testtype: IsOfType(
+                                              Function_decl["outputs"][0][1],
+                                              testtype), OutTypes))
+                            inps = reduce(lambda a, b: a or b,
+                                          map(lambda testtype: IsOfType(
+                                              Function_decl["inputs"][0][1],
+                                              testtype), InTypes))
                             if inps and outs and Function_decl["outputs"][0][1] != Function_decl["inputs"][0][1]:
                                 store = True
                                 break
                             else:
                                 store = False
-                        if store :
+                        if store:
                             # create the copy of decl dict to be appended to section
                             Function_decl_copy = Function_decl.copy()
                             Current_section["list"].append(Function_decl_copy)
             else:
                 raise "First function must be in a category"
-    
+
     return Standard_Functions_Decl
 
+
 StdBlckLst.extend(get_standard_funtions(csv_file_to_table(open(StdFuncsCSV))))
 
 # Dictionary to speedup block type fetching by name
@@ -266,17 +277,17 @@
         words = desc["comment"].split('"')
         if len(words) > 1:
             desc["comment"] = words[1]
-        desc["usage"] = ("\n (%s) => (%s)" % 
-            (", ".join(["%s:%s" % (input[1], input[0]) 
-                        for input in desc["inputs"]]),
-             ", ".join(["%s:%s" % (output[1], output[0]) 
-                        for output in desc["outputs"]])))
-        BlkLst = StdBlckDct.setdefault(desc["name"],[])
+        desc["usage"] = ("\n (%s) => (%s)" %
+                         (", ".join(["%s:%s" % (input[1], input[0])
+                                     for input in desc["inputs"]]),
+                          ", ".join(["%s:%s" % (output[1], output[0])
+                                     for output in desc["outputs"]])))
+        BlkLst = StdBlckDct.setdefault(desc["name"], [])
         BlkLst.append((section["name"], desc))
 
-#-------------------------------------------------------------------------------
+# -------------------------------------------------------------------------------
 #                            Languages Keywords
-#-------------------------------------------------------------------------------
+# -------------------------------------------------------------------------------
 
 # Keywords for Pou Declaration
 POU_BLOCK_START_KEYWORDS = ["FUNCTION", "FUNCTION_BLOCK", "PROGRAM"]
@@ -313,16 +324,20 @@
 
 
 # Keywords for Instruction List
-IL_KEYWORDS = ["TRUE", "FALSE", "LD", "LDN", "ST", "STN", "S", "R", "AND", "ANDN", "OR", "ORN",
- "XOR", "XORN", "NOT", "ADD", "SUB", "MUL", "DIV", "MOD", "GT", "GE", "EQ", "NE",
- "LE", "LT", "JMP", "JMPC", "JMPCN", "CAL", "CALC", "CALCN", "RET", "RETC", "RETCN"]
+IL_KEYWORDS = [
+    "TRUE", "FALSE", "LD", "LDN", "ST", "STN", "S", "R", "AND", "ANDN", "OR", "ORN",
+    "XOR", "XORN", "NOT", "ADD", "SUB", "MUL", "DIV", "MOD", "GT", "GE", "EQ", "NE",
+    "LE", "LT", "JMP", "JMPC", "JMPCN", "CAL", "CALC", "CALCN", "RET", "RETC", "RETCN"
+]
 
 
 # Keywords for Structured Text
 ST_BLOCK_START_KEYWORDS = ["IF", "ELSIF", "ELSE", "CASE", "FOR", "WHILE", "REPEAT"]
 ST_BLOCK_END_KEYWORDS = ["END_IF", "END_CASE", "END_FOR", "END_WHILE", "END_REPEAT"]
-ST_KEYWORDS = ["TRUE", "FALSE", "THEN", "OF", "TO", "BY", "DO", "DO", "UNTIL", "EXIT", 
- "RETURN", "NOT", "MOD", "AND", "XOR", "OR"] + ST_BLOCK_START_KEYWORDS + ST_BLOCK_END_KEYWORDS
+ST_KEYWORDS = [
+    "TRUE", "FALSE", "THEN", "OF", "TO", "BY", "DO", "DO", "UNTIL", "EXIT",
+    "RETURN", "NOT", "MOD", "AND", "XOR", "OR"
+] + ST_BLOCK_START_KEYWORDS + ST_BLOCK_END_KEYWORDS
 
 # All the keywords of IEC
 IEC_BLOCK_START_KEYWORDS = []
@@ -338,5 +353,3 @@
                                                     SFC_KEYWORDS, IL_KEYWORDS, ST_KEYWORDS])]:
     for keywords in keywords_list:
         all_keywords.extend([keyword for keyword in keywords if keyword not in all_keywords])
-
-