static int call_dupterm_read(void) { if (MP_STATE_PORT(term_obj) == NULL) { return -1; } nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_obj_t read_m[3]; mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_read, read_m); read_m[2] = MP_OBJ_NEW_SMALL_INT(1); mp_obj_t res = mp_call_method_n_kw(1, 0, read_m); if (res == mp_const_none) { return -2; } mp_buffer_info_t bufinfo; mp_get_buffer_raise(res, &bufinfo, MP_BUFFER_READ); if (bufinfo.len == 0) { mp_printf(&mp_plat_print, "dupterm: EOF received, deactivating\n"); MP_STATE_PORT(term_obj) = NULL; return -1; } nlr_pop(); return *(byte*)bufinfo.buf; } else { // Temporarily disable dupterm to avoid infinite recursion mp_obj_t save_term = MP_STATE_PORT(term_obj); MP_STATE_PORT(term_obj) = NULL; mp_printf(&mp_plat_print, "dupterm: "); mp_obj_print_exception(&mp_plat_print, nlr.ret_val); MP_STATE_PORT(term_obj) = save_term; } return -1; }
STATIC mp_obj_t mp_sys_print_exception(size_t n_args, const mp_obj_t *args) { #if MICROPY_PY_IO void *stream_obj = &mp_sys_stdout_obj; if (n_args > 1) { stream_obj = MP_OBJ_TO_PTR(args[1]); // XXX may fail } mp_print_t print = {stream_obj, mp_stream_write_adaptor}; mp_obj_print_exception(&print, args[0]); #else (void)n_args; mp_obj_print_exception(&mp_plat_print, args[0]); #endif return mp_const_none; }
STATIC void *thread_entry(void *args_in) { // Execution begins here for a new thread. We do not have the GIL. thread_entry_args_t *args = (thread_entry_args_t*)args_in; mp_state_thread_t ts; mp_thread_set_state(&ts); mp_stack_set_top(&ts + 1); // need to include ts in root-pointer scan mp_stack_set_limit(args->stack_size); #if MICROPY_ENABLE_PYSTACK // TODO threading and pystack is not fully supported, for now just make a small stack mp_obj_t mini_pystack[128]; mp_pystack_init(mini_pystack, &mini_pystack[128]); #endif // set locals and globals from the calling context mp_locals_set(args->dict_locals); mp_globals_set(args->dict_globals); MP_THREAD_GIL_ENTER(); // signal that we are set up and running mp_thread_start(); // TODO set more thread-specific state here: // mp_pending_exception? (root pointer) // cur_exception (root pointer) DEBUG_printf("[thread] start ts=%p args=%p stack=%p\n", &ts, &args, MP_STATE_THREAD(stack_top)); nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_call_function_n_kw(args->fun, args->n_args, args->n_kw, args->args); nlr_pop(); } else { // uncaught exception // check for SystemExit mp_obj_base_t *exc = (mp_obj_base_t*)nlr.ret_val; if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(exc->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) { // swallow exception silently } else { // print exception out mp_printf(MICROPY_ERROR_PRINTER, "Unhandled exception in thread started by "); mp_obj_print_helper(MICROPY_ERROR_PRINTER, args->fun, PRINT_REPR); mp_printf(MICROPY_ERROR_PRINTER, "\n"); mp_obj_print_exception(MICROPY_ERROR_PRINTER, MP_OBJ_FROM_PTR(exc)); } } DEBUG_printf("[thread] finish ts=%p\n", &ts); // signal that we are finished mp_thread_finish(); MP_THREAD_GIL_EXIT(); return NULL; }
// Interrupt handler void Handle_EXTI_Irq(uint32_t line) { if (__HAL_GPIO_EXTI_GET_FLAG(1 << line)) { __HAL_GPIO_EXTI_CLEAR_FLAG(1 << line); if (line < EXTI_NUM_VECTORS) { mp_obj_t *cb = &MP_STATE_PORT(pyb_extint_callback)[line]; if (*cb != mp_const_none) { // When executing code within a handler we must lock the GC to prevent // any memory allocations. We must also catch any exceptions. gc_lock(); nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_call_function_1(*cb, MP_OBJ_NEW_SMALL_INT(line)); nlr_pop(); } else { // Uncaught exception; disable the callback so it doesn't run again. *cb = mp_const_none; extint_disable(line); printf("Uncaught exception in ExtInt interrupt handler line %lu\n", line); mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); } gc_unlock(); } } } }
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: ; }
mp_obj_t call_function_2_protected(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { return mp_call_function_2(fun, arg1, arg2); } else { mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); return (mp_obj_t)nlr.ret_val; } }
void mp_uos_deactivate(const char *msg, mp_obj_t exc) { mp_obj_t term = MP_STATE_PORT(term_obj); MP_STATE_PORT(term_obj) = NULL; mp_printf(&mp_plat_print, msg); if (exc != MP_OBJ_NULL) { mp_obj_print_exception(&mp_plat_print, exc); } mp_stream_close(term); }
STATIC void execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bool is_repl) { if (lex == NULL) { return; } if (0) { // just tokenise while (!mp_lexer_is_kind(lex, MP_TOKEN_END)) { mp_token_show(mp_lexer_cur(lex)); mp_lexer_to_next(lex); } mp_lexer_free(lex); return; } mp_parse_error_kind_t parse_error_kind; mp_parse_node_t pn = mp_parse(lex, input_kind, &parse_error_kind); if (pn == MP_PARSE_NODE_NULL) { // parse error mp_parse_show_exception(lex, parse_error_kind); mp_lexer_free(lex); return; } qstr source_name = mp_lexer_source_name(lex); mp_lexer_free(lex); /* printf("----------------\n"); mp_parse_node_print(pn, 0); printf("----------------\n"); */ mp_obj_t module_fun = mp_compile(pn, source_name, emit_opt, is_repl); if (module_fun == mp_const_none) { // compile error return; } if (compile_only) { return; } // execute it nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_call_function_0(module_fun); nlr_pop(); } else { // uncaught exception mp_obj_print_exception((mp_obj_t)nlr.ret_val); } }
mp_obj_t micropy_call_0(mp_obj_t module_obj, const char *func) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_obj_t py_func = mp_load_attr(module_obj, qstr_from_str(func)); mp_obj_t module_obj = mp_call_function_0(py_func); nlr_pop(); return module_obj; } else { mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); // uncaught exception return 0; } }
STATIC void *thread_entry(void *args_in) { // Execution begins here for a new thread. We do not have the GIL. thread_entry_args_t *args = (thread_entry_args_t*)args_in; mp_state_thread_t ts; mp_thread_set_state(&ts); mp_stack_set_top(&ts + 1); // need to include ts in root-pointer scan mp_stack_set_limit(args->stack_size); MP_THREAD_GIL_ENTER(); // signal that we are set up and running mp_thread_start(); // TODO set more thread-specific state here: // mp_pending_exception? (root pointer) // cur_exception (root pointer) // dict_locals? (root pointer) uPy doesn't make a new locals dict for functions, just for classes, so it's different to CPy DEBUG_printf("[thread] start ts=%p args=%p stack=%p\n", &ts, &args, MP_STATE_THREAD(stack_top)); nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_call_function_n_kw(args->fun, args->n_args, args->n_kw, args->args); nlr_pop(); } else { // uncaught exception // check for SystemExit mp_obj_base_t *exc = (mp_obj_base_t*)nlr.ret_val; if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(exc->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) { // swallow exception silently } else { // print exception out mp_printf(&mp_plat_print, "Unhandled exception in thread started by "); mp_obj_print_helper(&mp_plat_print, args->fun, PRINT_REPR); mp_printf(&mp_plat_print, "\n"); mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(exc)); } } DEBUG_printf("[thread] finish ts=%p\n", &ts); // signal that we are finished mp_thread_finish(); MP_THREAD_GIL_EXIT(); return NULL; }
mp_obj_t micropy_call_1(mp_obj_t module_obj, const char* func, const char* _arg0) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_obj_t py_func = mp_load_attr(module_obj, qstr_from_str(func)); mp_obj_t arg0 = mp_obj_new_str(_arg0, strnlen(_arg0,256)); mp_obj_t ret = mp_call_function_1(py_func, arg0); nlr_pop(); return ret; } else { mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); // uncaught exception return 0; } }
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) { return; } mp_parse_error_kind_t parse_error_kind; mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT, &parse_error_kind); if (pn == MP_PARSE_NODE_NULL) { // parse error mp_parse_show_exception(lex, parse_error_kind); mp_lexer_free(lex); return; } // parse okay qstr source_name = mp_lexer_source_name(lex); mp_lexer_free(lex); mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, true); if (mp_obj_is_exception_instance(module_fun)) { // compile error mp_obj_print_exception(module_fun); return; } nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_call_function_0(module_fun); nlr_pop(); } else { // uncaught exception mp_obj_print_exception((mp_obj_t)nlr.ret_val); } }
mp_obj_t micropy_call_2(mp_obj_t module_obj, const char *func, uint64_t code, uint64_t type) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_obj_t py_func = mp_load_attr(module_obj, qstr_from_str(func)); mp_obj_t arg0 = mp_obj_new_int_from_ll((long long)code); mp_obj_t arg1 = mp_obj_new_int_from_ll((long long)type); mp_obj_t ret = mp_call_function_2(py_func, arg0, arg1); nlr_pop(); return ret; } else { mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); // uncaught exception return 0; } }
// If exc is SystemExit, return value where FORCED_EXIT bit set, // and lower 8 bits are SystemExit value. For all other exceptions, // return 1. STATIC int handle_uncaught_exception(mp_obj_t exc) { // check for SystemExit if (mp_obj_is_subclass_fast(mp_obj_get_type(exc), &mp_type_SystemExit)) { // None is an exit value of 0; an int is its value; anything else is 1 mp_obj_t exit_val = mp_obj_exception_get_value(exc); mp_int_t val = 0; if (exit_val != mp_const_none && !mp_obj_get_int_maybe(exit_val, &val)) { val = 1; } return FORCED_EXIT | (val & 255); } // Report all other exceptions mp_obj_print_exception(&mp_stderr_print, exc); return 1; }
STATIC int compile_and_save(const char *file, const char *output_file, const char *source_file) { mp_lexer_t *lex = mp_lexer_new_from_file(file); if (lex == NULL) { printf("could not open file '%s' for reading\n", file); return 1; } nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { qstr source_name; if (source_file == NULL) { source_name = lex->source_name; } else { source_name = qstr_from_str(source_file); } #if MICROPY_PY___FILE__ if (input_kind == MP_PARSE_FILE_INPUT) { mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); } #endif mp_parse_tree_t parse_tree = mp_parse(lex, MP_PARSE_FILE_INPUT); mp_raw_code_t *rc = mp_compile_to_raw_code(&parse_tree, source_name, emit_opt, false); vstr_t vstr; vstr_init(&vstr, 16); if (output_file == NULL) { vstr_add_str(&vstr, file); vstr_cut_tail_bytes(&vstr, 2); vstr_add_str(&vstr, "mpy"); } else { vstr_add_str(&vstr, output_file); } mp_raw_code_save_file(rc, vstr_null_terminated_str(&vstr)); vstr_clear(&vstr); nlr_pop(); return 0; } else { // uncaught exception mp_obj_print_exception(&mp_stderr_print, (mp_obj_t)nlr.ret_val); return 1; } }
void do_str(const char *src, mp_parse_input_kind_t input_kind) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); qstr source_name = lex->source_name; mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); mp_obj_t module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, false); mp_call_function_0(module_fun); nlr_pop(); } else { // uncaught exception if (mp_obj_is_subclass_fast(mp_obj_get_type((mp_obj_t)nlr.ret_val), &mp_type_SystemExit)) { // at the moment, the value of SystemExit is unused } else { mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); } } }
void do_str(const char *src, mp_parse_input_kind_t input_kind) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); if (lex == NULL) { return; } nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { qstr source_name = lex->source_name; mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); mp_obj_t module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, true); mp_call_function_0(module_fun); nlr_pop(); } else { // uncaught exception mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); } }
void do_file(const char *file) { mp_lexer_t *lex = mp_lexer_new_from_file(file); if (lex == NULL) { return; } if (0) { // just tokenise while (lex->tok_kind != MP_TOKEN_END) { mp_lexer_show_token(lex); mp_lexer_to_next(lex); } mp_lexer_free(lex); } else { // parse mp_parse_error_kind_t parse_error_kind; mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_error_kind); if (pn == MP_PARSE_NODE_NULL) { // parse error mp_parse_show_exception(lex, parse_error_kind); mp_lexer_free(lex); return; } mp_lexer_free(lex); if (pn != MP_PARSE_NODE_NULL) { //printf("----------------\n"); //mp_parse_node_print(pn, 0); //printf("----------------\n"); // compile mp_obj_t module_fun = mp_compile(pn, 0, MP_EMIT_OPT_NONE, false); //printf("----------------\n"); if (mp_obj_is_exception_instance(module_fun)) { mp_obj_print_exception(module_fun); } } } }
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) { printf("MemoryError: lexer could not allocate memory\n"); return; } 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_SINGLE_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 { // uncaught exception mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); } }
STATIC int execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t kind, bool repl) { if (lex == NULL) { init_console(); printf("MemoryError: lexer could not allocate memory\n"); return ERR_MEMORY_ALLOC; } nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { qstr source_name = lex->source_name; if (kind == MP_PARSE_FILE_INPUT) { mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); } mp_parse_tree_t parse_tree = mp_parse(lex, kind); mp_obj_t module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, repl); mp_call_function_0(module_fun); if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) { mp_obj_t obj = MP_STATE_VM(mp_pending_exception); MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL; nlr_raise(obj); } nlr_pop(); return 0; } else { if (mp_obj_exception_match(nlr.ret_val, &mp_type_SystemExit)) { return ERR_SYS_EXIT; } if (mp_obj_is_exception_type(nlr.ret_val) && ((mp_obj_exception_t *) nlr.ret_val)->args != NULL && ((mp_obj_exception_t *) nlr.ret_val)->args->len == 1) { int code = mp_obj_get_int(((mp_obj_exception_t *) nlr.ret_val)->args->items[0]); if (code == 0xDEAD0000) { return ERR_NETLOAD; } } init_console(); mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val)); return ERR_PARSE; } }
void mp_uos_dupterm_tx_strn(const char *str, size_t len) { if (MP_STATE_PORT(term_obj) != MP_OBJ_NULL) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_obj_t write_m[3]; mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_write, write_m); write_m[2] = mp_obj_new_bytearray_by_ref(len, (char*)str); mp_call_method_n_kw(1, 0, write_m); nlr_pop(); } else { // Temporarily disable dupterm to avoid infinite recursion mp_obj_t save_term = MP_STATE_PORT(term_obj); MP_STATE_PORT(term_obj) = NULL; mp_printf(&mp_plat_print, "dupterm: "); mp_obj_print_exception(&mp_plat_print, nlr.ret_val); MP_STATE_PORT(term_obj) = save_term; } } }
void pyb_rtc_exec_callback(pyb_rtc_obj_t* self) { // execute callback if it's set if (self->callback != mp_const_none) { // When executing code within a handler we must lock the GC to prevent // any memory allocations. We must also catch any exceptions. gc_lock(); nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_call_function_1(self->callback, self); nlr_pop(); } else { // Uncaught exception; disable the callback so it doesn't run again. self->callback = mp_const_none; printf("uncaught exception in RTC(%u) interrupt handler\n",RTC_ID(self)); mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); } gc_unlock(); } }
void do_strn(const char *src, size_t len) { mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR___main__, src, len, 0); if (lex == NULL) { printf("MemoryError: lexer could not allocate memory\n"); return; } nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { qstr source_name = lex->source_name; mp_parse_tree_t parse_tree = mp_parse(lex, MP_PARSE_FILE_INPUT); mp_obj_t module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, false); mp_hal_set_interrupt_char(3); // allow ctrl-C to interrupt us mp_call_function_0(module_fun); mp_hal_set_interrupt_char(-1); // disable interrupt nlr_pop(); } else { // uncaught exception mp_hal_set_interrupt_char(-1); // disable interrupt mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); microbit_display_exception(nlr.ret_val); } }
//mp_lexer_t *mp_lexer_new_from_str_len(qstr src_name, const char *str, size_t len, size_t free_len) int compile_and_save_to_buffer(const char* src_name, const char *src_buffer, size_t src_size, char* buffer, size_t size) { nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { // mp_lexer_t *lex = mp_lexer_new_from_file(file); mp_lexer_t *lex = mp_lexer_new_from_str_len(qstr_from_str(src_name), src_buffer, src_size, false); qstr source_name; source_name = lex->source_name; mp_parse_tree_t parse_tree = mp_parse(lex, MP_PARSE_FILE_INPUT); mp_raw_code_t *rc = mp_compile_to_raw_code(&parse_tree, source_name, emit_opt, false); int length = mp_raw_code_save_to_buffer(rc, buffer, size); nlr_pop(); return length; } else { // uncaught exception mp_obj_print_exception(&mp_stderr_print, (mp_obj_t)nlr.ret_val); return 0; } }
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"); } mp_parse_error_kind_t parse_error_kind; mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_error_kind); if (pn == MP_PARSE_NODE_NULL) { mp_parse_show_exception(lex, parse_error_kind); mp_lexer_free(lex); tt_abort_msg("Parser error"); } // parse okay qstr source_name = mp_lexer_source_name(lex); mp_lexer_free(lex); mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, true); mp_parse_node_free(pn); if (module_fun == mp_const_none) { tt_abort_msg("Computer error"); } nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_call_function_0(module_fun); nlr_pop(); } else { mp_obj_print_exception((mp_obj_t)nlr.ret_val); tt_abort_msg("Uncaught exception"); } end: ; }
void mp_irq_handler (mp_obj_t self_in) { mp_irq_obj_t *self = self_in; if (self && self->handler != mp_const_none) { // when executing code within a handler we must lock the GC to prevent // any memory allocations. gc_lock(); nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_call_function_1(self->handler, self->parent); nlr_pop(); } else { // uncaught exception; disable the callback so that it doesn't run again self->methods->disable (self->parent); self->handler = mp_const_none; // signal the error using the heart beat led and // by printing a message printf("Uncaught exception in callback handler\n"); mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); mperror_signal_error(); } gc_unlock(); } }
// parses, compiles and executes the code in the lexer // frees the lexer before returning // EXEC_FLAG_PRINT_EOF prints 2 EOF chars: 1 after normal output, 1 after exception output // EXEC_FLAG_ALLOW_DEBUGGING allows debugging info to be printed after executing the code // EXEC_FLAG_IS_REPL is used for REPL inputs (flag passed on to mp_compile) STATIC int parse_compile_execute(const void *source, mp_parse_input_kind_t input_kind, int exec_flags) { int ret = 0; // by default a SystemExit exception returns 0 pyexec_system_exit = 0; nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_obj_t module_fun; #if MICROPY_MODULE_FROZEN_MPY if (exec_flags & EXEC_FLAG_SOURCE_IS_RAW_CODE) { // source is a raw_code object, create the function module_fun = mp_make_function_from_raw_code(source, MP_OBJ_NULL, MP_OBJ_NULL); } else #endif { #if MICROPY_ENABLE_COMPILER mp_lexer_t *lex; if (exec_flags & EXEC_FLAG_SOURCE_IS_VSTR) { const vstr_t *vstr = source; lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, vstr->buf, vstr->len, 0); } else if (exec_flags & EXEC_FLAG_SOURCE_IS_FILENAME) { lex = mp_lexer_new_from_file(source); } else { lex = (mp_lexer_t*)source; } // source is a lexer, parse and compile the script qstr source_name = lex->source_name; mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, exec_flags & EXEC_FLAG_IS_REPL); #else mp_raise_msg(&mp_type_RuntimeError, "script compilation not supported"); #endif } // execute code mp_hal_set_interrupt_char(CHAR_CTRL_C); // allow ctrl-C to interrupt us mp_call_function_0(module_fun); mp_hal_set_interrupt_char(-1); // disable interrupt nlr_pop(); ret = 1; if (exec_flags & EXEC_FLAG_PRINT_EOF) { mp_hal_stdout_tx_strn("\x04", 1); } } else { // uncaught exception // FIXME it could be that an interrupt happens just before we disable it here mp_hal_set_interrupt_char(-1); // disable interrupt // print EOF after normal output if (exec_flags & EXEC_FLAG_PRINT_EOF) { mp_hal_stdout_tx_strn("\x04", 1); } // check for SystemExit if (mp_obj_is_subclass_fast(mp_obj_get_type((mp_obj_t)nlr.ret_val), &mp_type_SystemExit)) { // at the moment, the value of SystemExit is unused ret = pyexec_system_exit; } else { mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); ret = 0; } } if (exec_flags & EXEC_FLAG_PRINT_EOF) { mp_hal_stdout_tx_strn("\x04", 1); } return ret; }
// returns standard error codes: 0 for success, 1 for all other errors STATIC int execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, bool is_repl) { if (lex == NULL) { return 1; } if (0) { // just tokenise while (!mp_lexer_is_kind(lex, MP_TOKEN_END)) { mp_token_show(mp_lexer_cur(lex)); mp_lexer_to_next(lex); } mp_lexer_free(lex); return 0; } mp_parse_error_kind_t parse_error_kind; mp_parse_node_t pn = mp_parse(lex, input_kind, &parse_error_kind); if (pn == MP_PARSE_NODE_NULL) { // parse error mp_parse_show_exception(lex, parse_error_kind); mp_lexer_free(lex); return 1; } qstr source_name = mp_lexer_source_name(lex); #if MICROPY_PY___FILE__ if (input_kind == MP_PARSE_FILE_INPUT) { mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name)); } #endif mp_lexer_free(lex); /* printf("----------------\n"); mp_parse_node_print(pn, 0); printf("----------------\n"); */ mp_obj_t module_fun = mp_compile(pn, source_name, emit_opt, is_repl); if (module_fun == mp_const_none) { // compile error return 1; } if (compile_only) { return 0; } // execute it nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_call_function_0(module_fun); nlr_pop(); return 0; } else { // uncaught exception // check for SystemExit mp_obj_t exc = (mp_obj_t)nlr.ret_val; if (mp_obj_is_subclass_fast(mp_obj_get_type(exc), &mp_type_SystemExit)) { mp_obj_t exit_val = mp_obj_exception_get_value(exc); mp_int_t val; if (!mp_obj_get_int_maybe(exit_val, &val)) { val = 0; } exit(val); } mp_obj_print_exception((mp_obj_t)nlr.ret_val); return 1; } }
// parses, compiles and executes the code in the lexer // frees the lexer before returning // EXEC_FLAG_PRINT_EOF prints 2 EOF chars: 1 after normal output, 1 after exception output // EXEC_FLAG_ALLOW_DEBUGGING allows debugging info to be printed after executing the code // EXEC_FLAG_IS_REPL is used for REPL inputs (flag passed on to mp_compile) STATIC int parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, int exec_flags) { int ret = 0; mp_parse_error_kind_t parse_error_kind; mp_parse_node_t pn = mp_parse(lex, input_kind, &parse_error_kind); qstr source_name = mp_lexer_source_name(lex); // check for parse error if (pn == MP_PARSE_NODE_NULL) { if (exec_flags & EXEC_FLAG_PRINT_EOF) { stdout_tx_strn("\x04", 1); } mp_parse_show_exception(lex, parse_error_kind); mp_lexer_free(lex); goto finish; } mp_lexer_free(lex); mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, exec_flags & EXEC_FLAG_IS_REPL); // check for compile error if (mp_obj_is_exception_instance(module_fun)) { if (exec_flags & EXEC_FLAG_PRINT_EOF) { stdout_tx_strn("\x04", 1); } mp_obj_print_exception(module_fun); goto finish; } // execute code nlr_buf_t nlr; uint32_t start = HAL_GetTick(); if (nlr_push(&nlr) == 0) { mp_hal_set_interrupt_char(CHAR_CTRL_C); // allow ctrl-C to interrupt us mp_call_function_0(module_fun); mp_hal_set_interrupt_char(-1); // disable interrupt nlr_pop(); ret = 1; if (exec_flags & EXEC_FLAG_PRINT_EOF) { stdout_tx_strn("\x04", 1); } } else { // uncaught exception // FIXME it could be that an interrupt happens just before we disable it here mp_hal_set_interrupt_char(-1); // disable interrupt // print EOF after normal output if (exec_flags & EXEC_FLAG_PRINT_EOF) { stdout_tx_strn("\x04", 1); } // check for SystemExit if (mp_obj_is_subclass_fast(mp_obj_get_type((mp_obj_t)nlr.ret_val), &mp_type_SystemExit)) { // at the moment, the value of SystemExit is unused ret = PYEXEC_FORCED_EXIT; } else { mp_obj_print_exception((mp_obj_t)nlr.ret_val); ret = 0; } } // display debugging info if wanted if ((exec_flags & EXEC_FLAG_ALLOW_DEBUGGING) && repl_display_debugging_info) { mp_uint_t ticks = HAL_GetTick() - start; // TODO implement a function that does this properly printf("took " UINT_FMT " ms\n", ticks); gc_collect(); // qstr info { mp_uint_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes; qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes); printf("qstr:\n n_pool=" UINT_FMT "\n n_qstr=" UINT_FMT "\n n_str_data_bytes=" UINT_FMT "\n n_total_bytes=" UINT_FMT "\n", n_pool, n_qstr, n_str_data_bytes, n_total_bytes); } // GC info { gc_info_t info; gc_info(&info); printf("GC:\n"); printf(" " UINT_FMT " total\n", info.total); printf(" " UINT_FMT " : " UINT_FMT "\n", info.used, info.free); printf(" 1=" UINT_FMT " 2=" UINT_FMT " m=" UINT_FMT "\n", info.num_1block, info.num_2block, info.max_block); } } finish: if (exec_flags & EXEC_FLAG_PRINT_EOF) { stdout_tx_strn("\x04", 1); } return ret; }
// parses, compiles and executes the code in the lexer // frees the lexer before returning // EXEC_FLAG_PRINT_EOF prints 2 EOF chars: 1 after normal output, 1 after exception output // EXEC_FLAG_ALLOW_DEBUGGING allows debugging info to be printed after executing the code // EXEC_FLAG_IS_REPL is used for REPL inputs (flag passed on to mp_compile) STATIC int parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t input_kind, int exec_flags) { int ret = 0; uint32_t start = 0; nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { // parse and compile the script qstr source_name = lex->source_name; mp_parse_node_t pn = mp_parse(lex, input_kind); mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, exec_flags & EXEC_FLAG_IS_REPL); // execute code mp_hal_set_interrupt_char(CHAR_CTRL_C); // allow ctrl-C to interrupt us start = HAL_GetTick(); mp_call_function_0(module_fun); mp_hal_set_interrupt_char(-1); // disable interrupt nlr_pop(); ret = 1; if (exec_flags & EXEC_FLAG_PRINT_EOF) { mp_hal_stdout_tx_strn("\x04", 1); } } else { // uncaught exception // FIXME it could be that an interrupt happens just before we disable it here mp_hal_set_interrupt_char(-1); // disable interrupt // print EOF after normal output if (exec_flags & EXEC_FLAG_PRINT_EOF) { mp_hal_stdout_tx_strn("\x04", 1); } // check for SystemExit if (mp_obj_is_subclass_fast(mp_obj_get_type((mp_obj_t)nlr.ret_val), &mp_type_SystemExit)) { // at the moment, the value of SystemExit is unused ret = PYEXEC_FORCED_EXIT; } else { mp_obj_print_exception(printf_wrapper, NULL, (mp_obj_t)nlr.ret_val); ret = 0; } } // display debugging info if wanted if ((exec_flags & EXEC_FLAG_ALLOW_DEBUGGING) && repl_display_debugging_info) { mp_uint_t ticks = HAL_GetTick() - start; // TODO implement a function that does this properly printf("took " UINT_FMT " ms\n", ticks); gc_collect(); // qstr info { mp_uint_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes; qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes); printf("qstr:\n n_pool=" UINT_FMT "\n n_qstr=" UINT_FMT "\n n_str_data_bytes=" UINT_FMT "\n n_total_bytes=" UINT_FMT "\n", n_pool, n_qstr, n_str_data_bytes, n_total_bytes); } // GC info gc_dump_info(); } if (exec_flags & EXEC_FLAG_PRINT_EOF) { mp_hal_stdout_tx_strn("\x04", 1); } return ret; }