plcopen/structures.py
changeset 22 a765fae3b361
parent 21 e619d7bea692
child 23 cce8d5662738
equal deleted inserted replaced
21:e619d7bea692 22:a765fae3b361
   144 Ordored list of common data types defined in the IEC 61131-3
   144 Ordored list of common data types defined in the IEC 61131-3
   145 Each type is associated to his direct parent type. It defines then a hierarchy
   145 Each type is associated to his direct parent type. It defines then a hierarchy
   146 between type that permits to make a comparison of two types
   146 between type that permits to make a comparison of two types
   147 """
   147 """
   148 TypeHierarchy_list = [
   148 TypeHierarchy_list = [
   149 	("ANY", None),
   149     ("ANY", None),
   150 	("ANY_DERIVED", "ANY"),
   150     ("ANY_DERIVED", "ANY"),
   151 	("ANY_ELEMENTARY", "ANY"),
   151     ("ANY_ELEMENTARY", "ANY"),
   152 	("ANY_MAGNITUDE", "ANY_ELEMENTARY"),
   152     ("ANY_MAGNITUDE", "ANY_ELEMENTARY"),
   153 	("ANY_BIT", "ANY_ELEMENTARY"),
   153     ("ANY_BIT", "ANY_ELEMENTARY"),
   154 	("ANY_STRING", "ANY_ELEMENTARY"),
   154     ("ANY_STRING", "ANY_ELEMENTARY"),
   155 	("ANY_DATE", "ANY_ELEMENTARY"),
   155     ("ANY_DATE", "ANY_ELEMENTARY"),
   156 	("ANY_NUM", "ANY_MAGNITUDE"),
   156     ("ANY_NUM", "ANY_MAGNITUDE"),
   157 	("ANY_REAL", "ANY_NUM"),
   157     ("ANY_REAL", "ANY_NUM"),
   158 	("ANY_INT", "ANY_NUM"),
   158     ("ANY_INT", "ANY_NUM"),
   159 	("REAL", "ANY_REAL"),
   159     ("REAL", "ANY_REAL"),
   160 	("LREAL", "ANY_REAL"),
   160     ("LREAL", "ANY_REAL"),
   161 	("SINT", "ANY_INT"),
   161     ("SINT", "ANY_INT"),
   162 	("INT", "ANY_INT"),
   162     ("INT", "ANY_INT"),
   163 	("DINT", "ANY_INT"),
   163     ("DINT", "ANY_INT"),
   164 	("LINT", "ANY_INT"),
   164     ("LINT", "ANY_INT"),
   165 	("USINT", "ANY_INT"),
   165     ("USINT", "ANY_INT"),
   166 	("UINT", "ANY_INT"),
   166     ("UINT", "ANY_INT"),
   167 	("UDINT", "ANY_INT"),
   167     ("UDINT", "ANY_INT"),
   168 	("ULINT", "ANY_INT"),
   168     ("ULINT", "ANY_INT"),
   169 	("TIME", "ANY_MAGNITUDE"),
   169     ("TIME", "ANY_MAGNITUDE"),
   170 	("BOOL", "ANY_BIT"),
   170     ("BOOL", "ANY_BIT"),
   171 	("BYTE", "ANY_BIT"),
   171     ("BYTE", "ANY_BIT"),
   172 	("WORD", "ANY_BIT"),
   172     ("WORD", "ANY_BIT"),
   173 	("DWORD", "ANY_BIT"),
   173     ("DWORD", "ANY_BIT"),
   174 	("LWORD", "ANY_BIT"),
   174     ("LWORD", "ANY_BIT"),
   175 	("STRING", "ANY_STRING"),
   175     ("STRING", "ANY_STRING"),
   176 	("WSTRING", "ANY_STRING"),
   176     ("WSTRING", "ANY_STRING"),
   177 	("DATE", "ANY_DATE"),
   177     ("DATE", "ANY_DATE"),
   178 	("TOD", "ANY_DATE"),
   178     ("TOD", "ANY_DATE"),
   179 	("DT", "ANY_DATE")]
   179     ("DT", "ANY_DATE")]
   180 
   180 
   181 TypeHierarchy = dict(TypeHierarchy_list)
   181 TypeHierarchy = dict(TypeHierarchy_list)
   182 
   182 
   183 """
   183 """
   184 returns true if the given data type is the same that "reference" meta-type or one of its types.
   184 returns true if the given data type is the same that "reference" meta-type or one of its types.
   193 
   193 
   194 """
   194 """
   195 returns list of all types that correspont to the ANY* meta type
   195 returns list of all types that correspont to the ANY* meta type
   196 """
   196 """
   197 def GetSubTypes(reference):
   197 def GetSubTypes(reference):
   198     return [ typename for typename in TypeHierarchy.iterkeys() if typename[:3] != "ANY" and IsOfType(typename, reference)]
   198     return [ typename for typename, parenttype in TypeHierarchy_list if typename[:3] != "ANY" and IsOfType(typename, reference)]
   199 
   199 
   200 
   200 
   201 #-------------------------------------------------------------------------------
   201 #-------------------------------------------------------------------------------
   202 #                             Test identifier
   202 #                             Test identifier
   203 #-------------------------------------------------------------------------------
   203 #-------------------------------------------------------------------------------
   279 
   279 
   280 """
   280 """
   281 take a .csv file and translate it it a "csv_table"
   281 take a .csv file and translate it it a "csv_table"
   282 """            
   282 """            
   283 def csv_file_to_table(file):
   283 def csv_file_to_table(file):
   284 	return [ map(string.strip,line.split(';')) for line in file.xreadlines()]
   284     return [ map(string.strip,line.split(';')) for line in file.xreadlines()]
   285 
   285 
   286 """
   286 """
   287 seek into the csv table to a section ( section_name match 1st field )
   287 seek into the csv table to a section ( section_name match 1st field )
   288 return the matching row without first field
   288 return the matching row without first field
   289 """
   289 """
   290 def find_section(section_name, table):
   290 def find_section(section_name, table):
   291 	fields = [None]
   291     fields = [None]
   292 	while(fields[0] != section_name):
   292     while(fields[0] != section_name):
   293 		fields = table.pop(0)
   293         fields = table.pop(0)
   294 	return fields[1:]
   294     return fields[1:]
   295 
   295 
   296 """
   296 """
   297 extract the standard functions standard parameter names and types...
   297 extract the standard functions standard parameter names and types...
   298 return a { ParameterName: Type, ...}
   298 return a { ParameterName: Type, ...}
   299 """
   299 """
   300 def get_standard_funtions_input_variables(table):
   300 def get_standard_funtions_input_variables(table):
   301 	variables = find_section("Standard_functions_variables_types", table)
   301     variables = find_section("Standard_functions_variables_types", table)
   302 	standard_funtions_input_variables = {}
   302     standard_funtions_input_variables = {}
   303 	fields = [True,True]
   303     fields = [True,True]
   304 	while(fields[1]):
   304     while(fields[1]):
   305 		fields = table.pop(0)
   305         fields = table.pop(0)
   306 		variable_from_csv = dict([(champ, val) for champ, val in zip(variables, fields[1:]) if champ!=''])
   306         variable_from_csv = dict([(champ, val) for champ, val in zip(variables, fields[1:]) if champ!=''])
   307 		standard_funtions_input_variables[variable_from_csv['name']] = variable_from_csv['type']
   307         standard_funtions_input_variables[variable_from_csv['name']] = variable_from_csv['type']
   308 	return standard_funtions_input_variables
   308     return standard_funtions_input_variables
   309 	
   309     
   310 """
   310 """
   311 translate .csv file input declaration into PLCOpenEditor interessting values
   311 translate .csv file input declaration into PLCOpenEditor interessting values
   312 in : "(ANY_NUM, ANY_NUM)" and { ParameterName: Type, ...}
   312 in : "(ANY_NUM, ANY_NUM)" and { ParameterName: Type, ...}
   313 return [("IN1","ANY_NUM","none"),("IN2","ANY_NUM","none")] 
   313 return [("IN1","ANY_NUM","none"),("IN2","ANY_NUM","none")] 
   314 """
   314 """
   315 def csv_input_translate(str_decl, variables, base):
   315 def csv_input_translate(str_decl, variables, base):
   316 	decl = str_decl.replace('(','').replace(')','').replace(' ','').split(',')
   316     decl = str_decl.replace('(','').replace(')','').replace(' ','').split(',')
   317 	param_types = []
   317     params = []
   318 	param_names = []
   318     
   319 	modifiers = []
   319     len_of_not_predifined_variable = len([True for param_type in decl if param_type not in variables])
   320 
   320     
   321 	len_of_not_predifined_variable = 0
   321     for param_type in decl:
   322 	for param_type in decl:
   322         if param_type in variables.keys():
   323 		predifined_variable_param_type = variables.get(param_type,None)
   323             param_name = param_type
   324 		if not predifined_variable_param_type :
   324             param_type = variables[param_type]
   325 			len_of_not_predifined_variable += 1
   325         elif len_of_not_predifined_variable > 1:
   326 
   326             param_name = "IN%d"%base
   327 	if len_of_not_predifined_variable>1 : suffix = str(base)
   327             base += 1
   328 	else: suffix = ''
   328         else:
   329 	
   329             param_name = "IN"
   330 	for param_type in decl:
   330         params.append((param_name, param_type, "none"))
   331 		predifined_variable_param_type = variables.get(param_type,None)
   331     return params
   332 		if predifined_variable_param_type :
   332 
   333 			param_types.append(predifined_variable_param_type)
   333 
   334 			param_names.append(param_type)
   334 ANY_T0_ANY_LIST=[
   335 		else:
   335         (("ANY_NUM","ANY_BIT"),("ANY_NUM","ANY_BIT"), "(%(return_type)s)%(IN_value)s"),
   336 			param_types.append(param_type)
   336         (("ANY_NUM","ANY_BIT"),("ANY_DATE","TIME"), "(%(return_type)s)real_to_time(%(IN_value)s)"), 
   337 			param_names.append("IN"+suffix)
   337         (("ANY_DATE","TIME"), ("ANY_NUM","ANY_BIT"), "(%(return_type)s)time_to_real(%(IN_value)s)"), 
   338 			base+=1
   338         (("ANY_DATE","TIME"), ("ANY_STRING",), "(%(return_type)s)time_to_string(%(IN_value)s)"),
   339 			suffix = str(base)
   339         (("ANY_STRING",), ("ANY_DATE","TIME"), "(%(return_type)s)string_to_time(%(IN_value)s)"),
   340 
   340         (("ANY_BIT",), ("ANY_STRING",), "(%(return_type)s)int_to_string(%(IN_value)s, 16)"),
   341 	modifiers = ["none"]*len(param_types)
   341         (("ANY_NUM",), ("ANY_STRING",), "(%(return_type)s)int_to_string(%(IN_value)s, 10)"),
   342 	return zip(param_names,param_types,modifiers)
   342         (("ANY_STRING",), ("ANY_BIT",), "(%(return_type)s)string_to_int(%(IN_value)s, 16)"),
   343 
   343         (("ANY_STRING",), ("ANY_NUM",), "(%(return_type)s)string_to_int(%(IN_value)s, 10)")]
   344 """
       
   345 Fillin the PLCOpenEditor standard function dictionnary
       
   346 translate input and output declaration to something more pythonesque
       
   347 and add interface description to comment
       
   348 """
       
   349 def decl_function(dico_from_table, variables):
       
   350 	Function_decl = { "type" : "function" }
       
   351 	for field, val in dico_from_table:
       
   352 		translate = {
       
   353 			"baseinputnumber" : lambda x:int(x),
       
   354 			"extensible" : lambda x: {"yes":True, "no":False}[x],
       
   355 			"inputs" : lambda x:csv_input_translate(x,variables,Function_decl.get("baseinputnumber",1)),
       
   356 			"outputs":lambda x:[("OUT",x,"none")]}
       
   357 		Function_decl[field] = translate.get(field,lambda x:x)(val)
       
   358 	return Function_decl
       
   359 
       
   360 
   344 
   361 def ANY_TO_ANY_FORMAT_GEN(fdecl):
   345 def ANY_TO_ANY_FORMAT_GEN(fdecl):
   362 
   346 
   363 	ANY_T0_ANY_LIST=[
   347     for (InTypes, OutTypes, Format) in ANY_T0_ANY_LIST:
   364 		(("ANY_NUM","ANY_BIT"),("ANY_NUM","ANY_BIT"), "(%(return_type)s)%(IN_value)s"),
   348         outs = reduce(lambda a,b: a or b, map(lambda testtype : IsOfType(fdecl["outputs"][0][1],testtype), OutTypes))
   365 		(("ANY_NUM","ANY_BIT"),("ANY_DATE","TIME"), "(%(return_type)s)real_to_time(%(IN_value)s)"), 
   349         inps = reduce(lambda a,b: a or b, map(lambda testtype : IsOfType(fdecl["inputs"][0][1],testtype), InTypes))
   366 		(("ANY_DATE","TIME"), ("ANY_NUM","ANY_BIT"), "(%(return_type)s)time_to_real(%(IN_value)s)"), 
   350         if inps and outs and fdecl["outputs"][0][1] != fdecl["inputs"][0][1]:
   367 		(("ANY_DATE","TIME"), ("ANY_STRING",), "(%(return_type)s)time_to_string(%(IN_value)s)"),
   351              return Format
   368 		(("ANY_STRING",), ("ANY_DATE","TIME"), "(%(return_type)s)string_to_time(%(IN_value)s)"),
   352     
   369 		(("ANY_BIT",), ("ANY_STRING",), "(%(return_type)s)int_to_string(%(IN_value)s, 16)"),
   353     return None
   370 		(("ANY_NUM",), ("ANY_STRING",), "(%(return_type)s)int_to_string(%(IN_value)s, 10)"),
       
   371 		(("ANY_STRING",), ("ANY_BIT",), "(%(return_type)s)string_to_int(%(IN_value)s, 16)"),
       
   372 		(("ANY_STRING",), ("ANY_NUM",), "(%(return_type)s)string_to_int(%(IN_value)s, 10)")]
       
   373 	
       
   374 	for (InTypes, OutTypes, Format) in ANY_T0_ANY_LIST:
       
   375 		inps = reduce(lambda a,b: a or b, map(lambda testtype : IsOfType(fdecl["outputs"][0][1],testtype), InTypes))
       
   376 		#print "IN     ",inps , fdecl["outputs"][0][1], InTypes
       
   377 		outs = reduce(lambda a,b: a or b, map(lambda testtype : IsOfType(fdecl["inputs"][0][1],testtype), OutTypes))
       
   378 		#print "OUT    ",outs , fdecl["inputs"][0][1], OutTypes
       
   379 		if (inps and outs ):
       
   380 		 	return Format
       
   381 
       
   382 	#print "IN:", fdecl["outputs"][0][1], "    OUT:", fdecl["inputs"][0][1]
       
   383 	
       
   384 	return "#error %s_TO_%s not implemented!"%(fdecl["inputs"][0][1],fdecl["outputs"][0][1])
       
   385 
   354 
   386 
   355 
   387 """
   356 """
   388 Returns this kind of declaration for all standard functions
   357 Returns this kind of declaration for all standard functions
   389 
   358 
   396                 'name': 'ADD',
   365                 'name': 'ADD',
   397                 'outputs': [('OUT', 'ANY_NUM', 'none')],
   366                 'outputs': [('OUT', 'ANY_NUM', 'none')],
   398                 'type': 'function'}, ...... ] },.....]
   367                 'type': 'function'}, ...... ] },.....]
   399 """
   368 """
   400 def get_standard_funtions(table):
   369 def get_standard_funtions(table):
   401 	
   370     
   402 	variables = get_standard_funtions_input_variables(table)
   371     variables = get_standard_funtions_input_variables(table)
   403 	
   372     
   404 	fonctions = find_section("Standard_functions_type",table)
   373     fonctions = find_section("Standard_functions_type",table)
   405 
   374 
   406 	Standard_Functions_Decl = []
   375     Standard_Functions_Decl = []
   407 	Current_section = None
   376     Current_section = None
   408 	for fields in table:
   377     
   409 		if fields[1]:
   378     translate = {
   410 			# If function section name given
   379             "extensible" : lambda x: {"yes":True, "no":False}[x],
   411 			if fields[0] :
   380             "inputs" : lambda x:csv_input_translate(x,variables,baseinputnumber),
   412 				if Current_section: 
   381             "outputs":lambda x:[("OUT",x,"none")]}
   413 					Standard_Functions_Decl.append(Current_section)
   382     
   414 				Current_section = { "name" : fields[0], "list" : [] }
   383     for fields in table:
   415 				Function_decl_list = []
   384         if fields[1]:
   416 		
   385             # If function section name given
   417 			dico_from_table = [ (champ,val) for champ,val in zip(fonctions, fields[1:]) if champ ]
   386             if fields[0]:
   418 			Function_decl = decl_function(dico_from_table,variables)
   387                 Current_section = {"name" : fields[0], "list" : []}
   419 			if Function_decl["name"].startswith('*') :
   388                 Standard_Functions_Decl.append(Current_section)
   420 				input_types = [ GetSubTypes(inpdecl[1]) for inpdecl in Function_decl["inputs"] ]
   389                 Function_decl_list = []
   421 				input_ovrloading_types = input_types[map(len,input_types).index(max(map(len,input_types)))]
   390             if Current_section:
   422 			else:
   391                 Function_decl = dict([(champ, val) for champ, val in zip(fonctions, fields[1:]) if champ])
   423 				input_ovrloading_types = [None]
   392                 baseinputnumber = int(Function_decl.get("baseinputnumber",1))
   424 				
   393                 Function_decl["baseinputnumber"] = baseinputnumber
   425 			if Function_decl["name"].endswith('*') :
   394                 for param, value in Function_decl.iteritems():
   426 				output_types = GetSubTypes(Function_decl["outputs"][0][1])
   395                     if param in translate:
   427 			else:
   396                         Function_decl[param] = translate[param](value)
   428 				output_types = [None]
   397                 Function_decl["type"] = "function"
   429 				
   398                 
   430 			funcdeclname_orig = Function_decl["name"]
   399                 if Function_decl["name"].startswith('*') :
   431 			funcdeclname = Function_decl["name"].strip('*_')
   400                     input_ovrloading_types = GetSubTypes(Function_decl["inputs"][0][1])
   432 			fdc = Function_decl["inputs"][:]
   401                 else:
   433 			for intype in input_ovrloading_types:
   402                     input_ovrloading_types = [None]
   434 				if intype != None:
   403                     
   435 					Function_decl["inputs"] = []
   404                 if Function_decl["name"].endswith('*') :
   436 					for decl_tpl in fdc:
   405                     output_types = GetSubTypes(Function_decl["outputs"][0][1])
   437 						if IsOfType(intype, decl_tpl[1]):
   406                 else:
   438 							Function_decl["inputs"] += [(decl_tpl[0], intype, decl_tpl[2])]
   407                     output_types = [None]
   439 						else:
   408                     
   440 							Function_decl["inputs"] += [(decl_tpl)]
   409                 funcdeclname_orig = Function_decl["name"]
   441 						
   410                 funcdeclname = Function_decl["name"].strip('*_')
   442 						if funcdeclname_orig.startswith('*'):
   411                 fdc = Function_decl["inputs"][:]
   443 							funcdeclin = intype + '_' + funcdeclname 
   412                 for intype in input_ovrloading_types:
   444 						else:
   413                     if intype != None:
   445 							funcdeclin = funcdeclname
   414                         Function_decl["inputs"] = []
   446 				else:
   415                         for decl_tpl in fdc:
   447 					funcdeclin = funcdeclname
   416                             if IsOfType(intype, decl_tpl[1]):
   448 							
   417                                 Function_decl["inputs"] += [(decl_tpl[0], intype, decl_tpl[2])]
   449 
   418                             else:
   450 				if Function_decl["return_type_rule"] == "copy_input":
   419                                 Function_decl["inputs"] += [(decl_tpl)]
   451 					output_types = [intype]
   420                             
   452 				elif Function_decl["return_type_rule"] == "defined":
   421                             if funcdeclname_orig.startswith('*'):
   453 					pass
   422                                 funcdeclin = intype + '_' + funcdeclname 
   454 
   423                             else:
   455 				for outype in output_types:
   424                                 funcdeclin = funcdeclname
   456 					if outype != None:
   425                     else:
   457 						decl_tpl = Function_decl["outputs"][0]
   426                         funcdeclin = funcdeclname
   458 						Function_decl["outputs"] = [ (decl_tpl[0] , outype,  decl_tpl[2])]
   427                         
   459 						if funcdeclname_orig.endswith('*'):
   428                     for outype in output_types:
   460 							funcdeclout =  funcdeclin + '_' + outype
   429                         if outype != None:
   461 						else:
   430                             decl_tpl = Function_decl["outputs"][0]
   462 							funcdeclout =  funcdeclin
   431                             Function_decl["outputs"] = [ (decl_tpl[0] , outype,  decl_tpl[2])]
   463 					else:
   432                             if funcdeclname_orig.endswith('*'):
   464 						funcdeclout =  funcdeclin
   433                                 funcdeclout =  funcdeclin + '_' + outype
   465 					Function_decl["name"] = funcdeclout
   434                             else:
   466 
   435                                 funcdeclout =  funcdeclin
   467 
   436                         else:
   468 					try:
   437                             funcdeclout =  funcdeclin
   469 						fdecl = Function_decl
   438                         Function_decl["name"] = funcdeclout
   470 						res = eval(Function_decl["python_eval_c_code_format"])
   439 
   471 					except Exception,e:
   440 
   472 						res = None
   441                         fdecl = Function_decl
   473 
   442                         res = eval(Function_decl["python_eval_c_code_format"])
   474 					if res != None :
   443 
   475 						# create the copy of decl dict to be appended to section
   444                         if res != None :
   476 						Function_decl_copy = Function_decl.copy()
   445                             # create the copy of decl dict to be appended to section
   477 						# Have to generate type description in comment with freshly redefined types
   446                             Function_decl_copy = Function_decl.copy()
   478 						Function_decl_copy["comment"] += (
   447                             # Have to generate type description in comment with freshly redefined types
   479 							"\n (" +
   448                             Function_decl_copy["comment"] += (
   480 							str([ " " + fctdecl[1]+":"+fctdecl[0] for fctdecl in Function_decl["inputs"]]).strip("[]").replace("'",'') +
   449                                 "\n (" +
   481 							" ) => (" +
   450                                 str([ " " + fctdecl[1]+":"+fctdecl[0] for fctdecl in Function_decl["inputs"]]).strip("[]").replace("'",'') +
   482 							str([ " " + fctdecl[1]+":"+fctdecl[0] for fctdecl in Function_decl["outputs"]]).strip("[]").replace("'",'') +
   451                                 " ) => (" +
   483 							" )")
   452                                 str([ " " + fctdecl[1]+":"+fctdecl[0] for fctdecl in Function_decl["outputs"]]).strip("[]").replace("'",'') +
   484 						Current_section["list"].append(Function_decl_copy)
   453                                 " )")
   485 						#pp.pprint(Function_decl_copy)
   454                             Current_section["list"].append(Function_decl_copy)
   486 						
   455                             #pp.pprint(Function_decl_copy)
   487 	Standard_Functions_Decl.append(Current_section)
   456             else:
   488 	
   457                 raise "First function must be in a category"
   489 	return Standard_Functions_Decl
   458     
       
   459     return Standard_Functions_Decl
   490 
   460 
   491 
   461 
   492 if __name__ == '__main__':
   462 if __name__ == '__main__':
   493 	
   463     
   494 	import pprint
   464     import pprint
   495 	pp = pprint.PrettyPrinter(indent=4)
   465     pp = pprint.PrettyPrinter(indent=4)
   496 
   466 
   497 	def ANY_to_compiler_test_type_GEN(typename, paramname):
   467     def ANY_to_compiler_test_type_GEN(typename, paramname):
   498 		return {"ANY" : "",
   468         return {"ANY" : "",
   499 		"ANY_BIT" : "if(search_expression_type->is_binary_type(%(paramname)s_type_symbol))",
   469         "ANY_BIT" : "if(search_expression_type->is_binary_type(%(paramname)s_type_symbol))",
   500 		"ANY_NUM" : "if(search_expression_type->is_num_type(%(paramname)s_type_symbol))",
   470         "ANY_NUM" : "if(search_expression_type->is_num_type(%(paramname)s_type_symbol))",
   501 		"ANY_REAL" : "if(search_expression_type->is_real_type(%(paramname)s_type_symbol))",
   471         "ANY_REAL" : "if(search_expression_type->is_real_type(%(paramname)s_type_symbol))",
   502 		"ANY_INT" : "if(search_expression_type->is_integer_type(%(paramname)s_type_symbol))"
   472         "ANY_INT" : "if(search_expression_type->is_integer_type(%(paramname)s_type_symbol))"
   503 		}.get(typename,
   473         }.get(typename,
   504 			"if (typeid(*last_type_symbol) == typeid(%(typename)s_type_name_c))")%{
   474             "if (typeid(*last_type_symbol) == typeid(%(typename)s_type_name_c))")%{
   505 					"paramname" : paramname, "typename": typename.lower()}
   475                     "paramname" : paramname, "typename": typename.lower()}
   506 	
   476     
   507 	def recurse_and_indent(fdecls, indent, do_type_search_only = False):
   477     def recurse_and_indent(fdecls, indent, do_type_search_only = False, do_il = False):
   508 		if type(fdecls) != type(tuple()):
   478         if type(fdecls) != type(tuple()):
   509 			res = ""
   479             res = ""
   510 			for Paramname, ParamTypes in fdecls.iteritems():
   480             for Paramname, ParamTypes in fdecls.iteritems():
   511 				res += ("""
   481                 if do_il:
       
   482                     res += """
   512 {
   483 {
   513 	identifier_c param_name("%(input_name)s");
   484     /* Get the value from a foo(<param_name> = <param_value>) style call */
   514 	/* Get the value from a foo(<param_name> = <param_value>) style call */
   485     symbol_c *%(input_name)s_param_value = &this->default_variable_name;
   515 	symbol_c *%(input_name)s_param_value = function_call_param_iterator.search(&param_name);
   486     
   516 	
   487     last_type_symbol = param_data_type;
   517 	/* Get the value from a foo(<param_value>) style call */
   488 """%{"input_name":Paramname}
   518 	if (%(input_name)s_param_value == NULL)
   489                 else:
   519 	  %(input_name)s_param_value = function_call_param_iterator.next();
   490                     res += """
   520 	symbol_c *%(input_name)s_type_symbol = search_expression_type->get_type(%(input_name)s_param_value);
   491 {
   521 	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 ;
   492     identifier_c param_name("%(input_name)s");
   522 """%{"input_name":Paramname})
   493     /* Get the value from a foo(<param_name> = <param_value>) style call */
   523 				
   494     symbol_c *%(input_name)s_param_value = function_call_param_iterator.search(&param_name);
   524 				for ParamType,NextParamDecl in ParamTypes.iteritems():
   495     
   525 				
   496     /* Get the value from a foo(<param_value>) style call */
   526 					res += ("""	
   497     if (%(input_name)s_param_value == NULL)
   527 	%(type_test)s
   498       %(input_name)s_param_value = function_call_param_iterator.next();
   528 	{
   499     symbol_c *%(input_name)s_type_symbol = search_expression_type->get_type(%(input_name)s_param_value);
       
   500     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 ;
       
   501 """%{"input_name":Paramname}
       
   502                 
       
   503                 for ParamType,NextParamDecl in ParamTypes.iteritems():
       
   504                 
       
   505                     res += """    
       
   506     %(type_test)s
       
   507     {
   529 %(if_good_type_code)s
   508 %(if_good_type_code)s
   530 	}
   509     }
   531 """%{
   510 """%{
   532 	"type_test":ANY_to_compiler_test_type_GEN(ParamType,Paramname), 
   511     "type_test":ANY_to_compiler_test_type_GEN(ParamType,Paramname), 
   533 	"if_good_type_code":recurse_and_indent(NextParamDecl,indent,do_type_search_only).replace('\n','\n	')})
   512     "if_good_type_code":recurse_and_indent(NextParamDecl,indent,do_type_search_only).replace('\n','\n    ')}
   534 
   513 
   535 				res += """	
   514                 res += """    
   536 	ERROR;
   515     ERROR;
   537 }
   516 }
   538 """
   517 """
   539 			
   518             
   540 			return res.replace('\n','\n'+indent)
   519             return res.replace('\n','\n'+indent)
   541 		else:
   520         else:
   542 			res = "\n"
   521             res = "\n"
   543 			fdecl=fdecls[0]
   522             fdecl=fdecls[0]
   544 			
   523             
   545 			result_type_rule = fdecl["return_type_rule"]
   524             result_type_rule = fdecl["return_type_rule"]
   546 			res += {
   525             res += {
   547 				"copy_input" : "symbol_c * return_type_symbol = last_type_symbol;\n",
   526                 "copy_input" : "symbol_c * return_type_symbol = last_type_symbol;\n",
   548 				"defined" : "symbol_c * return_type_symbol = &search_constant_type_c::%s_type_name;\n"%fdecl["outputs"][0][1].lower(),
   527                 "defined" : "symbol_c * return_type_symbol = &search_constant_type_c::%s_type_name;\n"%fdecl["outputs"][0][1].lower(),
   549 				}.get(result_type_rule, "symbol_c * return_type_symbol = %s;\n"%result_type_rule)
   528                 }.get(result_type_rule, "symbol_c * return_type_symbol = %s;\n"%result_type_rule)
   550 			
   529             
   551 			if not do_type_search_only:
   530             if not do_type_search_only:
   552 				try:
   531                 code_gen = eval(fdecl["python_eval_c_code_format"])
   553 					code_gen = eval(fdecl["python_eval_c_code_format"])
   532     
   554 				except Exception:
   533                 code_gen_dic_decl = {}
   555 					code_gen = "#error in eval of " + fdecl["name"]
   534                 for paramname,paramtype,unused in fdecl["inputs"]:
   556 	
   535                     code_gen_dic_decl[paramname+"_value"] = '");\n%s_param_value->accept(*this);\ns4o.print("'%(paramname)
   557 				code_gen_dic_decl = {}
   536                     code_gen_dic_decl[paramname+"_type"] = '");\n%s_type_symbol->accept(*this);\ns4o.print("'%(paramname)
   558 				for paramname,paramtype,unused in fdecl["inputs"]:
   537                 code_gen_dic_decl["return_type"] = '");\nreturn_type_symbol->accept(*this);\ns4o.print("'
   559 					code_gen_dic_decl[paramname+"_value"] = '");\n%s_param_value->accept(*this);\ns4o.print("'%(paramname)
   538                 code_gen_dic_decl["param_count"] = '");\ns4o.print_integer(nb_param);\ns4o.print("'
   560 					code_gen_dic_decl[paramname+"_type"] = '");\n%s_type_symbol->accept(*this);\ns4o.print("'%(paramname)
   539                 code_gen_dic_decl["start_bool_filter"] = '");\nif (search_expression_type->is_bool_type(last_type_symbol))\n  s4o.print("('
   561 				code_gen_dic_decl["return_type"] = '");\nreturn_type_symbol->accept(*this);\ns4o.print("'
   540                 code_gen_dic_decl["end_bool_filter"] = '");\nif (search_expression_type->is_bool_type(last_type_symbol)) {\n  s4o.print("&1");\n  s4o.print(")");\n}\ns4o.print("'
   562 				code_gen_dic_decl["param_count"] = '");\ns4o.print_integer(nb_param);\ns4o.print("'
       
   563 				code_gen_dic_decl["start_bool_filter"] = '");\nif (search_expression_type->is_bool_type(last_type_symbol))\n  s4o.print("('
       
   564 				code_gen_dic_decl["end_bool_filter"] = '");\nif (search_expression_type->is_bool_type(last_type_symbol)) {\n  s4o.print("&1");\n  s4o.print(")");\n}\ns4o.print("'
       
   565                 
   541                 
   566 				if type(code_gen) == type(tuple()):
   542                 if type(code_gen) == type(tuple()):
   567 					res += 's4o.print("%s");\n'%(code_gen[0]%code_gen_dic_decl)
   543                     res += 's4o.print("%s");\n'%(code_gen[0]%code_gen_dic_decl)
   568 					static_param_accept_list = []
   544                     static_param_accept_list = []
   569 					for paramname,paramtype,unused in fdecl["inputs"]:
   545                     for paramname,paramtype,unused in fdecl["inputs"]:
   570 						static_param_accept_list.append("%s_param_value->accept(*this);\n"%(paramname))
   546                         static_param_accept_list.append("%s_param_value->accept(*this);\n"%(paramname))
   571 					res += ('s4o.print("%s");\n'%(code_gen[1])).join(static_param_accept_list)
   547                     res += ('s4o.print("%s");\n'%(code_gen[1])).join(static_param_accept_list)
   572 					code = 's4o.print("%s");\nparam_value->accept(*this);\n'%(code_gen[1])
   548                     code = 's4o.print("%s");\nparam_value->accept(*this);\n'%(code_gen[1])
   573 					end_code = 's4o.print("%s");\nreturn NULL;\n'%(code_gen[2]%code_gen_dic_decl)
   549                     end_code = 's4o.print("%s");\nreturn NULL;\n'%(code_gen[2]%code_gen_dic_decl)
   574 				else:
   550                 else:
   575 					code = ''
   551                     code = ''
   576 					end_code = ('s4o.print("' + code_gen%code_gen_dic_decl + '");\nreturn NULL;\n').replace('s4o.print("");\n','')
   552                     end_code = ('s4o.print("' + code_gen%code_gen_dic_decl + '");\nreturn NULL;\n').replace('s4o.print("");\n','')
   577 	
   553     
   578 				if fdecl["extensible"]:
   554                 if fdecl["extensible"]:
   579 					res += ("""
   555                     res += ("""
   580 int base_num = %d;
   556 int base_num = %d;
   581 symbol_c *param_value = NULL;
   557 symbol_c *param_value = NULL;
   582 do{
   558 do{
   583 	char my_name[10];
   559     char my_name[10];
   584 	sprintf(my_name, "IN%%d", base_num++);
   560     sprintf(my_name, "IN%%d", base_num++);
   585 	identifier_c param_name(my_name);
   561     identifier_c param_name(my_name);
   586 	
   562     
   587 	/* Get the value from a foo(<param_name> = <param_value>) style call */
   563     /* Get the value from a foo(<param_name> = <param_value>) style call */
   588 	param_value = function_call_param_iterator.search(&param_name);
   564     param_value = function_call_param_iterator.search(&param_name);
   589 	
   565     
   590 	/* Get the value from a foo(<param_value>) style call */
   566     /* Get the value from a foo(<param_value>) style call */
   591 	if (param_value == NULL)
   567     if (param_value == NULL)
   592 	  param_value = function_call_param_iterator.next();
   568       param_value = function_call_param_iterator.next();
   593 	if (param_value != NULL){
   569     if (param_value != NULL){
   594 		symbol_c *current_type_symbol = search_expression_type->get_type(param_value);
   570         symbol_c *current_type_symbol = search_expression_type->get_type(param_value);
   595 		last_type_symbol = last_type_symbol && search_expression_type->is_same_type(current_type_symbol, last_type_symbol) ? search_expression_type->common_type(current_type_symbol, last_type_symbol) : current_type_symbol ;
   571         last_type_symbol = last_type_symbol && search_expression_type->is_same_type(current_type_symbol, last_type_symbol) ? search_expression_type->common_type(current_type_symbol, last_type_symbol) : current_type_symbol ;
   596 	
   572     
   597 		/*Function specific CODE */
   573         /*Function specific CODE */
   598 		%s
   574         %s
   599 	}
   575     }
   600 	
   576     
   601 }while(param_value != NULL);
   577 }while(param_value != NULL);
   602 %s
   578 %s
   603 """%(fdecl["baseinputnumber"]+2, code.replace('\n','\n		'), end_code))
   579 """%(fdecl["baseinputnumber"]+2, code.replace('\n','\n        '), end_code))
   604 				else:
   580                 else:
   605 					#res += code + end_code
   581                     #res += code + end_code
   606 					res += end_code
   582                     res += end_code
   607 			else:
   583             else:
   608 				res += "return return_type_symbol;\n"
   584                 res += "return return_type_symbol;\n"
   609 			
   585             
   610 					
   586                     
   611 			return res.replace('\n','\n'+indent)
   587             return res.replace('\n','\n'+indent)
   612 
   588 
   613 ###################################################################
   589 ###################################################################
   614 ###                                                             ###
   590 ###                                                             ###
   615 ###                           MAIN                              ###
   591 ###                           MAIN                              ###
   616 ###                                                             ###
   592 ###                                                             ###
   617 ###################################################################
   593 ###################################################################
   618 
   594 
   619 	# Get definitions
   595     # Get definitions
   620 	std_decl = get_standard_funtions(csv_file_to_table(open("iec_std.csv")))#, True)
   596     std_decl = get_standard_funtions(csv_file_to_table(open("iec_std.csv")))#, True)
   621 	
   597     
   622 	# Reorganize into a dict of dict, according 
   598     # Reorganize into a dict of dict, according 
   623 	# fname : paramname : paramtype : paraname : paramtype...
   599     # fname : paramname : paramtype : paraname : paramtype...
   624 	# Keep ptrack of original order in a separated list
   600     # Keep ptrack of original order in a separated list
   625 	std_fdecls = {}
   601     std_fdecls = {}
   626 	official_order = []
   602     official_order = []
   627 	for section in std_decl:
   603     for section in std_decl:
   628 		for fdecl in section["list"]:
   604         for fdecl in section["list"]:
   629 			if len(official_order)==0 or official_order[-1] != fdecl["name"]:
   605             if len(official_order)==0 or official_order[-1] != fdecl["name"]:
   630 				official_order.append(fdecl["name"])
   606                 official_order.append(fdecl["name"])
   631 			# store all func by name in a dict
   607             # store all func by name in a dict
   632 			std_fdecls_fdecl_name = std_fdecls.get(fdecl["name"], {})
   608             std_fdecls_fdecl_name = std_fdecls.get(fdecl["name"], {})
   633 			current = std_fdecls_fdecl_name
   609             current = std_fdecls_fdecl_name
   634 			for i in fdecl["inputs"]:
   610             for i in fdecl["inputs"]:
   635 				current[i[0]] = current.get(i[0], {})
   611                 current[i[0]] = current.get(i[0], {})
   636 				current = current[i[0]]
   612                 current = current[i[0]]
   637 				last = current
   613                 last = current
   638 				current[i[1]] = current.get(i[1], {})
   614                 current[i[1]] = current.get(i[1], {})
   639 				current = current[i[1]]
   615                 current = current[i[1]]
   640 			last[i[1]]=(fdecl,)
   616             last[i[1]]=(fdecl,)
   641 			std_fdecls[fdecl["name"]] = std_fdecls_fdecl_name
   617             std_fdecls[fdecl["name"]] = std_fdecls_fdecl_name
   642 
   618 
   643 	# Generate the long enumeration of std function types
   619     # Generate the long enumeration of std function types
   644 	function_type_decl =  """
   620     function_type_decl =  """
   645 /****
   621 /****
   646  * IEC 61131-3 standard function lib
   622  * IEC 61131-3 standard function lib
   647  * generated code, do not edit by hand
   623  * generated code, do not edit by hand
   648  */
   624  */
   649 typedef enum {
   625 typedef enum {
   650 """
   626 """
   651 	for fname, fdecls in [ (fname,std_fdecls[fname]) for fname in official_order ]:
   627     for fname, fdecls in [ (fname,std_fdecls[fname]) for fname in official_order ]:
   652 		function_type_decl += "	function_"+fname.lower()+",\n"
   628         function_type_decl += "    function_"+fname.lower()+",\n"
   653 
   629 
   654 	function_type_decl += """	function_none
   630     function_type_decl += """    function_none
   655 } function_type_t;
   631 } function_type_t;
   656 """
   632 """
   657 
   633 
   658 	# Generate the funct thaat return enumerated according function name
   634     # Generate the funct thaat return enumerated according function name
   659 	get_function_type_decl = """
   635     get_function_type_decl = """
   660 /****
   636 /****
   661  * IEC 61131-3 standard function lib
   637  * IEC 61131-3 standard function lib
   662  * generated code, do not edit by hand
   638  * generated code, do not edit by hand
   663  */
   639  */
   664 function_type_t get_function_type(identifier_c *function_name) {
   640 function_type_t get_function_type(identifier_c *function_name) {
   665 """
   641 """
   666 	for fname, fdecls in [ (fname,std_fdecls[fname]) for fname in official_order ]:
   642     for fname, fdecls in [ (fname,std_fdecls[fname]) for fname in official_order ]:
   667 		get_function_type_decl += """
   643         get_function_type_decl += """
   668 	if (!strcasecmp(function_name->value, "%s"))
   644     if (!strcasecmp(function_name->value, "%s"))
   669 		return function_%s;
   645         return function_%s;
   670 """%(fname,fname.lower())
   646 """%(fname,fname.lower())
   671 
   647 
   672 	get_function_type_decl += """
   648     get_function_type_decl += """
   673 	else return function_none;
   649     else return function_none;
   674 }
   650 }
   675 
   651 
   676 """
   652 """
   677 
   653 
   678 	# Generate the part of generate_cc_st_c::visit(function_invocation)
   654     # Generate the part of generate_cc_st_c::visit(function_invocation)
   679 	# that is responsible to generate C code for std lib calls.
   655     # that is responsible to generate C code for std lib calls.
   680 	st_code_gen = """
   656     st_code_gen = """
   681 /****
   657 /****
   682  * IEC 61131-3 standard function lib
   658  * IEC 61131-3 standard function lib
   683  * generated code, do not edit by hand
   659  * generated code, do not edit by hand
   684  */
   660  */
   685 switch(current_function_type){
   661 switch(current_function_type){
   686 """
   662 """
   687 	
   663     
   688 	for fname, fdecls in [ (fname,std_fdecls[fname]) for fname in official_order ]:
   664     for fname, fdecls in [ (fname,std_fdecls[fname]) for fname in official_order ]:
   689 		st_code_gen += """
   665         st_code_gen += """
   690 /****
   666 /****
   691  *%s
   667  *%s
   692  */
   668  */
   693 	case function_%s :
   669     case function_%s :
   694 	{
   670     {
   695 		symbol_c *last_type_symbol = NULL;
   671         symbol_c *last_type_symbol = NULL;
   696 """	%(fname, fname.lower())
   672 """    %(fname, fname.lower())
   697 		indent =  "	"
   673         indent =  "    "
   698 
   674 
   699 		st_code_gen += recurse_and_indent(fdecls, indent).replace('\n','\n	')
   675         st_code_gen += recurse_and_indent(fdecls, indent).replace('\n','\n    ')
   700 		
   676         
   701 		st_code_gen += """
   677         st_code_gen += """
   702 	}/*function_%s*/
   678     }/*function_%s*/
   703 	break;
   679     break;
   704 """	%(fname.lower())
   680 """    %(fname.lower())
   705 	st_code_gen +=  """
   681     st_code_gen +=  """
   706 	case function_none :
   682     case function_none :
   707 	ERROR;
   683     ERROR;
   708 }
   684 }
   709 return NULL;
   685 return NULL;
   710 """
   686 """
   711 
   687 
   712 
   688     # Generate the part of generate_cc_il_c::visit(il_function_call)
   713 	# Generate the part of search_expression_type_c::visit(function_invocation)
   689     # that is responsible to generate C code for std lib calls.
   714 	# that is responsible of returning type symbol for function invocation.
   690     il_code_gen = """
   715 	search_type_code =  """
       
   716 /****
   691 /****
   717  * IEC 61131-3 standard function lib
   692  * IEC 61131-3 standard function lib
   718  * generated code, do not edit by hand
   693  * generated code, do not edit by hand
   719  */
   694  */
   720 switch(current_function_type){
   695 switch(current_function_type){
   721 """
   696 """
   722 	
   697     
   723 	for fname, fdecls in [ (fname,std_fdecls[fname]) for fname in official_order ]:
   698     for fname, fdecls in [ (fname,std_fdecls[fname]) for fname in official_order ]:
   724 		search_type_code += """
   699         il_code_gen += """
   725 /****
   700 /****
   726  *%s
   701  *%s
   727  */
   702  */
   728 	case function_%s :
   703     case function_%s :
   729 	{
   704     {
   730 		symbol_c *last_type_symbol = NULL;
   705         symbol_c *last_type_symbol = NULL;
   731 """	%(fname, fname.lower())
   706 """    %(fname, fname.lower())
   732 		indent =  "	"
   707         indent =  "    "
   733 
   708 
   734 		search_type_code += recurse_and_indent(fdecls, indent, True).replace('\n','\n	')
   709         il_code_gen += recurse_and_indent(fdecls, indent).replace('\n','\n    ')
   735 		
   710         
   736 		search_type_code += """
   711         il_code_gen += """
   737 	}/*function_%s*/
   712     }/*function_%s*/
   738 	break;
   713     break;
   739 """	%(fname.lower())
   714 """    %(fname.lower())
   740 	search_type_code += """
   715     st_code_gen +=  """
   741 	case function_none :
   716     case function_none :
   742 	ERROR;
   717     ERROR;
   743 }
   718 }
   744 return NULL;
   719 return NULL;
   745 """
   720 """
   746 
   721 
   747 
   722     # Generate the part of search_expression_type_c::visit(function_invocation)
   748 	# Now, print that out, or write to files from sys.argv
   723     # that is responsible of returning type symbol for function invocation.
   749 	for name, ext in [
   724     search_type_code =  """
   750 			('function_type_decl','h'),
   725 /****
   751 			('get_function_type_decl','c'),
   726  * IEC 61131-3 standard function lib
   752 			('st_code_gen','c'),
   727  * generated code, do not edit by hand
   753 			('search_type_code','c')]:
   728  */
   754 		fd = open(os.path.join(sys.argv[1],name+'.'+ext),'w')
   729 switch(current_function_type){
   755 		fd.write(eval(name))
   730 """
   756 		fd.close()
   731     
       
   732     for fname, fdecls in [ (fname,std_fdecls[fname]) for fname in official_order ]:
       
   733         search_type_code += """
       
   734 /****
       
   735  *%s
       
   736  */
       
   737     case function_%s :
       
   738     {
       
   739         symbol_c *last_type_symbol = NULL;
       
   740 """    %(fname, fname.lower())
       
   741         indent =  "    "
       
   742 
       
   743         search_type_code += recurse_and_indent(fdecls, indent, True).replace('\n','\n    ')
       
   744         
       
   745         search_type_code += """
       
   746     }/*function_%s*/
       
   747     break;
       
   748 """    %(fname.lower())
       
   749     search_type_code += """
       
   750     case function_none :
       
   751     ERROR;
       
   752 }
       
   753 return NULL;
       
   754 """
       
   755 
       
   756 
       
   757     # Now, print that out, or write to files from sys.argv
       
   758     for name, ext in [
       
   759             ('function_type_decl','h'),
       
   760             ('get_function_type_decl','c'),
       
   761             ('st_code_gen','c'),
       
   762             ('il_code_gen','c'),
       
   763             ('search_type_code','c')]:
       
   764         fd = open(os.path.join(sys.argv[1],name+'.'+ext),'w')
       
   765         fd.write(eval(name))
       
   766         fd.close()
   757 else:
   767 else:
   758 	# Put standard functions declaration in Bloktypes
   768     # Put standard functions declaration in Bloktypes
   759 	BlockTypes.extend(get_standard_funtions(csv_file_to_table(open(os.path.join(sys.path[0], "plcopen/iec_std.csv")))))
   769     BlockTypes.extend(get_standard_funtions(csv_file_to_table(open(os.path.join(sys.path[0], "plcopen/iec_std.csv")))))
   760 	
   770 
       
   771