Example #1
0
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)
Example #2
0
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))
Example #3
0
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'])