@@ -55,8 +55,6 @@ void pbsys_main_stop_program(bool force_stop) {
5555 if (force_stop ) {
5656 mp_sched_vm_abort ();
5757 } else {
58- pyexec_system_exit = PYEXEC_FORCED_EXIT ;
59-
6058 static mp_obj_exception_t system_exit ;
6159 system_exit .base .type = & mp_type_SystemExit ;
6260 system_exit .traceback_alloc = system_exit .traceback_len = 0 ;
@@ -106,9 +104,9 @@ static void mp_vfs_map_minimal_new_reader(mp_reader_t *reader, mp_vfs_map_minima
106104}
107105
108106// Prints the exception that ended the program.
109- static void print_final_exception (mp_obj_t exc ) {
107+ static void print_final_exception (mp_obj_t exc , int ret ) {
110108 // Handle graceful stop with button.
111- if (pyexec_system_exit == PYEXEC_FORCED_EXIT &&
109+ if (( ret & PYEXEC_FORCED_EXIT ) &&
112110 mp_obj_exception_match (exc , MP_OBJ_FROM_PTR (& mp_type_SystemExit ))) {
113111 mp_printf (& mp_plat_print , "The program was stopped (%q).\n" ,
114112 ((mp_obj_exception_t * )MP_OBJ_TO_PTR (exc ))-> base .type -> name );
@@ -121,8 +119,9 @@ static void print_final_exception(mp_obj_t exc) {
121119
122120#if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL
123121static void run_repl (void ) {
122+ int ret ;
123+
124124 readline_init0 ();
125- pyexec_system_exit = 0 ;
126125
127126 nlr_buf_t nlr ;
128127 nlr .ret_val = NULL ;
@@ -134,12 +133,12 @@ static void run_repl(void) {
134133 if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL ) {
135134 // Compatibility with mpremote.
136135 mp_printf (& mp_plat_print , "MPY: soft reboot\n" );
137- pyexec_raw_repl ();
136+ ret = pyexec_raw_repl ();
138137 } else {
139- pyexec_friendly_repl ();
138+ ret = pyexec_friendly_repl ();
140139 }
141140 #else // PYBRICKS_OPT_RAW_REPL
142- pyexec_friendly_repl ();
141+ ret = pyexec_friendly_repl ();
143142 #endif // PYBRICKS_OPT_RAW_REPL
144143 nlr_pop ();
145144 } else {
@@ -152,7 +151,7 @@ static void run_repl(void) {
152151 // clear any pending exceptions (and run any callbacks).
153152 mp_handle_pending (false);
154153 // Print which exception triggered this.
155- print_final_exception (MP_OBJ_FROM_PTR (nlr .ret_val ));
154+ print_final_exception (MP_OBJ_FROM_PTR (nlr .ret_val ), ret );
156155 }
157156
158157 nlr_set_abort (NULL );
@@ -175,7 +174,7 @@ static void do_execute_raw_code(mp_module_context_t *context, const mp_raw_code_
175174
176175 nlr_buf_t nlr ;
177176 if (nlr_push (& nlr ) == 0 ) {
178- mp_obj_t module_fun = mp_make_function_from_raw_code (rc , mc , NULL );
177+ mp_obj_t module_fun = mp_make_function_from_proto_fun (rc , mc , NULL );
179178 mp_call_function_0 (module_fun );
180179
181180 // finish nlr block, restore context
@@ -241,7 +240,7 @@ static mpy_info_t *mpy_data_find(qstr name) {
241240 * Runs the __main__ module from user RAM.
242241 */
243242static void run_user_program (void ) {
244- pyexec_system_exit = 0 ;
243+ int ret = 0 ;
245244
246245 nlr_buf_t nlr ;
247246 nlr .ret_val = NULL ;
@@ -264,7 +263,7 @@ static void run_user_program(void) {
264263 mp_compiled_module_t compiled_module ;
265264 compiled_module .context = context ;
266265 mp_raw_code_load (& reader , & compiled_module );
267- mp_obj_t module_fun = mp_make_function_from_raw_code (compiled_module .rc , context , NULL );
266+ mp_obj_t module_fun = mp_make_function_from_proto_fun (compiled_module .rc , context , NULL );
268267
269268 // Run the script while letting CTRL-C interrupt it.
270269 mp_hal_set_interrupt_char (CHAR_CTRL_C );
@@ -287,7 +286,12 @@ static void run_user_program(void) {
287286 // Clear any pending exceptions (and run any callbacks).
288287 mp_handle_pending (false);
289288
290- print_final_exception (MP_OBJ_FROM_PTR (nlr .ret_val ));
289+ if (mp_obj_is_subclass_fast (MP_OBJ_FROM_PTR (((mp_obj_base_t * )nlr .ret_val )-> type ), MP_OBJ_FROM_PTR (& mp_type_SystemExit ))) {
290+ // at the moment, the value of SystemExit is unused
291+ ret = PYEXEC_FORCED_EXIT ;
292+ }
293+
294+ print_final_exception (MP_OBJ_FROM_PTR (nlr .ret_val ), ret );
291295
292296 #if PBSYS_CONFIG_FEATURE_BUILTIN_USER_PROGRAM_REPL
293297 // On KeyboardInterrupt, drop to REPL for debugging.
@@ -422,6 +426,53 @@ mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs)
422426}
423427MP_DEFINE_CONST_FUN_OBJ_KW (mp_builtin_open_obj , 1 , mp_builtin_open );
424428
429+ // REVISIT: These functions were removed from upstream MicroPython. We should
430+ // see if there is a better way to do this now.
431+
432+ static void mp_module_register (mp_obj_t module_name , mp_obj_t module ) {
433+ mp_map_t * mp_loaded_modules_map = & MP_STATE_VM (mp_loaded_modules_dict ).map ;
434+ mp_map_lookup (mp_loaded_modules_map , module_name , MP_MAP_LOOKUP_ADD_IF_NOT_FOUND )-> value = module ;
435+ }
436+
437+ static void mp_module_call_init (mp_obj_t module_name , mp_obj_t module_obj ) {
438+ // Look for __init__ and call it if it exists
439+ mp_obj_t dest [2 ];
440+ mp_load_method_maybe (module_obj , MP_QSTR___init__ , dest );
441+ if (dest [0 ] != MP_OBJ_NULL ) {
442+ mp_call_method_n_kw (0 , 0 , dest );
443+ // Register module so __init__ is not called again.
444+ // If a module can be referenced by more than one name (eg due to weak links)
445+ // then __init__ will still be called for each distinct import, and it's then
446+ // up to the particular module to make sure it's __init__ code only runs once.
447+ mp_module_register (module_name , module_obj );
448+ }
449+ }
450+
451+ // Tries to find a loaded module, otherwise attempts to load a builtin, otherwise MP_OBJ_NULL.
452+ static mp_obj_t mp_module_get_loaded_or_builtin (qstr module_name ) {
453+ // First try loaded modules.
454+ mp_map_elem_t * elem = mp_map_lookup (& MP_STATE_VM (mp_loaded_modules_dict ).map , MP_OBJ_NEW_QSTR (module_name ), MP_MAP_LOOKUP );
455+
456+ if (!elem ) {
457+ #if MICROPY_MODULE_WEAK_LINKS
458+ return mp_module_get_builtin (module_name );
459+ #else
460+ // Otherwise try builtin.
461+ elem = mp_map_lookup ((mp_map_t * )& mp_builtin_module_map , MP_OBJ_NEW_QSTR (module_name ), MP_MAP_LOOKUP );
462+ if (!elem ) {
463+ return MP_OBJ_NULL ;
464+ }
465+
466+ #if MICROPY_MODULE_BUILTIN_INIT
467+ // If found, it's a newly loaded built-in, so init it.
468+ mp_module_call_init (MP_OBJ_NEW_QSTR (module_name ), elem -> value );
469+ #endif
470+ #endif
471+ }
472+
473+ return elem -> value ;
474+ }
475+
425476// Overrides MicroPython's mp_builtin___import__
426477// IMPORTANT: this needs to be kept in sync with mp_builtin___import___default().
427478mp_obj_t pb_builtin_import (size_t n_args , const mp_obj_t * args ) {
@@ -473,7 +524,7 @@ mp_obj_t pb_builtin_import(size_t n_args, const mp_obj_t *args) {
473524 mp_module_context_t * context = MP_OBJ_TO_PTR (module_obj );
474525 const mp_frozen_module_t * frozen = modref ;
475526 context -> constants = frozen -> constants ;
476- do_execute_raw_code (context , frozen -> rc , context );
527+ do_execute_raw_code (context , frozen -> proto_fun , context );
477528 return module_obj ;
478529 }
479530 #endif
@@ -486,7 +537,7 @@ mp_import_stat_t mp_import_stat(const char *path) {
486537 return MP_IMPORT_STAT_NO_EXIST ;
487538}
488539
489- mp_lexer_t * mp_lexer_new_from_file (const char * filename ) {
540+ mp_lexer_t * mp_lexer_new_from_file (qstr filename ) {
490541 mp_raise_OSError (MP_ENOENT );
491542}
492543
0 commit comments