def rewrite_optional_args(func, env): """ Rewrite function application with missing arguments, which are supplied from defaults. def f(x, y=4): ... call(f, [x]) -> call(f, [x, const(4)]) """ from flypy import typeof def f(context, py_func, f_env, op): f, args = op.args # Add any potentially remaining values remaining = get_remaining_args(py_func, (None,) * len(args)) consts = [allocate_const(func, env, op, value, typeof(value)) for value in remaining] op.set_args([f, args + consts]) jitcallmap(f, func, env)
def rewrite_varargs(func, env): """ Rewrite function application with arguments that go in the varargs: def f(x, *args): ... call(f, [x, y, z]) -> call(f, [x, (y, z)]) """ b = Builder(func) caller = Caller(b, env['flypy.typing.context'], env) caller = Caller(b, env['flypy.typing.context'], env) call_flags = env['flypy.state.call_flags'] def f(context, py_func, f_env, op): f, args = op.args flags = call_flags.get(op, {}) if flags.get('varargs'): return # Retrieve any remaining arguments meant for *args flattened = flatargs(py_func, args, {}) if flattened.have_varargs: b.position_before(op) #print(py_func, flattened.varargs) # -- Build the tuple -- # result = caller.apply_constructor(EmptyTuple) for item in flattened.varargs: result = caller.apply_constructor(StaticTuple, args=[item, result]) # -- Patch callsite -- # args = list(flattened.positional) + [result] op.set_args([f, args]) jitcallmap(f, func, env)
def rewrite_optional_args(func, env): """ Rewrite function application with missing arguments, which are supplied from defaults. def f(x, y=4): ... call(f, [x]) -> call(f, [x, const(4)]) """ from flypy import typeof def f(context, py_func, f_env, op): f, args = op.args # Add any potentially remaining values remaining = get_remaining_args(py_func, (None, ) * len(args)) consts = [ allocate_const(func, env, op, value, typeof(value)) for value in remaining ] op.set_args([f, args + consts]) jitcallmap(f, func, env)
def rewrite_unpacking(func, env): """ Rewrite argument unpacking: f(x, *args) ^^^^^ temp = tuple(args) f(x, temp[0], temp[1]) """ from flypy.pipeline import phase b = Builder(func) caller = Caller(b, env['flypy.typing.context'], env) call_flags = env['flypy.state.call_flags'] 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]) jitcallmap(f, func, env)