Ejemplo n.º 1
0
def handle_unpacking_varargs(func, py_func, argtypes):
    """
    Handle unpacking of varargs:

        f(10, *args)
              ^^^^^

    We assume that unpacking consumes all positional arguments, i.e. we
    do not support shenanigans such as the following:

        def f(a, b=2, c=3):
            ...

        f(1, *(4,))

    To support that we'd have to call a wrapper function, that takes a tuple
    and supplies missing defaults dynamically.
    """
    argspec = inspect.getargspec(py_func)

    tuple_type = argtypes[-1]
    argtypes   = argtypes[:-1]
    missing  = compute_missing(py_func, argtypes)

    # Extract remaining argument types
    remaining = extract_tuple_eltypes(tuple_type, missing)
    if len(remaining) > missing and not argspec.varargs:
        raise TypeError(
            "Too many arguments supplied to function %s: %s %s %s" % (
                py_func, argtypes, remaining, missing))

    return tuple(argtypes) + tuple(remaining)
Ejemplo n.º 2
0
def handle_unpacking_varargs(func, py_func, argtypes):
    """
    Handle unpacking of varargs:

        f(10, *args)
              ^^^^^

    We assume that unpacking consumes all positional arguments, i.e. we
    do not support shenanigans such as the following:

        def f(a, b=2, c=3):
            ...

        f(1, *(4,))

    To support that we'd have to call a wrapper function, that takes a tuple
    and supplies missing defaults dynamically.
    """
    argspec = inspect.getargspec(py_func)

    tuple_type = argtypes[-1]
    argtypes = argtypes[:-1]
    missing = compute_missing(py_func, argtypes)

    # Extract remaining argument types
    remaining = extract_tuple_eltypes(tuple_type, missing)
    if len(remaining) > missing and not argspec.varargs:
        raise TypeError(
            "Too many arguments supplied to function %s: %s %s %s" %
            (py_func, argtypes, remaining, missing))

    return tuple(argtypes) + tuple(remaining)
Ejemplo n.º 3
0
    def f(context, py_func, f_env, op):
        f, args = op.args
        flags = call_flags.get(op, {})

        if not flags.get('varargs'):
            return

        # Unpack positional and varargs argument
        # For f(x, *args): positional = [x], varargs = args
        positional, varargs = args[:-1], args[-1]
        varargs_type = context[varargs]

        # Missing number of positional arguments (int)
        missing = compute_missing(py_func, positional)

        # Types in the tuple, may be heterogeneous
        eltypes = extract_tuple_eltypes(varargs_type, missing)

        # Now supply the missing positional arguments
        b.position_before(op)
        for i, argty in zip(range(missing), eltypes):
            idx = OConst(i)
            context[idx] = types.int32

            #hd = b.getfield(ptypes.Opaque, varargs, 'hd')
            #tl = b.getfield(ptypes.Opaque, varargs, 'tl')

            positional_arg = caller.call(phase.typing,
                                         primitives.getitem,
                                         [varargs, idx])
            positional.append(positional_arg)

        # TODO: For GenericTuple unpacking, assure that
        #       len(remaining_tuple) == missing

        if len(eltypes) > missing:
            # In case we have more element types than positional parameters,
            # we must have a function that takes varargs, e.g.
            #
            #   def f(x, y, *args):
            #       ...
            #
            # That we call as follows (for example):
            #
            #       f(x, *args)
            idx = OConst(missing)
            context[idx] = types.int32

            argstup = caller.call(phase.typing,
                                  slicetuple,
                                  [varargs, idx])
            positional.append(argstup)

        # Update with new positional arguments
        op.set_args([f, positional])
Ejemplo n.º 4
0
    def f(context, py_func, f_env, op):
        f, args = op.args
        flags = call_flags.get(op, {})

        if not flags.get('varargs'):
            return

        # Unpack positional and varargs argument
        # For f(x, *args): positional = [x], varargs = args
        positional, varargs = args[:-1], args[-1]
        varargs_type = context[varargs]

        # Missing number of positional arguments (int)
        missing = compute_missing(py_func, positional)

        # Types in the tuple, may be heterogeneous
        eltypes = extract_tuple_eltypes(varargs_type, missing)

        # Now supply the missing positional arguments
        b.position_before(op)
        for i, argty in zip(range(missing), eltypes):
            idx = OConst(i)
            context[idx] = types.int32

            #hd = b.getfield(ptypes.Opaque, varargs, 'hd')
            #tl = b.getfield(ptypes.Opaque, varargs, 'tl')

            positional_arg = caller.call(phase.typing, primitives.getitem,
                                         [varargs, idx])
            positional.append(positional_arg)

        # TODO: For GenericTuple unpacking, assure that
        #       len(remaining_tuple) == missing

        if len(eltypes) > missing:
            # In case we have more element types than positional parameters,
            # we must have a function that takes varargs, e.g.
            #
            #   def f(x, y, *args):
            #       ...
            #
            # That we call as follows (for example):
            #
            #       f(x, *args)
            idx = OConst(missing)
            context[idx] = types.int32

            argstup = caller.call(phase.typing, slicetuple, [varargs, idx])
            positional.append(argstup)

        # Update with new positional arguments
        op.set_args([f, positional])