@@ -61,8 +61,8 @@ bool mp_execute_byte_code_2(const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **
6161 mp_obj_t fast0 = fastn [0 ], fast1 = fastn [1 ], fast2 = fastn [2 ];
6262 nlr_buf_t nlr ;
6363
64- // on the exception stack we store (ip, sp) for each block
65- machine_uint_t exc_stack [8 ];
64+ volatile machine_uint_t currently_in_except_block = 0 ; // 0 or 1, to detect nested exceptions
65+ machine_uint_t exc_stack [8 ]; // on the exception stack we store (ip, sp | X) for each block, X = previous value of currently_in_except_block
6666 machine_uint_t * volatile exc_sp = & exc_stack [-1 ]; // stack grows up, exc_sp points to top of stack
6767
6868 // outer exception handling loop
@@ -275,7 +275,8 @@ bool mp_execute_byte_code_2(const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **
275275 case MP_BC_SETUP_EXCEPT :
276276 DECODE_ULABEL ; // except labels are always forward
277277 * ++ exc_sp = (machine_uint_t )ip + unum ;
278- * ++ exc_sp = (machine_uint_t )sp ;
278+ * ++ exc_sp = (((machine_uint_t )sp ) | currently_in_except_block );
279+ currently_in_except_block = 0 ; // in a try block now
279280 break ;
280281
281282 case MP_BC_END_FINALLY :
@@ -313,7 +314,8 @@ bool mp_execute_byte_code_2(const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **
313314 assert (exc_sp >= & exc_stack [0 ]);
314315 //sp = (mp_obj_t*)(*exc_sp--);
315316 //exc_sp--; // discard ip
316- exc_sp -= 2 ;
317+ currently_in_except_block = (exc_sp [0 ] & 1 ); // restore previous state
318+ exc_sp -= 2 ; // pop back to previous exception handler
317319 //sp += 3; // pop 3 exception values
318320 break ;
319321
@@ -466,16 +468,33 @@ bool mp_execute_byte_code_2(const byte **ip_in_out, mp_obj_t *fastn, mp_obj_t **
466468 } else {
467469 // exception occurred
468470
471+ while (currently_in_except_block ) {
472+ // nested exception
473+
474+ assert (exc_sp >= & exc_stack [0 ]);
475+
476+ // TODO make a proper message for nested exception
477+ // at the moment we are just raising the very last exception (the one that caused the nested exception)
478+
479+ // move up to previous exception handler
480+ currently_in_except_block = (exc_sp [0 ] & 1 ); // restore previous state
481+ exc_sp -= 2 ; // pop back to previous exception handler
482+ }
483+
469484 if (exc_sp >= & exc_stack [0 ]) {
485+ // set flag to indicate that we are now handling an exception
486+ currently_in_except_block = 1 ;
487+
470488 // catch exception and pass to byte code
471- sp = (mp_obj_t * )(exc_sp [0 ]);
489+ sp = (mp_obj_t * )(exc_sp [0 ] & (~(( machine_uint_t ) 1 )) );
472490 ip = (const byte * )(exc_sp [-1 ]);
473491 // push(traceback, exc-val, exc-type)
474492 PUSH (mp_const_none );
475493 PUSH (nlr .ret_val );
476494 PUSH (mp_const_none );
495+
477496 } else {
478- // re-raise exception
497+ // re-raise exception to higher level
479498 // TODO what to do if this is a generator??
480499 nlr_jump (nlr .ret_val );
481500 }
0 commit comments