vm: Implement CALL_FUNCTION_VAR opcode (foo(*(1, 2, 3))).
This commit is contained in:
parent
48bdb21332
commit
55ca075cab
3
py/obj.h
3
py/obj.h
@ -422,6 +422,7 @@ mp_obj_t mp_obj_complex_binary_op(int op, mp_float_t lhs_real, mp_float_t lhs_im
|
||||
void mp_obj_tuple_get(mp_obj_t self_in, uint *len, mp_obj_t **items);
|
||||
void mp_obj_tuple_del(mp_obj_t self_in);
|
||||
machine_int_t mp_obj_tuple_hash(mp_obj_t self_in);
|
||||
mp_obj_t mp_obj_tuple_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args);
|
||||
|
||||
// list
|
||||
mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg);
|
||||
@ -485,7 +486,7 @@ typedef struct _mp_obj_static_class_method_t {
|
||||
void mp_seq_multiply(const void *items, uint item_sz, uint len, uint times, void *dest);
|
||||
bool m_seq_get_fast_slice_indexes(machine_uint_t len, mp_obj_t slice, machine_uint_t *begin, machine_uint_t *end);
|
||||
#define m_seq_copy(dest, src, len, item_t) memcpy(dest, src, len * sizeof(item_t))
|
||||
#define m_seq_cat(dest, src1, len1, src2, len2, item_t) { memcpy(dest, src1, len1 * sizeof(item_t)); memcpy(dest + len1, src2, len2 * sizeof(item_t)); }
|
||||
#define m_seq_cat(dest, src1, len1, src2, len2, item_t) { memcpy(dest, src1, (len1) * sizeof(item_t)); memcpy(dest + (len1), src2, (len2) * sizeof(item_t)); }
|
||||
bool mp_seq_cmp_bytes(int op, const byte *data1, uint len1, const byte *data2, uint len2);
|
||||
bool mp_seq_cmp_objs(int op, const mp_obj_t *items1, uint len1, const mp_obj_t *items2, uint len2);
|
||||
mp_obj_t mp_seq_index_obj(const mp_obj_t *items, uint len, uint n_args, const mp_obj_t *args);
|
||||
|
@ -30,7 +30,7 @@ void tuple_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_o
|
||||
print(env, ")");
|
||||
}
|
||||
|
||||
STATIC mp_obj_t tuple_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
|
||||
mp_obj_t mp_obj_tuple_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
|
||||
// TODO check n_kw == 0
|
||||
|
||||
switch (n_args) {
|
||||
@ -175,7 +175,7 @@ const mp_obj_type_t mp_type_tuple = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_tuple,
|
||||
.print = tuple_print,
|
||||
.make_new = tuple_make_new,
|
||||
.make_new = mp_obj_tuple_make_new,
|
||||
.unary_op = tuple_unary_op,
|
||||
.binary_op = tuple_binary_op,
|
||||
.getiter = tuple_getiter,
|
||||
|
28
py/vm.c
28
py/vm.c
@ -1,4 +1,5 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "nlr.h"
|
||||
@ -10,6 +11,7 @@
|
||||
#include "bc0.h"
|
||||
#include "bc.h"
|
||||
#include "objgenerator.h"
|
||||
#include "objtuple.h"
|
||||
|
||||
// Value stack grows up (this makes it incompatible with native C stack, but
|
||||
// makes sure that arguments to functions are in natural order arg1..argN
|
||||
@ -665,6 +667,32 @@ unwind_jump:
|
||||
SET_TOP(mp_call_function_n_kw(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1));
|
||||
break;
|
||||
|
||||
case MP_BC_CALL_FUNCTION_VAR: {
|
||||
DECODE_UINT;
|
||||
// unum & 0xff == n_positional
|
||||
// (unum >> 8) & 0xff == n_keyword
|
||||
// We have folowing stack layout here:
|
||||
// arg0 arg1 ... kw0 val0 kw1 val1 ... seq <- TOS
|
||||
// We need to splice seq after all positional args and before kwargs
|
||||
// TODO: optimize one day to avoid constructing new arg array? Will be hard.
|
||||
mp_obj_t seq = POP();
|
||||
int total_stack_args = (unum & 0xff) + ((unum >> 7) & 0x1fe);
|
||||
sp -= total_stack_args;
|
||||
|
||||
// Convert vararg sequence to tuple. Note that it can be arbitrary iterator.
|
||||
// This is null call for tuple, and TODO: we actually could optimize case of list.
|
||||
mp_obj_tuple_t *varargs = mp_obj_tuple_make_new(MP_OBJ_NULL, 1, 0, &seq);
|
||||
|
||||
int pos_args_len = (unum & 0xff) + varargs->len;
|
||||
mp_obj_t *args = m_new(mp_obj_t, total_stack_args + varargs->len);
|
||||
m_seq_cat(args, sp + 1, unum & 0xff, varargs->items, varargs->len, mp_obj_t);
|
||||
m_seq_copy(args + pos_args_len, sp + (unum & 0xff) + 1, ((unum >> 7) & 0x1fe), mp_obj_t);
|
||||
|
||||
SET_TOP(mp_call_function_n_kw(*sp, pos_args_len, (unum >> 8) & 0xff, args));
|
||||
m_del(mp_obj_t, args, total_stack_args + varargs->len);
|
||||
break;
|
||||
}
|
||||
|
||||
case MP_BC_CALL_METHOD:
|
||||
DECODE_UINT;
|
||||
// unum & 0xff == n_positional
|
||||
|
13
tests/basics/fun-callstar.py
Normal file
13
tests/basics/fun-callstar.py
Normal file
@ -0,0 +1,13 @@
|
||||
def foo(a, b, c):
|
||||
print(a, b, c)
|
||||
|
||||
foo(*(1, 2, 3))
|
||||
foo(1, *(2, 3))
|
||||
foo(1, 2, *(3,))
|
||||
foo(1, 2, 3, *())
|
||||
|
||||
# Another sequence type
|
||||
foo(1, 2, *[100])
|
||||
|
||||
# Iterator
|
||||
foo(*range(3))
|
Loading…
Reference in New Issue
Block a user