def constrAbstractClassHeaderCode(class_el, class_name, abstr_class_name, namespaces, is_template, has_copy_constructor, construct_assignment_operator, abstr_class_fname, file_for_gambit=False): if file_for_gambit: abstr_class_fname = abstr_class_fname + '.FOR_GAMBIT' class_decl = '' # Add include statements ilude_statements = [] include_statements = [ '#include "' + os.path.join(gb.gambit_backend_incl_dir, 'abstractbase.hpp') + '"' ] include_statements += [ '#include "' + gb.frwd_decls_abs_fname + cfg.header_extension + '"' ] include_statements += [ '#include "' + gb.frwd_decls_wrp_fname + cfg.header_extension + '"' ] include_statements += utils.getIncludeStatements( class_el, convert_loaded_to='wrapper_decl', exclude_types=[class_name], include_parents=True, use_full_path=False, forward_declared='include') include_statements += ['#include <cstddef>'] if gb.debug_mode or file_for_gambit: include_statements += ['#include <iostream>'] include_statements_code = '\n'.join(include_statements) + 2 * '\n' class_decl += include_statements_code # # Add include statement for the enum declaration header. Put this inside a #ifndef ... #endif block # # to avoid multiple declaration when the abstract class header is included from the original class header. # enum_include_statement_code = '' # enum_include_statement_code += '#ifndef ENUMS_DECLARED\n' # enum_include_statement_code += '#define ENUMS_DECLARED\n' # enum_include_statement_code += '#include "' + gb.enum_decls_wrp_fname + cfg.header_extension + '"\n' # # enum_include_statement_code += '#include "' + os.path.join(gb.backend_types_basedir, gb.gambit_backend_name_full, gb.enum_decls_wrp_fname + cfg.header_extension) + '"\n' # enum_include_statement_code += '#endif\n' # enum_include_statement_code += '\n' # class_decl += enum_include_statement_code # Add the the code for the abstract class if (is_template == True) and (class_name['long'] in templ_spec_done): pass elif (is_template == True) and (class_name['long'] not in templ_spec_done): class_decl += classutils.constrAbstractClassDecl( class_el, class_name, abstr_class_name, namespaces, indent=cfg.indent, file_for_gambit=file_for_gambit, template_types=spec_template_types, construct_assignment_operator=construct_assignment_operator) class_decl += '\n' else: class_decl += classutils.constrAbstractClassDecl( class_el, class_name, abstr_class_name, namespaces, indent=cfg.indent, file_for_gambit=file_for_gambit, construct_assignment_operator=construct_assignment_operator) class_decl += '\n' # - Register code gb.new_code[abstr_class_fname]['code_tuples'].append((-1, class_decl))
def generateClassMemberInterface(class_el, class_name, abstr_class_name, namespaces, original_file_name, original_file_content_nocomments, original_class_file_el, extras_src_file_name): # Find class name position in the original file class_name_pos = classutils.findClassNamePosition( class_el, original_file_content_nocomments) # Create lists of all public, 'non-artificial' members of the class member_methods = [] member_variables = [] member_operators = [] if 'members' in class_el.keys(): for mem_id in class_el.get('members').split(): el = gb.id_dict[mem_id] if not 'artificial' in el.keys(): if el.get('access') == 'public': if (el.tag == 'Method' ): # and (not funcutils.ignoreFunction(el)): member_methods.append(el) elif (el.tag == 'OperatorMethod' ): #and (not funcutils.ignoreFunction(el)): if funcutils.usesNativeType(el): member_operators.append(el) elif (el.tag in ('Field', 'Variable')): if classutils.isAcceptedMemberVariable(el): member_variables.append(el) # Determine insert position rel_pos_start, rel_pos_end = utils.getBracketPositions( original_file_content_nocomments[class_name_pos:], delims=['{', '}']) class_body_start = class_name_pos + rel_pos_start class_body_end = class_name_pos + rel_pos_end insert_pos = class_body_end # Generate code for wrapper functions for each each member function. # A declaration goes into the original class header, # while implementations are put in a new source file. declaration_code = '\n' implementation_code = '\n' current_access = None for method_el in member_methods: # We need to generate as many overloaded versions as there are arguments with default values n_overloads = funcutils.numberOfDefaultArgs(method_el) # Check for native types uses_native_type = funcutils.usesNativeType(method_el) # If no native types are used and no arguments have default values, we don't need a wrapper if (not uses_native_type) and (n_overloads == 0): continue # Generate wrapper code for remove_n_args in range(n_overloads + 1): # Check that function is acceptable if funcutils.ignoreFunction(method_el, remove_n_args=remove_n_args): continue if (remove_n_args == 0) and (not uses_native_type): continue # The declaration is put inside the original class method_access = method_el.get('access') if method_access != current_access: declaration_code += ' ' * ( len(namespaces) + 1) * cfg.indent + method_access + ':\n' current_access = method_access declaration_code += classutils.constrWrapperFunction( method_el, indent=cfg.indent, n_indents=len(namespaces) + 2, remove_n_args=remove_n_args, only_declaration=True) declaration_code += '\n' # The implementation goes into a new source file implementation_code += classutils.constrWrapperFunction( method_el, indent=cfg.indent, n_indents=0, remove_n_args=remove_n_args, include_full_namespace=True) implementation_code += 2 * '\n' # - Register code gb.new_code[original_file_name]['code_tuples'].append( (insert_pos, declaration_code)) gb.new_code[extras_src_file_name]['code_tuples'].append( (-1, implementation_code)) # Generate code for each member operator operator_declaration_code = '\n' operator_implementation_code = '\n' for operator_el in member_operators: operator_access = operator_el.get('access') if operator_access != current_access: operator_declaration_code += ' ' * ( len(namespaces) + 1) * cfg.indent + operator_access + ':\n' current_access = operator_access # If default arguments are used, we need several overloads n_overloads = funcutils.numberOfDefaultArgs(operator_el) for remove_n_args in range(n_overloads + 1): # Put declaration in original class operator_declaration_code += classutils.constrWrapperFunction( operator_el, indent=cfg.indent, n_indents=len(namespaces) + 2, remove_n_args=remove_n_args, only_declaration=True) operator_declaration_code += '\n' # Put implementation in a new source file operator_implementation_code += classutils.constrWrapperFunction( operator_el, indent=cfg.indent, n_indents=0, remove_n_args=remove_n_args, include_full_namespace=True) operator_implementation_code += 2 * '\n' # - Register code gb.new_code[original_file_name]['code_tuples'].append( (insert_pos, operator_declaration_code)) gb.new_code[extras_src_file_name]['code_tuples'].append( (-1, operator_implementation_code)) # Generate a reference-returning method for each (public) member variable: ref_func_declaration_code = '' ref_func_implementation_code = '' if len(member_variables) > 0: n_indents = len(namespaces) ref_func_declaration_code += '\n' ref_func_declaration_code += ' ' * cfg.indent * (n_indents + 1) + 'public:\n' for var_el in member_variables: # Put declaration in original code ref_func_declaration_code += classutils.constrVariableRefFunction( var_el, virtual=False, indent=cfg.indent, n_indents=n_indents + 2, only_declaration=True, add_return_type_suffix=True) ref_func_declaration_code += '\n' # Put implementation in a new source file ref_func_implementation_code += classutils.constrVariableRefFunction( var_el, virtual=False, indent=cfg.indent, n_indents=0, include_full_namespace=True, add_return_type_suffix=True) ref_func_implementation_code += '\n' # - Register code if ref_func_declaration_code != '': gb.new_code[original_file_name]['code_tuples'].append( (insert_pos, ref_func_declaration_code)) gb.new_code[extras_src_file_name]['code_tuples'].append( (-1, ref_func_implementation_code)) # Generate pointer-based copy and assignment functions # If class contains pure virtual members, do not generate any factory functions if class_name['long_templ'] in gb.contains_pure_virtual_members: reason = "Contains pure virtual member functions." infomsg.NoPointerCopyAndAssignmentFunctions(class_name['long_templ'], reason).printMessage() else: n_indents = len(namespaces) ptr_declaration_code = '\n' ptr_implementation_code = '\n' ptr_declaration_code += ' ' * cfg.indent * (n_indents + 1) + 'public:\n' ptr_declaration_code += classutils.constrPtrCopyFunc( class_el, abstr_class_name['short'], class_name['short'], virtual=False, indent=cfg.indent, n_indents=n_indents + 2, only_declaration=True) ptr_declaration_code += '\n' ptr_declaration_code += ' ' * cfg.indent * ( n_indents + 2) + 'using ' + abstr_class_name[ 'short'] + '::pointer_assign' + gb.code_suffix + ';\n' ptr_declaration_code += classutils.constrPtrAssignFunc( class_el, abstr_class_name['short'], class_name['short'], virtual=False, indent=cfg.indent, n_indents=n_indents + 2, only_declaration=True) ptr_implementation_code += '#include "' + os.path.join( gb.backend_types_basedir, gb.gambit_backend_name_full, 'identification.hpp') + '"\n' ptr_implementation_code += '\n' ptr_implementation_code += classutils.constrPtrCopyFunc( class_el, abstr_class_name['short'], class_name['short'], virtual=False, indent=cfg.indent, n_indents=0, include_full_namespace=True) ptr_implementation_code += '\n' ptr_implementation_code += classutils.constrPtrAssignFunc( class_el, abstr_class_name['short'], class_name['short'], virtual=False, indent=cfg.indent, n_indents=0, include_full_namespace=True) ptr_implementation_code += '\n' ptr_implementation_code += '#include "' + os.path.join( gb.gambit_backend_incl_dir, 'backend_undefs.hpp') + '"\n' # - Generate include statements for the new source file include_statements = [] include_statements += utils.getIncludeStatements( class_el, convert_loaded_to='none', input_element='class', use_full_path=True, forward_declared='only') include_statements += utils.getIncludeStatements( class_el, convert_loaded_to='wrapper', input_element='class', use_full_path=True, forward_declared='exclude') 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) + '"') if utils.isHeader(original_class_file_el): use_path = utils.shortenHeaderPath(original_file_name) include_statements.append('#include "' + use_path + '"') include_statements = list(OrderedDict.fromkeys(include_statements)) include_statements_code = '\n'.join(include_statements) + '\n' # - Register the code gb.new_code[original_file_name]['code_tuples'].append( (insert_pos, ptr_declaration_code)) gb.new_code[extras_src_file_name]['code_tuples'].append( (0, include_statements_code)) gb.new_code[extras_src_file_name]['code_tuples'].append( (-1, ptr_implementation_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