summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/obj.h67
-rw-r--r--py/objfun.c86
-rw-r--r--py/runtime.c8
3 files changed, 107 insertions, 54 deletions
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);