Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
uPython-mirror
Commits
004cdceb
Commit
004cdceb
authored
Jan 09, 2014
by
Damien George
Browse files
py: Implement base class lookup, issubclass, isinstance.
parent
062478e6
Changes
9
Hide whitespace changes
Inline
Side-by-side
py/builtin.h
View file @
004cdceb
...
...
@@ -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
);
py/mpqstrraw.h
View file @
004cdceb
...
...
@@ -44,6 +44,8 @@ Q(divmod)
Q
(
float
)
Q
(
hash
)
Q
(
int
)
Q
(
isinstance
)
Q
(
issubclass
)
Q
(
iter
)
Q
(
len
)
Q
(
list
)
...
...
py/obj.h
View file @
004cdceb
...
...
@@ -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
local
s
_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
);
...
...
py/objtuple.c
View file @
004cdceb
...
...
@@ -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
];
...
...
py/objtype.c
View file @
004cdceb
...
...
@@ -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
);
py/runtime.c
View file @
004cdceb
...
...
@@ -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
));
...
...
stm/pybwlan.c
View file @
004cdceb
...
...
@@ -78,7 +78,7 @@ mp_obj_t pyb_wlan_get_ip(void) {
// if it doesn't already exist, make a new empty class for NetAddress objects
if
(
net_address_type
==
MP_OBJ_NULL
)
{
net_address_type
=
mp_obj_new_type
(
qstr_from_str_static
(
"NetAddress"
),
mp_obj_new_dict
(
0
));
net_address_type
=
mp_obj_new_type
(
qstr_from_str_static
(
"NetAddress"
),
mp_const_empty_tuple
,
mp_obj_new_dict
(
0
));
}
// make a new NetAddress object
...
...
tests/basics/tests/class3.py
0 → 100644
View file @
004cdceb
# inheritance
class
A
:
def
a
():
print
(
'A.a() called'
)
class
B
(
A
):
pass
print
(
type
(
A
))
print
(
type
(
B
))
print
(
issubclass
(
A
,
A
))
print
(
issubclass
(
A
,
B
))
print
(
issubclass
(
B
,
A
))
print
(
issubclass
(
B
,
B
))
print
(
isinstance
(
A
(),
A
))
print
(
isinstance
(
A
(),
B
))
print
(
isinstance
(
B
(),
A
))
print
(
isinstance
(
B
(),
B
))
A
.
a
()
B
.
a
()
unix/main.c
View file @
004cdceb
...
...
@@ -218,7 +218,7 @@ int main(int argc, char **argv) {
// test_obj = TestClass()
// test_obj.attr = 42
mp_obj_t
test_class_type
,
test_class_instance
;
test_class_type
=
mp_obj_new_type
(
qstr_from_str_static
(
"TestClass"
),
mp_obj_new_dict
(
0
));
test_class_type
=
mp_obj_new_type
(
qstr_from_str_static
(
"TestClass"
),
mp_const_empty_tuple
,
mp_obj_new_dict
(
0
));
rt_store_name
(
qstr_from_str_static
(
"test_obj"
),
test_class_instance
=
rt_call_function_0
(
test_class_type
));
rt_store_attr
(
test_class_instance
,
qstr_from_str_static
(
"attr"
),
mp_obj_new_int
(
42
));
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment