diff --git a/drivers/cc3000/src/ccspi.c b/drivers/cc3000/src/ccspi.c index 1606bfd571..64900efe46 100644 --- a/drivers/cc3000/src/ccspi.c +++ b/drivers/cc3000/src/ccspi.c @@ -99,7 +99,7 @@ STATIC tSpiInformation sSpiInformation; STATIC char spi_buffer[CC3000_RX_BUFFER_SIZE]; unsigned char wlan_tx_buffer[CC3000_TX_BUFFER_SIZE]; -STATIC const mp_obj_fun_builtin_t irq_callback_obj; +STATIC const mp_obj_fun_builtin_fixed_t irq_callback_obj; // set the pins to use to communicate with the CC3000 // the arguments must be of type pin_obj_t* and SPI_HandleTypeDef* diff --git a/py/obj.h b/py/obj.h index e4fa19ac99..61db65a9a2 100644 --- a/py/obj.h +++ b/py/obj.h @@ -270,35 +270,35 @@ static inline bool mp_obj_is_integer(mp_const_obj_t o) { return MP_OBJ_IS_INT(o) // These macros are used to declare and define constant function objects // You can put "static" in front of the definitions to make them local -#define MP_DECLARE_CONST_FUN_OBJ_0(obj_name) extern const mp_obj_fun_builtin_t obj_name -#define MP_DECLARE_CONST_FUN_OBJ_1(obj_name) extern const mp_obj_fun_builtin_t obj_name -#define MP_DECLARE_CONST_FUN_OBJ_2(obj_name) extern const mp_obj_fun_builtin_t obj_name -#define MP_DECLARE_CONST_FUN_OBJ_3(obj_name) extern const mp_obj_fun_builtin_t obj_name -#define MP_DECLARE_CONST_FUN_OBJ_VAR(obj_name) extern const mp_obj_fun_builtin_t obj_name -#define MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(obj_name) extern const mp_obj_fun_builtin_t obj_name -#define MP_DECLARE_CONST_FUN_OBJ_KW(obj_name) extern const mp_obj_fun_builtin_t obj_name +#define MP_DECLARE_CONST_FUN_OBJ_0(obj_name) extern const mp_obj_fun_builtin_fixed_t obj_name +#define MP_DECLARE_CONST_FUN_OBJ_1(obj_name) extern const mp_obj_fun_builtin_fixed_t obj_name +#define MP_DECLARE_CONST_FUN_OBJ_2(obj_name) extern const mp_obj_fun_builtin_fixed_t obj_name +#define MP_DECLARE_CONST_FUN_OBJ_3(obj_name) extern const mp_obj_fun_builtin_fixed_t obj_name +#define MP_DECLARE_CONST_FUN_OBJ_VAR(obj_name) extern const mp_obj_fun_builtin_var_t obj_name +#define MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(obj_name) extern const mp_obj_fun_builtin_var_t obj_name +#define MP_DECLARE_CONST_FUN_OBJ_KW(obj_name) extern const mp_obj_fun_builtin_var_t obj_name #define MP_DEFINE_CONST_FUN_OBJ_0(obj_name, fun_name) \ - const mp_obj_fun_builtin_t obj_name = \ - {{&mp_type_fun_builtin}, false, 0, 0, .fun._0 = fun_name} + const mp_obj_fun_builtin_fixed_t obj_name = \ + {{&mp_type_fun_builtin_0}, .fun._0 = fun_name} #define MP_DEFINE_CONST_FUN_OBJ_1(obj_name, fun_name) \ - const mp_obj_fun_builtin_t obj_name = \ - {{&mp_type_fun_builtin}, false, 1, 1, .fun._1 = fun_name} + const mp_obj_fun_builtin_fixed_t obj_name = \ + {{&mp_type_fun_builtin_1}, .fun._1 = fun_name} #define MP_DEFINE_CONST_FUN_OBJ_2(obj_name, fun_name) \ - const mp_obj_fun_builtin_t obj_name = \ - {{&mp_type_fun_builtin}, false, 2, 2, .fun._2 = fun_name} + const mp_obj_fun_builtin_fixed_t obj_name = \ + {{&mp_type_fun_builtin_2}, .fun._2 = fun_name} #define MP_DEFINE_CONST_FUN_OBJ_3(obj_name, fun_name) \ - const mp_obj_fun_builtin_t obj_name = \ - {{&mp_type_fun_builtin}, false, 3, 3, .fun._3 = fun_name} + const mp_obj_fun_builtin_fixed_t obj_name = \ + {{&mp_type_fun_builtin_3}, .fun._3 = fun_name} #define MP_DEFINE_CONST_FUN_OBJ_VAR(obj_name, n_args_min, fun_name) \ - const mp_obj_fun_builtin_t obj_name = \ - {{&mp_type_fun_builtin}, false, n_args_min, MP_OBJ_FUN_ARGS_MAX, .fun.var = fun_name} + const mp_obj_fun_builtin_var_t obj_name = \ + {{&mp_type_fun_builtin_var}, false, n_args_min, MP_OBJ_FUN_ARGS_MAX, .fun.var = fun_name} #define MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(obj_name, n_args_min, n_args_max, fun_name) \ - const mp_obj_fun_builtin_t obj_name = \ - {{&mp_type_fun_builtin}, false, n_args_min, n_args_max, .fun.var = fun_name} + const mp_obj_fun_builtin_var_t obj_name = \ + {{&mp_type_fun_builtin_var}, false, n_args_min, n_args_max, .fun.var = fun_name} #define MP_DEFINE_CONST_FUN_OBJ_KW(obj_name, n_args_min, fun_name) \ - const mp_obj_fun_builtin_t obj_name = \ - {{&mp_type_fun_builtin}, true, n_args_min, MP_OBJ_FUN_ARGS_MAX, .fun.kw = fun_name} + const mp_obj_fun_builtin_var_t obj_name = \ + {{&mp_type_fun_builtin_var}, true, n_args_min, MP_OBJ_FUN_ARGS_MAX, .fun.kw = fun_name} // These macros are used to define constant map/dict objects // You can put "static" in front of the definition to make it local @@ -536,7 +536,11 @@ extern const mp_obj_type_t mp_type_zip; extern const mp_obj_type_t mp_type_array; extern const mp_obj_type_t mp_type_super; extern const mp_obj_type_t mp_type_gen_instance; -extern const mp_obj_type_t mp_type_fun_builtin; +extern const mp_obj_type_t mp_type_fun_builtin_0; +extern const mp_obj_type_t mp_type_fun_builtin_1; +extern const mp_obj_type_t mp_type_fun_builtin_2; +extern const mp_obj_type_t mp_type_fun_builtin_3; +extern const mp_obj_type_t mp_type_fun_builtin_var; extern const mp_obj_type_t mp_type_fun_bc; extern const mp_obj_type_t mp_type_module; extern const mp_obj_type_t mp_type_staticmethod; @@ -746,21 +750,28 @@ void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item); void mp_obj_slice_get(mp_obj_t self_in, mp_obj_t *start, mp_obj_t *stop, mp_obj_t *step); // functions -#define MP_OBJ_FUN_ARGS_MAX (0xffff) // to set maximum value in n_args_max below -typedef struct _mp_obj_fun_builtin_t { // use this to make const objects that go in ROM + +typedef struct _mp_obj_fun_builtin_fixed_t { mp_obj_base_t base; - bool is_kw : 1; - mp_uint_t n_args_min : 15; // inclusive - mp_uint_t n_args_max : 16; // inclusive union { mp_fun_0_t _0; mp_fun_1_t _1; mp_fun_2_t _2; mp_fun_3_t _3; + } fun; +} mp_obj_fun_builtin_fixed_t; + +#define MP_OBJ_FUN_ARGS_MAX (0xffff) // to set maximum value in n_args_max below +typedef struct _mp_obj_fun_builtin_var_t { + mp_obj_base_t base; + bool is_kw : 1; + mp_uint_t n_args_min : 15; // inclusive + mp_uint_t n_args_max : 16; // inclusive + union { mp_fun_var_t var; mp_fun_kw_t kw; } fun; -} mp_obj_fun_builtin_t; +} mp_obj_fun_builtin_var_t; qstr mp_obj_fun_get_name(mp_const_obj_t fun); qstr mp_obj_code_get_name(const byte *code_info); diff --git a/py/objfun.c b/py/objfun.c index 405f38127a..6b8fe6d382 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -50,11 +50,66 @@ /******************************************************************************/ /* builtin functions */ -// mp_obj_fun_builtin_t defined in obj.h +STATIC mp_obj_t fun_builtin_0_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { + (void)args; + assert(MP_OBJ_IS_TYPE(self_in, &mp_type_fun_builtin_0)); + mp_obj_fun_builtin_fixed_t *self = MP_OBJ_TO_PTR(self_in); + mp_arg_check_num(n_args, n_kw, 0, 0, false); + return self->fun._0(); +} -STATIC mp_obj_t fun_builtin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { - assert(MP_OBJ_IS_TYPE(self_in, &mp_type_fun_builtin)); - mp_obj_fun_builtin_t *self = MP_OBJ_TO_PTR(self_in); +const mp_obj_type_t mp_type_fun_builtin_0 = { + { &mp_type_type }, + .name = MP_QSTR_function, + .call = fun_builtin_0_call, + .unary_op = mp_generic_unary_op, +}; + +STATIC mp_obj_t fun_builtin_1_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { + assert(MP_OBJ_IS_TYPE(self_in, &mp_type_fun_builtin_1)); + mp_obj_fun_builtin_fixed_t *self = MP_OBJ_TO_PTR(self_in); + mp_arg_check_num(n_args, n_kw, 1, 1, false); + return self->fun._1(args[0]); +} + +const mp_obj_type_t mp_type_fun_builtin_1 = { + { &mp_type_type }, + .name = MP_QSTR_function, + .call = fun_builtin_1_call, + .unary_op = mp_generic_unary_op, +}; + +STATIC mp_obj_t fun_builtin_2_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { + assert(MP_OBJ_IS_TYPE(self_in, &mp_type_fun_builtin_2)); + mp_obj_fun_builtin_fixed_t *self = MP_OBJ_TO_PTR(self_in); + mp_arg_check_num(n_args, n_kw, 2, 2, false); + return self->fun._2(args[0], args[1]); +} + +const mp_obj_type_t mp_type_fun_builtin_2 = { + { &mp_type_type }, + .name = MP_QSTR_function, + .call = fun_builtin_2_call, + .unary_op = mp_generic_unary_op, +}; + +STATIC mp_obj_t fun_builtin_3_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { + assert(MP_OBJ_IS_TYPE(self_in, &mp_type_fun_builtin_3)); + mp_obj_fun_builtin_fixed_t *self = MP_OBJ_TO_PTR(self_in); + mp_arg_check_num(n_args, n_kw, 3, 3, false); + return self->fun._3(args[0], args[1], args[2]); +} + +const mp_obj_type_t mp_type_fun_builtin_3 = { + { &mp_type_type }, + .name = MP_QSTR_function, + .call = fun_builtin_3_call, + .unary_op = mp_generic_unary_op, +}; + +STATIC mp_obj_t fun_builtin_var_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) { + assert(MP_OBJ_IS_TYPE(self_in, &mp_type_fun_builtin_var)); + mp_obj_fun_builtin_var_t *self = MP_OBJ_TO_PTR(self_in); // check number of arguments mp_arg_check_num(n_args, n_kw, self->n_args_min, self->n_args_max, self->is_kw); @@ -68,25 +123,6 @@ STATIC mp_obj_t fun_builtin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, c return self->fun.kw(n_args, args, &kw_args); - } else if (self->n_args_min <= 3 && self->n_args_min == self->n_args_max) { - // function requires a fixed number of arguments - - // dispatch function call - switch (self->n_args_min) { - case 0: - return self->fun._0(); - - case 1: - return self->fun._1(args[0]); - - case 2: - return self->fun._2(args[0], args[1]); - - case 3: - default: - return self->fun._3(args[0], args[1], args[2]); - } - } else { // function takes a variable number of arguments, but no keywords @@ -94,10 +130,10 @@ STATIC mp_obj_t fun_builtin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, c } } -const mp_obj_type_t mp_type_fun_builtin = { +const mp_obj_type_t mp_type_fun_builtin_var = { { &mp_type_type }, .name = MP_QSTR_function, - .call = fun_builtin_call, + .call = fun_builtin_var_call, .unary_op = mp_generic_unary_op, }; diff --git a/py/runtime.c b/py/runtime.c index 6eda77ee9c..c255574643 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -972,7 +972,13 @@ void mp_convert_member_lookup(mp_obj_t self, const mp_obj_type_t *type, mp_obj_t || ((mp_obj_base_t*)MP_OBJ_TO_PTR(member))->type->name == MP_QSTR_generator))) { // only functions, closures and generators objects can be bound to self #if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG - if (self == MP_OBJ_NULL && mp_obj_get_type(member) == &mp_type_fun_builtin) { + const mp_obj_type_t *m_type = ((mp_obj_base_t*)MP_OBJ_TO_PTR(member))->type; + if (self == MP_OBJ_NULL + && (m_type == &mp_type_fun_builtin_0 + || m_type == &mp_type_fun_builtin_1 + || m_type == &mp_type_fun_builtin_2 + || m_type == &mp_type_fun_builtin_3 + || m_type == &mp_type_fun_builtin_var)) { // we extracted a builtin method without a first argument, so we must // wrap this function in a type checker dest[0] = mp_obj_new_checked_fun(type, member);