py: Stuff qstr in object pointer; keys for mp_map_t are now always mp_obj_t.
This commit is contained in:
parent
ea9e441a75
commit
38a2da68c2
@ -23,7 +23,7 @@ mp_obj_t mp_builtin___build_class__(int n_args, const mp_obj_t *args) {
|
||||
|
||||
// we differ from CPython: we set the new __locals__ object here
|
||||
mp_map_t *old_locals = rt_locals_get();
|
||||
mp_map_t *class_locals = mp_map_new(MP_MAP_QSTR, 0);
|
||||
mp_map_t *class_locals = mp_map_new(0);
|
||||
rt_locals_set(class_locals);
|
||||
|
||||
// call the class code
|
||||
|
39
py/map.c
39
py/map.c
@ -26,21 +26,22 @@ int get_doubling_prime_greater_or_equal_to(int x) {
|
||||
/******************************************************************************/
|
||||
/* map */
|
||||
|
||||
void mp_map_init(mp_map_t *map, mp_map_kind_t kind, int n) {
|
||||
map->kind = kind;
|
||||
map->used = 0;
|
||||
void mp_map_init(mp_map_t *map, int n) {
|
||||
map->alloc = get_doubling_prime_greater_or_equal_to(n + 1);
|
||||
map->used = 0;
|
||||
map->all_keys_are_qstrs = 1;
|
||||
map->table = m_new0(mp_map_elem_t, map->alloc);
|
||||
}
|
||||
|
||||
mp_map_t *mp_map_new(mp_map_kind_t kind, int n) {
|
||||
mp_map_t *mp_map_new(int n) {
|
||||
mp_map_t *map = m_new(mp_map_t, 1);
|
||||
mp_map_init(map, kind, n);
|
||||
mp_map_init(map, n);
|
||||
return map;
|
||||
}
|
||||
|
||||
void mp_map_clear(mp_map_t *map) {
|
||||
map->used = 0;
|
||||
map->all_keys_are_qstrs = 1;
|
||||
machine_uint_t a = map->alloc;
|
||||
map->alloc = 0;
|
||||
map->table = m_renew(mp_map_elem_t, map->table, a, map->alloc);
|
||||
@ -55,25 +56,21 @@ static void mp_map_rehash (mp_map_t *map) {
|
||||
mp_map_elem_t *old_table = map->table;
|
||||
map->alloc = get_doubling_prime_greater_or_equal_to(map->alloc + 1);
|
||||
map->used = 0;
|
||||
map->all_keys_are_qstrs = 1;
|
||||
map->table = m_new0(mp_map_elem_t, map->alloc);
|
||||
for (int i = 0; i < old_alloc; i++) {
|
||||
if (old_table[i].key != NULL) {
|
||||
mp_map_lookup_helper(map, old_table[i].key, true, false)->value = old_table[i].value;
|
||||
mp_map_lookup(map, old_table[i].key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = old_table[i].value;
|
||||
}
|
||||
}
|
||||
m_del(mp_map_elem_t, old_table, old_alloc);
|
||||
}
|
||||
|
||||
mp_map_elem_t* mp_map_lookup_helper(mp_map_t *map, mp_obj_t index, bool add_if_not_found, bool remove_if_found) {
|
||||
bool is_map_mp_obj = (map->kind == MP_MAP_OBJ);
|
||||
mp_map_elem_t* mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t lookup_kind) {
|
||||
machine_uint_t hash;
|
||||
if (is_map_mp_obj) {
|
||||
hash = mp_obj_hash(index);
|
||||
} else {
|
||||
hash = (machine_uint_t)index;
|
||||
}
|
||||
if (map->alloc == 0) {
|
||||
if (add_if_not_found) {
|
||||
if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {
|
||||
mp_map_rehash(map);
|
||||
} else {
|
||||
return NULL;
|
||||
@ -84,7 +81,7 @@ mp_map_elem_t* mp_map_lookup_helper(mp_map_t *map, mp_obj_t index, bool add_if_n
|
||||
mp_map_elem_t *elem = &map->table[pos];
|
||||
if (elem->key == NULL) {
|
||||
// not in table
|
||||
if (add_if_not_found) {
|
||||
if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {
|
||||
if (map->used + 1 >= map->alloc) {
|
||||
// not enough room in table, rehash it
|
||||
mp_map_rehash(map);
|
||||
@ -93,21 +90,24 @@ mp_map_elem_t* mp_map_lookup_helper(mp_map_t *map, mp_obj_t index, bool add_if_n
|
||||
} else {
|
||||
map->used += 1;
|
||||
elem->key = index;
|
||||
if (!MP_OBJ_IS_QSTR(index)) {
|
||||
map->all_keys_are_qstrs = 0;
|
||||
}
|
||||
return elem;
|
||||
}
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
} else if (elem->key == index || (is_map_mp_obj && mp_obj_equal(elem->key, index))) {
|
||||
} else if (elem->key == index || (!map->all_keys_are_qstrs && mp_obj_equal(elem->key, index))) {
|
||||
// found it
|
||||
/* it seems CPython does not replace the index; try x={True:'true'};x[1]='one';x
|
||||
if (add_if_not_found) {
|
||||
elem->key = index;
|
||||
}
|
||||
*/
|
||||
if (remove_if_found) {
|
||||
if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) {
|
||||
map->used--;
|
||||
/* this leaks this memory (but see dict_get_helper) */
|
||||
// this leaks this memory (but see dict_get_helper)
|
||||
mp_map_elem_t *retval = m_new(mp_map_elem_t, 1);
|
||||
retval->key = elem->key;
|
||||
retval->value = elem->value;
|
||||
@ -123,11 +123,6 @@ mp_map_elem_t* mp_map_lookup_helper(mp_map_t *map, mp_obj_t index, bool add_if_n
|
||||
}
|
||||
}
|
||||
|
||||
mp_map_elem_t* mp_qstr_map_lookup(mp_map_t *map, qstr index, bool add_if_not_found) {
|
||||
mp_obj_t o = (mp_obj_t)(machine_uint_t)index;
|
||||
return mp_map_lookup_helper(map, o, add_if_not_found, false);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* set */
|
||||
|
||||
|
22
py/map.h
22
py/map.h
@ -1,8 +1,3 @@
|
||||
typedef enum {
|
||||
MP_MAP_QSTR,
|
||||
MP_MAP_OBJ,
|
||||
} mp_map_kind_t;
|
||||
|
||||
typedef struct _mp_map_elem_t {
|
||||
mp_obj_t key;
|
||||
mp_obj_t value;
|
||||
@ -10,8 +5,8 @@ typedef struct _mp_map_elem_t {
|
||||
|
||||
typedef struct _mp_map_t {
|
||||
struct {
|
||||
mp_map_kind_t kind : 1;
|
||||
machine_uint_t used : (8 * BYTES_PER_WORD - 1);
|
||||
machine_uint_t all_keys_are_qstrs : 1;
|
||||
machine_uint_t used : (8 * sizeof(machine_uint_t) - 1);
|
||||
};
|
||||
machine_uint_t alloc;
|
||||
mp_map_elem_t *table;
|
||||
@ -23,11 +18,16 @@ typedef struct _mp_set_t {
|
||||
mp_obj_t *table;
|
||||
} mp_set_t;
|
||||
|
||||
typedef enum {
|
||||
MP_MAP_LOOKUP,
|
||||
MP_MAP_LOOKUP_ADD_IF_NOT_FOUND,
|
||||
MP_MAP_LOOKUP_REMOVE_IF_FOUND,
|
||||
} mp_map_lookup_kind_t;
|
||||
|
||||
int get_doubling_prime_greater_or_equal_to(int x);
|
||||
void mp_map_init(mp_map_t *map, mp_map_kind_t kind, int n);
|
||||
mp_map_t *mp_map_new(mp_map_kind_t kind, int n);
|
||||
mp_map_elem_t* mp_map_lookup_helper(mp_map_t *map, mp_obj_t index, bool add_if_not_found, bool remove_if_found);
|
||||
mp_map_elem_t* mp_qstr_map_lookup(mp_map_t *map, qstr index, bool add_if_not_found);
|
||||
void mp_map_init(mp_map_t *map, int n);
|
||||
mp_map_t *mp_map_new(int n);
|
||||
mp_map_elem_t* mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t lookup_kind);
|
||||
void mp_map_clear(mp_map_t *map);
|
||||
|
||||
void mp_set_init(mp_set_t *set, int n);
|
||||
|
6
py/obj.c
6
py/obj.c
@ -16,6 +16,8 @@
|
||||
mp_obj_t mp_obj_get_type(mp_obj_t o_in) {
|
||||
if (MP_OBJ_IS_SMALL_INT(o_in)) {
|
||||
return (mp_obj_t)&int_type;
|
||||
} else if (MP_OBJ_IS_QSTR(o_in)) {
|
||||
return (mp_obj_t)&str_type;
|
||||
} else {
|
||||
mp_obj_base_t *o = o_in;
|
||||
return (mp_obj_t)o->type;
|
||||
@ -71,6 +73,8 @@ machine_int_t mp_obj_hash(mp_obj_t o_in) {
|
||||
return 1; // needs to hash to same as the integer 1, since True==1
|
||||
} else if (MP_OBJ_IS_SMALL_INT(o_in)) {
|
||||
return MP_OBJ_SMALL_INT_VALUE(o_in);
|
||||
} else if (MP_OBJ_IS_QSTR(o_in)) {
|
||||
return MP_OBJ_QSTR_VALUE(o_in);
|
||||
} else if (MP_OBJ_IS_TYPE(o_in, &none_type)) {
|
||||
return (machine_int_t)o_in;
|
||||
} else if (MP_OBJ_IS_TYPE(o_in, &str_type)) {
|
||||
@ -107,6 +111,8 @@ bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (MP_OBJ_IS_QSTR(o1) || MP_OBJ_IS_QSTR(o2)) {
|
||||
return false;
|
||||
} else if (MP_OBJ_IS_TYPE(o1, &str_type) && MP_OBJ_IS_TYPE(o2, &str_type)) {
|
||||
return mp_obj_str_get(o1) == mp_obj_str_get(o2);
|
||||
} else {
|
||||
|
16
py/obj.h
16
py/obj.h
@ -29,13 +29,21 @@ typedef struct _mp_obj_base_t mp_obj_base_t;
|
||||
|
||||
#define MP_OBJ_NULL ((mp_obj_t)NULL)
|
||||
|
||||
// These macros check for small int or object, and access small int values
|
||||
// These macros check for small int, qstr or object, and access small int and qstr values
|
||||
// - xxxx...xxx1: a small int, bits 1 and above are the value
|
||||
// - xxxx...xx10: a qstr, bits 2 and above are the value
|
||||
// - xxxx...xx00: a pointer to an mp_obj_base_t
|
||||
|
||||
#define MP_OBJ_IS_OBJ(o) ((((mp_small_int_t)(o)) & 1) == 0)
|
||||
#define MP_OBJ_IS_SMALL_INT(o) ((((mp_small_int_t)(o)) & 1) != 0)
|
||||
#define MP_OBJ_IS_TYPE(o, t) (((((mp_small_int_t)(o)) & 1) == 0) && (((mp_obj_base_t*)(o))->type == (t)))
|
||||
#define MP_OBJ_IS_QSTR(o) ((((mp_small_int_t)(o)) & 3) == 2)
|
||||
#define MP_OBJ_IS_OBJ(o) ((((mp_small_int_t)(o)) & 3) == 0)
|
||||
#define MP_OBJ_IS_TYPE(o, t) (MP_OBJ_IS_OBJ(o) && (((mp_obj_base_t*)(o))->type == (t)))
|
||||
|
||||
#define MP_OBJ_SMALL_INT_VALUE(o) (((mp_small_int_t)(o)) >> 1)
|
||||
#define MP_OBJ_NEW_SMALL_INT(o) ((mp_obj_t)(((o) << 1) | 1))
|
||||
#define MP_OBJ_NEW_SMALL_INT(small_int) ((mp_obj_t)(((small_int) << 1) | 1))
|
||||
|
||||
#define MP_OBJ_QSTR_VALUE(o) (((mp_small_int_t)(o)) >> 2)
|
||||
#define MP_OBJ_NEW_QSTR(qstr) ((mp_obj_t)((((machine_uint_t)qstr) << 2) | 2))
|
||||
|
||||
// These macros are used to declare and define constant function objects
|
||||
// You can put "static" in front of the definitions to make them local
|
||||
|
@ -26,7 +26,7 @@ mp_obj_t class_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args) {
|
||||
mp_obj_t o = mp_obj_new_instance(self_in);
|
||||
|
||||
// look for __init__ function
|
||||
mp_map_elem_t *init_fn = mp_qstr_map_lookup(self->locals, MP_QSTR___init__, false);
|
||||
mp_map_elem_t *init_fn = mp_map_lookup(self->locals, MP_OBJ_NEW_QSTR(MP_QSTR___init__), MP_MAP_LOOKUP);
|
||||
|
||||
if (init_fn != NULL) {
|
||||
// call __init__ function
|
||||
|
26
py/objdict.c
26
py/objdict.c
@ -50,7 +50,7 @@ static mp_obj_t dict_binary_op(int op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||
case RT_BINARY_OP_SUBSCR:
|
||||
{
|
||||
// dict load
|
||||
mp_map_elem_t *elem = mp_map_lookup_helper(&o->map, rhs_in, false, false);
|
||||
mp_map_elem_t *elem = mp_map_lookup(&o->map, rhs_in, MP_MAP_LOOKUP);
|
||||
if (elem == NULL) {
|
||||
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_KeyError, "<value>"));
|
||||
} else {
|
||||
@ -139,12 +139,12 @@ static mp_obj_t dict_copy(mp_obj_t self_in) {
|
||||
}
|
||||
static MP_DEFINE_CONST_FUN_OBJ_1(dict_copy_obj, dict_copy);
|
||||
|
||||
static mp_obj_t dict_get_helper(mp_map_t *self, mp_obj_t key, mp_obj_t deflt, bool pop, bool set) {
|
||||
mp_map_elem_t *elem = mp_map_lookup_helper(self, key, set, pop);
|
||||
static mp_obj_t dict_get_helper(mp_map_t *self, mp_obj_t key, mp_obj_t deflt, mp_map_lookup_kind_t lookup_kind) {
|
||||
mp_map_elem_t *elem = mp_map_lookup(self, key, lookup_kind);
|
||||
mp_obj_t value;
|
||||
if (elem == NULL || elem->value == NULL) {
|
||||
if (deflt == NULL) {
|
||||
if (pop) {
|
||||
if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) {
|
||||
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_KeyError, "<value>"));
|
||||
} else {
|
||||
value = mp_const_none;
|
||||
@ -154,12 +154,12 @@ static mp_obj_t dict_get_helper(mp_map_t *self, mp_obj_t key, mp_obj_t deflt, bo
|
||||
}
|
||||
} else {
|
||||
value = elem->value;
|
||||
if (pop) {
|
||||
/* catch the leak (from mp_map_lookup_helper) */
|
||||
if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) {
|
||||
// catch the leak (from mp_map_lookup)
|
||||
m_free(elem, sizeof(mp_map_elem_t));
|
||||
}
|
||||
}
|
||||
if (set) {
|
||||
if (lookup_kind == MP_MAP_LOOKUP_ADD_IF_NOT_FOUND) {
|
||||
elem->value = value;
|
||||
}
|
||||
return value;
|
||||
@ -172,7 +172,7 @@ static mp_obj_t dict_get(int n_args, const mp_obj_t *args) {
|
||||
return dict_get_helper(&((mp_obj_dict_t *)args[0])->map,
|
||||
args[1],
|
||||
n_args == 3 ? args[2] : NULL,
|
||||
false, false);
|
||||
MP_MAP_LOOKUP);
|
||||
}
|
||||
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_get_obj, 2, 3, dict_get);
|
||||
|
||||
@ -183,7 +183,7 @@ static mp_obj_t dict_pop(int n_args, const mp_obj_t *args) {
|
||||
return dict_get_helper(&((mp_obj_dict_t *)args[0])->map,
|
||||
args[1],
|
||||
n_args == 3 ? args[2] : NULL,
|
||||
true, false);
|
||||
MP_MAP_LOOKUP_REMOVE_IF_FOUND);
|
||||
}
|
||||
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_pop_obj, 2, 3, dict_pop);
|
||||
|
||||
@ -195,7 +195,7 @@ static mp_obj_t dict_setdefault(int n_args, const mp_obj_t *args) {
|
||||
return dict_get_helper(&((mp_obj_dict_t *)args[0])->map,
|
||||
args[1],
|
||||
n_args == 3 ? args[2] : NULL,
|
||||
false, true);
|
||||
MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
|
||||
}
|
||||
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_setdefault_obj, 2, 3, dict_setdefault);
|
||||
|
||||
@ -237,7 +237,7 @@ static mp_obj_t dict_update(mp_obj_t self_in, mp_obj_t iterable) {
|
||||
MP_QSTR_ValueError,
|
||||
"dictionary update sequence has the wrong length"));
|
||||
} else {
|
||||
mp_map_lookup_helper(&self->map, key, true, false)->value = value;
|
||||
mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -273,7 +273,7 @@ const mp_obj_type_t dict_type = {
|
||||
mp_obj_t mp_obj_new_dict(int n_args) {
|
||||
mp_obj_dict_t *o = m_new_obj(mp_obj_dict_t);
|
||||
o->base.type = &dict_type;
|
||||
mp_map_init(&o->map, MP_MAP_OBJ, n_args);
|
||||
mp_map_init(&o->map, n_args);
|
||||
return o;
|
||||
}
|
||||
|
||||
@ -284,6 +284,6 @@ uint mp_obj_dict_len(mp_obj_t self_in) {
|
||||
mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) {
|
||||
assert(MP_OBJ_IS_TYPE(self_in, &dict_type));
|
||||
mp_obj_dict_t *self = self_in;
|
||||
mp_map_lookup_helper(&self->map, key, true, false)->value = value;
|
||||
mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
|
||||
return self_in;
|
||||
}
|
||||
|
@ -81,13 +81,13 @@ mp_obj_t fun_native_call_n_kw(mp_obj_t self_in, int n_args, int n_kw, const mp_o
|
||||
}
|
||||
|
||||
mp_obj_t *vargs = mp_obj_new_tuple_reverse(n_args, args + 2*n_kw);
|
||||
mp_map_t *kw_args = mp_map_new(MP_MAP_QSTR, 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_qstr_map_lookup(kw_args, name, true)->value = args[i];
|
||||
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 */
|
||||
// TODO clean up vargs and kw_args
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -30,12 +30,12 @@ type needs to be specified dynamically
|
||||
mp_obj_t mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr) {
|
||||
// logic: look in obj members then class locals (TODO check this against CPython)
|
||||
mp_obj_instance_t *self = self_in;
|
||||
mp_map_elem_t *elem = mp_qstr_map_lookup(self->members, attr, false);
|
||||
mp_map_elem_t *elem = mp_map_lookup(self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
|
||||
if (elem != NULL) {
|
||||
// object member, always treated as a value
|
||||
return elem->value;
|
||||
}
|
||||
elem = mp_qstr_map_lookup(mp_obj_class_get_locals(self->class), attr, false);
|
||||
elem = mp_map_lookup(mp_obj_class_get_locals(self->class), MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
|
||||
if (elem != NULL) {
|
||||
if (mp_obj_is_callable(elem->value)) {
|
||||
// class member is callable so build a bound method
|
||||
@ -51,14 +51,14 @@ mp_obj_t mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr) {
|
||||
void mp_obj_instance_load_method(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
|
||||
// logic: look in obj members then class locals (TODO check this against CPython)
|
||||
mp_obj_instance_t *self = self_in;
|
||||
mp_map_elem_t *elem = mp_qstr_map_lookup(self->members, attr, false);
|
||||
mp_map_elem_t *elem = mp_map_lookup(self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
|
||||
if (elem != NULL) {
|
||||
// object member, always treated as a value
|
||||
dest[1] = elem->value;
|
||||
dest[0] = NULL;
|
||||
return;
|
||||
}
|
||||
elem = mp_qstr_map_lookup(mp_obj_class_get_locals(self->class), attr, false);
|
||||
elem = mp_map_lookup(mp_obj_class_get_locals(self->class), MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
|
||||
if (elem != NULL) {
|
||||
if (mp_obj_is_callable(elem->value)) {
|
||||
// class member is callable so build a bound method
|
||||
@ -81,11 +81,11 @@ void mp_obj_instance_load_method(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
|
||||
void mp_obj_instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
|
||||
// logic: look in class locals (no add) then obj members (add) (TODO check this against CPython)
|
||||
mp_obj_instance_t *self = self_in;
|
||||
mp_map_elem_t *elem = mp_qstr_map_lookup(mp_obj_class_get_locals(self->class), attr, false);
|
||||
mp_map_elem_t *elem = mp_map_lookup(mp_obj_class_get_locals(self->class), MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
|
||||
if (elem != NULL) {
|
||||
elem->value = value;
|
||||
} else {
|
||||
mp_qstr_map_lookup(self->members, attr, true)->value = value;
|
||||
mp_map_lookup(self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,6 +98,6 @@ mp_obj_t mp_obj_new_instance(mp_obj_t class) {
|
||||
mp_obj_instance_t *o = m_new_obj(mp_obj_instance_t);
|
||||
o->base.type = &instance_type;
|
||||
o->class = class;
|
||||
o->members = mp_map_new(MP_MAP_QSTR, 0);
|
||||
o->members = mp_map_new(0);
|
||||
return o;
|
||||
}
|
||||
|
@ -146,8 +146,6 @@ static void mp_quicksort(mp_obj_t *head, mp_obj_t *tail, mp_obj_t key_fn, bool r
|
||||
static mp_obj_t list_sort(mp_obj_t args, mp_map_t *kwargs) {
|
||||
mp_obj_t *args_items = NULL;
|
||||
uint args_len = 0;
|
||||
qstr key_idx = qstr_from_str_static("key");
|
||||
qstr reverse_idx = qstr_from_str_static("reverse");
|
||||
|
||||
assert(MP_OBJ_IS_TYPE(args, &tuple_type));
|
||||
mp_obj_tuple_get(args, &args_len, &args_items);
|
||||
@ -158,8 +156,8 @@ static mp_obj_t list_sort(mp_obj_t args, mp_map_t *kwargs) {
|
||||
}
|
||||
mp_obj_list_t *self = args_items[0];
|
||||
if (self->len > 1) {
|
||||
mp_map_elem_t *keyfun = mp_qstr_map_lookup(kwargs, key_idx, false);
|
||||
mp_map_elem_t *reverse = mp_qstr_map_lookup(kwargs, reverse_idx, false);
|
||||
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);
|
||||
mp_quicksort(self->items, self->items + self->len - 1,
|
||||
keyfun ? keyfun->value : NULL,
|
||||
reverse && reverse->value ? rt_is_true(reverse->value) : false);
|
||||
|
@ -32,8 +32,8 @@ mp_obj_t mp_obj_new_module(qstr module_name) {
|
||||
mp_obj_module_t *o = m_new_obj(mp_obj_module_t);
|
||||
o->base.type = &module_type;
|
||||
o->name = module_name;
|
||||
o->globals = mp_map_new(MP_MAP_QSTR, 1);
|
||||
mp_qstr_map_lookup(o->globals, MP_QSTR___name__, true)->value = mp_obj_new_str(module_name);
|
||||
o->globals = mp_map_new(1);
|
||||
mp_map_lookup(o->globals, MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = mp_obj_new_str(module_name);
|
||||
return o;
|
||||
}
|
||||
|
||||
|
109
py/runtime.c
109
py/runtime.c
@ -68,64 +68,69 @@ static mp_code_t *unique_codes = NULL;
|
||||
FILE *fp_write_code = NULL;
|
||||
#endif
|
||||
|
||||
// a good optimising compiler will inline this if necessary
|
||||
static void mp_map_add_qstr(mp_map_t *map, qstr qstr, mp_obj_t value) {
|
||||
mp_map_lookup(map, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
|
||||
}
|
||||
|
||||
void rt_init(void) {
|
||||
// locals = globals for outer module (see Objects/frameobject.c/PyFrame_New())
|
||||
map_locals = map_globals = mp_map_new(MP_MAP_QSTR, 1);
|
||||
mp_qstr_map_lookup(map_globals, MP_QSTR___name__, true)->value = mp_obj_new_str(MP_QSTR___main__);
|
||||
map_locals = map_globals = mp_map_new(1);
|
||||
mp_map_add_qstr(map_globals, MP_QSTR___name__, mp_obj_new_str(MP_QSTR___main__));
|
||||
|
||||
// init built-in hash table
|
||||
mp_map_init(&map_builtins, MP_MAP_QSTR, 3);
|
||||
mp_map_init(&map_builtins, 3);
|
||||
|
||||
// built-in exceptions (TODO, make these proper classes)
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_AttributeError, true)->value = mp_obj_new_exception(MP_QSTR_AttributeError);
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_IndexError, true)->value = mp_obj_new_exception(MP_QSTR_IndexError);
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_KeyError, true)->value = mp_obj_new_exception(MP_QSTR_KeyError);
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_NameError, true)->value = mp_obj_new_exception(MP_QSTR_NameError);
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_TypeError, true)->value = mp_obj_new_exception(MP_QSTR_TypeError);
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_SyntaxError, true)->value = mp_obj_new_exception(MP_QSTR_SyntaxError);
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_ValueError, true)->value = mp_obj_new_exception(MP_QSTR_ValueError);
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_OSError, true)->value = mp_obj_new_exception(MP_QSTR_OSError);
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_AttributeError, mp_obj_new_exception(MP_QSTR_AttributeError));
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_IndexError, mp_obj_new_exception(MP_QSTR_IndexError));
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_KeyError, mp_obj_new_exception(MP_QSTR_KeyError));
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_NameError, mp_obj_new_exception(MP_QSTR_NameError));
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_TypeError, mp_obj_new_exception(MP_QSTR_TypeError));
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_SyntaxError, mp_obj_new_exception(MP_QSTR_SyntaxError));
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_ValueError, mp_obj_new_exception(MP_QSTR_ValueError));
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_OSError, mp_obj_new_exception(MP_QSTR_OSError));
|
||||
|
||||
// built-in objects
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_Ellipsis, true)->value = mp_const_ellipsis;
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_Ellipsis, mp_const_ellipsis);
|
||||
|
||||
// built-in core functions
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR___build_class__, true)->value = (mp_obj_t)&mp_builtin___build_class___obj;
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR___repl_print__, true)->value = rt_make_function_1(mp_builtin___repl_print__);
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR___build_class__, (mp_obj_t)&mp_builtin___build_class___obj);
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR___repl_print__, rt_make_function_1(mp_builtin___repl_print__));
|
||||
|
||||
// built-in types
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_bool, true)->value = (mp_obj_t)&bool_type;
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_bool, (mp_obj_t)&bool_type);
|
||||
#if MICROPY_ENABLE_FLOAT
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_complex, true)->value = (mp_obj_t)&complex_type;
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_complex, (mp_obj_t)&complex_type);
|
||||
#endif
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_dict, true)->value = (mp_obj_t)&dict_type;
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_dict, (mp_obj_t)&dict_type);
|
||||
#if MICROPY_ENABLE_FLOAT
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_float, true)->value = (mp_obj_t)&float_type;
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_float, (mp_obj_t)&float_type);
|
||||
#endif
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_int, true)->value = (mp_obj_t)&int_type;
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_list, true)->value = (mp_obj_t)&list_type;
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_set, true)->value = (mp_obj_t)&set_type;
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_tuple, true)->value = (mp_obj_t)&tuple_type;
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_type, true)->value = (mp_obj_t)&mp_builtin_type_obj; // TODO
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_int, (mp_obj_t)&int_type);
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_list, (mp_obj_t)&list_type);
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_set, (mp_obj_t)&set_type);
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_tuple, (mp_obj_t)&tuple_type);
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_type, (mp_obj_t)&mp_builtin_type_obj); // TODO
|
||||
|
||||
// built-in user functions; TODO covert all to &mp_builtin_xxx's
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_abs, true)->value = rt_make_function_1(mp_builtin_abs);
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_all, true)->value = rt_make_function_1(mp_builtin_all);
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_any, true)->value = rt_make_function_1(mp_builtin_any);
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_callable, true)->value = rt_make_function_1(mp_builtin_callable);
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_chr, true)->value = rt_make_function_1(mp_builtin_chr);
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_divmod, true)->value = rt_make_function_2(mp_builtin_divmod);
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_hash, true)->value = (mp_obj_t)&mp_builtin_hash_obj;
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_iter, true)->value = (mp_obj_t)&mp_builtin_iter_obj;
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_len, true)->value = rt_make_function_1(mp_builtin_len);
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_max, true)->value = rt_make_function_var(1, mp_builtin_max);
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_min, true)->value = rt_make_function_var(1, mp_builtin_min);
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_next, true)->value = (mp_obj_t)&mp_builtin_next_obj;
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_ord, true)->value = rt_make_function_1(mp_builtin_ord);
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_pow, true)->value = rt_make_function_var(2, mp_builtin_pow);
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_print, true)->value = rt_make_function_var(0, mp_builtin_print);
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_range, true)->value = rt_make_function_var(1, mp_builtin_range);
|
||||
mp_qstr_map_lookup(&map_builtins, MP_QSTR_sum, true)->value = rt_make_function_var(1, mp_builtin_sum);
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_abs, rt_make_function_1(mp_builtin_abs));
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_all, rt_make_function_1(mp_builtin_all));
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_any, rt_make_function_1(mp_builtin_any));
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_callable, rt_make_function_1(mp_builtin_callable));
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_chr, rt_make_function_1(mp_builtin_chr));
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_divmod, rt_make_function_2(mp_builtin_divmod));
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_hash, (mp_obj_t)&mp_builtin_hash_obj);
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_iter, (mp_obj_t)&mp_builtin_iter_obj);
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_len, rt_make_function_1(mp_builtin_len));
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_max, rt_make_function_var(1, mp_builtin_max));
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_min, rt_make_function_var(1, mp_builtin_min));
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_next, (mp_obj_t)&mp_builtin_next_obj);
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_ord, rt_make_function_1(mp_builtin_ord));
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_pow, rt_make_function_var(2, mp_builtin_pow));
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_print, rt_make_function_var(0, mp_builtin_print));
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_range, rt_make_function_var(1, mp_builtin_range));
|
||||
mp_map_add_qstr(&map_builtins, MP_QSTR_sum, rt_make_function_var(1, mp_builtin_sum));
|
||||
|
||||
next_unique_code_id = 1; // 0 indicates "no code"
|
||||
unique_codes_alloc = 0;
|
||||
@ -362,11 +367,11 @@ mp_obj_t rt_load_const_str(qstr qstr) {
|
||||
mp_obj_t rt_load_name(qstr qstr) {
|
||||
// logic: search locals, globals, builtins
|
||||
DEBUG_OP_printf("load name %s\n", qstr_str(qstr));
|
||||
mp_map_elem_t *elem = mp_qstr_map_lookup(map_locals, qstr, false);
|
||||
mp_map_elem_t *elem = mp_map_lookup(map_locals, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP);
|
||||
if (elem == NULL) {
|
||||
elem = mp_qstr_map_lookup(map_globals, qstr, false);
|
||||
elem = mp_map_lookup(map_globals, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP);
|
||||
if (elem == NULL) {
|
||||
elem = mp_qstr_map_lookup(&map_builtins, qstr, false);
|
||||
elem = mp_map_lookup(&map_builtins, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP);
|
||||
if (elem == NULL) {
|
||||
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_NameError, "name '%s' is not defined", qstr_str(qstr)));
|
||||
}
|
||||
@ -378,9 +383,9 @@ mp_obj_t rt_load_name(qstr qstr) {
|
||||
mp_obj_t rt_load_global(qstr qstr) {
|
||||
// logic: search globals, builtins
|
||||
DEBUG_OP_printf("load global %s\n", qstr_str(qstr));
|
||||
mp_map_elem_t *elem = mp_qstr_map_lookup(map_globals, qstr, false);
|
||||
mp_map_elem_t *elem = mp_map_lookup(map_globals, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP);
|
||||
if (elem == NULL) {
|
||||
elem = mp_qstr_map_lookup(&map_builtins, qstr, false);
|
||||
elem = mp_map_lookup(&map_builtins, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP);
|
||||
if (elem == NULL) {
|
||||
nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_NameError, "name '%s' is not defined", qstr_str(qstr)));
|
||||
}
|
||||
@ -390,7 +395,7 @@ mp_obj_t rt_load_global(qstr qstr) {
|
||||
|
||||
mp_obj_t rt_load_build_class(void) {
|
||||
DEBUG_OP_printf("load_build_class\n");
|
||||
mp_map_elem_t *elem = mp_qstr_map_lookup(&map_builtins, MP_QSTR___build_class__, false);
|
||||
mp_map_elem_t *elem = mp_map_lookup(&map_builtins, MP_OBJ_NEW_QSTR(MP_QSTR___build_class__), MP_MAP_LOOKUP);
|
||||
if (elem == NULL) {
|
||||
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_NameError, "name '__build_class__' is not defined"));
|
||||
}
|
||||
@ -407,12 +412,12 @@ void rt_set_cell(mp_obj_t cell, mp_obj_t val) {
|
||||
|
||||
void rt_store_name(qstr qstr, mp_obj_t obj) {
|
||||
DEBUG_OP_printf("store name %s <- %p\n", qstr_str(qstr), obj);
|
||||
mp_qstr_map_lookup(map_locals, qstr, true)->value = obj;
|
||||
mp_map_lookup(map_locals, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = obj;
|
||||
}
|
||||
|
||||
void rt_store_global(qstr qstr, mp_obj_t obj) {
|
||||
DEBUG_OP_printf("store global %s <- %p\n", qstr_str(qstr), obj);
|
||||
mp_qstr_map_lookup(map_globals, qstr, true)->value = obj;
|
||||
mp_map_lookup(map_globals, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = obj;
|
||||
}
|
||||
|
||||
mp_obj_t rt_unary_op(int op, mp_obj_t arg) {
|
||||
@ -772,7 +777,7 @@ mp_obj_t rt_store_map(mp_obj_t map, mp_obj_t key, mp_obj_t value) {
|
||||
mp_obj_t rt_load_attr(mp_obj_t base, qstr attr) {
|
||||
DEBUG_OP_printf("load attr %s\n", qstr_str(attr));
|
||||
if (MP_OBJ_IS_TYPE(base, &class_type)) {
|
||||
mp_map_elem_t *elem = mp_qstr_map_lookup(mp_obj_class_get_locals(base), attr, false);
|
||||
mp_map_elem_t *elem = mp_map_lookup(mp_obj_class_get_locals(base), MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
|
||||
if (elem == NULL) {
|
||||
// TODO what about generic method lookup?
|
||||
goto no_attr;
|
||||
@ -782,7 +787,7 @@ mp_obj_t rt_load_attr(mp_obj_t base, qstr attr) {
|
||||
return mp_obj_instance_load_attr(base, attr);
|
||||
} else if (MP_OBJ_IS_TYPE(base, &module_type)) {
|
||||
DEBUG_OP_printf("lookup module map %p\n", mp_obj_module_get_globals(base));
|
||||
mp_map_elem_t *elem = mp_qstr_map_lookup(mp_obj_module_get_globals(base), attr, false);
|
||||
mp_map_elem_t *elem = mp_map_lookup(mp_obj_module_get_globals(base), MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
|
||||
if (elem == NULL) {
|
||||
// TODO what about generic method lookup?
|
||||
goto no_attr;
|
||||
@ -839,13 +844,13 @@ void rt_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) {
|
||||
if (MP_OBJ_IS_TYPE(base, &class_type)) {
|
||||
// TODO CPython allows STORE_ATTR to a class, but is this the correct implementation?
|
||||
mp_map_t *locals = mp_obj_class_get_locals(base);
|
||||
mp_qstr_map_lookup(locals, attr, true)->value = value;
|
||||
mp_map_lookup(locals, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
|
||||
} else if (MP_OBJ_IS_TYPE(base, &instance_type)) {
|
||||
mp_obj_instance_store_attr(base, attr, value);
|
||||
} else if (MP_OBJ_IS_TYPE(base, &module_type)) {
|
||||
// TODO CPython allows STORE_ATTR to a module, but is this the correct implementation?
|
||||
mp_map_t *globals = mp_obj_module_get_globals(base);
|
||||
mp_qstr_map_lookup(globals, attr, true)->value = value;
|
||||
mp_map_lookup(globals, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
|
||||
} else {
|
||||
nlr_jump(mp_obj_new_exception_msg_2_args(MP_QSTR_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr)));
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ mp_obj_t pyb_wlan_get_ip(void) {
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t data = mp_obj_new_class(mp_map_new(MP_MAP_QSTR, 0)); // TODO should this be an instance of a class?
|
||||
mp_obj_t data = mp_obj_new_class(mp_map_new(0)); // TODO should this be an instance of a class?
|
||||
decode_addr_and_store(data, qstr_from_str_static("ip"), &ipconfig.aucIP[0], 4);
|
||||
decode_addr_and_store(data, qstr_from_str_static("subnet"), &ipconfig.aucSubnetMask[0], 4);
|
||||
decode_addr_and_store(data, qstr_from_str_static("gateway"), &ipconfig.aucDefaultGateway[0], 4);
|
||||
|
Loading…
Reference in New Issue
Block a user