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.
This commit is contained in:
Damien George
2014-01-18 14:10:48 +00:00
parent 8655065f8c
commit 20006dbba9
28 changed files with 325 additions and 372 deletions
+12 -19
View File
@@ -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
// create the new class using a call to the meta object
// (arguments must be backwards in the array)
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[0] = class_locals; // dict of members
mp_obj_t new_class = rt_call_function_n(meta, 3, meta_args);
meta_args[2] = class_locals; // dict of members
mp_obj_t new_class = rt_call_function_n_kw(meta, 3, 0, meta_args);
// store into cell if neede
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) {
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 i2 = MP_OBJ_SMALL_INT_VALUE(o2_in);
mp_obj_t revs_args[2];
revs_args[1] = MP_OBJ_NEW_SMALL_INT(i1 / i2);
revs_args[0] = MP_OBJ_NEW_SMALL_INT(i1 % i2);
return rt_build_tuple(2, revs_args);
mp_obj_t args[2];
args[0] = MP_OBJ_NEW_SMALL_INT(i1 / i2);
args[1] = MP_OBJ_NEW_SMALL_INT(i1 % i2);
return rt_build_tuple(2, args);
} 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)));
}
@@ -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);
static mp_obj_t mp_builtin_sorted(mp_obj_t args, mp_map_t *kwargs) {
mp_obj_t *args_items = NULL;
uint args_len = 0;
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) {
static mp_obj_t mp_builtin_sorted(uint n_args, const mp_obj_t *args, mp_map_t *kwargs) {
assert(n_args >= 1);
if (n_args > 1) {
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError,
"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 new_args = rt_build_tuple(1, &self);
mp_obj_list_sort(new_args, kwargs);
mp_obj_t self = list_type.make_new((mp_obj_t)&list_type, 1, 0, args);
mp_obj_list_sort(1, &self, kwargs);
return self;
}
+4 -2
View File
@@ -1156,7 +1156,8 @@ static void emit_native_call_function(emit_t *emit, int n_positional, int n_keyw
vtype_kind_t vtype_fun;
emit_pre_pop_reg(emit, &vtype_fun, REG_ARG_1); // the function
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);
}
@@ -1181,7 +1182,8 @@ static void emit_native_call_method(emit_t *emit, int n_positional, int n_keywor
*/
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_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);
}
+1 -1
View File
@@ -63,7 +63,7 @@ bool mp_obj_is_callable(mp_obj_t o_in) {
return false;
} else {
mp_obj_base_t *o = o_in;
return o->type->call_n != NULL;
return o->type->call != NULL;
}
}
+7 -11
View File
@@ -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_t)(void);
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 {
PRINT_STR, PRINT_REPR
} 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 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_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_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_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_fun_t)(mp_obj_t fun, uint n_args, uint n_kw, const mp_obj_t *args);
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 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 struct _mp_method_t {
@@ -144,8 +143,7 @@ struct _mp_obj_type_t {
mp_print_fun_t print;
mp_make_new_fun_t make_new; // to make an instance of the type
mp_call_n_fun_t call_n;
mp_call_n_kw_fun_t call_n_kw;
mp_call_fun_t call;
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
@@ -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_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_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_reverse(uint n, mp_obj_t *items);
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_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_get_type(mp_obj_t o_in);
@@ -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);
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);
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)
extern const mp_obj_type_t map_type;
+3 -2
View File
@@ -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, int n_args, const mp_obj_t *args) {
static mp_obj_t bool_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) {
case 0: return mp_const_false;
case 1: if (rt_is_true(args[0])) { return mp_const_true; } else { return mp_const_false; }
+21 -16
View File
@@ -1,5 +1,6 @@
#include <stdlib.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "nlr.h"
@@ -14,32 +15,36 @@ typedef struct _mp_obj_bound_meth_t {
mp_obj_t self;
} mp_obj_bound_meth_t;
// args are in reverse order in the array
mp_obj_t bound_meth_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
mp_obj_t bound_meth_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
mp_obj_bound_meth_t *self = self_in;
if (n_args == 0) {
return rt_call_function_n(self->meth, 1, &self->self);
} else if (n_args == 1) {
mp_obj_t args2[2];
args2[1] = self->self;
args2[0] = args[0];
return rt_call_function_n(self->meth, 2, args2);
// need to insert self->self before all other args and then call self->meth
int n_total = n_args + 2 * n_kw;
if (n_total <= 4) {
// use stack to allocate temporary args array
mp_obj_t args2[5];
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 {
// TODO not implemented
assert(0);
return mp_const_none;
//return rt_call_function_2(self->meth, n_args + 1, self->self + args);
// use heap to allocate temporary args array
mp_obj_t *args2 = m_new(mp_obj_t, 1 + n_total);
args2[0] = self->self;
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 = {
{ &mp_const_type },
"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);
o->base.type = &bound_meth_type;
o->meth = meth;
+19 -12
View File
@@ -16,26 +16,33 @@ typedef struct _mp_obj_closure_t {
mp_obj_t *closed;
} mp_obj_closure_t;
// args are in reverse order in the array
mp_obj_t closure_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
mp_obj_t closure_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
mp_obj_closure_t *self = self_in;
// concatenate args and closed-over-vars, in reverse order
// 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];
}
// need to concatenate closed-over-vars and args
// call the function with the new vars array
return rt_call_function_n(self->fun, n_args + self->n_closed, args2);
int n_total = self->n_closed + n_args + 2 * n_kw;
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 = {
{ &mp_const_type },
"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) {
+9 -8
View File
@@ -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, int n_args, const mp_obj_t *args) {
static mp_obj_t complex_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) {
case 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
case 2:
{
mp_float_t real, imag;
if (MP_OBJ_IS_TYPE(args[1], &complex_type)) {
mp_obj_complex_get(args[1], &real, &imag);
if (MP_OBJ_IS_TYPE(args[0], &complex_type)) {
mp_obj_complex_get(args[0], &real, &imag);
} else {
real = mp_obj_get_float(args[1]);
real = mp_obj_get_float(args[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_obj_complex_get(args[0], &real2, &imag2);
mp_obj_complex_get(args[1], &real2, &imag2);
real -= imag2;
imag += real2;
} else {
imag += mp_obj_get_float(args[0]);
imag += mp_obj_get_float(args[1]);
}
return mp_obj_new_complex(real, imag);
}
+1 -2
View File
@@ -38,8 +38,7 @@ static void dict_print(void (*print)(void *env, const char *fmt, ...), void *env
print(env, "}");
}
// args are reverse in the array
static mp_obj_t dict_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
static mp_obj_t dict_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
// TODO create from an iterable!
return rt_build_map(0);
}
+2 -5
View File
@@ -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.
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) {
/* NOTE: args are backwards */
static mp_obj_t enumerate_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
assert(n_args > 0);
args += n_args - 1;
mp_obj_enumerate_t *o = m_new_obj(mp_obj_enumerate_t);
o->base.type = &enumerate_type;
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;
}
+10 -10
View File
@@ -7,6 +7,7 @@
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "objtuple.h"
@@ -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, int n_args, const mp_obj_t *args) {
static mp_obj_t exception_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
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->id = base->id;
o->msg = 0;
o->args.len = n_args;
// 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++];
}
memcpy(o->args.items, args, n_args * sizeof(mp_obj_t));
return o;
}
@@ -64,7 +64,7 @@ const mp_obj_type_t exception_type = {
{ &mp_const_type },
"exception",
.print = exception_print,
.call_n = exception_call,
.call = exception_call,
};
mp_obj_t mp_obj_new_exception(qstr id) {
+5 -6
View File
@@ -14,16 +14,15 @@ typedef struct _mp_obj_filter_t {
mp_obj_t iter;
} mp_obj_filter_t;
static mp_obj_t filter_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
/* NOTE: args are backwards */
if (n_args != 2) {
static mp_obj_t filter_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
if (n_args != 2 || n_kw != 0) {
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "filter expected 2 arguments"));
}
assert(n_args == 2);
mp_obj_filter_t *o = m_new_obj(mp_obj_filter_t);
o->base.type = &filter_type;
o->fun = args[1];
o->iter = rt_getiter(args[0]);
o->fun = args[0];
o->iter = rt_getiter(args[1]);
return o;
}
@@ -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) {
mp_obj_t val;
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 {
val = next;
}
+3 -2
View File
@@ -24,8 +24,9 @@ static void float_print(void (*print)(void *env, const char *fmt, ...), void *en
print(env, "%.8g", o->value);
}
// args are reverse in the array
static mp_obj_t float_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
static mp_obj_t float_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) {
case 0:
return mp_obj_new_float(0);
+36 -46
View File
@@ -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);
// args are in reverse order in the array
mp_obj_t fun_native_call_n(mp_obj_t self_in, int n_args, 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) {
assert(MP_OBJ_IS_TYPE(self_in, &fun_native_type));
mp_obj_fun_native_t *self = self_in;
// check number of arguments
check_nargs(self, n_args, 0);
check_nargs(self, n_args, n_kw);
if (self->is_kw) {
return fun_native_call_n_kw(self_in, n_args, 0, args);
}
if (self->n_args_min == self->n_args_max) {
// function allows keywords
// 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;
} else if (self->n_args_min == self->n_args_max) {
// function requires a fixed number of arguments
// dispatch function call
@@ -64,10 +76,10 @@ mp_obj_t fun_native_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
return ((mp_fun_1_t)self->fun)(args[0]);
case 2:
return ((mp_fun_2_t)self->fun)(args[1], args[0]);
return ((mp_fun_2_t)self->fun)(args[0], args[1]);
case 3:
return ((mp_fun_3_t)self->fun)(args[2], args[1], args[0]);
return ((mp_fun_3_t)self->fun)(args[0], args[1], args[2]);
default:
assert(0);
@@ -75,42 +87,16 @@ mp_obj_t fun_native_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
}
} else {
// function takes a variable number of arguments
// function takes a variable number of arguments, but no keywords
// TODO really the args need to be passed in as a Python tuple, as the form f(*[1,2]) can be used to pass var args
mp_obj_t *args_ordered = m_new(mp_obj_t, n_args);
for (int i = 0; i < n_args; i++) {
args_ordered[i] = args[n_args - i - 1];
}
mp_obj_t res = ((mp_fun_var_t)self->fun)(n_args, args_ordered);
m_del(mp_obj_t, args_ordered, n_args);
return res;
return ((mp_fun_var_t)self->fun)(n_args, args);
}
}
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_fun_native_t *self = self_in;
check_nargs(self, n_args, n_kw);
mp_obj_t *vargs = mp_obj_new_tuple_reverse(n_args, args + 2*n_kw);
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[i+1]);
mp_map_lookup(kw_args, MP_OBJ_NEW_QSTR(name), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = args[i];
}
mp_obj_t res = ((mp_fun_kw_t)self->fun)(vargs, kw_args);
// TODO clean up vargs and kw_args
return res;
}
const mp_obj_type_t fun_native_type = {
{ &mp_const_type },
"function",
.call_n = fun_native_call_n,
.call_n_kw = fun_native_call_n_kw,
.call = fun_native_call,
};
// fun must have the correct signature for n_args fixed arguments
@@ -156,13 +142,15 @@ typedef struct _mp_obj_fun_bc_t {
const byte *bytecode; // bytecode for the function
} mp_obj_fun_bc_t;
// args are in reverse order in the array
mp_obj_t fun_bc_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
mp_obj_t fun_bc_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
mp_obj_fun_bc_t *self = self_in;
if (n_args != self->n_args) {
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)self->n_args, (const char*)(machine_int_t)n_args));
}
if (n_kw != 0) {
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "function does not take keyword arguments"));
}
// optimisation: allow the compiler to optimise this tail call for
// the common case when the globals don't need to be changed
@@ -180,7 +168,7 @@ mp_obj_t fun_bc_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
const mp_obj_type_t fun_bc_type = {
{ &mp_const_type },
"function",
.call_n = fun_bc_call_n,
.call = fun_bc_call,
};
mp_obj_t mp_obj_new_fun_bc(int n_args, uint n_state, const byte *code) {
@@ -257,13 +245,15 @@ mp_obj_t convert_val_from_inline_asm(machine_uint_t val) {
return MP_OBJ_NEW_SMALL_INT(val);
}
// args are in reverse order in the array
mp_obj_t fun_asm_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
mp_obj_t fun_asm_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
mp_obj_fun_asm_t *self = self_in;
if (n_args != self->n_args) {
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)self->n_args, (const char*)(machine_int_t)n_args));
}
if (n_kw != 0) {
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "function does not take keyword arguments"));
}
machine_uint_t ret;
if (n_args == 0) {
@@ -271,9 +261,9 @@ mp_obj_t fun_asm_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
} else if (n_args == 1) {
ret = ((inline_asm_fun_1_t)self->fun)(convert_obj_for_inline_asm(args[0]));
} else if (n_args == 2) {
ret = ((inline_asm_fun_2_t)self->fun)(convert_obj_for_inline_asm(args[1]), convert_obj_for_inline_asm(args[0]));
ret = ((inline_asm_fun_2_t)self->fun)(convert_obj_for_inline_asm(args[0]), convert_obj_for_inline_asm(args[1]));
} else if (n_args == 3) {
ret = ((inline_asm_fun_3_t)self->fun)(convert_obj_for_inline_asm(args[2]), convert_obj_for_inline_asm(args[1]), convert_obj_for_inline_asm(args[0]));
ret = ((inline_asm_fun_3_t)self->fun)(convert_obj_for_inline_asm(args[0]), convert_obj_for_inline_asm(args[1]), convert_obj_for_inline_asm(args[2]));
} else {
assert(0);
ret = 0;
@@ -285,7 +275,7 @@ mp_obj_t fun_asm_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
static const mp_obj_type_t fun_asm_type = {
{ &mp_const_type },
"function",
.call_n = fun_asm_call_n,
.call = fun_asm_call,
};
mp_obj_t mp_obj_new_fun_asm(uint n_args, void *fun) {
+11 -8
View File
@@ -20,8 +20,7 @@ typedef struct _mp_obj_gen_wrap_t {
mp_obj_t *fun;
} mp_obj_gen_wrap_t;
// args are in reverse order in the array
mp_obj_t gen_wrap_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
mp_obj_t gen_wrap_call(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) {
mp_obj_gen_wrap_t *self = self_in;
mp_obj_t self_fun = self->fun;
assert(MP_OBJ_IS_TYPE(self_fun, &fun_bc_type));
@@ -32,6 +31,9 @@ mp_obj_t gen_wrap_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
if (n_args != bc_n_args) {
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_TypeError, "function takes %d positional arguments but %d were given", (const char*)(machine_int_t)bc_n_args, (const char*)(machine_int_t)n_args));
}
if (n_kw != 0) {
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "function does not take keyword arguments"));
}
return mp_obj_new_gen_instance(bc_code, self->n_state, n_args, args);
}
@@ -39,7 +41,7 @@ mp_obj_t gen_wrap_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
const mp_obj_type_t gen_wrap_type = {
{ &mp_const_type },
"generator",
.call_n = gen_wrap_call_n,
.call = gen_wrap_call,
};
mp_obj_t mp_obj_new_gen_wrap(uint n_locals, uint n_stack, mp_obj_t fun) {
@@ -58,6 +60,7 @@ typedef struct _mp_obj_gen_instance_t {
mp_obj_base_t base;
const byte *ip;
mp_obj_t *sp;
uint n_state;
mp_obj_t state[];
} mp_obj_gen_instance_t;
@@ -71,7 +74,7 @@ mp_obj_t gen_instance_getiter(mp_obj_t self_in) {
mp_obj_t gen_instance_iternext(mp_obj_t self_in) {
mp_obj_gen_instance_t *self = self_in;
bool yield = mp_execute_byte_code_2(&self->ip, &self->state[0], &self->sp);
bool yield = mp_execute_byte_code_2(&self->ip, &self->state[self->n_state - 1], &self->sp);
if (yield) {
return *self->sp;
} else {
@@ -92,16 +95,16 @@ const mp_obj_type_t gen_instance_type = {
.iternext = gen_instance_iternext,
};
// args are in reverse order in the array
mp_obj_t mp_obj_new_gen_instance(const byte *bytecode, uint n_state, int n_args, const mp_obj_t *args) {
mp_obj_gen_instance_t *o = m_new_obj_var(mp_obj_gen_instance_t, mp_obj_t, n_state);
o->base.type = &gen_instance_type;
o->ip = bytecode;
o->sp = o->state + n_state;
o->sp = &o->state[0] - 1; // sp points to top of stack, which starts off 1 below the state
o->n_state = n_state;
// copy args (which are in reverse order) to start of state array
// copy args to end of state array, in reverse (that's how mp_execute_byte_code_2 needs it)
for (int i = 0; i < n_args; i++) {
o->state[i] = args[n_args - 1 - i];
o->state[n_state - 1 - i] = args[i];
}
// TODO
+4 -2
View File
@@ -12,7 +12,9 @@
// This dispatcher function is expected to be independent of the implementation
// of long int
static mp_obj_t int_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
static mp_obj_t int_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) {
case 0:
return MP_OBJ_NEW_SMALL_INT(0);
@@ -28,7 +30,7 @@ static mp_obj_t int_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args)
case 2:
// should be a string, parse it
// TODO proper error checking of argument types
return MP_OBJ_NEW_SMALL_INT(strtonum(qstr_str(mp_obj_get_qstr(args[1])), mp_obj_get_int(args[0])));
return MP_OBJ_NEW_SMALL_INT(strtonum(qstr_str(mp_obj_get_qstr(args[0])), mp_obj_get_int(args[1])));
default:
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_TypeError, "int takes at most 2 arguments, %d given", (void*)(machine_int_t)n_args));
+8 -19
View File
@@ -38,7 +38,9 @@ static void list_print(void (*print)(void *env, const char *fmt, ...), void *env
print(env, "]");
}
static mp_obj_t list_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
static mp_obj_t list_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) {
case 0:
// return a new, empty list
@@ -248,19 +250,14 @@ static void mp_quicksort(mp_obj_t *head, mp_obj_t *tail, mp_obj_t key_fn, bool r
}
}
mp_obj_t mp_obj_list_sort(mp_obj_t args, mp_map_t *kwargs) {
mp_obj_t *args_items = NULL;
uint args_len = 0;
assert(MP_OBJ_IS_TYPE(args, &tuple_type));
mp_obj_tuple_get(args, &args_len, &args_items);
assert(args_len >= 1);
assert(MP_OBJ_IS_TYPE(args_items[0], &list_type));
if (args_len > 1) {
mp_obj_t mp_obj_list_sort(uint n_args, const mp_obj_t *args, mp_map_t *kwargs) {
assert(n_args >= 1);
assert(MP_OBJ_IS_TYPE(args[0], &list_type));
if (n_args > 1) {
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError,
"list.sort takes no positional arguments"));
}
mp_obj_list_t *self = args_items[0];
mp_obj_list_t *self = args[0];
if (self->len > 1) {
mp_map_elem_t *keyfun = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(qstr_from_str_static("key")), MP_MAP_LOOKUP);
mp_map_elem_t *reverse = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(qstr_from_str_static("reverse")), MP_MAP_LOOKUP);
@@ -425,14 +422,6 @@ mp_obj_t mp_obj_new_list(uint n, mp_obj_t *items) {
return o;
}
mp_obj_t mp_obj_new_list_reverse(uint n, mp_obj_t *items) {
mp_obj_list_t *o = list_new(n);
for (int i = 0; i < n; i++) {
o->items[i] = items[n - i - 1];
}
return o;
}
void mp_obj_list_get(mp_obj_t self_in, uint *len, mp_obj_t **items) {
mp_obj_list_t *self = self_in;
*len = self->len;
+6 -7
View File
@@ -15,18 +15,17 @@ typedef struct _mp_obj_map_t {
mp_obj_t iters[];
} mp_obj_map_t;
static mp_obj_t map_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
/* NOTE: args are backwards */
if (n_args < 2) {
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "map must have at least 2 arguments"));
static mp_obj_t map_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) {
if (n_args < 2 || n_kw != 0) {
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "map must have at least 2 arguments and no keyword arguments"));
}
assert(n_args >= 2);
mp_obj_map_t *o = m_new_obj_var(mp_obj_map_t, mp_obj_t, n_args - 1);
o->base.type = &map_type;
o->n_iters = n_args - 1;
o->fun = args[n_args - 1];
o->fun = args[0];
for (int i = 0; i < n_args - 1; i++) {
o->iters[i] = rt_getiter(args[n_args-i-2]);
o->iters[i] = rt_getiter(args[i + 1]);
}
return o;
}
@@ -48,7 +47,7 @@ static mp_obj_t map_iternext(mp_obj_t self_in) {
}
nextses[i] = next;
}
return rt_call_function_n(self->fun, self->n_iters, nextses);
return rt_call_function_n_kw(self->fun, self->n_iters, 0, nextses);
}
const mp_obj_type_t map_type = {
+1 -1
View File
@@ -26,7 +26,7 @@ static void module_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
mp_obj_module_t *self = self_in;
mp_map_elem_t *elem = mp_map_lookup(self->globals, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
if (elem != NULL) {
dest[1] = elem->value;
dest[0] = elem->value;
}
}
+5 -3
View File
@@ -46,7 +46,9 @@ void set_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj
}
static mp_obj_t set_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args) {
static mp_obj_t set_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) {
case 0:
// return a new, empty set
@@ -239,7 +241,7 @@ static mp_obj_t set_issubset_internal(mp_obj_t self_in, mp_obj_t other_in, bool
if (MP_OBJ_IS_TYPE(self_in, &set_type)) {
self = self_in;
} else {
self = set_make_new(NULL, 1, &self_in);
self = set_make_new((mp_obj_t)&set_type, 1, 0, &self_in);
cleanup_self = true;
}
@@ -248,7 +250,7 @@ static mp_obj_t set_issubset_internal(mp_obj_t self_in, mp_obj_t other_in, bool
if (MP_OBJ_IS_TYPE(other_in, &set_type)) {
other = other_in;
} else {
other = set_make_new(NULL, 1, &other_in);
other = set_make_new((mp_obj_t)&set_type, 1, 0, &other_in);
cleanup_other = true;
}
bool out = true;

Some files were not shown because too many files have changed in this diff Show More