def addIncludesToOriginalClassFile(class_el, namespaces, is_template, original_file_name, original_file_content_nocomments, original_file_content, short_abstr_class_fname): # Generate include statement for abstract class header include_line = '#include "' + os.path.join(gb.backend_types_basedir, gb.gambit_backend_name_full, short_abstr_class_fname) + '"' # Check that we haven't included that statement already if include_line in includes[original_file_name]: return # Check for namespace has_namespace = bool(len(namespaces)) # Find class name position in the original file class_name_pos = classutils.findClassNamePosition( class_el, original_file_content_nocomments) # Find insert position if is_template == True: insert_pos = original_file_content_nocomments[:class_name_pos].rfind( 'template') else: insert_pos = max( original_file_content_nocomments[:class_name_pos].rfind('class'), original_file_content_nocomments[:class_name_pos].rfind('struct')) # - Adjust for the indentation use_indent = '' while insert_pos > 0: char = original_file_content[insert_pos - 1] if char in [' ', '\t']: use_indent += char insert_pos -= 1 else: break # Construct code include_code = '' include_code += use_indent for ns in namespaces: include_code += '} ' include_code += '\n' * has_namespace include_code += use_indent + '#define ENUMS_DECLARED\n' include_code += use_indent + include_line + '\n' include_code += use_indent + '#include "' + os.path.join( gb.gambit_backend_incl_dir, gb.abstract_typedefs_fname + cfg.header_extension) + '"\n' include_code += use_indent + '#include "' + os.path.join( gb.gambit_backend_incl_dir, gb.wrapper_typedefs_fname + cfg.header_extension) + '"\n' include_code += use_indent for ns in namespaces: include_code += 'namespace ' + ns + ' { ' include_code += '\n' * has_namespace # Register code gb.new_code[original_file_name]['code_tuples'].append( (insert_pos, include_code)) # Register include line includes[original_file_name].append(include_line)
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 addAbsClassToInheritanceList(class_el, class_name, abstr_class_name, is_template, original_file_name, original_file_content_nocomments): # Find positions in the original file line_number = int(class_el.get('line')) class_name_pos = classutils.findClassNamePosition( class_el, original_file_content_nocomments) newline_pos = utils.findNewLinePos(original_file_content_nocomments, line_number) # Special preparations for template classes: if is_template: # - Determine whether this is the source for the general template # or for a specialization (look for '<' after class name) temp_pos = class_name_pos + len(class_name['short']) while True: next_char = original_file_content_nocomments[temp_pos] if next_char not in [' ', '\t', '\n']: break else: temp_pos += 1 if next_char == '<': src_is_specialization = True else: src_is_specialization = False # - Prepare the template bracket string if src_is_specialization: add_template_bracket = '<' + ','.join(spec_template_types) + '>' else: add_template_bracket = '<' + ','.join(template_types) + '>' # If no previous parent classes: if ('bases' not in class_el.keys()) and (class_name['long'] not in added_parent): # - Calculate insert position insert_pos = class_name_pos + len(class_name['short']) if is_template and src_is_specialization: insert_pos += len(add_template_bracket) # - Generate code add_code = ' : public virtual ' + abstr_class_name['short'] if is_template == True: add_code += add_template_bracket # If there are previous parent classes else: # - Get colon position if is_template and src_is_specialization: temp_pos = class_name_pos + len( class_name['short']) + len(add_template_bracket) else: temp_pos = class_name_pos + len(class_name['short']) colon_pos = temp_pos + original_file_content_nocomments[ temp_pos:newline_pos].find(':') # - Calculate insert position insert_pos = colon_pos + 1 # - Generate code add_code = ' public virtual ' + abstr_class_name['short'] if is_template == True: add_code += add_template_bracket add_code += ',' # - Register new code gb.new_code[original_file_name]['code_tuples'].append( (insert_pos, add_code)) # - Update added_parent dict added_parent.append(class_name['long'])