STATIC mp_obj_t gen_resume_and_raise(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value) { mp_obj_t ret; switch (mp_obj_gen_resume(self_in, send_value, throw_value, &ret)) { case MP_VM_RETURN_NORMAL: // Optimize return w/o value in case generator is used in for loop if (ret == mp_const_none || ret == MP_OBJ_STOP_ITERATION) { return MP_OBJ_STOP_ITERATION; } else { nlr_raise(mp_obj_new_exception_args(&mp_type_StopIteration, 1, &ret)); } case MP_VM_RETURN_YIELD: if (throw_value != MP_OBJ_NULL && mp_obj_is_subclass_fast(mp_obj_get_type(throw_value), &mp_type_GeneratorExit)) { nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "generator ignored GeneratorExit")); } return ret; case MP_VM_RETURN_EXCEPTION: // TODO: Optimization of returning MP_OBJ_STOP_ITERATION is really part // of mp_iternext() protocol, but this function is called by other methods // too, which may not handled MP_OBJ_STOP_ITERATION. if (mp_obj_is_subclass_fast(mp_obj_get_type(ret), &mp_type_StopIteration)) { return MP_OBJ_STOP_ITERATION; } else { nlr_raise(ret); } default: assert(0); return mp_const_none; } }
STATIC mp_obj_t gen_resume_and_raise(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value) { mp_obj_t ret; switch (mp_obj_gen_resume(self_in, send_value, throw_value, &ret)) { case MP_VM_RETURN_NORMAL: default: // Optimize return w/o value in case generator is used in for loop if (ret == mp_const_none || ret == MP_OBJ_STOP_ITERATION) { return MP_OBJ_STOP_ITERATION; } else { nlr_raise(mp_obj_new_exception_args(&mp_type_StopIteration, 1, &ret)); } case MP_VM_RETURN_YIELD: return ret; case MP_VM_RETURN_EXCEPTION: // TODO: Optimization of returning MP_OBJ_STOP_ITERATION is really part // of mp_iternext() protocol, but this function is called by other methods // too, which may not handled MP_OBJ_STOP_ITERATION. if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(ret)), MP_OBJ_FROM_PTR(&mp_type_StopIteration))) { mp_obj_t val = mp_obj_exception_get_value(ret); if (val == mp_const_none) { return MP_OBJ_STOP_ITERATION; } } nlr_raise(ret); } }
inline void do_str(const char *src) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); if (lex == NULL) { tt_abort_msg("Lexer initialization error"); } nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { qstr source_name = lex->source_name; mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT); mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, true); mp_call_function_0(module_fun); nlr_pop(); } else { mp_obj_t exc = (mp_obj_t)nlr.ret_val; if (mp_obj_is_subclass_fast(mp_obj_get_type(exc), &mp_type_SystemExit)) { // Assume that sys.exit() is called to skip the test. // TODO: That can be always true, we should set up convention to // use specific exit code as skip indicator. tinytest_set_test_skipped_(); return; } mp_obj_print_exception(&mp_plat_print, exc); tt_abort_msg("Uncaught exception"); } end: ; }
// Don't pass MP_BINARY_OP_NOT_EQUAL here STATIC bool tuple_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in) { // type check is done on getiter method to allow tuple, namedtuple, attrtuple mp_check_self(mp_obj_get_type(self_in)->getiter == mp_obj_tuple_getiter); mp_obj_type_t *another_type = mp_obj_get_type(another_in); mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); if (another_type->getiter != mp_obj_tuple_getiter) { // Slow path for user subclasses another_in = mp_instance_cast_to_native_base(another_in, MP_OBJ_FROM_PTR(&mp_type_tuple)); if (another_in == MP_OBJ_NULL) { return false; } } mp_obj_tuple_t *another = MP_OBJ_TO_PTR(another_in); return mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len); }
bool mp_obj_is_callable(mp_obj_t o_in) { mp_call_fun_t call = mp_obj_get_type(o_in)->call; if (call != mp_obj_instance_call) { return call != NULL; } return mp_obj_instance_is_callable(o_in); }
STATIC mp_obj_t mp_builtin_dir(uint n_args, const mp_obj_t *args) { // TODO make this function more general and less of a hack mp_obj_dict_t *dict = NULL; if (n_args == 0) { // make a list of names in the local name space dict = mp_locals_get(); } else { // n_args == 1 // make a list of names in the given object if (MP_OBJ_IS_TYPE(args[0], &mp_type_module)) { dict = mp_obj_module_get_globals(args[0]); } else { mp_obj_type_t *type; if (MP_OBJ_IS_TYPE(args[0], &mp_type_type)) { type = args[0]; } else { type = mp_obj_get_type(args[0]); } if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)) { dict = type->locals_dict; } } } mp_obj_t dir = mp_obj_new_list(0, NULL); if (dict != NULL) { for (uint i = 0; i < dict->map.alloc; i++) { if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) { mp_obj_list_append(dir, dict->map.table[i].key); } } } return dir; }
mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) { mp_obj_type_t *type = mp_obj_get_type(base); if (type->subscr != NULL) { mp_obj_t ret = type->subscr(base, index, value); if (ret != MP_OBJ_NULL) { return ret; } // TODO: call base classes here? } if (value == MP_OBJ_NULL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "object does not support item deletion")); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object does not support item deletion", mp_obj_get_type_str(base))); } } else if (value == MP_OBJ_SENTINEL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object is not subscriptable")); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not subscriptable", mp_obj_get_type_str(base))); } } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "object does not support item assignment")); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object does not support item assignment", mp_obj_get_type_str(base))); } } }
STATIC mp_obj_t pyb_help(uint n_args, const mp_obj_t *args) { if (n_args == 0) { // print a general help message printf("%s", help_text); } else { // try to print something sensible about the given object printf("object "); mp_obj_print(args[0], PRINT_STR); printf(" is of type %s\n", mp_obj_get_type_str(args[0])); mp_map_t *map = NULL; if (MP_OBJ_IS_TYPE(args[0], &mp_type_module)) { map = mp_obj_dict_get_map(mp_obj_module_get_globals(args[0])); } else { mp_obj_type_t *type; if (MP_OBJ_IS_TYPE(args[0], &mp_type_type)) { type = args[0]; } else { type = mp_obj_get_type(args[0]); } if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)) { map = mp_obj_dict_get_map(type->locals_dict); } } if (map != NULL) { for (uint i = 0; i < map->alloc; i++) { if (map->table[i].key != MP_OBJ_NULL) { pyb_help_print_info_about_object(map->table[i].key, map->table[i].value); } } } } return mp_const_none; }
// Return true if exception (type or instance) is a subclass of given // exception type. Assumes exc_type is a subclass of BaseException, as // defined by mp_obj_is_exception_type(exc_type). bool mp_obj_exception_match(mp_obj_t exc, mp_const_obj_t exc_type) { // if exc is an instance of an exception, then extract and use its type if (mp_obj_is_exception_instance(exc)) { exc = MP_OBJ_FROM_PTR(mp_obj_get_type(exc)); } return mp_obj_is_subclass_fast(exc, exc_type); }
pyb_pin_obj_t *mp_obj_get_pin_obj(mp_obj_t pin_in) { if (mp_obj_get_type(pin_in) != &pyb_pin_type) { nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "expecting a pin")); } pyb_pin_obj_t *self = pin_in; return self; }
mp_obj_t mp_obj_tuple_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) { mp_obj_tuple_t *o = lhs; switch (op) { case MP_BINARY_OP_ADD: { if (!mp_obj_is_subclass_fast(mp_obj_get_type(rhs), (mp_obj_t)&mp_type_tuple)) { return MP_OBJ_NULL; // op not supported } mp_obj_tuple_t *p = rhs; mp_obj_tuple_t *s = mp_obj_new_tuple(o->len + p->len, NULL); mp_seq_cat(s->items, o->items, o->len, p->items, p->len, mp_obj_t); return s; } case MP_BINARY_OP_MULTIPLY: { mp_int_t n; if (!mp_obj_get_int_maybe(rhs, &n)) { return MP_OBJ_NULL; // op not supported } if (n <= 0) { return mp_const_empty_tuple; } mp_obj_tuple_t *s = mp_obj_new_tuple(o->len * n, NULL); mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items); return s; } case MP_BINARY_OP_EQUAL: case MP_BINARY_OP_LESS: case MP_BINARY_OP_LESS_EQUAL: case MP_BINARY_OP_MORE: case MP_BINARY_OP_MORE_EQUAL: return MP_BOOL(tuple_cmp_helper(op, lhs, rhs)); default: return MP_OBJ_NULL; // op not supported } }
mp_import_stat_t mp_vfs_import_stat(const char *path) { const char *path_out; mp_vfs_mount_t *vfs = mp_vfs_lookup_path(path, &path_out); if (vfs == MP_VFS_NONE || vfs == MP_VFS_ROOT) { return MP_IMPORT_STAT_NO_EXIST; } // If the mounted object has the VFS protocol, call its import_stat helper const mp_vfs_proto_t *proto = mp_obj_get_type(vfs->obj)->protocol; if (proto != NULL) { return proto->import_stat(MP_OBJ_TO_PTR(vfs->obj), path_out); } // delegate to vfs.stat() method mp_obj_t path_o = mp_obj_new_str(path_out, strlen(path_out)); mp_obj_t stat; nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { stat = mp_vfs_proxy_call(vfs, MP_QSTR_stat, 1, &path_o); nlr_pop(); } else { // assume an exception means that the path is not found return MP_IMPORT_STAT_NO_EXIST; } mp_obj_t *items; mp_obj_get_array_fixed_n(stat, 10, &items); mp_int_t st_mode = mp_obj_get_int(items[0]); if (st_mode & MP_S_IFDIR) { return MP_IMPORT_STAT_DIR; } else { return MP_IMPORT_STAT_FILE; } }
// function usocket.getaddrinfo(host, port) /// \function getaddrinfo(host, port) STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) { mp_uint_t hlen; const char *host = mp_obj_str_get_data(host_in, &hlen); mp_int_t port = mp_obj_get_int(port_in); // find a NIC that can do a name lookup for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) { mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i]; mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic); if (nic_type->gethostbyname != NULL) { // Only IPv4 is supported uint8_t out_ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; int32_t result = nic_type->gethostbyname(nic, host, hlen, out_ip, AF_INET); if (result != 0) { nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(result))); } mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL); tuple->items[0] = MP_OBJ_NEW_SMALL_INT(AF_INET); tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SOCK_STREAM); tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); tuple->items[4] = mod_network_format_inet_addr(out_ip, port); return mp_obj_new_list(1, (mp_obj_t*)&tuple); } } nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable)); }
mp_obj_t mp_obj_tuple_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { mp_obj_tuple_t *o = lhs; switch (op) { case MP_BINARY_OP_ADD: { if (!mp_obj_is_subclass_fast(mp_obj_get_type(rhs), (mp_obj_t)&mp_type_tuple)) { return MP_OBJ_NULL; // op not supported } mp_obj_tuple_t *p = rhs; mp_obj_tuple_t *s = mp_obj_new_tuple(o->len + p->len, NULL); mp_seq_cat(s->items, o->items, o->len, p->items, p->len, mp_obj_t); return s; } case MP_BINARY_OP_MULTIPLY: { if (!MP_OBJ_IS_SMALL_INT(rhs)) { return MP_OBJ_NULL; // op not supported } int n = MP_OBJ_SMALL_INT_VALUE(rhs); mp_obj_tuple_t *s = mp_obj_new_tuple(o->len * n, NULL); mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items); return s; } case MP_BINARY_OP_EQUAL: case MP_BINARY_OP_LESS: case MP_BINARY_OP_LESS_EQUAL: case MP_BINARY_OP_MORE: case MP_BINARY_OP_MORE_EQUAL: return MP_BOOL(tuple_cmp_helper(op, lhs, rhs)); default: return MP_OBJ_NULL; // op not supported } }
// function usocket.getaddrinfo(host, port) STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) { mp_uint_t hlen; const char *host = mp_obj_str_get_data(host_in, &hlen); mp_int_t port = mp_obj_get_int(port_in); // find a NIC that can do a name lookup for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) { mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i]; mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic); if (nic_type->gethostbyname != NULL) { uint8_t out_ip[MOD_NETWORK_IPADDR_BUF_SIZE]; int ret = nic_type->gethostbyname(nic, host, hlen, out_ip); if (ret != 0) { // TODO CPython raises: socket.gaierror: [Errno -2] Name or service not known nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ret))); } mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL); tuple->items[0] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET); tuple->items[1] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM); tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_); tuple->items[4] = mod_network_format_inet_addr(out_ip, port); return mp_obj_new_list(1, (mp_obj_t*)&tuple); } } nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "no available NIC")); }
bool mp_obj_is_true(mp_obj_t arg) { if (arg == mp_const_false) { return 0; } else if (arg == mp_const_true) { return 1; } else if (arg == mp_const_none) { return 0; } else if (MP_OBJ_IS_SMALL_INT(arg)) { if (MP_OBJ_SMALL_INT_VALUE(arg) == 0) { return 0; } else { return 1; } } else { mp_obj_type_t *type = mp_obj_get_type(arg); if (type->unary_op != NULL) { mp_obj_t result = type->unary_op(MP_UNARY_OP_BOOL, arg); if (result != MP_OBJ_NULL) { return result == mp_const_true; } } mp_obj_t len = mp_obj_len_maybe(arg); if (len != MP_OBJ_NULL) { // obj has a length, truth determined if len != 0 return len != MP_OBJ_NEW_SMALL_INT(0); } else { // any other obj is true per Python semantics return 1; } } }
mp_obj_t microbit_display_show_func(mp_uint_t n_args, const mp_obj_t *args) { // TODO: Support async mode. microbit_display_obj_t *self = (microbit_display_obj_t*)args[0]; // Cancel any animations. MP_STATE_PORT(async_data)[0] = NULL; MP_STATE_PORT(async_data)[1] = NULL; MP_STATE_PORT(async_data)[2] = NULL; if (MP_OBJ_IS_STR(args[1])) { // arg is a string object mp_uint_t len; const char *str = mp_obj_str_get_data(args[1], &len); if (len == 0) { // There are no chars; do nothing. } else if (len == 1) { // A single char; convert to an image and print that. microbit_display_show(self, microbit_image_for_char(str[0])); } else { mp_int_t delay; if (n_args == 3) { delay = mp_obj_get_int(args[2]); } else { delay = MICROBIT_DEFAULT_PRINT_SPEED; } microbit_display_animate(self, args[1], delay, false, false); } } else if (mp_obj_get_type(args[1]) == µbit_image_type) { microbit_display_show(self, (microbit_image_obj_t *)args[1]); } else { nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "expecting an image or a string.")); } return mp_const_none; }
STATIC void poll_map_add(mp_map_t *poll_map, const mp_obj_t *obj, mp_uint_t obj_len, mp_uint_t flags, bool or_flags) { for (mp_uint_t i = 0; i < obj_len; i++) { mp_map_elem_t *elem = mp_map_lookup(poll_map, mp_obj_id(obj[i]), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND); if (elem->value == NULL) { // object not found; get its ioctl and add it to the poll list mp_obj_type_t *type = mp_obj_get_type(obj[i]); if (type->stream_p == NULL || type->stream_p->ioctl == NULL) { nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "object with stream.ioctl required")); } poll_obj_t *poll_obj = m_new_obj(poll_obj_t); poll_obj->obj = obj[i]; poll_obj->ioctl = type->stream_p->ioctl; poll_obj->flags = flags; poll_obj->flags_ret = 0; elem->value = poll_obj; } else { // object exists; update its flags if (or_flags) { ((poll_obj_t*)elem->value)->flags |= flags; } else { ((poll_obj_t*)elem->value)->flags = flags; } } } }
STATIC void mp_help_print_obj(mp_obj_t obj) { #if MICROPY_PY_BUILTINS_HELP_MODULES if (obj == MP_OBJ_NEW_QSTR(MP_QSTR_modules)) { mp_help_print_modules(); return; } #endif // Extract method from bound method, for better error messages if (mp_obj_get_type(obj)->name == MP_QSTR_bound_method) { obj = ((mp_obj_t*)obj)[1]; // extract method } // Hook into platform-specific help for this object extern bool mp_plat_specific_help(mp_obj_t obj); if (mp_plat_specific_help(obj)) { return; } // try to print something sensible about the given object mp_print_str(MP_PYTHON_PRINTER, "object "); mp_obj_print(obj, PRINT_STR); mp_printf(MP_PYTHON_PRINTER, " is of type %s\n", mp_obj_get_type_str(obj)); mp_map_t *map = NULL; if (MP_OBJ_IS_TYPE(obj, &mp_type_module)) { map = mp_obj_dict_get_map(mp_obj_module_get_globals(obj)); } else { mp_obj_type_t *type; if (MP_OBJ_IS_TYPE(obj, &mp_type_type)) { type = obj; } else { type = mp_obj_get_type(obj); } if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)) { map = mp_obj_dict_get_map(type->locals_dict); } } if (map != NULL) { for (uint i = 0; i < map->alloc; i++) { if (map->table[i].key != MP_OBJ_NULL) { mp_help_print_info_about_object(map->table[i].key, map->table[i].value); } } } }
void mp_obj_print_helper(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) { mp_obj_type_t *type = mp_obj_get_type(o_in); if (type->print != NULL) { type->print(print, env, o_in, kind); } else { print(env, "<%s>", qstr_str(type->name)); } }
// Don't pass MP_BINARY_OP_NOT_EQUAL here STATIC bool tuple_cmp_helper(int op, mp_obj_t self_in, mp_obj_t another_in) { mp_obj_type_t *self_type = mp_obj_get_type(self_in); if (self_type->getiter != mp_obj_tuple_getiter) { assert(0); } mp_obj_type_t *another_type = mp_obj_get_type(another_in); mp_obj_tuple_t *self = self_in; mp_obj_tuple_t *another = another_in; if (another_type->getiter != mp_obj_tuple_getiter) { // Slow path for user subclasses another = mp_instance_cast_to_native_base(another, &mp_type_tuple); if (another == MP_OBJ_NULL) { return false; } } return mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len); }
// Version of mp_vfs_lookup_path that takes and returns uPy string objects. STATIC mp_vfs_mount_t *lookup_path(mp_obj_t path_in, mp_obj_t *path_out) { const char *path = mp_obj_str_get_str(path_in); const char *p_out; mp_vfs_mount_t *vfs = mp_vfs_lookup_path(path, &p_out); if (vfs != MP_VFS_NONE && vfs != MP_VFS_ROOT) { *path_out = mp_obj_new_str_of_type(mp_obj_get_type(path_in), (const byte*)p_out, strlen(p_out)); } return vfs; }
void mp_obj_exception_clear_traceback(mp_obj_t self_in) { // make sure self_in is an exception instance // TODO add traceback information to user-defined exceptions (need proper builtin subclassing for that) if (mp_obj_get_type(self_in)->make_new == mp_obj_exception_make_new) { mp_obj_exception_t *self = self_in; // just set the traceback to the null object // we don't want to call any memory management functions here self->traceback = MP_OBJ_NULL; } }
bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) { mp_obj_type_t *type = mp_obj_get_type(obj); if (type->buffer_p.get_buffer == NULL) { return false; } int ret = type->buffer_p.get_buffer(obj, bufinfo, flags); if (ret != 0) { return false; } return true; }
STATIC mp_obj_t gen_instance_close(mp_obj_t self_in) { mp_obj_t ret; switch (mp_obj_gen_resume(self_in, mp_const_none, (mp_obj_t)&mp_const_GeneratorExit_obj, &ret)) { case MP_VM_RETURN_YIELD: nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "generator ignored GeneratorExit")); // Swallow StopIteration & GeneratorExit (== successful close), and re-raise any other case MP_VM_RETURN_EXCEPTION: // ret should always be an instance of an exception class if (mp_obj_is_subclass_fast(mp_obj_get_type(ret), &mp_type_GeneratorExit) || mp_obj_is_subclass_fast(mp_obj_get_type(ret), &mp_type_StopIteration)) { return mp_const_none; } nlr_raise(ret); default: // The only choice left is MP_VM_RETURN_NORMAL which is successful close return mp_const_none; } }
STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args) { // This structure holds the Python function and arguments for thread entry. // We copy all arguments into this structure to keep ownership of them. // We must be very careful about root pointers because this pointer may // disappear from our address space before the thread is created. thread_entry_args_t *th_args; // get positional arguments size_t pos_args_len; mp_obj_t *pos_args_items; mp_obj_get_array(args[1], &pos_args_len, &pos_args_items); // check for keyword arguments if (n_args == 2) { // just position arguments th_args = m_new_obj_var(thread_entry_args_t, mp_obj_t, pos_args_len); th_args->n_kw = 0; } else { // positional and keyword arguments if (mp_obj_get_type(args[2]) != &mp_type_dict) { mp_raise_TypeError("expecting a dict for keyword args"); } mp_map_t *map = &((mp_obj_dict_t*)MP_OBJ_TO_PTR(args[2]))->map; th_args = m_new_obj_var(thread_entry_args_t, mp_obj_t, pos_args_len + 2 * map->used); th_args->n_kw = map->used; // copy across the keyword arguments for (size_t i = 0, n = pos_args_len; i < map->alloc; ++i) { if (mp_map_slot_is_filled(map, i)) { th_args->args[n++] = map->table[i].key; th_args->args[n++] = map->table[i].value; } } } // copy agross the positional arguments th_args->n_args = pos_args_len; memcpy(th_args->args, pos_args_items, pos_args_len * sizeof(mp_obj_t)); // pass our locals and globals into the new thread th_args->dict_locals = mp_locals_get(); th_args->dict_globals = mp_globals_get(); // set the stack size to use th_args->stack_size = thread_stack_size; // set the function for thread entry th_args->fun = args[0]; // spawn the thread! mp_thread_create(thread_entry, th_args, &th_args->stack_size); return mp_const_none; }
// may return MP_OBJ_NULL mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) { if (MP_OBJ_IS_STR(o_in)) { return MP_OBJ_NEW_SMALL_INT((machine_int_t)mp_obj_str_get_len(o_in)); } else { mp_obj_type_t *type = mp_obj_get_type(o_in); if (type->unary_op != NULL) { return type->unary_op(MP_UNARY_OP_LEN, o_in); } else { return MP_OBJ_NULL; } } }
mp_obj_t tuple_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { mp_obj_tuple_t *o = lhs; switch (op) { case MP_BINARY_OP_SUBSCR: { #if MICROPY_ENABLE_SLICE if (MP_OBJ_IS_TYPE(rhs, &mp_type_slice)) { machine_uint_t start, stop; if (!m_seq_get_fast_slice_indexes(o->len, rhs, &start, &stop)) { assert(0); } mp_obj_tuple_t *res = mp_obj_new_tuple(stop - start, NULL); m_seq_copy(res->items, o->items + start, res->len, mp_obj_t); return res; } #endif uint index = mp_get_index(o->base.type, o->len, rhs, false); return o->items[index]; } case MP_BINARY_OP_ADD: { if (!mp_obj_is_subclass_fast(mp_obj_get_type(rhs), (mp_obj_t)&mp_type_tuple)) { return NULL; } mp_obj_tuple_t *p = rhs; mp_obj_tuple_t *s = mp_obj_new_tuple(o->len + p->len, NULL); m_seq_cat(s->items, o->items, o->len, p->items, p->len, mp_obj_t); return s; } case MP_BINARY_OP_MULTIPLY: { if (!MP_OBJ_IS_SMALL_INT(rhs)) { return NULL; } int n = MP_OBJ_SMALL_INT_VALUE(rhs); mp_obj_tuple_t *s = mp_obj_new_tuple(o->len * n, NULL); mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items); return s; } case MP_BINARY_OP_EQUAL: case MP_BINARY_OP_LESS: case MP_BINARY_OP_LESS_EQUAL: case MP_BINARY_OP_MORE: case MP_BINARY_OP_MORE_EQUAL: return MP_BOOL(tuple_cmp_helper(op, lhs, rhs)); case MP_BINARY_OP_NOT_EQUAL: return MP_BOOL(!tuple_cmp_helper(MP_BINARY_OP_EQUAL, lhs, rhs)); default: // op not supported return NULL; } }
const mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags) { mp_obj_type_t *type = mp_obj_get_type(self_in); const mp_stream_p_t *stream_p = type->protocol; if (stream_p == NULL || ((flags & MP_STREAM_OP_READ) && stream_p->read == NULL) || ((flags & MP_STREAM_OP_WRITE) && stream_p->write == NULL) || ((flags & MP_STREAM_OP_IOCTL) && stream_p->ioctl == NULL)) { // CPython: io.UnsupportedOperation, OSError subclass mp_raise_msg(&mp_type_OSError, "stream operation not supported"); } return stream_p; }
// this function implements the '==' operator (and so the inverse of '!=') // from the python language reference: // "The objects need not have the same type. If both are numbers, they are converted // to a common type. Otherwise, the == and != operators always consider objects of // different types to be unequal." // note also that False==0 and True==1 are true expressions bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) { if (o1 == o2) { return true; } if (o1 == mp_const_none || o2 == mp_const_none) { return false; } // fast path for small ints if (MP_OBJ_IS_SMALL_INT(o1)) { if (MP_OBJ_IS_SMALL_INT(o2)) { // both SMALL_INT, and not equal if we get here return false; } else { mp_obj_t temp = o2; o2 = o1; o1 = temp; // o2 is now the SMALL_INT, o1 is not // fall through to generic op } } // fast path for strings if (MP_OBJ_IS_STR(o1)) { if (MP_OBJ_IS_STR(o2)) { // both strings, use special function return mp_obj_str_equal(o1, o2); } else { // a string is never equal to anything else return false; } } else if (MP_OBJ_IS_STR(o2)) { // o1 is not a string (else caught above), so the objects are not equal return false; } // generic type, call binary_op(MP_BINARY_OP_EQUAL) mp_obj_type_t *type = mp_obj_get_type(o1); if (type->binary_op != NULL) { mp_obj_t r = type->binary_op(MP_BINARY_OP_EQUAL, o1, o2); if (r != MP_OBJ_NULL) { return r == mp_const_true ? true : false; } } if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError, "equality for given types not yet implemented")); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_NotImplementedError, "equality for '%s' and '%s' types not yet implemented", mp_obj_get_type_str(o1), mp_obj_get_type_str(o2))); } }