예제 #1
0
 def get_param_name(param):
     if type_manager.get_type(param.arg_type).has_default_value() \
        or param.default_value is not None:
         fmt = '?{}'
     else:
         fmt = '{}'
     return fmt.format(param.ocaml_name)
예제 #2
0
 def get_optioned_type(param):
     typ = type_manager.get_type(param.arg_type)
     if typ.has_default_value() or param.default_value is not None:
         return '?{}:{}'.format(param.ocaml_name,
                                typ.get_ocaml_param_type())
     else:
         return typ.get_ocaml_param_type()
예제 #3
0
 def get_param_type(param):
     typ = type_manager.get_type(param.arg_type)
     typ_name = check_enclosing_module(typ.get_ocaml_param_type())
     if typ.has_default_value() or param.default_value is not None:
         return '?{}:{}'.format(param.ocaml_name, typ_name)
     else:
         return typ_name
예제 #4
0
 def get_param_name(param):
     typ = type_manager.get_type(param.arg_type)
     if param.default_value is not None:
         return '?({} = {} ())' \
             .format(param.ocaml_name,
                     param.get_default_val_ocaml_name(enclosing_module,
                                                      function.ocaml_name))
     elif typ.has_default_value():
         return '?({} = {})'.format(param.ocaml_name,
                                    typ.get_default_value())
     else:
         return param.ocaml_name
예제 #5
0
 def is_optional_param(param):
     return type_manager.get_type(param.arg_type).has_default_value() \
         or param.default_value is not None
예제 #6
0
    def write_function(function, enclosing_module=None, mli_only=False):
        if not type_manager.has_type(function.return_type):
            print('Skipping {} because return type {} not in type map'.format(
                function.cpp_name, function.return_type))
            missing_types.add(function.return_type)
            return
        for param in function.parameters:
            if not type_manager.has_type(param.arg_type):
                print(
                    'Skipping {} because param type {} not in type map'.format(
                        function.cpp_name, param.arg_type))
                missing_types.add(param.arg_type)
                return

        def check_enclosing_module(name):
            # return name[len(enclosing_module) + 1:] if enclosing_module is not None \
            #    and name.startswith(enclosing_module + '.') else name
            return name.replace('{}.t'.format(enclosing_module), 't')

        def pointerize_type(typ, cpp=False):
            fmt = '{} *' if typ.must_pass_pointer(
            ) and not typ.is_pointer() else '{}'
            return fmt.format(typ.get_cpp_type() if cpp else typ.get_c_type())

        params_h = ', '.join([
            '{} {}'.format(
                pointerize_type(type_manager.get_type(param.arg_type)),
                param.name) for param in function.parameters
        ])
        stub = '{} {}({})'.format(
            pointerize_type(type_manager.get_type(function.return_type),
                            cpp=True), function.c_name, params_h)

        if not mli_only:
            opencv_h.write('{};'.format(stub))

        draw_in_out_mat_count = 0

        # Keep track of number of default parameters.
        # If all of the parameters have default values, then we need
        # to add a unit to the end so that we can used properly (OCaml
        # functions where the last parameter is optional cannot be applied
        # without supplying that parameter)
        total_default_params = 0

        # default parameters
        for param in function.parameters:
            arg_type = type_manager.get_type(param.arg_type)
            draw_in_out_mat_count += arg_type.is_draw_function()

            if param.default_value is not None:
                c_name = param.get_default_val_c_name(enclosing_module,
                                                      function.c_name)
                ocaml_name = param.get_default_val_ocaml_name(
                    enclosing_module, function.ocaml_name)

                cpp_type = arg_type.get_cpp_type()
                pointerized_type = pointerize_type(arg_type, cpp=True)

                # There are screwy things with autoboxing rules and whatnot,
                # so the easiest thing for us to do here is put the default
                # value as a default argument in a helper function and then
                # call that function - that way it is the same syntactic
                # class as the header file from which it is pulled.

                opencv_h.write('{} {}();'.format(pointerized_type, c_name))

                opencv_cpp.write('{} _{}({} v = {}) {{'.format(
                    cpp_type, c_name, cpp_type, param.default_value))
                opencv_cpp.indent()
                opencv_cpp.write('return v;')
                opencv_cpp.unindent()
                opencv_cpp.write('}')

                opencv_cpp.write('{} {}() {{'.format(pointerized_type, c_name))
                opencv_cpp.indent()
                if arg_type.must_pass_pointer() and not arg_type.is_pointer():
                    opencv_cpp.write('return new {}(_{}());'.format(
                        cpp_type, c_name))
                else:
                    opencv_cpp.write('return _{}();'.format(c_name))
                opencv_cpp.unindent()
                opencv_cpp.write('}')

                opencv_ml.write('let {} ='.format(ocaml_name))
                opencv_ml.indent()
                opencv_ml.write(
                    'let f = foreign "{}" (void @-> returning ({})) in'.format(
                        c_name, arg_type.get_ctypes_value()))
                opencv_ml.write('fun () -> let v = f () in {}'.format(
                    arg_type.ctypes_to_ocaml('v')))
                opencv_ml.unindent()

                total_default_params += 1
            elif type_manager.get_type(param.arg_type).has_default_value():
                total_default_params += 1

        def pointerize_value(typ, val):
            fmt = '*({})' if typ.must_pass_pointer(
            ) and not typ.is_pointer() else '{}'
            return fmt.format(typ.c_to_cpp(val))

        def depointerize_value(typ, val):
            pass

        params_cpp = ', '.join([
            pointerize_value(type_manager.get_type(param.arg_type), param.name)
            for param in function.c_params
        ])
        value = '{}({})'.format(function.cpp_name, params_cpp)
        ret_type = type_manager.get_type(function.return_type)

        if function.return_type == 'void':
            invoke_fmt = '{};'
        elif ret_type.must_pass_pointer() and not ret_type.is_pointer():
            invoke_fmt = 'return new {} ({{}});'.format(
                ret_type.get_cpp_type())
        else:
            invoke_fmt = 'return {};'

        if not mli_only:
            opencv_cpp.write('{} {{'.format(stub))
            opencv_cpp.indent()
            opencv_cpp.write(invoke_fmt.format(ret_type.cpp_to_c(value)))
            opencv_cpp.unindent()
            opencv_cpp.write('}')

        def get_param_name(param):
            typ = type_manager.get_type(param.arg_type)
            if param.default_value is not None:
                return '?({} = {} ())' \
                    .format(param.ocaml_name,
                            param.get_default_val_ocaml_name(enclosing_module,
                                                             function.ocaml_name))
            elif typ.has_default_value():
                return '?({} = {})'.format(param.ocaml_name,
                                           typ.get_default_value())
            else:
                return param.ocaml_name

        def is_optional_param(param):
            return type_manager.get_type(param.arg_type).has_default_value() \
                or param.default_value is not None

        # move (float) optional params to the front to prevent un-erasable optional arguments
        # (basically optional arguments can't be the last parameter in OCaml)
        floated_params = list(
            sorted(function.parameters,
                   key=lambda param: not is_optional_param(param)))
        optional_param_count = len(
            list(filter(is_optional_param, function.parameters)))

        # add extra parameters for optionally disabling cloning of cloneable params
        inserted_param_count = 0
        for i, param in enumerate(floated_params.copy()):
            if type_manager.get_type(param.arg_type).is_cloneable():
                floated_params.insert(
                    i + inserted_param_count,
                    Parameter('', '{}_recycle'.format(param.ocaml_name),
                              '__recycle_flag', None, False))
                inserted_param_count += 1

        floated_param_names = list(map(get_param_name, floated_params))
        param_names_prime = [
            "{}'".format(param.ocaml_name) for param in function.parameters
        ]
        if len(function.parameters) <= total_default_params:
            floated_param_names.append('()')
        if len(function.parameters) == 0:
            param_names_prime.append('()')

        ctypes_sig_list = [
            type_manager.get_type(param.arg_type).get_ctypes_value()
            for param in function.parameters
        ]
        if len(ctypes_sig_list) == 0:
            ctypes_sig_list.append('void')
        ctypes_sig_list.append('returning ({})'.format(
            type_manager.get_type(function.return_type).get_ctypes_value()))
        ctypes_sig = ' @-> '.join(ctypes_sig_list)

        returned_params = list(
            filter(
                lambda param: type_manager.get_type(param.arg_type).
                return_value('') is not None, function.parameters))
        returned_values = list(
            map(
                lambda param: type_manager.get_type(param.arg_type).
                return_value(param.ocaml_name), returned_params))
        returned_types = list(
            map(
                lambda param: check_enclosing_module(
                    type_manager.get_type(param.arg_type).get_ocaml_type()),
                returned_params))
        erase_return_unit = function.return_type == 'void' and len(
            returned_params) > 0
        if not erase_return_unit:
            returned_values.append('res')
            returned_types.append(
                check_enclosing_module(
                    type_manager.get_type(
                        function.return_type).get_ocaml_type()))

        is_draw_function = draw_in_out_mat_count == 1 \
            and function.return_type == 'void' \
            and len(returned_params) == 0 \
            and optional_param_count < len(floated_params) - 1

        if not mli_only:
            opencv_ml.write('let __{} = foreign "{}" ({})'.format(
                function.ocaml_name, function.c_name, ctypes_sig))
            opencv_ml.write('let {} {} ='.format(
                function.ocaml_name, ' '.join(floated_param_names)))
            opencv_ml.indent()
            for param in function.parameters:
                param_type = type_manager.get_type(param.arg_type)
                if param_type.is_cloneable():
                    fmt = "let {0} = if {0}_recycle then {0} else Cvdata.clone {0} in let {{}}' = {{}} in" \
                        .format(param.ocaml_name)
                else:
                    fmt = "let {}' = {} in"
                opencv_ml.write(
                    fmt.format(param.ocaml_name,
                               param_type.ocaml_to_ctypes(param.ocaml_name)))
            opencv_ml.write('let {} = {} in'.format(
                '_' if erase_return_unit else 'res',
                type_manager.get_type(function.return_type).ctypes_to_ocaml(
                    '__{} {}'.format(function.ocaml_name,
                                     ' '.join(param_names_prime)))))
            for param in function.parameters:
                post_func = type_manager.get_type(param.arg_type) \
                    .ocaml_to_ctypes(param.ocaml_name).post
                if post_func is not None:
                    post = post_func(param.ocaml_name,
                                     "{}'".format(param.ocaml_name))
                    opencv_ml.write('{};'.format(post))
            opencv_ml.write(', '.join(returned_values))
            opencv_ml.unindent()

        def get_param_type(param):
            typ = type_manager.get_type(param.arg_type)
            typ_name = check_enclosing_module(typ.get_ocaml_param_type())
            if typ.has_default_value() or param.default_value is not None:
                return '?{}:{}'.format(param.ocaml_name, typ_name)
            else:
                return typ_name

        ocaml_sig_list = list(map(get_param_type, floated_params))
        if 0 < len(function.parameters) <= total_default_params:
            ocaml_sig_list.append('unit')
        if len(ocaml_sig_list) == 0:
            ocaml_sig_list.append('unit')
        ocaml_sig_list.append(' * '.join(returned_types))
        ocaml_sig = ' -> '.join(ocaml_sig_list)

        opencv_mli.write()

        opencv_mli.write('(**')
        opencv_mli.write(
            sanitize_docs(
                function.docs,
                name=function.ocaml_name,
                params=floated_params,
                param_map=function.param_map,
                extra_unit=len(function.parameters) <= total_default_params))
        opencv_mli.write('*)')

        opencv_mli.write('val {} : {}'.format(function.ocaml_name, ocaml_sig))

        if is_draw_function:

            def is_draw_function_param(param):
                return type_manager.get_type(param.arg_type).is_draw_function()

            filtered_params = list(
                filter(lambda x: not is_draw_function_param(x),
                       floated_params))
            draw_function_param = list(
                filter(is_draw_function_param, floated_params))[0]
            draw_functions.append((function, floated_params, filtered_params,
                                   draw_function_param, enclosing_module))
예제 #7
0
 def get_val_type(self):
     return type_manager.get_type(self.val_type_cpp_name)
예제 #8
0
 def is_draw_function_param(param):
     return type_manager.get_type(param.arg_type).is_draw_function()