Commit 20006dbb authored by Damien George's avatar Damien George
Browse files

Make VM stack grow upwards, and so no reversed args arrays.

Change state layout in VM so the stack starts at state[0] and grows
upwards.  Locals are at the top end of the state and number downwards.
This cleans up a lot of the interface connecting the VM to C: now all
functions that take an array of Micro Python objects are in order (ie no
longer in reverse).

Also clean up C API with keyword arguments (call_n and call_n_kw
replaced with single call method that takes keyword arguments).  And now
make_new takes keyword arguments.

emitnative.c has not yet been changed to comply with the new order of
stack layout.
parent 8655065f
...@@ -45,12 +45,11 @@ static mp_obj_t mp_builtin___build_class__(int n_args, const mp_obj_t *args) { ...@@ -45,12 +45,11 @@ static mp_obj_t mp_builtin___build_class__(int n_args, const mp_obj_t *args) {
// TODO do proper metaclass resolution for multiple base objects // TODO do proper metaclass resolution for multiple base objects
// create the new class using a call to the meta object // create the new class using a call to the meta object
// (arguments must be backwards in the array)
mp_obj_t meta_args[3]; mp_obj_t meta_args[3];
meta_args[2] = args[1]; // class name meta_args[0] = args[1]; // class name
meta_args[1] = mp_obj_new_tuple(n_args - 2, args + 2); // tuple of bases meta_args[1] = mp_obj_new_tuple(n_args - 2, args + 2); // tuple of bases
meta_args[0] = class_locals; // dict of members meta_args[2] = class_locals; // dict of members
mp_obj_t new_class = rt_call_function_n(meta, 3, meta_args); mp_obj_t new_class = rt_call_function_n_kw(meta, 3, 0, meta_args);
// store into cell if neede // store into cell if neede
if (cell != mp_const_none) { if (cell != mp_const_none) {
...@@ -153,10 +152,10 @@ static mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) { ...@@ -153,10 +152,10 @@ static mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) {
if (MP_OBJ_IS_SMALL_INT(o1_in) && MP_OBJ_IS_SMALL_INT(o2_in)) { if (MP_OBJ_IS_SMALL_INT(o1_in) && MP_OBJ_IS_SMALL_INT(o2_in)) {
mp_small_int_t i1 = MP_OBJ_SMALL_INT_VALUE(o1_in); mp_small_int_t i1 = MP_OBJ_SMALL_INT_VALUE(o1_in);
mp_small_int_t i2 = MP_OBJ_SMALL_INT_VALUE(o2_in); mp_small_int_t i2 = MP_OBJ_SMALL_INT_VALUE(o2_in);
mp_obj_t revs_args[2]; mp_obj_t args[2];
revs_args[1] = MP_OBJ_NEW_SMALL_INT(i1 / i2); args[0] = MP_OBJ_NEW_SMALL_INT(i1 / i2);
revs_args[0] = MP_OBJ_NEW_SMALL_INT(i1 % i2); args[1] = MP_OBJ_NEW_SMALL_INT(i1 % i2);
return rt_build_tuple(2, revs_args); return rt_build_tuple(2, args);
} else { } else {
nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", mp_obj_get_type_str(o1_in), mp_obj_get_type_str(o2_in))); nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", mp_obj_get_type_str(o1_in), mp_obj_get_type_str(o2_in)));
} }
...@@ -327,20 +326,14 @@ static mp_obj_t mp_builtin_sum(int n_args, const mp_obj_t *args) { ...@@ -327,20 +326,14 @@ static mp_obj_t mp_builtin_sum(int n_args, const mp_obj_t *args) {
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj, 1, 2, mp_builtin_sum); MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj, 1, 2, mp_builtin_sum);
static mp_obj_t mp_builtin_sorted(mp_obj_t args, mp_map_t *kwargs) { static mp_obj_t mp_builtin_sorted(uint n_args, const mp_obj_t *args, mp_map_t *kwargs) {
mp_obj_t *args_items = NULL; assert(n_args >= 1);
uint args_len = 0; if (n_args > 1) {
assert(MP_OBJ_IS_TYPE(args, &tuple_type));
mp_obj_tuple_get(args, &args_len, &args_items);
assert(args_len >= 1);
if (args_len > 1) {
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError,
"must use keyword argument for key function")); "must use keyword argument for key function"));
} }
mp_obj_t self = list_type.make_new((mp_obj_t)&list_type, 1, args_items); mp_obj_t self = list_type.make_new((mp_obj_t)&list_type, 1, 0, args);
mp_obj_t new_args = rt_build_tuple(1, &self); mp_obj_list_sort(1, &self, kwargs);
mp_obj_list_sort(new_args, kwargs);
return self; return self;
} }
......
...@@ -1156,7 +1156,8 @@ static void emit_native_call_function(emit_t *emit, int n_positional, int n_keyw ...@@ -1156,7 +1156,8 @@ static void emit_native_call_function(emit_t *emit, int n_positional, int n_keyw
vtype_kind_t vtype_fun; vtype_kind_t vtype_fun;
emit_pre_pop_reg(emit, &vtype_fun, REG_ARG_1); // the function emit_pre_pop_reg(emit, &vtype_fun, REG_ARG_1); // the function
assert(vtype_fun == VTYPE_PYOBJ); assert(vtype_fun == VTYPE_PYOBJ);
emit_call_with_imm_arg(emit, RT_F_CALL_FUNCTION_N, rt_call_function_n, n_positional, REG_ARG_2); // XXX rt_call_function_n now merged with rt_call_function_n_kw
//emit_call_with_imm_arg(emit, RT_F_CALL_FUNCTION_N, rt_call_function_n, n_positional, REG_ARG_2);
//} //}
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
} }
...@@ -1181,7 +1182,8 @@ static void emit_native_call_method(emit_t *emit, int n_positional, int n_keywor ...@@ -1181,7 +1182,8 @@ static void emit_native_call_method(emit_t *emit, int n_positional, int n_keywor
*/ */
emit_pre(emit); emit_pre(emit);
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_positional + 2); // pointer to items in reverse order, including meth and self emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, n_positional + 2); // pointer to items in reverse order, including meth and self
emit_call_with_imm_arg(emit, RT_F_CALL_METHOD_N, rt_call_method_n, n_positional, REG_ARG_1); // XXX rt_call_method_n now merged with rt_call_method_n_kw
//emit_call_with_imm_arg(emit, RT_F_CALL_METHOD_N, rt_call_method_n, n_positional, REG_ARG_1);
//} //}
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
} }
......
...@@ -63,7 +63,7 @@ bool mp_obj_is_callable(mp_obj_t o_in) { ...@@ -63,7 +63,7 @@ bool mp_obj_is_callable(mp_obj_t o_in) {
return false; return false;
} else { } else {
mp_obj_base_t *o = o_in; mp_obj_base_t *o = o_in;
return o->type->call_n != NULL; return o->type->call != NULL;
} }
} }
......
...@@ -83,19 +83,18 @@ typedef mp_obj_t (*mp_fun_2_t)(mp_obj_t, mp_obj_t); ...@@ -83,19 +83,18 @@ typedef mp_obj_t (*mp_fun_2_t)(mp_obj_t, mp_obj_t);
typedef mp_obj_t (*mp_fun_3_t)(mp_obj_t, mp_obj_t, mp_obj_t); typedef mp_obj_t (*mp_fun_3_t)(mp_obj_t, mp_obj_t, mp_obj_t);
typedef mp_obj_t (*mp_fun_t)(void); typedef mp_obj_t (*mp_fun_t)(void);
typedef mp_obj_t (*mp_fun_var_t)(int n, const mp_obj_t *); typedef mp_obj_t (*mp_fun_var_t)(int n, const mp_obj_t *);
typedef mp_obj_t (*mp_fun_kw_t)(mp_obj_t, struct _mp_map_t*); typedef mp_obj_t (*mp_fun_kw_t)(uint n, const mp_obj_t *, struct _mp_map_t *);
typedef enum { typedef enum {
PRINT_STR, PRINT_REPR PRINT_STR, PRINT_REPR
} mp_print_kind_t; } mp_print_kind_t;
typedef void (*mp_print_fun_t)(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o, mp_print_kind_t kind); typedef void (*mp_print_fun_t)(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o, mp_print_kind_t kind);
typedef mp_obj_t (*mp_make_new_fun_t)(mp_obj_t type_in, int n_args, const mp_obj_t *args); // args are in reverse order in the array typedef mp_obj_t (*mp_make_new_fun_t)(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args);
typedef mp_obj_t (*mp_call_n_fun_t)(mp_obj_t fun, int n_args, const mp_obj_t *args); // args are in reverse order in the array typedef mp_obj_t (*mp_call_fun_t)(mp_obj_t fun, uint n_args, uint n_kw, const mp_obj_t *args);
typedef mp_obj_t (*mp_call_n_kw_fun_t)(mp_obj_t fun, int n_args, int n_kw, const mp_obj_t *args); // args are in reverse order in the array
typedef mp_obj_t (*mp_unary_op_fun_t)(int op, mp_obj_t); typedef mp_obj_t (*mp_unary_op_fun_t)(int op, mp_obj_t);
typedef mp_obj_t (*mp_binary_op_fun_t)(int op, mp_obj_t, mp_obj_t); typedef mp_obj_t (*mp_binary_op_fun_t)(int op, mp_obj_t, mp_obj_t);
typedef void (*mp_load_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t *dest); // for fail, do nothing; for attr, dest[1] = value; for method, dest[0] = self, dest[1] = method typedef void (*mp_load_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t *dest); // for fail, do nothing; for attr, dest[0] = value; for method, dest[0] = method, dest[1] = self
typedef bool (*mp_store_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t value); // return true if store succeeded typedef bool (*mp_store_attr_fun_t)(mp_obj_t self_in, qstr attr, mp_obj_t value); // return true if store succeeded
typedef struct _mp_method_t { typedef struct _mp_method_t {
...@@ -144,8 +143,7 @@ struct _mp_obj_type_t { ...@@ -144,8 +143,7 @@ struct _mp_obj_type_t {
mp_print_fun_t print; mp_print_fun_t print;
mp_make_new_fun_t make_new; // to make an instance of the type mp_make_new_fun_t make_new; // to make an instance of the type
mp_call_n_fun_t call_n; mp_call_fun_t call;
mp_call_n_kw_fun_t call_n_kw;
mp_unary_op_fun_t unary_op; // can return NULL if op not supported mp_unary_op_fun_t unary_op; // can return NULL if op not supported
mp_binary_op_fun_t binary_op; // can return NULL if op not supported mp_binary_op_fun_t binary_op; // can return NULL if op not supported
...@@ -222,13 +220,11 @@ mp_obj_t mp_obj_new_gen_wrap(uint n_locals, uint n_stack, mp_obj_t fun); ...@@ -222,13 +220,11 @@ mp_obj_t mp_obj_new_gen_wrap(uint n_locals, uint n_stack, mp_obj_t fun);
mp_obj_t mp_obj_new_gen_instance(const byte *bytecode, uint n_state, int n_args, const mp_obj_t *args); mp_obj_t mp_obj_new_gen_instance(const byte *bytecode, uint n_state, int n_args, const mp_obj_t *args);
mp_obj_t mp_obj_new_closure(mp_obj_t fun, mp_obj_t closure_tuple); mp_obj_t mp_obj_new_closure(mp_obj_t fun, mp_obj_t closure_tuple);
mp_obj_t mp_obj_new_tuple(uint n, const mp_obj_t *items); mp_obj_t mp_obj_new_tuple(uint n, const mp_obj_t *items);
mp_obj_t mp_obj_new_tuple_reverse(uint n, const mp_obj_t *items);
mp_obj_t mp_obj_new_list(uint n, mp_obj_t *items); mp_obj_t mp_obj_new_list(uint n, mp_obj_t *items);
mp_obj_t mp_obj_new_list_reverse(uint n, mp_obj_t *items);
mp_obj_t mp_obj_new_dict(int n_args); mp_obj_t mp_obj_new_dict(int n_args);
mp_obj_t mp_obj_new_set(int n_args, mp_obj_t *items); mp_obj_t mp_obj_new_set(int n_args, mp_obj_t *items);
mp_obj_t mp_obj_new_slice(mp_obj_t start, mp_obj_t stop, mp_obj_t step); mp_obj_t mp_obj_new_slice(mp_obj_t start, mp_obj_t stop, mp_obj_t step);
mp_obj_t mp_obj_new_bound_meth(mp_obj_t self, mp_obj_t meth); mp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self);
mp_obj_t mp_obj_new_module(qstr module_name); mp_obj_t mp_obj_new_module(qstr module_name);
mp_obj_t mp_obj_get_type(mp_obj_t o_in); mp_obj_t mp_obj_get_type(mp_obj_t o_in);
...@@ -296,7 +292,7 @@ extern const mp_obj_type_t list_type; ...@@ -296,7 +292,7 @@ extern const mp_obj_type_t list_type;
mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg); mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg);
void mp_obj_list_get(mp_obj_t self_in, uint *len, mp_obj_t **items); void mp_obj_list_get(mp_obj_t self_in, uint *len, mp_obj_t **items);
void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value); void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value);
mp_obj_t mp_obj_list_sort(mp_obj_t args, struct _mp_map_t *kwargs); mp_obj_t mp_obj_list_sort(uint n_args, const mp_obj_t *args, struct _mp_map_t *kwargs);
// map (the python builtin, not the dict implementation detail) // map (the python builtin, not the dict implementation detail)
extern const mp_obj_type_t map_type; extern const mp_obj_type_t map_type;
......
...@@ -22,8 +22,9 @@ static void bool_print(void (*print)(void *env, const char *fmt, ...), void *env ...@@ -22,8 +22,9 @@ static void bool_print(void (*print)(void *env, const char *fmt, ...), void *env
} }
} }
// args are reverse in the array static mp_obj_t bool_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
static mp_obj_t bool_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) { // TODO check n_kw == 0
switch (n_args) { switch (n_args) {
case 0: return mp_const_false; case 0: return mp_const_false;
case 1: if (rt_is_true(args[0])) { return mp_const_true; } else { return mp_const_false; } case 1: if (rt_is_true(args[0])) { return mp_const_true; } else { return mp_const_false; }
......
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdlib.h>
#include <string.h>
#include <assert.h> #include <assert.h>
#include "nlr.h" #include "nlr.h"
...@@ -14,32 +15,36 @@ typedef struct _mp_obj_bound_meth_t { ...@@ -14,32 +15,36 @@ typedef struct _mp_obj_bound_meth_t {
mp_obj_t self; mp_obj_t self;
} mp_obj_bound_meth_t; } mp_obj_bound_meth_t;
// args are in reverse order in the array mp_obj_t bound_meth_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
mp_obj_t bound_meth_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
mp_obj_bound_meth_t *self = self_in; mp_obj_bound_meth_t *self = self_in;
if (n_args == 0) { // need to insert self->self before all other args and then call self->meth
return rt_call_function_n(self->meth, 1, &self->self);
} else if (n_args == 1) { int n_total = n_args + 2 * n_kw;
mp_obj_t args2[2]; if (n_total <= 4) {
args2[1] = self->self; // use stack to allocate temporary args array
args2[0] = args[0]; mp_obj_t args2[5];
return rt_call_function_n(self->meth, 2, args2); args2[0] = self->self;
memcpy(args2 + 1, args, n_total * sizeof(mp_obj_t));
return rt_call_function_n_kw(self->meth, n_args + 1, n_kw, &args2[0]);
} else { } else {
// TODO not implemented // use heap to allocate temporary args array
assert(0); mp_obj_t *args2 = m_new(mp_obj_t, 1 + n_total);
return mp_const_none; args2[0] = self->self;
//return rt_call_function_2(self->meth, n_args + 1, self->self + args); memcpy(args2 + 1, args, n_total * sizeof(mp_obj_t));
mp_obj_t res = rt_call_function_n_kw(self->meth, n_args + 1, n_kw, &args2[0]);
m_del(mp_obj_t, args2, 1 + n_total);
return res;
} }
} }
const mp_obj_type_t bound_meth_type = { const mp_obj_type_t bound_meth_type = {
{ &mp_const_type }, { &mp_const_type },
"bound_method", "bound_method",
.call_n = bound_meth_call_n, .call = bound_meth_call,
}; };
mp_obj_t mp_obj_new_bound_meth(mp_obj_t self, mp_obj_t meth) { mp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self) {
mp_obj_bound_meth_t *o = m_new_obj(mp_obj_bound_meth_t); mp_obj_bound_meth_t *o = m_new_obj(mp_obj_bound_meth_t);
o->base.type = &bound_meth_type; o->base.type = &bound_meth_type;
o->meth = meth; o->meth = meth;
......
...@@ -16,26 +16,33 @@ typedef struct _mp_obj_closure_t { ...@@ -16,26 +16,33 @@ typedef struct _mp_obj_closure_t {
mp_obj_t *closed; mp_obj_t *closed;
} mp_obj_closure_t; } mp_obj_closure_t;
// args are in reverse order in the array mp_obj_t closure_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
mp_obj_t closure_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
mp_obj_closure_t *self = self_in; mp_obj_closure_t *self = self_in;
// concatenate args and closed-over-vars, in reverse order // need to concatenate closed-over-vars and args
// TODO perhaps cache this array so we don't need to create it each time we are called
mp_obj_t *args2 = m_new(mp_obj_t, self->n_closed + n_args);
memcpy(args2, args, n_args * sizeof(mp_obj_t));
for (int i = 0; i < self->n_closed; i++) {
args2[n_args + i] = self->closed[self->n_closed - 1 - i];
}
// call the function with the new vars array int n_total = self->n_closed + n_args + 2 * n_kw;
return rt_call_function_n(self->fun, n_args + self->n_closed, args2); if (n_total <= 5) {
// use stack to allocate temporary args array
mp_obj_t args2[5];
memcpy(args2, self->closed, self->n_closed * sizeof(mp_obj_t));
memcpy(args2 + self->n_closed, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t));
return rt_call_function_n_kw(self->fun, self->n_closed + n_args, n_kw, args2);
} else {
// use heap to allocate temporary args array
mp_obj_t *args2 = m_new(mp_obj_t, n_total);
memcpy(args2, self->closed, self->n_closed * sizeof(mp_obj_t));
memcpy(args2 + self->n_closed, args, (n_args + 2 * n_kw) * sizeof(mp_obj_t));
mp_obj_t res = rt_call_function_n_kw(self->fun, self->n_closed + n_args, n_kw, args2);
m_del(mp_obj_t, args2, n_total);
return res;
}
} }
const mp_obj_type_t closure_type = { const mp_obj_type_t closure_type = {
{ &mp_const_type }, { &mp_const_type },
"closure", "closure",
.call_n = closure_call_n, .call = closure_call,
}; };
mp_obj_t mp_obj_new_closure(mp_obj_t fun, mp_obj_t closure_tuple) { mp_obj_t mp_obj_new_closure(mp_obj_t fun, mp_obj_t closure_tuple) {
......
...@@ -30,8 +30,9 @@ void complex_print(void (*print)(void *env, const char *fmt, ...), void *env, mp ...@@ -30,8 +30,9 @@ void complex_print(void (*print)(void *env, const char *fmt, ...), void *env, mp
} }
} }
// args are reverse in the array static mp_obj_t complex_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
static mp_obj_t complex_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) { // TODO check n_kw == 0
switch (n_args) { switch (n_args) {
case 0: case 0:
return mp_obj_new_complex(0, 0); return mp_obj_new_complex(0, 0);
...@@ -47,19 +48,19 @@ static mp_obj_t complex_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *a ...@@ -47,19 +48,19 @@ static mp_obj_t complex_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *a
case 2: case 2:
{ {
mp_float_t real, imag; mp_float_t real, imag;
if (MP_OBJ_IS_TYPE(args[1], &complex_type)) { if (MP_OBJ_IS_TYPE(args[0], &complex_type)) {
mp_obj_complex_get(args[1], &real, &imag); mp_obj_complex_get(args[0], &real, &imag);
} else { } else {
real = mp_obj_get_float(args[1]); real = mp_obj_get_float(args[0]);
imag = 0; imag = 0;
} }
if (MP_OBJ_IS_TYPE(args[0], &complex_type)) { if (MP_OBJ_IS_TYPE(args[1], &complex_type)) {
mp_float_t real2, imag2; mp_float_t real2, imag2;
mp_obj_complex_get(args[0], &real2, &imag2); mp_obj_complex_get(args[1], &real2, &imag2);
real -= imag2; real -= imag2;
imag += real2; imag += real2;
} else { } else {
imag += mp_obj_get_float(args[0]); imag += mp_obj_get_float(args[1]);
} }
return mp_obj_new_complex(real, imag); return mp_obj_new_complex(real, imag);
} }
......
...@@ -38,8 +38,7 @@ static void dict_print(void (*print)(void *env, const char *fmt, ...), void *env ...@@ -38,8 +38,7 @@ static void dict_print(void (*print)(void *env, const char *fmt, ...), void *env
print(env, "}"); print(env, "}");
} }
// args are reverse in the array static mp_obj_t dict_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
static mp_obj_t dict_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
// TODO create from an iterable! // TODO create from an iterable!
return rt_build_map(0); return rt_build_map(0);
} }
......
...@@ -20,15 +20,12 @@ static mp_obj_t enumerate_iternext(mp_obj_t self_in); ...@@ -20,15 +20,12 @@ static mp_obj_t enumerate_iternext(mp_obj_t self_in);
/* TODO: enumerate is one of the ones that can take args or kwargs. /* TODO: enumerate is one of the ones that can take args or kwargs.
Sticking to args for now */ Sticking to args for now */
static mp_obj_t enumerate_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) { static mp_obj_t enumerate_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
/* NOTE: args are backwards */
assert(n_args > 0); assert(n_args > 0);
args += n_args - 1;
mp_obj_enumerate_t *o = m_new_obj(mp_obj_enumerate_t); mp_obj_enumerate_t *o = m_new_obj(mp_obj_enumerate_t);
o->base.type = &enumerate_type; o->base.type = &enumerate_type;
o->iter = rt_getiter(args[0]); o->iter = rt_getiter(args[0]);
o->cur = n_args > 1 ? mp_obj_get_int(args[-1]) : 0; o->cur = n_args > 1 ? mp_obj_get_int(args[1]) : 0;
return o; return o;
} }
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "nlr.h" #include "nlr.h"
#include "misc.h" #include "misc.h"
#include "mpconfig.h" #include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h" #include "obj.h"
#include "objtuple.h" #include "objtuple.h"
...@@ -43,20 +44,19 @@ void exception_print(void (*print)(void *env, const char *fmt, ...), void *env, ...@@ -43,20 +44,19 @@ void exception_print(void (*print)(void *env, const char *fmt, ...), void *env,
} }
} }
// args in reversed order static mp_obj_t exception_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
static mp_obj_t exception_call(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
mp_obj_exception_t *base = self_in; mp_obj_exception_t *base = self_in;
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t*, n_args);
if (n_kw != 0) {
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "%s does not take keyword arguments", qstr_str(base->id)));
}
mp_obj_exception_t *o = m_new_obj_var(mp_obj_exception_t, mp_obj_t, n_args);
o->base.type = &exception_type; o->base.type = &exception_type;
o->id = base->id; o->id = base->id;
o->msg = 0; o->msg = 0;
o->args.len = n_args; o->args.len = n_args;
memcpy(o->args.items, args, n_args * sizeof(mp_obj_t));
// TODO: factor out as reusable copy_reversed()
int j = 0;
for (int i = n_args - 1; i >= 0; i--) {
o->args.items[i] = args[j++];
}
return o; return o;
} }
...@@ -64,7 +64,7 @@ const mp_obj_type_t exception_type = { ...@@ -64,7 +64,7 @@ const mp_obj_type_t exception_type = {
{ &mp_const_type }, { &mp_const_type },
"exception", "exception",
.print = exception_print, .print = exception_print,
.call_n = exception_call, .call = exception_call,
}; };
mp_obj_t mp_obj_new_exception(qstr id) { mp_obj_t mp_obj_new_exception(qstr id) {
......
...@@ -14,16 +14,15 @@ typedef struct _mp_obj_filter_t { ...@@ -14,16 +14,15 @@ typedef struct _mp_obj_filter_t {
mp_obj_t iter; mp_obj_t iter;
} mp_obj_filter_t; } mp_obj_filter_t;
static mp_obj_t filter_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) { static mp_obj_t filter_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
/* NOTE: args are backwards */ if (n_args != 2 || n_kw != 0) {
if (n_args != 2) {
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "filter expected 2 arguments")); nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "filter expected 2 arguments"));
} }
assert(n_args == 2); assert(n_args == 2);
mp_obj_filter_t *o = m_new_obj(mp_obj_filter_t); mp_obj_filter_t *o = m_new_obj(mp_obj_filter_t);
o->base.type = &filter_type; o->base.type = &filter_type;
o->fun = args[1]; o->fun = args[0];
o->iter = rt_getiter(args[0]); o->iter = rt_getiter(args[1]);
return o; return o;
} }
...@@ -38,7 +37,7 @@ static mp_obj_t filter_iternext(mp_obj_t self_in) { ...@@ -38,7 +37,7 @@ static mp_obj_t filter_iternext(mp_obj_t self_in) {
while ((next = rt_iternext(self->iter)) != mp_const_stop_iteration) { while ((next = rt_iternext(self->iter)) != mp_const_stop_iteration) {
mp_obj_t val; mp_obj_t val;
if (self->fun != mp_const_none) { if (self->fun != mp_const_none) {
val = rt_call_function_n(self->fun, 1, &next); val = rt_call_function_n_kw(self->fun, 1, 0, &next);
} else { } else {
val = next; val = next;
} }
......
...@@ -24,8 +24,9 @@ static void float_print(void (*print)(void *env, const char *fmt, ...), void *en ...@@ -24,8 +24,9 @@ static void float_print(void (*print)(void *env, const char *fmt, ...), void *en
print(env, "%.8g", o->value); print(env, "%.8g", o->value);
} }
// args are reverse in the array static mp_obj_t float_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
static mp_obj_t float_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) { // TODO check n_kw == 0
switch (n_args) { switch (n_args) {
case 0: case 0:
return mp_obj_new_float(0); return mp_obj_new_float(0);
......
...@@ -43,16 +43,28 @@ void check_nargs(mp_obj_fun_native_t *self, int n_args, int n_kw) { ...@@ -43,16 +43,28 @@ void check_nargs(mp_obj_fun_native_t *self, int n_args, int n_kw) {
} }
} }
mp_obj_t fun_native_call_n_kw(mp_obj_t self_in, int n_args, int n_kw, const mp_obj_t *args); mp_obj_t fun_native_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
// args are in reverse order in the array assert(MP_OBJ_IS_TYPE(self_in, &fun_native_type));
mp_obj_t fun_native_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
mp_obj_fun_native_t *self = self_in; mp_obj_fun_native_t *self = self_in;
// check number of arguments // check number of arguments
check_nargs(self, n_args, 0); check_nargs(self, n_args, n_kw);
if (self->is_kw) { if (self->is_kw) {
return fun_native_call_n_kw(self_in, n_args, 0, args); // function allows keywords
}
if (self->n_args_min == self->n_args_max) { // TODO if n_kw==0 then don't allocate any memory for map (either pass NULL or allocate it on the heap)
mp_map_t *kw_args = mp_map_new(n_kw);
for (int i = 0; i < 2 * n_kw; i += 2) {
qstr name = mp_obj_str_get(args[n_args + i]);
mp_map_lookup(kw_args, MP_OBJ_NEW_QSTR(name), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = args[n_args + i + 1];
}
mp_obj_t res = ((mp_fun_kw_t)self->fun)(n_args, args, kw_args);
// TODO clean up kw_args
return res;