summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
Diffstat (limited to 'py')
-rw-r--r--py/builtin.h13
-rw-r--r--py/mpqstrraw.h2
-rw-r--r--py/obj.h10
-rw-r--r--py/objtuple.c1
-rw-r--r--py/objtype.c116
-rw-r--r--py/runtime.c2
6 files changed, 110 insertions, 34 deletions
diff --git a/py/builtin.h b/py/builtin.h
index 2cd0ef15f2..db7d517a06 100644
--- a/py/builtin.h
+++ b/py/builtin.h
@@ -6,19 +6,12 @@ mp_obj_t mp_builtin___repl_print__(mp_obj_t o);
mp_obj_t mp_builtin_abs(mp_obj_t o_in);
mp_obj_t mp_builtin_all(mp_obj_t o_in);
mp_obj_t mp_builtin_any(mp_obj_t o_in);
-mp_obj_t mp_builtin_bool(int n_args, const mp_obj_t *args);
mp_obj_t mp_builtin_callable(mp_obj_t o_in);
-#if MICROPY_ENABLE_FLOAT
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_complex_obj);
-#endif
mp_obj_t mp_builtin_chr(mp_obj_t o_in);
-mp_obj_t mp_builtin_dict(void);
mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in);
-#if MICROPY_ENABLE_FLOAT
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_float_obj);
-#endif
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_hash_obj);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_int_obj);
+MP_DECLARE_CONST_FUN_OBJ(mp_builtin_isinstance_obj);
+MP_DECLARE_CONST_FUN_OBJ(mp_builtin_issubclass_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_iter_obj);
mp_obj_t mp_builtin_len(mp_obj_t o_in);
mp_obj_t mp_builtin_list(int n_args, const mp_obj_t *args);
@@ -29,6 +22,4 @@ mp_obj_t mp_builtin_ord(mp_obj_t o_in);
mp_obj_t mp_builtin_pow(int n_args, const mp_obj_t *args);
mp_obj_t mp_builtin_print(int n_args, const mp_obj_t *args);
mp_obj_t mp_builtin_range(int n_args, const mp_obj_t *args);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_set_obj);
mp_obj_t mp_builtin_sum(int n_args, const mp_obj_t *args);
-MP_DECLARE_CONST_FUN_OBJ(mp_builtin_type_obj);
diff --git a/py/mpqstrraw.h b/py/mpqstrraw.h
index eeed6f3a0a..e44df5ad18 100644
--- a/py/mpqstrraw.h
+++ b/py/mpqstrraw.h
@@ -44,6 +44,8 @@ Q(divmod)
Q(float)
Q(hash)
Q(int)
+Q(isinstance)
+Q(issubclass)
Q(iter)
Q(len)
Q(list)
diff --git a/py/obj.h b/py/obj.h
index 8643dbb91b..48080a0ec0 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -147,7 +147,10 @@ struct _mp_obj_type_t {
mp_load_attr_fun_t load_attr;
mp_store_attr_fun_t store_attr;
- mp_obj_t locals;
+
+ // these are for dynamically created types (classes)
+ mp_obj_t bases_tuple;
+ mp_obj_t locals_dict;
/*
What we might need to add here:
@@ -180,7 +183,7 @@ extern const mp_obj_t mp_const_stop_iteration; // special object indicating end
// General API for objects
-mp_obj_t mp_obj_new_type(qstr name, mp_obj_t local_dict);
+mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict);
mp_obj_t mp_obj_new_none(void);
mp_obj_t mp_obj_new_bool(bool value);
mp_obj_t mp_obj_new_cell(mp_obj_t obj);
@@ -308,9 +311,6 @@ void mp_obj_fun_bc_get(mp_obj_t self_in, int *n_args, uint *n_state, const byte
// generator
extern const mp_obj_type_t gen_instance_type;
-// class
-struct _mp_map_elem_t *mp_obj_class_lookup(mp_obj_t self_in, qstr attr, enum _mp_map_lookup_kind_t lookup_kind);
-
// module
extern const mp_obj_type_t module_type;
mp_obj_t mp_obj_new_module(qstr module_name);
diff --git a/py/objtuple.c b/py/objtuple.c
index 0050fc5ea0..7685cc449f 100644
--- a/py/objtuple.c
+++ b/py/objtuple.c
@@ -136,6 +136,7 @@ mp_obj_t mp_obj_new_tuple_reverse(uint n, const mp_obj_t *items) {
}
void mp_obj_tuple_get(mp_obj_t self_in, uint *len, mp_obj_t **items) {
+ assert(MP_OBJ_IS_TYPE(self_in, &tuple_type));
mp_obj_tuple_t *self = self_in;
*len = self->len;
*items = &self->items[0];
diff --git a/py/objtype.c b/py/objtype.c
index 58854ca98d..6c89c1ff2b 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -27,6 +27,45 @@ static mp_obj_t mp_obj_new_class(mp_obj_t class) {
return o;
}
+static mp_map_elem_t *mp_obj_class_lookup(mp_obj_t self_in, qstr attr, mp_map_lookup_kind_t lookup_kind) {
+ for (;;) {
+ assert(MP_OBJ_IS_TYPE(self_in, &mp_const_type));
+ mp_obj_type_t *self = self_in;
+ if (self->locals_dict == NULL) {
+ return NULL;
+ }
+ assert(MP_OBJ_IS_TYPE(self->locals_dict, &dict_type)); // Micro Python restriction, for now
+ mp_map_t *locals_map = ((void*)self->locals_dict + sizeof(mp_obj_base_t)); // XXX hack to get map object from dict object
+ mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), lookup_kind);
+ if (elem != NULL) {
+ return elem;
+ }
+
+ // attribute not found, keep searching base classes
+
+ // for a const struct, this entry might be NULL
+ if (self->bases_tuple == MP_OBJ_NULL) {
+ return NULL;
+ }
+
+ uint len;
+ mp_obj_t *items;
+ mp_obj_tuple_get(self->bases_tuple, &len, &items);
+ if (len == 0) {
+ return NULL;
+ }
+ for (uint i = 0; i < len - 1; i++) {
+ elem = mp_obj_class_lookup(items[i], attr, lookup_kind);
+ if (elem != NULL) {
+ return elem;
+ }
+ }
+
+ // search last base (simple tail recursion elimination)
+ self_in = items[len - 1];
+ }
+}
+
static void class_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
print(env, "<%s object at %p>", mp_obj_get_type_str(self_in), self_in);
}
@@ -102,17 +141,6 @@ static bool class_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
return true;
}
-mp_map_elem_t *mp_obj_class_lookup(mp_obj_t self_in, qstr attr, mp_map_lookup_kind_t lookup_kind) {
- assert(MP_OBJ_IS_TYPE(self_in, &mp_const_type));
- mp_obj_type_t *self = self_in;
- if (self->locals == NULL) {
- return NULL;
- }
- assert(MP_OBJ_IS_TYPE(self->locals, &dict_type)); // Micro Python restriction, for now
- mp_map_t *locals_map = ((void*)self->locals + sizeof(mp_obj_base_t)); // XXX hack to get map object from dict object
- return mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), lookup_kind);
-}
-
/******************************************************************************/
// type object
// - the struct is mp_obj_type_t and is defined in obj.h so const types can be made
@@ -131,13 +159,10 @@ static mp_obj_t type_make_new(mp_obj_t type_in, int n_args, const mp_obj_t *args
return mp_obj_get_type(args[0]);
case 3:
- {
// args[2] = name
// args[1] = bases tuple
// args[0] = locals dict
-
- return mp_obj_new_type(mp_obj_get_qstr(args[2]), args[0]);
- }
+ return mp_obj_new_type(mp_obj_get_qstr(args[2]), args[1], args[0]);
default:
nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "type takes at 1 or 3 arguments"));
@@ -192,7 +217,9 @@ const mp_obj_type_t mp_const_type = {
.store_attr = type_store_attr,
};
-mp_obj_t mp_obj_new_type(qstr name, mp_obj_t local_dict) {
+mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) {
+ assert(MP_OBJ_IS_TYPE(bases_tuple, &tuple_type)); // Micro Python restriction, for now
+ assert(MP_OBJ_IS_TYPE(locals_dict, &dict_type)); // Micro Python restriction, for now
mp_obj_type_t *o = m_new0(mp_obj_type_t, 1);
o->base.type = &mp_const_type;
o->name = qstr_str(name);
@@ -200,7 +227,60 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t local_dict) {
o->make_new = class_make_new;
o->load_attr = class_load_attr;
o->store_attr = class_store_attr;
- o->locals = local_dict;
- assert(MP_OBJ_IS_TYPE(o->locals, &dict_type)); // Micro Python restriction, for now
+ o->bases_tuple = bases_tuple;
+ o->locals_dict = locals_dict;
return o;
}
+
+/******************************************************************************/
+// built-ins specific to types
+
+static mp_obj_t mp_builtin_issubclass(mp_obj_t object, mp_obj_t classinfo) {
+ if (!MP_OBJ_IS_TYPE(object, &mp_const_type)) {
+ nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "issubclass() arg 1 must be a class"));
+ }
+
+ // TODO support a tuple of classes for second argument
+ if (!MP_OBJ_IS_TYPE(classinfo, &mp_const_type)) {
+ nlr_jump(mp_obj_new_exception_msg(MP_QSTR_TypeError, "issubclass() arg 2 must be a class"));
+ }
+
+ for (;;) {
+ if (object == classinfo) {
+ return mp_const_true;
+ }
+
+ // not equivalent classes, keep searching base classes
+
+ assert(MP_OBJ_IS_TYPE(object, &mp_const_type));
+ mp_obj_type_t *self = object;
+
+ // for a const struct, this entry might be NULL
+ if (self->bases_tuple == MP_OBJ_NULL) {
+ return mp_const_false;
+ }
+
+ uint len;
+ mp_obj_t *items;
+ mp_obj_tuple_get(self->bases_tuple, &len, &items);
+ if (len == 0) {
+ return mp_const_false;
+ }
+ for (uint i = 0; i < len - 1; i++) {
+ if (mp_builtin_issubclass(items[i], classinfo) == mp_const_true) {
+ return mp_const_true;
+ }
+ }
+
+ // search last base (simple tail recursion elimination)
+ object = items[len - 1];
+ }
+}
+
+MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_issubclass_obj, mp_builtin_issubclass);
+
+static mp_obj_t mp_builtin_isinstance(mp_obj_t object, mp_obj_t classinfo) {
+ return mp_builtin_issubclass(mp_obj_get_type(object), classinfo);
+}
+
+MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_isinstance_obj, mp_builtin_isinstance);
diff --git a/py/runtime.c b/py/runtime.c
index 2c3ff803bc..795cc4624c 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -121,6 +121,8 @@ void rt_init(void) {
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_isinstance, (mp_obj_t)&mp_builtin_isinstance_obj);
+ mp_map_add_qstr(&map_builtins, MP_QSTR_issubclass, (mp_obj_t)&mp_builtin_issubclass_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));