Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
M
micropython
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
This is an archived project. Repository and other project resources are read-only.
Show more breadcrumbs
card10
micropython
Commits
eae16445
Commit
eae16445
authored
Jan 11, 2014
by
Damien George
Browse files
Options
Downloads
Patches
Plain Diff
py: Implement staticmethod and classmethod (internally).
Still need to make built-ins by these names, and write tests.
parent
bcbeea0a
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
py/obj.c
+2
-2
2 additions, 2 deletions
py/obj.c
py/obj.h
+24
-0
24 additions, 0 deletions
py/obj.h
py/objdict.c
+44
-76
44 additions, 76 deletions
py/objdict.c
py/objtype.c
+59
-15
59 additions, 15 deletions
py/objtype.c
py/runtime.c
+15
-2
15 additions, 2 deletions
py/runtime.c
with
144 additions
and
95 deletions
py/obj.c
+
2
−
2
View file @
eae16445
...
@@ -231,7 +231,7 @@ uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index)
...
@@ -231,7 +231,7 @@ uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index)
}
}
}
}
// may return NULL
// may return
MP_OBJ_
NULL
mp_obj_t
mp_obj_len_maybe
(
mp_obj_t
o_in
)
{
mp_obj_t
mp_obj_len_maybe
(
mp_obj_t
o_in
)
{
mp_small_int_t
len
=
0
;
mp_small_int_t
len
=
0
;
if
(
MP_OBJ_IS_TYPE
(
o_in
,
&
str_type
))
{
if
(
MP_OBJ_IS_TYPE
(
o_in
,
&
str_type
))
{
...
@@ -249,7 +249,7 @@ mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) {
...
@@ -249,7 +249,7 @@ mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) {
}
else
if
(
MP_OBJ_IS_TYPE
(
o_in
,
&
dict_type
))
{
}
else
if
(
MP_OBJ_IS_TYPE
(
o_in
,
&
dict_type
))
{
len
=
mp_obj_dict_len
(
o_in
);
len
=
mp_obj_dict_len
(
o_in
);
}
else
{
}
else
{
return
NULL
;
return
MP_OBJ_
NULL
;
}
}
return
MP_OBJ_NEW_SMALL_INT
(
len
);
return
MP_OBJ_NEW_SMALL_INT
(
len
);
}
}
This diff is collapsed.
Click to expand it.
py/obj.h
+
24
−
0
View file @
eae16445
...
@@ -59,6 +59,15 @@ typedef struct _mp_obj_base_t mp_obj_base_t;
...
@@ -59,6 +59,15 @@ 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_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, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, true, 0, (~((machine_uint_t)0)), (mp_fun_kw_t)fun_name)
#define MP_DEFINE_CONST_FUN_OBJ_KW(obj_name, fun_name) MP_DEFINE_CONST_FUN_OBJ_VOID_PTR(obj_name, true, 0, (~((machine_uint_t)0)), (mp_fun_kw_t)fun_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
#define MP_DECLARE_CONST_STATICMETHOD_OBJ(obj_name) extern const mp_obj_staticmethod_t obj_name
#define MP_DECLARE_CONST_CLASSMETHOD_OBJ(obj_name) extern const mp_obj_classmethod_t obj_name
#define MP_DEFINE_CONST_STATICMETHOD_OBJ(obj_name, fun_name) const mp_obj_staticmethod_t obj_name = {{&mp_type_staticmethod}, fun_name}
#define MP_DEFINE_CONST_CLASSMETHOD_OBJ(obj_name, fun_name) const mp_obj_classmethod_t obj_name = {{&mp_type_classmethod}, fun_name}
// Need to declare this here so we are not dependent on map.h
// Need to declare this here so we are not dependent on map.h
struct
_mp_map_t
;
struct
_mp_map_t
;
struct
_mp_map_elem_t
;
struct
_mp_map_elem_t
;
...
@@ -316,3 +325,18 @@ extern const mp_obj_type_t gen_instance_type;
...
@@ -316,3 +325,18 @@ extern const mp_obj_type_t gen_instance_type;
extern
const
mp_obj_type_t
module_type
;
extern
const
mp_obj_type_t
module_type
;
mp_obj_t
mp_obj_new_module
(
qstr
module_name
);
mp_obj_t
mp_obj_new_module
(
qstr
module_name
);
struct
_mp_map_t
*
mp_obj_module_get_globals
(
mp_obj_t
self_in
);
struct
_mp_map_t
*
mp_obj_module_get_globals
(
mp_obj_t
self_in
);
// staticmethod and classmethod types; defined here so we can make const versions
extern
const
mp_obj_type_t
mp_type_staticmethod
;
extern
const
mp_obj_type_t
mp_type_classmethod
;
typedef
struct
_mp_obj_staticmethod_t
{
mp_obj_base_t
base
;
mp_obj_t
fun
;
}
mp_obj_staticmethod_t
;
typedef
struct
_mp_obj_classmethod_t
{
mp_obj_base_t
base
;
mp_obj_t
fun
;
}
mp_obj_classmethod_t
;
This diff is collapsed.
Click to expand it.
py/objdict.c
+
44
−
76
View file @
eae16445
...
@@ -139,6 +139,35 @@ static mp_obj_t dict_copy(mp_obj_t self_in) {
...
@@ -139,6 +139,35 @@ 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_DEFINE_CONST_FUN_OBJ_1
(
dict_copy_obj
,
dict_copy
);
// this is a classmethod
static
mp_obj_t
dict_fromkeys
(
int
n_args
,
const
mp_obj_t
*
args
)
{
assert
(
2
<=
n_args
&&
n_args
<=
3
);
mp_obj_t
iter
=
rt_getiter
(
args
[
1
]);
mp_obj_t
len
=
mp_obj_len_maybe
(
iter
);
mp_obj_t
value
=
mp_const_none
;
mp_obj_t
next
=
NULL
;
mp_obj_dict_t
*
self
=
NULL
;
if
(
n_args
>
2
)
{
value
=
args
[
2
];
}
if
(
len
==
MP_OBJ_NULL
)
{
/* object's type doesn't have a __len__ slot */
self
=
mp_obj_new_dict
(
0
);
}
else
{
self
=
mp_obj_new_dict
(
MP_OBJ_SMALL_INT_VALUE
(
len
));
}
while
((
next
=
rt_iternext
(
iter
))
!=
mp_const_stop_iteration
)
{
mp_map_lookup
(
&
self
->
map
,
next
,
MP_MAP_LOOKUP_ADD_IF_NOT_FOUND
)
->
value
=
value
;
}
return
self
;
}
static
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN
(
dict_fromkeys_fun_obj
,
2
,
3
,
dict_fromkeys
);
static
MP_DEFINE_CONST_CLASSMETHOD_OBJ
(
dict_fromkeys_obj
,
(
const
mp_obj_t
)
&
dict_fromkeys_fun_obj
);
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
)
{
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_map_elem_t
*
elem
=
mp_map_lookup
(
self
,
key
,
lookup_kind
);
mp_obj_t
value
;
mp_obj_t
value
;
...
@@ -286,17 +315,12 @@ static mp_obj_t dict_view_it_iternext(mp_obj_t self_in) {
...
@@ -286,17 +315,12 @@ static mp_obj_t dict_view_it_iternext(mp_obj_t self_in) {
return
mp_obj_new_tuple
(
2
,
items
);
return
mp_obj_new_tuple
(
2
,
items
);
}
}
case
MP_DICT_VIEW_KEYS
:
case
MP_DICT_VIEW_KEYS
:
{
return
next
->
key
;
return
next
->
key
;
}
case
MP_DICT_VIEW_VALUES
:
case
MP_DICT_VIEW_VALUES
:
{
return
next
->
value
;
return
next
->
value
;
}
default:
default:
{
assert
(
0
);
/* can't happen */
assert
(
0
);
/* can't happen */
}
return
mp_const_none
;
}
}
}
else
{
}
else
{
return
mp_const_stop_iteration
;
return
mp_const_stop_iteration
;
...
@@ -320,7 +344,6 @@ static mp_obj_t dict_view_getiter(mp_obj_t view_in) {
...
@@ -320,7 +344,6 @@ static mp_obj_t dict_view_getiter(mp_obj_t view_in) {
return
o
;
return
o
;
}
}
static
void
dict_view_print
(
void
(
*
print
)(
void
*
env
,
const
char
*
fmt
,
...),
void
*
env
,
mp_obj_t
self_in
)
{
static
void
dict_view_print
(
void
(
*
print
)(
void
*
env
,
const
char
*
fmt
,
...),
void
*
env
,
mp_obj_t
self_in
)
{
assert
(
MP_OBJ_IS_TYPE
(
self_in
,
&
dict_view_type
));
assert
(
MP_OBJ_IS_TYPE
(
self_in
,
&
dict_view_type
));
mp_obj_dict_view_t
*
self
=
self_in
;
mp_obj_dict_view_t
*
self
=
self_in
;
...
@@ -354,7 +377,6 @@ mp_obj_t mp_obj_new_dict_view(mp_obj_dict_t *dict, mp_dict_view_kind_t kind) {
...
@@ -354,7 +377,6 @@ mp_obj_t mp_obj_new_dict_view(mp_obj_dict_t *dict, mp_dict_view_kind_t kind) {
return
o
;
return
o
;
}
}
static
mp_obj_t
dict_view
(
mp_obj_t
self_in
,
mp_dict_view_kind_t
kind
)
{
static
mp_obj_t
dict_view
(
mp_obj_t
self_in
,
mp_dict_view_kind_t
kind
)
{
assert
(
MP_OBJ_IS_TYPE
(
self_in
,
&
dict_type
));
assert
(
MP_OBJ_IS_TYPE
(
self_in
,
&
dict_type
));
mp_obj_dict_t
*
self
=
self_in
;
mp_obj_dict_t
*
self
=
self_in
;
...
@@ -376,67 +398,13 @@ static mp_obj_t dict_values(mp_obj_t self_in) {
...
@@ -376,67 +398,13 @@ static mp_obj_t dict_values(mp_obj_t self_in) {
}
}
static
MP_DEFINE_CONST_FUN_OBJ_1
(
dict_values_obj
,
dict_values
);
static
MP_DEFINE_CONST_FUN_OBJ_1
(
dict_values_obj
,
dict_values
);
/******************************************************************************/
/******************************************************************************/
/* dict metaclass */
/* dict constructors & public C API */
static
mp_obj_t
dict_fromkeys
(
int
n_args
,
const
mp_obj_t
*
args
)
{
assert
(
2
<=
n_args
&&
n_args
<=
3
);
mp_obj_t
iter
=
rt_getiter
(
args
[
1
]);
mp_obj_t
len
=
mp_obj_len_maybe
(
iter
);
mp_obj_t
value
=
mp_const_none
;
mp_obj_t
next
=
NULL
;
mp_obj_dict_t
*
self
=
NULL
;
if
(
n_args
>
2
)
{
value
=
args
[
2
];
}
if
(
len
==
NULL
)
{
/* object's type doesn't have a __len__ slot */
self
=
mp_obj_new_dict
(
0
);
}
else
{
self
=
mp_obj_new_dict
(
MP_OBJ_SMALL_INT_VALUE
(
len
));
}
while
((
next
=
rt_iternext
(
iter
))
!=
mp_const_stop_iteration
)
{
mp_map_lookup
(
&
self
->
map
,
next
,
MP_MAP_LOOKUP_ADD_IF_NOT_FOUND
)
->
value
=
value
;
}
return
self
;
}
static
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN
(
dict_fromkeys_obj
,
2
,
3
,
dict_fromkeys
);
static
const
mp_method_t
dict_class_methods
[]
=
{
{
"fromkeys"
,
&
dict_fromkeys_obj
},
{
NULL
,
NULL
},
// end-of-list sentinel
};
/* this should be unnecessary when inheritance works */
static
void
dict_class_print
(
void
(
*
print
)(
void
*
env
,
const
char
*
fmt
,
...),
void
*
env
,
mp_obj_t
self_in
)
{
print
(
env
,
"<class 'dict'>"
);
}
/* this should be unnecessary when inheritance works */
static
mp_obj_t
dict_class_call_n
(
mp_obj_t
self_in
,
int
n_args
,
const
mp_obj_t
*
args
)
{
return
rt_build_map
(
0
);
}
static
const
mp_obj_type_t
dict_class
=
{
{
&
mp_const_type
},
"dict_class"
,
.
print
=
dict_class_print
,
.
methods
=
dict_class_methods
,
.
call_n
=
dict_class_call_n
,
};
/******************************************************************************/
/* dict constructors & etc */
static
const
mp_method_t
dict_type_methods
[]
=
{
static
const
mp_method_t
dict_type_methods
[]
=
{
{
"clear"
,
&
dict_clear_obj
},
{
"clear"
,
&
dict_clear_obj
},
{
"copy"
,
&
dict_copy_obj
},
{
"copy"
,
&
dict_copy_obj
},
{
"fromkeys"
,
&
dict_fromkeys_obj
},
{
"get"
,
&
dict_get_obj
},
{
"get"
,
&
dict_get_obj
},
{
"items"
,
&
dict_items_obj
},
{
"items"
,
&
dict_items_obj
},
{
"keys"
,
&
dict_keys_obj
},
{
"keys"
,
&
dict_keys_obj
},
...
@@ -449,7 +417,7 @@ static const mp_method_t dict_type_methods[] = {
...
@@ -449,7 +417,7 @@ static const mp_method_t dict_type_methods[] = {
};
};
const
mp_obj_type_t
dict_type
=
{
const
mp_obj_type_t
dict_type
=
{
{
&
dict_class
},
{
&
mp_const_type
},
"dict"
,
"dict"
,
.
print
=
dict_print
,
.
print
=
dict_print
,
.
make_new
=
dict_make_new
,
.
make_new
=
dict_make_new
,
...
...
This diff is collapsed.
Click to expand it.
py/objtype.c
+
59
−
15
View file @
eae16445
...
@@ -27,15 +27,13 @@ static mp_obj_t mp_obj_new_class(mp_obj_t class) {
...
@@ -27,15 +27,13 @@ static mp_obj_t mp_obj_new_class(mp_obj_t class) {
return
o
;
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
)
{
static
mp_map_elem_t
*
mp_obj_class_lookup
(
const
mp_obj_type_t
*
type
,
qstr
attr
,
mp_map_lookup_kind_t
lookup_kind
)
{
for
(;;)
{
for
(;;)
{
assert
(
MP_OBJ_IS_TYPE
(
self_in
,
&
mp_const_type
));
if
(
type
->
locals_dict
==
NULL
)
{
mp_obj_type_t
*
self
=
self_in
;
if
(
self
->
locals_dict
==
NULL
)
{
return
NULL
;
return
NULL
;
}
}
assert
(
MP_OBJ_IS_TYPE
(
self
->
locals_dict
,
&
dict_type
));
// Micro Python restriction, for now
assert
(
MP_OBJ_IS_TYPE
(
type
->
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_t
*
locals_map
=
((
void
*
)
type
->
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
);
mp_map_elem_t
*
elem
=
mp_map_lookup
(
locals_map
,
MP_OBJ_NEW_QSTR
(
attr
),
lookup_kind
);
if
(
elem
!=
NULL
)
{
if
(
elem
!=
NULL
)
{
return
elem
;
return
elem
;
...
@@ -44,25 +42,27 @@ static mp_map_elem_t *mp_obj_class_lookup(mp_obj_t self_in, qstr attr, mp_map_lo
...
@@ -44,25 +42,27 @@ static mp_map_elem_t *mp_obj_class_lookup(mp_obj_t self_in, qstr attr, mp_map_lo
// attribute not found, keep searching base classes
// attribute not found, keep searching base classes
// for a const struct, this entry might be NULL
// for a const struct, this entry might be NULL
if
(
self
->
bases_tuple
==
MP_OBJ_NULL
)
{
if
(
type
->
bases_tuple
==
MP_OBJ_NULL
)
{
return
NULL
;
return
NULL
;
}
}
uint
len
;
uint
len
;
mp_obj_t
*
items
;
mp_obj_t
*
items
;
mp_obj_tuple_get
(
self
->
bases_tuple
,
&
len
,
&
items
);
mp_obj_tuple_get
(
type
->
bases_tuple
,
&
len
,
&
items
);
if
(
len
==
0
)
{
if
(
len
==
0
)
{
return
NULL
;
return
NULL
;
}
}
for
(
uint
i
=
0
;
i
<
len
-
1
;
i
++
)
{
for
(
uint
i
=
0
;
i
<
len
-
1
;
i
++
)
{
elem
=
mp_obj_class_lookup
(
items
[
i
],
attr
,
lookup_kind
);
assert
(
MP_OBJ_IS_TYPE
(
items
[
i
],
&
mp_const_type
));
elem
=
mp_obj_class_lookup
((
mp_obj_type_t
*
)
items
[
i
],
attr
,
lookup_kind
);
if
(
elem
!=
NULL
)
{
if
(
elem
!=
NULL
)
{
return
elem
;
return
elem
;
}
}
}
}
// search last base (simple tail recursion elimination)
// search last base (simple tail recursion elimination)
self_in
=
items
[
len
-
1
];
assert
(
MP_OBJ_IS_TYPE
(
items
[
len
-
1
],
&
mp_const_type
));
type
=
(
mp_obj_type_t
*
)
items
[
len
-
1
];
}
}
}
}
...
@@ -73,11 +73,12 @@ static void class_print(void (*print)(void *env, const char *fmt, ...), void *en
...
@@ -73,11 +73,12 @@ static void class_print(void (*print)(void *env, const char *fmt, ...), void *en
// args are reverse in the array
// args are reverse in the array
static
mp_obj_t
class_make_new
(
mp_obj_t
self_in
,
int
n_args
,
const
mp_obj_t
*
args
)
{
static
mp_obj_t
class_make_new
(
mp_obj_t
self_in
,
int
n_args
,
const
mp_obj_t
*
args
)
{
assert
(
MP_OBJ_IS_TYPE
(
self_in
,
&
mp_const_type
));
assert
(
MP_OBJ_IS_TYPE
(
self_in
,
&
mp_const_type
));
mp_obj_type_t
*
self
=
self_in
;
mp_obj_t
o
=
mp_obj_new_class
(
self_in
);
mp_obj_t
o
=
mp_obj_new_class
(
self_in
);
// look for __init__ function
// look for __init__ function
mp_map_elem_t
*
init_fn
=
mp_obj_class_lookup
(
self
_in
,
MP_QSTR___init__
,
MP_MAP_LOOKUP
);
mp_map_elem_t
*
init_fn
=
mp_obj_class_lookup
(
self
,
MP_QSTR___init__
,
MP_MAP_LOOKUP
);
if
(
init_fn
!=
NULL
)
{
if
(
init_fn
!=
NULL
)
{
// call __init__ function
// call __init__ function
...
@@ -114,7 +115,7 @@ static void class_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
...
@@ -114,7 +115,7 @@ static void class_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
dest
[
1
]
=
elem
->
value
;
dest
[
1
]
=
elem
->
value
;
return
;
return
;
}
}
elem
=
mp_obj_class_lookup
(
(
mp_obj_t
)
self
->
base
.
type
,
attr
,
MP_MAP_LOOKUP
);
elem
=
mp_obj_class_lookup
(
self
->
base
.
type
,
attr
,
MP_MAP_LOOKUP
);
if
(
elem
!=
NULL
)
{
if
(
elem
!=
NULL
)
{
if
(
mp_obj_is_callable
(
elem
->
value
))
{
if
(
mp_obj_is_callable
(
elem
->
value
))
{
// class member is callable so build a bound method
// class member is callable so build a bound method
...
@@ -132,7 +133,7 @@ static void class_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
...
@@ -132,7 +133,7 @@ static void class_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
static
bool
class_store_attr
(
mp_obj_t
self_in
,
qstr
attr
,
mp_obj_t
value
)
{
static
bool
class_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)
// logic: look in class locals (no add) then obj members (add) (TODO check this against CPython)
mp_obj_class_t
*
self
=
self_in
;
mp_obj_class_t
*
self
=
self_in
;
mp_map_elem_t
*
elem
=
mp_obj_class_lookup
(
(
mp_obj_t
)
self
->
base
.
type
,
attr
,
MP_MAP_LOOKUP
);
mp_map_elem_t
*
elem
=
mp_obj_class_lookup
(
self
->
base
.
type
,
attr
,
MP_MAP_LOOKUP
);
if
(
elem
!=
NULL
)
{
if
(
elem
!=
NULL
)
{
elem
->
value
=
value
;
elem
->
value
=
value
;
}
else
{
}
else
{
...
@@ -188,17 +189,47 @@ static mp_obj_t type_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args)
...
@@ -188,17 +189,47 @@ static mp_obj_t type_call_n(mp_obj_t self_in, int n_args, const mp_obj_t *args)
// for fail, do nothing; for attr, dest[1] = value; for method, dest[0] = self, dest[1] = method
// for fail, do nothing; for attr, dest[1] = value; for method, dest[0] = self, dest[1] = method
static
void
type_load_attr
(
mp_obj_t
self_in
,
qstr
attr
,
mp_obj_t
*
dest
)
{
static
void
type_load_attr
(
mp_obj_t
self_in
,
qstr
attr
,
mp_obj_t
*
dest
)
{
mp_map_elem_t
*
elem
=
mp_obj_class_lookup
(
self_in
,
attr
,
MP_MAP_LOOKUP
);
assert
(
MP_OBJ_IS_TYPE
(
self_in
,
&
mp_const_type
));
mp_obj_type_t
*
self
=
self_in
;
mp_map_elem_t
*
elem
=
mp_obj_class_lookup
(
self
,
attr
,
MP_MAP_LOOKUP
);
if
(
elem
!=
NULL
)
{
if
(
elem
!=
NULL
)
{
dest
[
1
]
=
elem
->
value
;
dest
[
1
]
=
elem
->
value
;
return
;
return
;
}
}
// generic method lookup
// this is a lookup in the class itself (ie not the classes type or instance)
const
mp_method_t
*
meth
=
self
->
methods
;
if
(
meth
!=
NULL
)
{
for
(;
meth
->
name
!=
NULL
;
meth
++
)
{
if
(
strcmp
(
meth
->
name
,
qstr_str
(
attr
))
==
0
)
{
// 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
[
1
]
=
((
mp_obj_staticmethod_t
*
)
meth
->
fun
)
->
fun
;
}
else
if
(
MP_OBJ_IS_TYPE
(
meth
->
fun
,
&
mp_type_classmethod
))
{
// return a bound method, with self being this class
dest
[
1
]
=
((
mp_obj_classmethod_t
*
)
meth
->
fun
)
->
fun
;
dest
[
0
]
=
self_in
;
}
else
{
// return just the function
// TODO need to wrap in a type check for the first argument; eg list.append(1,1) needs to throw an exception
dest
[
1
]
=
(
mp_obj_t
)
meth
->
fun
;
}
return
;
}
}
}
}
}
static
bool
type_store_attr
(
mp_obj_t
self_in
,
qstr
attr
,
mp_obj_t
value
)
{
static
bool
type_store_attr
(
mp_obj_t
self_in
,
qstr
attr
,
mp_obj_t
value
)
{
assert
(
MP_OBJ_IS_TYPE
(
self_in
,
&
mp_const_type
));
mp_obj_type_t
*
self
=
self_in
;
// TODO CPython allows STORE_ATTR to a class, but is this the correct implementation?
// TODO CPython allows STORE_ATTR to a class, but is this the correct implementation?
mp_map_elem_t
*
elem
=
mp_obj_class_lookup
(
self
_in
,
attr
,
MP_MAP_LOOKUP_ADD_IF_NOT_FOUND
);
mp_map_elem_t
*
elem
=
mp_obj_class_lookup
(
self
,
attr
,
MP_MAP_LOOKUP_ADD_IF_NOT_FOUND
);
if
(
elem
!=
NULL
)
{
if
(
elem
!=
NULL
)
{
elem
->
value
=
value
;
elem
->
value
=
value
;
return
true
;
return
true
;
...
@@ -284,3 +315,16 @@ static mp_obj_t mp_builtin_isinstance(mp_obj_t object, mp_obj_t classinfo) {
...
@@ -284,3 +315,16 @@ static mp_obj_t mp_builtin_isinstance(mp_obj_t object, mp_obj_t classinfo) {
}
}
MP_DEFINE_CONST_FUN_OBJ_2
(
mp_builtin_isinstance_obj
,
mp_builtin_isinstance
);
MP_DEFINE_CONST_FUN_OBJ_2
(
mp_builtin_isinstance_obj
,
mp_builtin_isinstance
);
/******************************************************************************/
// staticmethod and classmethod types (probably should go in a different file)
const
mp_obj_type_t
mp_type_staticmethod
=
{
{
&
mp_const_type
},
"staticmethod"
,
};
const
mp_obj_type_t
mp_type_classmethod
=
{
{
&
mp_const_type
},
"classmethod"
,
};
This diff is collapsed.
Click to expand it.
py/runtime.c
+
15
−
2
View file @
eae16445
...
@@ -774,12 +774,25 @@ void rt_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) {
...
@@ -774,12 +774,25 @@ void rt_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) {
dest
[
0
]
=
base
;
dest
[
0
]
=
base
;
}
else
{
}
else
{
// generic method lookup
// generic method lookup
// this is a lookup in the object (ie not class or type)
const
mp_method_t
*
meth
=
type
->
methods
;
const
mp_method_t
*
meth
=
type
->
methods
;
if
(
meth
!=
NULL
)
{
if
(
meth
!=
NULL
)
{
for
(;
meth
->
name
!=
NULL
;
meth
++
)
{
for
(;
meth
->
name
!=
NULL
;
meth
++
)
{
if
(
strcmp
(
meth
->
name
,
qstr_str
(
attr
))
==
0
)
{
if
(
strcmp
(
meth
->
name
,
qstr_str
(
attr
))
==
0
)
{
// 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
[
1
]
=
((
mp_obj_staticmethod_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
[
1
]
=
((
mp_obj_classmethod_t
*
)
meth
->
fun
)
->
fun
;
dest
[
0
]
=
mp_obj_get_type
(
base
);
}
else
{
// return a bound method, with self being this object
dest
[
1
]
=
(
mp_obj_t
)
meth
->
fun
;
dest
[
1
]
=
(
mp_obj_t
)
meth
->
fun
;
dest
[
0
]
=
base
;
dest
[
0
]
=
base
;
}
break
;
break
;
}
}
}
}
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
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!
Save comment
Cancel
Please
register
or
sign in
to comment