summaryrefslogtreecommitdiffstatshomepage
path: root/py
diff options
context:
space:
mode:
authorPaul Sokolovsky <pfalcon@users.sourceforge.net>2014-04-05 13:33:04 +0300
committerPaul Sokolovsky <pfalcon@users.sourceforge.net>2014-04-05 13:34:02 +0300
commitbfb7d6a26d6fe5b9a75447085514c609204eb469 (patch)
tree3313a205304d6583bc1af2e9ec563171708055b7 /py
parent438d504e27790bd3186051367f7c2afc266ba1e6 (diff)
downloadmicropython-bfb7d6a26d6fe5b9a75447085514c609204eb469.tar.gz
micropython-bfb7d6a26d6fe5b9a75447085514c609204eb469.zip
py: Support 3-arg getattr() builtin (with default value).
Diffstat (limited to 'py')
-rw-r--r--py/builtin.c12
-rw-r--r--py/runtime.c14
-rw-r--r--py/runtime.h1
3 files changed, 19 insertions, 8 deletions
diff --git a/py/builtin.c b/py/builtin.c
index 145bc65b14..2bf12e4928 100644
--- a/py/builtin.c
+++ b/py/builtin.c
@@ -400,9 +400,13 @@ 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 mp_load_attr(o_in, MP_OBJ_QSTR_VALUE(attr));
+STATIC mp_obj_t mp_builtin_getattr(uint n_args, const mp_obj_t *args) {
+ assert(MP_OBJ_IS_QSTR(args[1]));
+ mp_obj_t defval = MP_OBJ_NULL;
+ if (n_args > 2) {
+ defval = args[2];
+ }
+ return mp_load_attr_default(args[0], MP_OBJ_QSTR_VALUE(args[1]), defval);
}
-MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_getattr_obj, mp_builtin_getattr);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_getattr_obj, 2, 3, mp_builtin_getattr);
diff --git a/py/runtime.c b/py/runtime.c
index 773f998d34..df7de3e54f 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -689,12 +689,14 @@ too_long:
nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "too many values to unpack (expected %d)", num));
}
-mp_obj_t mp_load_attr(mp_obj_t base, qstr attr) {
+mp_obj_t mp_load_attr_default(mp_obj_t base, qstr attr, mp_obj_t defval) {
DEBUG_OP_printf("load attr %p.%s\n", base, qstr_str(attr));
- // use load_method
mp_obj_t dest[2];
- mp_load_method(base, attr, dest);
- if (dest[1] == MP_OBJ_NULL) {
+ // use load_method, raising or not raising exception
+ ((defval == MP_OBJ_NULL) ? mp_load_method : mp_load_method_maybe)(base, attr, dest);
+ if (dest[0] == MP_OBJ_NULL) {
+ return defval;
+ } else if (dest[1] == MP_OBJ_NULL) {
// load_method returned just a normal attribute
return dest[0];
} else {
@@ -703,6 +705,10 @@ mp_obj_t mp_load_attr(mp_obj_t base, qstr attr) {
}
}
+mp_obj_t mp_load_attr(mp_obj_t base, qstr attr) {
+ return mp_load_attr_default(base, attr, MP_OBJ_NULL);
+}
+
// no attribute found, returns: dest[0] == MP_OBJ_NULL, dest[1] == MP_OBJ_NULL
// normal attribute found, returns: dest[0] == <attribute>, dest[1] == MP_OBJ_NULL
// method attribute found, returns: dest[0] == <method>, dest[1] == <self>
diff --git a/py/runtime.h b/py/runtime.h
index b233d23b4a..22e7781be7 100644
--- a/py/runtime.h
+++ b/py/runtime.h
@@ -45,6 +45,7 @@ mp_obj_t mp_call_method_n_kw_var(bool have_self, uint n_args_n_kw, const mp_obj_
void mp_unpack_sequence(mp_obj_t seq, uint num, mp_obj_t *items);
mp_obj_t mp_store_map(mp_obj_t map, mp_obj_t key, mp_obj_t value);
mp_obj_t mp_load_attr(mp_obj_t base, qstr attr);
+mp_obj_t mp_load_attr_default(mp_obj_t base, qstr attr, mp_obj_t defval);
void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest);
void mp_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest);
void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t val);