Did I find the right examples for you? yes no

All Samples(2)  |  Call(2)  |  Derive(0)  |  Import(0)
Given a list args of arguments and a list of functions, choose one
to call which seems to be the "best" fit for this list of arguments.
This function is used, e.g., when deciding which overloaded method
to dispatch for C++ classes.

We first eliminate functions based on arity, and if only one
function has the correct arity, we return it. Otherwise, we weight
functions based on how much work must be done to convert the
arguments, with the following priorities:
  * identical types or pointers to identical types(more...)

        def best_match(args, functions, pos=None, env=None):
    """
    Given a list args of arguments and a list of functions, choose one
    to call which seems to be the "best" fit for this list of arguments.
    This function is used, e.g., when deciding which overloaded method
    to dispatch for C++ classes.

    We first eliminate functions based on arity, and if only one
    function has the correct arity, we return it. Otherwise, we weight
    functions based on how much work must be done to convert the
    arguments, with the following priorities:
      * identical types or pointers to identical types
      * promotions
      * non-Python types
    That is, we prefer functions where no arguments need converted,
    and failing that, functions where only promotions are required, and
    so on.

    If no function is deemed a good fit, or if two or more functions have
    the same weight, we return None (as there is no best match). If pos
    is not None, we also generate an error.
    """
    # TODO: args should be a list of types, not a list of Nodes.
    actual_nargs = len(args)

    candidates = []
    errors = []
    for func in functions:
        error_mesg = ""
        func_type = func.type
        if func_type.is_ptr:
            func_type = func_type.base_type
        # Check function type
        if not func_type.is_cfunction:
            if not func_type.is_error and pos is not None:
                error_mesg = "Calling non-function type '%s'" % func_type
            errors.append((func, error_mesg))
            continue
        # Check no. of args
        max_nargs = len(func_type.args)
        min_nargs = max_nargs - func_type.optional_arg_count
        if actual_nargs < min_nargs or \
            (not func_type.has_varargs and actual_nargs > max_nargs):
            if max_nargs == min_nargs and not func_type.has_varargs:
                expectation = max_nargs
            elif actual_nargs < min_nargs:
                expectation = "at least %s" % min_nargs
            else:
                expectation = "at most %s" % max_nargs
            error_mesg = "Call with wrong number of arguments (expected %s, got %s)" \
                         % (expectation, actual_nargs)
            errors.append((func, error_mesg))
            continue
        if func_type.templates:
            arg_types = [arg.type for arg in args]
            deductions = reduce(
                merge_template_deductions,
                [pattern.type.deduce_template_params(actual) for (pattern, actual) in zip(func_type.args, arg_types)],
                {})
            if deductions is None:
                errors.append((func, "Unable to deduce type parameters"))
            elif len(deductions) < len(func_type.templates):
                errors.append((func, "Unable to deduce type parameter %s" % (
                    ", ".join([param.name for param in set(func_type.templates) - set(deductions.keys())]))))
            else:
                type_list = [deductions[param] for param in func_type.templates]
                from Symtab import Entry
                specialization = Entry(
                    name = func.name + "[%s]" % ",".join([str(t) for t in type_list]),
                    cname = func.cname + "<%s>" % ",".join([t.declaration_code("") for t in type_list]),
                    type = func_type.specialize(deductions),
                    pos = func.pos)
                candidates.append((specialization, specialization.type))
        else:
            candidates.append((func, func_type))

    # Optimize the most common case of no overloading...
    if len(candidates) == 1:
        return candidates[0][0]
    elif len(candidates) == 0:
        if pos is not None:
            func, errmsg = errors[0]
            if len(errors) == 1 or [1 for func, e in errors if e == errmsg]:
                error(pos, errmsg)
            else:
                error(pos, "no suitable method found")
        return None

    possibilities = []
    bad_types = []
    needed_coercions = {}

    for index, (func, func_type) in enumerate(candidates):
        score = [0,0,0,0]
        for i in range(min(len(args), len(func_type.args))):
            src_type = args[i].type
            dst_type = func_type.args[i].type

            assignable = dst_type.assignable_from(src_type)

            # Now take care of normal string literals. So when you call a cdef
            # function that takes a char *, the coercion will mean that the
            # type will simply become bytes. We need to do this coercion
            # manually for overloaded and fused functions
            if not assignable and src_type.is_pyobject:
                if (src_type.is_builtin_type and src_type.name == 'str' and
                        dst_type.resolve() is c_char_ptr_type):
                    c_src_type = c_char_ptr_type
                else:
                    c_src_type = src_type.default_coerced_ctype()

                if c_src_type:
                    assignable = dst_type.assignable_from(c_src_type)
                    if assignable:
                        src_type = c_src_type
                        needed_coercions[func] = i, dst_type

            if assignable:
                if src_type == dst_type or dst_type.same_as(src_type):
                    pass # score 0
                elif func_type.is_strict_signature:
                    break # exact match requested but not found
                elif is_promotion(src_type, dst_type):
                    score[2] += 1
                elif ((src_type.is_int and dst_type.is_int) or
                      (src_type.is_float and dst_type.is_float)):
                    score[2] += abs(dst_type.rank + (not dst_type.signed) -
                                    (src_type.rank + (not src_type.signed))) + 1
                elif not src_type.is_pyobject:
                    score[1] += 1
                else:
                    score[0] += 1
            else:
                error_mesg = "Invalid conversion from '%s' to '%s'"%(src_type,
                                                                     dst_type)
                bad_types.append((func, error_mesg))
                break
        else:
            possibilities.append((score, index, func)) # so we can sort it

    if possibilities:
        possibilities.sort()
        if len(possibilities) > 1:
            score1 = possibilities[0][0]
            score2 = possibilities[1][0]
            if score1 == score2:
                if pos is not None:
                    error(pos, "ambiguous overloaded method")
                return None

        function = possibilities[0][-1]

        if function in needed_coercions and env:
            arg_i, coerce_to_type = needed_coercions[function]
            args[arg_i] = args[arg_i].coerce_to(coerce_to_type, env)

        return function

    if pos is not None:
        if len(bad_types) == 1:
            error(pos, bad_types[0][1])
        else:
            error(pos, "no suitable method found")

    return None
        


src/c/y/Cython-0.20.1/Cython/Compiler/Tests/TestSignatureMatching.py   Cython(Download)
    def assertMatches(self, expected_type, arg_types, functions):
        args = [ NameNode(None, type=arg_type) for arg_type in arg_types ]
        match = pt.best_match(args, functions)
        if expected_type is not None:
            self.assertNotEqual(None, match)

src/c/y/cython-HEAD/Cython/Compiler/Tests/TestSignatureMatching.py   cython(Download)
    def assertMatches(self, expected_type, arg_types, functions):
        args = [ NameNode(None, type=arg_type) for arg_type in arg_types ]
        match = pt.best_match(args, functions)
        if expected_type is not None:
            self.assertNotEqual(None, match)