def constrExternFuncDecl(func_el): extern_decl = '' return_type_dict = utils.findType( gb.id_dict[func_el.get('returns')] ) return_type = return_type_dict['name'] + '*'*return_type_dict['pointerness'] + '&'*return_type_dict['is_reference'] func_name = getFunctionNameDict(func_el) namespaces = utils.getNamespaces(func_el) n_indents = len(namespaces) extern_decl += utils.constrNamespace(namespaces, 'open') extern_decl += ' '*cfg.indent*n_indents + 'extern ' + return_type + ' ' + func_name['short_templ_args'] + ';\n' extern_decl += utils.constrNamespace(namespaces, 'close') return extern_decl
def addWrapperTypedefs(class_name, namespaces): short_wrapper_class_name = classutils.toWrapperType(class_name['short']) indent = ' ' * cfg.indent * len(namespaces) wrapper_typedef_code = '' wrapper_typedef_code += utils.constrNamespace(namespaces, 'open') temp_namespace_list = [gb.gambit_backend_namespace] + namespaces wrapper_typedef_code += indent + 'typedef ' + '::'.join( temp_namespace_list ) + '::' + class_name['short'] + ' ' + short_wrapper_class_name + ';\n' wrapper_typedef_code += utils.constrNamespace(namespaces, 'close') wrapper_typedef_code += '\n' frw_decl_include_statement = '#include "' + os.path.join( gb.backend_types_basedir, gb.gambit_backend_name_full, gb.frwd_decls_wrp_fname + cfg.header_extension) + '"\n' identification_include_statement = '#include "' + os.path.join( gb.backend_types_basedir, gb.gambit_backend_name_full, 'identification.hpp') + '"\n\n' undef_include_statement = '#include "' + os.path.join( gb.gambit_backend_incl_dir, 'backend_undefs.hpp') + '"\n' wrapper_typedefs_path = os.path.join( gb.boss_output_dir, gb.wrapper_typedefs_fname + cfg.header_extension) if wrapper_typedefs_path not in gb.new_code.keys(): gb.new_code[wrapper_typedefs_path] = { 'code_tuples': [], 'add_include_guard': False } gb.new_code[wrapper_typedefs_path]['code_tuples'].append( (0, frw_decl_include_statement)) gb.new_code[wrapper_typedefs_path]['code_tuples'].append( (len(frw_decl_include_statement), identification_include_statement)) gb.new_code[wrapper_typedefs_path]['code_tuples'].append( (-1, undef_include_statement)) gb.new_code[wrapper_typedefs_path]['code_tuples'].append( (-len(undef_include_statement), wrapper_typedef_code))
def addAbstractTypedefs(abstr_class_name, namespaces): indent = ' ' * cfg.indent * len(namespaces) abstr_typedef_code = '' abstr_typedef_code += utils.constrNamespace(namespaces, 'open', indent=cfg.indent) temp_namespace_list = [gb.gambit_backend_namespace] + namespaces abstr_typedef_code += indent + 'typedef ' + '::'.join( temp_namespace_list) + '::' + abstr_class_name[ 'short'] + ' ' + abstr_class_name['short'] + ';\n' abstr_typedef_code += utils.constrNamespace(namespaces, 'close', indent=cfg.indent) abstr_typedef_code += '\n' frw_decl_include_statement = '#include "' + os.path.join( gb.backend_types_basedir, gb.gambit_backend_name_full, gb.frwd_decls_abs_fname + cfg.header_extension) + '"\n' identification_include_statement = '#include "' + os.path.join( gb.backend_types_basedir, gb.gambit_backend_name_full, 'identification.hpp') + '"\n\n' undef_include_statement = '#include "' + os.path.join( gb.gambit_backend_incl_dir, 'backend_undefs.hpp') + '"\n' abstracts_typedefs_header_path = os.path.join( gb.boss_output_dir, gb.abstract_typedefs_fname + cfg.header_extension) if abstracts_typedefs_header_path not in gb.new_code.keys(): gb.new_code[abstracts_typedefs_header_path] = { 'code_tuples': [], 'add_include_guard': False } gb.new_code[abstracts_typedefs_header_path]['code_tuples'].append( (0, frw_decl_include_statement)) gb.new_code[abstracts_typedefs_header_path]['code_tuples'].append( (len(frw_decl_include_statement), identification_include_statement)) gb.new_code[abstracts_typedefs_header_path]['code_tuples'].append( (-1, undef_include_statement)) gb.new_code[abstracts_typedefs_header_path]['code_tuples'].append( (-len(undef_include_statement), abstr_typedef_code))
def run(): # # Loop over all functions # for func_name_full, func_el in gb.func_dict.items(): # Clear all info messages infomsg.clearInfoMessages() # Number of functions done func_i = len(gb.functions_done) # Generate dict with different variations of the function name func_name = funcutils.getFunctionNameDict(func_el) # Print current function print print ' ' + utils.modifyText( 'Function:', 'underline') + ' ' + func_name['long_templ_args'] # Check if this function is accepted if funcutils.ignoreFunction(func_el): continue # Function namespace namespaces = utils.getNamespaces(func_el) has_namespace = bool(len(namespaces)) # Check if this is a template function is_template = utils.isTemplateFunction(func_el) # If template function, figure out template variables if is_template == True: template_bracket, template_types = utils.getTemplateBracket( func_el) spec_template_types = utils.getSpecTemplateTypes(func_el) print 'TEMPLATE: ', template_bracket, template_types, spec_template_types # # Generate extra source file with overloaded and wrapper class versions # # Construct a wrapper function name, eg "someFunction__BOSS_7" wr_func_name = func_el.get('name') + gb.code_suffix + '_' + str( gb.symbol_name_counter) gb.symbol_name_counter += 1 # New source file name new_source_file_name = gb.function_files_prefix + func_el.get( 'name') + cfg.source_extension new_source_file_path = os.path.join(gb.boss_output_dir, new_source_file_name) # Get include statements include_statements = [] # - Generate include statements based on the types used in the function include_statements += utils.getIncludeStatements( func_el, convert_loaded_to='none', input_element='function') include_statements += utils.getIncludeStatements( func_el, convert_loaded_to='wrapper', input_element='function', use_full_path=True) include_statements.append('#include "' + os.path.join( gb.gambit_backend_incl_dir, gb.abstract_typedefs_fname + cfg.header_extension) + '"') include_statements.append('#include "' + os.path.join( gb.gambit_backend_incl_dir, gb.wrapper_typedefs_fname + cfg.header_extension) + '"') # - Then check if we have a header file for the function in question. # If not, declare the original function as 'extern' file_el = gb.id_dict[func_el.get('file')] has_function_header = utils.isHeader(file_el) if has_function_header: header_full_path = file_el.get('name') use_path = utils.shortenHeaderPath(header_full_path) include_statements.append('#include "' + use_path + '"') # Add include statement for gambit/Backends/function_return_utils.hpp include_statements.append('#include "' + os.path.join( gb.gambit_backend_incl_dir, 'function_return_utils.hpp') + '"') include_statements = list(OrderedDict.fromkeys(include_statements)) include_statements_code = '\n'.join(include_statements) + 2 * '\n' # If no header file is found for the original function, generate 'extern' declaration extern_declaration = '' if not has_function_header: extern_declaration += funcutils.constrExternFuncDecl(func_el) extern_declaration += '\n' # If we have access to the function header, we can implement one overloaded versions # to account for default value arguments. if has_function_header: n_overloads = funcutils.numberOfDefaultArgs(func_el) else: n_overloads = 0 # # Generate code for wrapper class version # # # Register the wrapper name # func_name['wr_name'] = wr_func_name # Construct wrapper function code wrapper_code = generateFunctionWrapperClassVersion( func_el, wr_func_name, namespaces, n_overloads) wrapper_code = utils.addIndentation(wrapper_code, len(namespaces) * cfg.indent) wrapper_code += '\n' # Prepare element in gb.new_code if new_source_file_path not in gb.new_code.keys(): gb.new_code[new_source_file_path] = { 'code_tuples': [], 'add_include_guard': False } # Define code string n_indents = len(namespaces) new_code = 2 * '\n' # - Add include statements new_code += include_statements_code # - Add extern function declaration new_code += extern_declaration # - Construct the beginning of the namespaces new_code += utils.constrNamespace(namespaces, 'open') # - Add code for 'wrapper' version new_code += wrapper_code # - Construct the closing of the namespaces new_code += utils.constrNamespace(namespaces, 'close') new_code += '\n' # Register new code in return_code_dict insert_pos = -1 # end of file # return_code_dict[new_source_file_path]['code_tuples'].append( (insert_pos, new_code) ) gb.new_code[new_source_file_path]['code_tuples'].append( (insert_pos, new_code)) # Register that this function has a source file gb.function_file_dict[ func_name['long_templ_args']] = new_source_file_path # # Keep track of functions done # gb.functions_done.append(func_name) gb.wr_func_names.append(wr_func_name) print
def createFrontendHeader(function_xml_files_dict): # Read all xml files utils.xmlFilesToDicts(function_xml_files_dict.values()) # # Generate typedefs for loaded classes, from ::BACKENDNAME_SAFE_VERSION::class_name # to ::Gambit::Backends::BACKENDNAME_SAFE_VERSION::class_name # outer_namespace_list = ['Gambit', 'Backends', gb.gambit_backend_name_full] typedef_code = '' typedef_code += utils.constrNamespace(outer_namespace_list, 'open', indent=cfg.indent) # Loop over all classes for class_name in gb.classes_done: if not class_name['long'] in gb.factory_info.keys(): continue else: class_typedef_code = '' class_namespace, class_name_short = utils.removeNamespace( class_name['long'], return_namespace=True) if class_namespace == '': class_typedef_code += 'typedef ::' + gb.gambit_backend_name_full + '::' + class_name[ 'long'] + ' ' + class_name['short'] + ';\n' else: class_namespace_list = class_namespace.split('::') class_typedef_code += utils.constrNamespace( class_namespace_list, 'open', indent=cfg.indent) class_typedef_code += ' ' * cfg.indent * len( class_namespace_list ) + 'typedef ::' + gb.gambit_backend_name_full + '::' + class_name[ 'long'] + ' ' + class_name['short'] + ';\n' class_typedef_code += utils.constrNamespace( class_namespace_list, 'close', indent=cfg.indent) class_typedef_code = utils.addIndentation(class_typedef_code, 3 * cfg.indent) typedef_code += class_typedef_code typedef_code += utils.constrNamespace(outer_namespace_list, 'close', indent=cfg.indent) # # Generate code for all the BE_FUNCTION macros # be_function_macro_code = '' for i, func_name in enumerate(gb.functions_done): # Set useful variables xml_file = function_xml_files_dict[func_name['long_templ_args']] # If new xml file, initialise global dicts if xml_file != gb.xml_file_name: gb.xml_file_name = xml_file utils.initGlobalXMLdicts(xml_file, id_and_name_only=True) # Get wrapper function element tree = ET.parse(xml_file) root = tree.getroot() wr_func_el = None for el in root.findall('Function'): if el.get('name') == gb.wr_func_names[i]: wr_func_el = el if wr_func_el is None: continue # Get information about the return type. return_type_dict = utils.findType(wr_func_el) return_el = return_type_dict['el'] pointerness = return_type_dict['pointerness'] is_ref = return_type_dict['is_reference'] return_kw = return_type_dict['cv_qualifiers'] return_kw_str = ' '.join(return_kw) + ' ' * bool(len(return_kw)) return_type = return_type_dict[ 'name'] + '*' * pointerness + '&' * is_ref # Construct argument bracket args = funcutils.getArgs(wr_func_el) args_bracket = funcutils.constrArgsBracket(args, include_arg_name=False, include_arg_type=True, include_namespace=True) # Get mangled symbol # symbol = wr_func_el.get('mangled') symbol = wr_func_el.get('name') be_function_macro_code += 'BE_FUNCTION(' be_function_macro_code += func_name['short'] + ', ' be_function_macro_code += return_type + ', ' be_function_macro_code += args_bracket + ', ' be_function_macro_code += '"' + symbol + '"' + ', ' be_function_macro_code += '"' + func_name['short'] + '"' + ')\n' # # Generate code for the frontend header # frontend_content = '' # - Comment at beginning backend_name_and_version = cfg.gambit_backend_name + ' ' + cfg.gambit_backend_version frontend_content += '//\n' frontend_content += '// Frontend header generated by BOSS for GAMBIT backend %s.\n' % ( backend_name_and_version) frontend_content += '//\n' # - Include statement for the identification header frontend_content += '\n' frontend_content += '#include "' + os.path.join( gb.gambit_backend_incl_dir, gb.backend_types_basedir, gb.gambit_backend_name_full, 'identification.hpp') + '"\n' # - LOAD_LIBRARY macro frontend_content += '\n' frontend_content += 'LOAD_LIBRARY\n' # - Class typedefs frontend_content += '\n' frontend_content += typedef_code # - BE_FUNCTION macros frontend_content += '\n' frontend_content += '// Functions\n' frontend_content += be_function_macro_code # - Descriptions of different things that can go into a frontend header frontend_content += '// Variables\n' frontend_content += '\n' frontend_content += '// Initialisation function (dependencies)\n' frontend_content += '\n' frontend_content += '// Convenience functions (registration)\n' frontend_content += '\n' frontend_content += '// Initialisation function (definition)\n' frontend_content += 'BE_INI_FUNCTION{} END_BE_INI_FUNCTION\n' frontend_content += '\n' frontend_content += '// Convenience functions (definitions)\n' # - Include statement for backend_undefs.hpp frontend_content += '\n' frontend_content += '// End\n' frontend_content += '#include "' + os.path.join( gb.gambit_backend_incl_dir, 'backend_undefs.hpp') + '"\n' # Write to file f = open(gb.frontend_path, 'w') f.write(frontend_content) f.close()