diff options
Diffstat (limited to 'py')
-rw-r--r-- | py/builtin.c | 32 | ||||
-rw-r--r-- | py/builtin.h | 1 | ||||
-rw-r--r-- | py/builtintables.c | 1 | ||||
-rw-r--r-- | py/map.h | 5 | ||||
-rw-r--r-- | py/obj.h | 17 | ||||
-rw-r--r-- | py/objarray.c | 9 | ||||
-rw-r--r-- | py/objdict.c | 37 | ||||
-rw-r--r-- | py/objgenerator.c | 14 | ||||
-rw-r--r-- | py/objlist.c | 29 | ||||
-rw-r--r-- | py/objset.c | 41 | ||||
-rw-r--r-- | py/objstr.c | 32 | ||||
-rw-r--r-- | py/objtuple.c | 12 | ||||
-rw-r--r-- | py/objtype.c | 77 | ||||
-rw-r--r-- | py/qstrdefs.h | 1 | ||||
-rw-r--r-- | py/runtime.c | 40 |
15 files changed, 182 insertions, 166 deletions
diff --git a/py/builtin.c b/py/builtin.c index 1e022becb..e8746c55c 100644 --- a/py/builtin.c +++ b/py/builtin.c @@ -152,20 +152,23 @@ 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(); } else { // n_args == 1 // make a list of names in the given object - mp_obj_type_t *type = mp_obj_get_type(args[0]); - if (type == &mp_type_module) { + if (MP_OBJ_IS_TYPE(args[0], &mp_type_module)) { map = mp_obj_module_get_globals(args[0]); - } 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; + } else { + mp_obj_type_t *type; + if (MP_OBJ_IS_TYPE(args[0], &mp_type_type)) { + type = args[0]; + } else { + type = mp_obj_get_type(args[0]); + } + 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); + } } } @@ -177,11 +180,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; } @@ -389,3 +388,10 @@ STATIC mp_obj_t mp_builtin_id(mp_obj_t o_in) { } MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_id_obj, mp_builtin_id); + +STATIC mp_obj_t mp_builtin_getattr(mp_obj_t o_in, mp_obj_t attr) { + assert(MP_OBJ_IS_QSTR(attr)); + return rt_load_attr(o_in, MP_OBJ_QSTR_VALUE(attr)); +} + +MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_getattr_obj, mp_builtin_getattr); diff --git a/py/builtin.h b/py/builtin.h index 45da172d1..50269dfe1 100644 --- a/py/builtin.h +++ b/py/builtin.h @@ -12,6 +12,7 @@ MP_DECLARE_CONST_FUN_OBJ(mp_builtin_dir_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_divmod_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_eval_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_exec_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_getattr_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_hash_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_id_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_isinstance_obj); diff --git a/py/builtintables.c b/py/builtintables.c index 0aa0b66a7..fd94f7678 100644 --- a/py/builtintables.c +++ b/py/builtintables.c @@ -60,6 +60,7 @@ STATIC const mp_builtin_elem_t builtin_object_table[] = { { MP_QSTR_divmod, (mp_obj_t)&mp_builtin_divmod_obj }, { MP_QSTR_eval, (mp_obj_t)&mp_builtin_eval_obj }, { MP_QSTR_exec, (mp_obj_t)&mp_builtin_exec_obj }, + { MP_QSTR_getattr, (mp_obj_t)&mp_builtin_getattr_obj }, { MP_QSTR_hash, (mp_obj_t)&mp_builtin_hash_obj }, { MP_QSTR_id, (mp_obj_t)&mp_builtin_id_obj }, { MP_QSTR_isinstance, (mp_obj_t)&mp_builtin_isinstance_obj }, @@ -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); @@ -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; diff --git a/py/objarray.c b/py/objarray.c index 9d795c1bf..eed21d946 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -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) { diff --git a/py/objdict.c b/py/objdict.c index 14d120a77..190d90105 100644 --- a/py/objdict.c +++ b/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) { diff --git a/py/objgenerator.c b/py/objgenerator.c index f440923ee..9f609ce50 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -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) { diff --git a/py/objlist.c b/py/objlist.c index afc4f3cf8..6677a8f8c 100644 --- a/py/objlist.c +++ b/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) { diff --git a/py/objset.c b/py/objset.c index 250d13247..e6071e538 100644 --- a/py/objset.c +++ b/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) { diff --git a/py/objstr.c b/py/objstr.c index d8b391d44..6812516b4 100644 --- a/py/objstr.c +++ b/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 diff --git a/py/objtuple.c b/py/objtuple.c index 334cf0562..eb3d8259a 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -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 diff --git a/py/objtype.c b/py/objtype.c index ceec78ea3..4c709c7ab 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -30,22 +30,13 @@ STATIC mp_obj_t mp_obj_new_class(mp_obj_t class) { STATIC mp_obj_t mp_obj_class_lookup(const mp_obj_type_t *type, qstr attr) { for (;;) { if (type->locals_dict != NULL) { - // search locals_dict (the dynamically created set of methods/attributes) - + // search locals_dict (the set of methods/attributes) 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) { return elem->value; } - } else if (type->methods != NULL) { - // search methods (the const set of methods) - - for (const mp_method_t *meth = type->methods; meth->name != MP_QSTR_NULL; meth++) { - if (meth->name == attr) { - return (mp_obj_t)meth->fun; - } - } } // attribute not found, keep searching base classes @@ -218,24 +209,20 @@ STATIC void class_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } mp_obj_t member = mp_obj_class_lookup(self->base.type, attr); if (member != MP_OBJ_NULL) { - if (mp_obj_is_callable(member)) { - // class member is callable so build a bound method - // check if the methods are functions, static or class methods - // see http://docs.python.org/3.3/howto/descriptor.html - // TODO check that this is the correct place to have this logic - if (MP_OBJ_IS_TYPE(member, &mp_type_staticmethod)) { - // return just the function - dest[0] = ((mp_obj_static_class_method_t*)member)->fun; - } else if (MP_OBJ_IS_TYPE(member, &mp_type_classmethod)) { - // return a bound method, with self being the type of this object - dest[0] = ((mp_obj_static_class_method_t*)member)->fun; - dest[1] = mp_obj_get_type(self_in); - } else { - // return a bound method, with self being this object - dest[0] = member; - dest[1] = self_in; - } - return; + // check if the methods are functions, static or class methods + // see http://docs.python.org/3.3/howto/descriptor.html + // TODO check that this is the correct place to have this logic + if (MP_OBJ_IS_TYPE(member, &mp_type_staticmethod)) { + // return just the function + dest[0] = ((mp_obj_static_class_method_t*)member)->fun; + } else if (MP_OBJ_IS_TYPE(member, &mp_type_classmethod)) { + // return a bound method, with self being the type of this object + dest[0] = ((mp_obj_static_class_method_t*)member)->fun; + dest[1] = mp_obj_get_type(self_in); + } else if (mp_obj_is_callable(member)) { + // return a bound method, with self being this object + dest[0] = member; + dest[1] = self_in; } else { // class member is a value, so just return that value dest[0] = member; @@ -423,29 +410,25 @@ STATIC void super_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { mp_obj_t member = mp_obj_class_lookup((mp_obj_type_t*)items[i], attr); if (member != MP_OBJ_NULL) { // XXX this and the code in class_load_attr need to be factored out - if (mp_obj_is_callable(member)) { - // class member is callable so build a bound method - // check if the methods are functions, static or class methods - // see http://docs.python.org/3.3/howto/descriptor.html - // TODO check that this is the correct place to have this logic - if (MP_OBJ_IS_TYPE(member, &mp_type_staticmethod)) { - // return just the function - dest[0] = ((mp_obj_static_class_method_t*)member)->fun; - } else if (MP_OBJ_IS_TYPE(member, &mp_type_classmethod)) { - // return a bound method, with self being the type of this object - dest[0] = ((mp_obj_static_class_method_t*)member)->fun; - dest[1] = mp_obj_get_type(self->obj); - } else { - // return a bound method, with self being this object - dest[0] = member; - dest[1] = self->obj; - } - return; + // check if the methods are functions, static or class methods + // see http://docs.python.org/3.3/howto/descriptor.html + // TODO check that this is the correct place to have this logic + if (MP_OBJ_IS_TYPE(member, &mp_type_staticmethod)) { + // return just the function + dest[0] = ((mp_obj_static_class_method_t*)member)->fun; + } else if (MP_OBJ_IS_TYPE(member, &mp_type_classmethod)) { + // return a bound method, with self being the type of this object + dest[0] = ((mp_obj_static_class_method_t*)member)->fun; + dest[1] = mp_obj_get_type(self->obj); + } if (mp_obj_is_callable(member)) { + // return a bound method, with self being this object + dest[0] = member; + dest[1] = self->obj; } else { // class member is a value, so just return that value dest[0] = member; - return; } + return; } } } diff --git a/py/qstrdefs.h b/py/qstrdefs.h index a2cdf8425..3be629506 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -92,6 +92,7 @@ Q(eval) Q(exec) Q(filter) Q(float) +Q(getattr) Q(hash) Q(id) Q(int) diff --git a/py/runtime.c b/py/runtime.c index eab414c9e..3fc7d6ac0 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -845,25 +845,27 @@ 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 if (mp_obj_is_callable(elem->value)) { + // return a bound method, with self being this object + dest[0] = elem->value; + dest[1] = base; + } else { + // class member is a value, so just return that value + dest[0] = elem->value; } } } |