mirror of
https://github.com/micropython/micropython.git
synced 2026-01-08 05:00:26 +01:00
Remove mp_obj_type_t.methods entry and use .locals_dict instead.
Originally, .methods was used for methods in a ROM class, and locals_dict for methods in a user-created class. That distinction is unnecessary, and we can use locals_dict for ROM classes now that we have ROMable maps. This removes an entry in the bloated mp_obj_type_t struct, saving a word for each ROM object and each RAM object. ROM objects that have a methods table (now a locals_dict) need an extra word in total (removed the methods pointer (1 word), no longer need the sentinel (2 words), but now need an mp_obj_dict_t wrapper (4 words)). But RAM objects save a word because they never used the methods entry. Overall the ROM usage is down by a few hundred bytes, and RAM usage is down 1 word per user-defined type/class. There is less code (no need to check 2 tables), and now consistent with the way ROM modules have their tables initialised. Efficiency is very close to equivaluent.
This commit is contained in:
10
py/builtin.c
10
py/builtin.c
@@ -152,7 +152,6 @@ STATIC mp_obj_t mp_builtin_dir(uint n_args, const mp_obj_t *args) {
|
||||
// TODO make this function more general and less of a hack
|
||||
|
||||
mp_map_t *map = NULL;
|
||||
const mp_method_t *meth = NULL;
|
||||
if (n_args == 0) {
|
||||
// make a list of names in the local name space
|
||||
map = rt_locals_get();
|
||||
@@ -164,9 +163,6 @@ STATIC mp_obj_t mp_builtin_dir(uint n_args, const mp_obj_t *args) {
|
||||
} else if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &dict_type)) {
|
||||
map = mp_obj_dict_get_map(type->locals_dict);
|
||||
}
|
||||
if (type->methods != NULL) {
|
||||
meth = type->methods;
|
||||
}
|
||||
}
|
||||
|
||||
mp_obj_t dir = mp_obj_new_list(0, NULL);
|
||||
@@ -177,11 +173,7 @@ STATIC mp_obj_t mp_builtin_dir(uint n_args, const mp_obj_t *args) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (meth != NULL) {
|
||||
for (; meth->name != MP_QSTR_NULL; meth++) {
|
||||
mp_obj_list_append(dir, MP_OBJ_NEW_QSTR(meth->name));
|
||||
}
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
|
||||
5
py/map.h
5
py/map.h
@@ -24,6 +24,11 @@ typedef enum _mp_map_lookup_kind_t {
|
||||
MP_MAP_LOOKUP_FIRST = 4,
|
||||
} mp_map_lookup_kind_t;
|
||||
|
||||
typedef struct _mp_obj_dict_t {
|
||||
mp_obj_base_t base;
|
||||
mp_map_t map;
|
||||
} mp_obj_dict_t;
|
||||
|
||||
int get_doubling_prime_greater_or_equal_to(int x);
|
||||
void mp_map_init(mp_map_t *map, int n);
|
||||
void mp_map_init_fixed_table(mp_map_t *map, int n, const mp_obj_t *table);
|
||||
|
||||
17
py/obj.h
17
py/obj.h
@@ -59,6 +59,21 @@ typedef struct _mp_obj_base_t mp_obj_base_t;
|
||||
#define MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(obj_name, n_args_min, n_args_max, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, false, n_args_min, n_args_max, (mp_fun_var_t)fun_name)
|
||||
#define MP_DEFINE_CONST_FUN_OBJ_KW(obj_name, n_args_min, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, true, n_args_min, MP_OBJ_FUN_ARGS_MAX, (mp_fun_kw_t)fun_name)
|
||||
|
||||
// This macro is used to define constant dict objects
|
||||
// You can put "static" in front of the definition to make it local
|
||||
|
||||
#define MP_DEFINE_CONST_DICT(dict_name, table_name) \
|
||||
const mp_obj_dict_t dict_name = { \
|
||||
.base = {&dict_type}, \
|
||||
.map = { \
|
||||
.all_keys_are_qstrs = 1, \
|
||||
.table_is_fixed_array = 1, \
|
||||
.used = sizeof(table_name) / sizeof(mp_map_elem_t), \
|
||||
.alloc = sizeof(table_name) / sizeof(mp_map_elem_t), \
|
||||
.table = (mp_map_elem_t*)table_name, \
|
||||
}, \
|
||||
}
|
||||
|
||||
// These macros are used to declare and define constant staticmethond and classmethod objects
|
||||
// You can put "static" in front of the definitions to make them local
|
||||
|
||||
@@ -160,8 +175,6 @@ struct _mp_obj_type_t {
|
||||
mp_buffer_p_t buffer_p;
|
||||
mp_stream_p_t stream_p;
|
||||
|
||||
const mp_method_t *methods;
|
||||
|
||||
// these are for dynamically created types (classes)
|
||||
mp_obj_t bases_tuple;
|
||||
mp_obj_t locals_dict;
|
||||
|
||||
@@ -149,11 +149,12 @@ STATIC machine_int_t array_get_buffer(mp_obj_t o_in, buffer_info_t *bufinfo, int
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC const mp_method_t array_type_methods[] = {
|
||||
{ MP_QSTR_append, &array_append_obj },
|
||||
{ MP_QSTR_NULL, NULL }, // end-of-list sentinel
|
||||
STATIC const mp_map_elem_t array_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_append), (mp_obj_t)&array_append_obj },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(array_locals_dict, array_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t mp_type_array = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_array,
|
||||
@@ -163,8 +164,8 @@ const mp_obj_type_t mp_type_array = {
|
||||
.unary_op = array_unary_op,
|
||||
.binary_op = array_binary_op,
|
||||
.store_item = array_store_item,
|
||||
.methods = array_type_methods,
|
||||
.buffer_p = { .get_buffer = array_get_buffer },
|
||||
.locals_dict = (mp_obj_t)&array_locals_dict,
|
||||
};
|
||||
|
||||
STATIC mp_obj_array_t *array_new(char typecode, uint n) {
|
||||
|
||||
37
py/objdict.c
37
py/objdict.c
@@ -7,14 +7,9 @@
|
||||
#include "mpconfig.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "map.h"
|
||||
#include "runtime0.h"
|
||||
#include "runtime.h"
|
||||
#include "map.h"
|
||||
|
||||
typedef struct _mp_obj_dict_t {
|
||||
mp_obj_base_t base;
|
||||
mp_map_t map;
|
||||
} mp_obj_dict_t;
|
||||
|
||||
STATIC mp_obj_t mp_obj_new_dict_iterator(mp_obj_dict_t *dict, int cur);
|
||||
STATIC mp_map_elem_t *dict_it_iternext_elem(mp_obj_t self_in);
|
||||
@@ -343,7 +338,6 @@ STATIC const mp_obj_type_t dict_view_it_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_iterator,
|
||||
.iternext = dict_view_it_iternext,
|
||||
.methods = NULL, /* set operations still to come */
|
||||
};
|
||||
|
||||
STATIC mp_obj_t dict_view_getiter(mp_obj_t view_in) {
|
||||
@@ -423,21 +417,22 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_values_obj, dict_values);
|
||||
/******************************************************************************/
|
||||
/* dict constructors & public C API */
|
||||
|
||||
STATIC const mp_method_t dict_type_methods[] = {
|
||||
{ MP_QSTR_clear, &dict_clear_obj },
|
||||
{ MP_QSTR_copy, &dict_copy_obj },
|
||||
{ MP_QSTR_fromkeys, &dict_fromkeys_obj },
|
||||
{ MP_QSTR_get, &dict_get_obj },
|
||||
{ MP_QSTR_items, &dict_items_obj },
|
||||
{ MP_QSTR_keys, &dict_keys_obj },
|
||||
{ MP_QSTR_pop, &dict_pop_obj },
|
||||
{ MP_QSTR_popitem, &dict_popitem_obj },
|
||||
{ MP_QSTR_setdefault, &dict_setdefault_obj },
|
||||
{ MP_QSTR_update, &dict_update_obj },
|
||||
{ MP_QSTR_values, &dict_values_obj },
|
||||
{ MP_QSTR_NULL, NULL }, // end-of-list sentinel
|
||||
STATIC const mp_map_elem_t dict_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_clear), (mp_obj_t)&dict_clear_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_copy), (mp_obj_t)&dict_copy_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_fromkeys), (mp_obj_t)&dict_fromkeys_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_get), (mp_obj_t)&dict_get_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_items), (mp_obj_t)&dict_items_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_keys), (mp_obj_t)&dict_keys_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_pop), (mp_obj_t)&dict_pop_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_popitem), (mp_obj_t)&dict_popitem_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_setdefault), (mp_obj_t)&dict_setdefault_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_update), (mp_obj_t)&dict_update_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_values), (mp_obj_t)&dict_values_obj },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(dict_locals_dict, dict_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t dict_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_dict,
|
||||
@@ -446,7 +441,7 @@ const mp_obj_type_t dict_type = {
|
||||
.unary_op = dict_unary_op,
|
||||
.binary_op = dict_binary_op,
|
||||
.getiter = dict_getiter,
|
||||
.methods = dict_type_methods,
|
||||
.locals_dict = (mp_obj_t)&dict_locals_dict,
|
||||
};
|
||||
|
||||
mp_obj_t mp_obj_new_dict(int n_args) {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "mpconfig.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "map.h"
|
||||
#include "runtime.h"
|
||||
#include "bc.h"
|
||||
#include "objgenerator.h"
|
||||
@@ -192,20 +193,21 @@ STATIC mp_obj_t gen_instance_close(mp_obj_t self_in) {
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(gen_instance_close_obj, gen_instance_close);
|
||||
|
||||
STATIC const mp_method_t gen_type_methods[] = {
|
||||
{ MP_QSTR_close, &gen_instance_close_obj },
|
||||
{ MP_QSTR_send, &gen_instance_send_obj },
|
||||
{ MP_QSTR_throw, &gen_instance_throw_obj },
|
||||
{ MP_QSTR_NULL, NULL }, // end-of-list sentinel
|
||||
STATIC const mp_map_elem_t gen_instance_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&gen_instance_close_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&gen_instance_send_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_throw), (mp_obj_t)&gen_instance_throw_obj },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(gen_instance_locals_dict, gen_instance_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t gen_instance_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_generator,
|
||||
.print = gen_instance_print,
|
||||
.getiter = gen_instance_getiter,
|
||||
.iternext = gen_instance_iternext,
|
||||
.methods = gen_type_methods,
|
||||
.locals_dict = (mp_obj_t)&gen_instance_locals_dict,
|
||||
};
|
||||
|
||||
mp_obj_t mp_obj_new_gen_instance(const byte *bytecode, uint n_state, int n_args, const mp_obj_t *args) {
|
||||
|
||||
29
py/objlist.c
29
py/objlist.c
@@ -328,21 +328,22 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(list_remove_obj, list_remove);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(list_reverse_obj, list_reverse);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(list_sort_obj, 0, mp_obj_list_sort);
|
||||
|
||||
STATIC const mp_method_t list_type_methods[] = {
|
||||
{ MP_QSTR_append, &list_append_obj },
|
||||
{ MP_QSTR_clear, &list_clear_obj },
|
||||
{ MP_QSTR_copy, &list_copy_obj },
|
||||
{ MP_QSTR_count, &list_count_obj },
|
||||
{ MP_QSTR_extend, &list_extend_obj },
|
||||
{ MP_QSTR_index, &list_index_obj },
|
||||
{ MP_QSTR_insert, &list_insert_obj },
|
||||
{ MP_QSTR_pop, &list_pop_obj },
|
||||
{ MP_QSTR_remove, &list_remove_obj },
|
||||
{ MP_QSTR_reverse, &list_reverse_obj },
|
||||
{ MP_QSTR_sort, &list_sort_obj },
|
||||
{ MP_QSTR_NULL, NULL }, // end-of-list sentinel
|
||||
STATIC const mp_map_elem_t list_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_append), (mp_obj_t)&list_append_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_clear), (mp_obj_t)&list_clear_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_copy), (mp_obj_t)&list_copy_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_count), (mp_obj_t)&list_count_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_extend), (mp_obj_t)&list_extend_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_index), (mp_obj_t)&list_index_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_insert), (mp_obj_t)&list_insert_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_pop), (mp_obj_t)&list_pop_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_remove), (mp_obj_t)&list_remove_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_reverse), (mp_obj_t)&list_reverse_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sort), (mp_obj_t)&list_sort_obj },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(list_locals_dict, list_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t list_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_list,
|
||||
@@ -351,7 +352,7 @@ const mp_obj_type_t list_type = {
|
||||
.unary_op = list_unary_op,
|
||||
.binary_op = list_binary_op,
|
||||
.getiter = list_getiter,
|
||||
.methods = list_type_methods,
|
||||
.locals_dict = (mp_obj_t)&list_locals_dict,
|
||||
};
|
||||
|
||||
STATIC mp_obj_list_t *list_new(uint n) {
|
||||
|
||||
41
py/objset.c
41
py/objset.c
@@ -423,27 +423,28 @@ STATIC mp_obj_t set_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) {
|
||||
/* set constructors & public C API */
|
||||
|
||||
|
||||
STATIC const mp_method_t set_type_methods[] = {
|
||||
{ MP_QSTR_add, &set_add_obj },
|
||||
{ MP_QSTR_clear, &set_clear_obj },
|
||||
{ MP_QSTR_copy, &set_copy_obj },
|
||||
{ MP_QSTR_discard, &set_discard_obj },
|
||||
{ MP_QSTR_difference, &set_diff_obj },
|
||||
{ MP_QSTR_difference_update, &set_diff_update_obj },
|
||||
{ MP_QSTR_intersection, &set_intersect_obj },
|
||||
{ MP_QSTR_intersection_update, &set_intersect_update_obj },
|
||||
{ MP_QSTR_isdisjoint, &set_isdisjoint_obj },
|
||||
{ MP_QSTR_issubset, &set_issubset_obj },
|
||||
{ MP_QSTR_issuperset, &set_issuperset_obj },
|
||||
{ MP_QSTR_pop, &set_pop_obj },
|
||||
{ MP_QSTR_remove, &set_remove_obj },
|
||||
{ MP_QSTR_symmetric_difference, &set_symmetric_difference_obj },
|
||||
{ MP_QSTR_symmetric_difference_update, &set_symmetric_difference_update_obj },
|
||||
{ MP_QSTR_union, &set_union_obj },
|
||||
{ MP_QSTR_update, &set_update_obj },
|
||||
{ MP_QSTR_NULL, NULL }, // end-of-list sentinel
|
||||
STATIC const mp_map_elem_t set_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_add), (mp_obj_t)&set_add_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_clear), (mp_obj_t)&set_clear_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_copy), (mp_obj_t)&set_copy_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_discard), (mp_obj_t)&set_discard_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_difference), (mp_obj_t)&set_diff_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_difference_update), (mp_obj_t)&set_diff_update_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_intersection), (mp_obj_t)&set_intersect_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_intersection_update), (mp_obj_t)&set_intersect_update_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_isdisjoint), (mp_obj_t)&set_isdisjoint_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_issubset), (mp_obj_t)&set_issubset_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_issuperset), (mp_obj_t)&set_issuperset_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_pop), (mp_obj_t)&set_pop_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_remove), (mp_obj_t)&set_remove_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_symmetric_difference), (mp_obj_t)&set_symmetric_difference_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_symmetric_difference_update), (mp_obj_t)&set_symmetric_difference_update_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_union), (mp_obj_t)&set_union_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_update), (mp_obj_t)&set_update_obj },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(set_locals_dict, set_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t set_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_set,
|
||||
@@ -451,7 +452,7 @@ const mp_obj_type_t set_type = {
|
||||
.make_new = set_make_new,
|
||||
.binary_op = set_binary_op,
|
||||
.getiter = set_getiter,
|
||||
.methods = set_type_methods,
|
||||
.locals_dict = (mp_obj_t)&set_locals_dict,
|
||||
};
|
||||
|
||||
mp_obj_t mp_obj_new_set(int n_args, mp_obj_t *items) {
|
||||
|
||||
32
py/objstr.c
32
py/objstr.c
@@ -7,6 +7,7 @@
|
||||
#include "mpconfig.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "map.h"
|
||||
#include "runtime0.h"
|
||||
#include "runtime.h"
|
||||
|
||||
@@ -693,21 +694,22 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_count_obj, 2, 4, str_count);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_partition_obj, str_partition);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_rpartition_obj, str_rpartition);
|
||||
|
||||
STATIC const mp_method_t str_type_methods[] = {
|
||||
{ MP_QSTR_find, &str_find_obj },
|
||||
{ MP_QSTR_rfind, &str_rfind_obj },
|
||||
{ MP_QSTR_join, &str_join_obj },
|
||||
{ MP_QSTR_split, &str_split_obj },
|
||||
{ MP_QSTR_startswith, &str_startswith_obj },
|
||||
{ MP_QSTR_strip, &str_strip_obj },
|
||||
{ MP_QSTR_format, &str_format_obj },
|
||||
{ MP_QSTR_replace, &str_replace_obj },
|
||||
{ MP_QSTR_count, &str_count_obj },
|
||||
{ MP_QSTR_partition, &str_partition_obj },
|
||||
{ MP_QSTR_rpartition, &str_rpartition_obj },
|
||||
{ MP_QSTR_NULL, NULL }, // end-of-list sentinel
|
||||
STATIC const mp_map_elem_t str_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_find), (mp_obj_t)&str_find_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_rfind), (mp_obj_t)&str_rfind_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_join), (mp_obj_t)&str_join_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_split), (mp_obj_t)&str_split_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_startswith), (mp_obj_t)&str_startswith_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_strip), (mp_obj_t)&str_strip_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_format), (mp_obj_t)&str_format_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_replace), (mp_obj_t)&str_replace_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_count), (mp_obj_t)&str_count_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_partition), (mp_obj_t)&str_partition_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_rpartition), (mp_obj_t)&str_rpartition_obj },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(str_locals_dict, str_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t str_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_str,
|
||||
@@ -715,8 +717,8 @@ const mp_obj_type_t str_type = {
|
||||
.make_new = str_make_new,
|
||||
.binary_op = str_binary_op,
|
||||
.getiter = mp_obj_new_str_iterator,
|
||||
.methods = str_type_methods,
|
||||
.buffer_p = { .get_buffer = str_get_buffer },
|
||||
.locals_dict = (mp_obj_t)&str_locals_dict,
|
||||
};
|
||||
|
||||
// Reuses most of methods from str
|
||||
@@ -727,7 +729,7 @@ const mp_obj_type_t bytes_type = {
|
||||
.make_new = bytes_make_new,
|
||||
.binary_op = str_binary_op,
|
||||
.getiter = mp_obj_new_bytes_iterator,
|
||||
.methods = str_type_methods,
|
||||
.locals_dict = (mp_obj_t)&str_locals_dict,
|
||||
};
|
||||
|
||||
// the zero-length bytes
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "mpconfig.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "map.h"
|
||||
#include "runtime0.h"
|
||||
#include "runtime.h"
|
||||
#include "objtuple.h"
|
||||
@@ -165,12 +166,13 @@ STATIC mp_obj_t tuple_index(uint n_args, const mp_obj_t *args) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(tuple_index_obj, 2, 4, tuple_index);
|
||||
|
||||
STATIC const mp_method_t tuple_type_methods[] = {
|
||||
{ MP_QSTR_count, &tuple_count_obj },
|
||||
{ MP_QSTR_index, &tuple_index_obj },
|
||||
{ MP_QSTR_NULL, NULL }, // end-of-list sentinel
|
||||
STATIC const mp_map_elem_t tuple_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_count), (mp_obj_t)&tuple_count_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_index), (mp_obj_t)&tuple_index_obj },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(tuple_locals_dict, tuple_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t tuple_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_tuple,
|
||||
@@ -179,7 +181,7 @@ const mp_obj_type_t tuple_type = {
|
||||
.unary_op = tuple_unary_op,
|
||||
.binary_op = tuple_binary_op,
|
||||
.getiter = tuple_getiter,
|
||||
.methods = tuple_type_methods,
|
||||
.locals_dict = (mp_obj_t)&tuple_locals_dict,
|
||||
};
|
||||
|
||||
// the zero-length tuple
|
||||
|
||||
@@ -38,6 +38,7 @@ STATIC mp_obj_t mp_obj_class_lookup(const mp_obj_type_t *type, qstr attr) {
|
||||
if (elem != NULL) {
|
||||
return elem->value;
|
||||
}
|
||||
/*
|
||||
} else if (type->methods != NULL) {
|
||||
// search methods (the const set of methods)
|
||||
|
||||
@@ -46,6 +47,7 @@ STATIC mp_obj_t mp_obj_class_lookup(const mp_obj_type_t *type, qstr attr) {
|
||||
return (mp_obj_t)meth->fun;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// attribute not found, keep searching base classes
|
||||
|
||||
37
py/runtime.c
37
py/runtime.c
@@ -845,25 +845,24 @@ STATIC void rt_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest) {
|
||||
} else if (type->load_attr == NULL) {
|
||||
// generic method lookup if type didn't provide a specific one
|
||||
// this is a lookup in the object (ie not class or type)
|
||||
const mp_method_t *meth = type->methods;
|
||||
if (meth != NULL) {
|
||||
for (; meth->name != MP_QSTR_NULL; meth++) {
|
||||
if (meth->name == attr) {
|
||||
// check if the methods are functions, static or class methods
|
||||
// see http://docs.python.org/3.3/howto/descriptor.html
|
||||
if (MP_OBJ_IS_TYPE(meth->fun, &mp_type_staticmethod)) {
|
||||
// return just the function
|
||||
dest[0] = ((mp_obj_static_class_method_t*)meth->fun)->fun;
|
||||
} else if (MP_OBJ_IS_TYPE(meth->fun, &mp_type_classmethod)) {
|
||||
// return a bound method, with self being the type of this object
|
||||
dest[0] = ((mp_obj_static_class_method_t*)meth->fun)->fun;
|
||||
dest[1] = mp_obj_get_type(base);
|
||||
} else {
|
||||
// return a bound method, with self being this object
|
||||
dest[0] = (mp_obj_t)meth->fun;
|
||||
dest[1] = base;
|
||||
}
|
||||
break;
|
||||
if (type->locals_dict != NULL) {
|
||||
assert(MP_OBJ_IS_TYPE(type->locals_dict, &dict_type)); // Micro Python restriction, for now
|
||||
mp_map_t *locals_map = mp_obj_dict_get_map(type->locals_dict);
|
||||
mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
|
||||
if (elem != NULL) {
|
||||
// check if the methods are functions, static or class methods
|
||||
// see http://docs.python.org/3.3/howto/descriptor.html
|
||||
if (MP_OBJ_IS_TYPE(elem->value, &mp_type_staticmethod)) {
|
||||
// return just the function
|
||||
dest[0] = ((mp_obj_static_class_method_t*)elem->value)->fun;
|
||||
} else if (MP_OBJ_IS_TYPE(elem->value, &mp_type_classmethod)) {
|
||||
// return a bound method, with self being the type of this object
|
||||
dest[0] = ((mp_obj_static_class_method_t*)elem->value)->fun;
|
||||
dest[1] = mp_obj_get_type(base);
|
||||
} else {
|
||||
// return a bound method, with self being this object
|
||||
dest[0] = (mp_obj_t)elem->value;
|
||||
dest[1] = base;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user