@@ -784,6 +784,14 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
784784 fun () -> (let id = ! counter in incr counter; id)
785785 in
786786
787+ let get_rethrow_state_id =
788+ let rethrow_state_id = ref (- 1 ) in
789+ fun () -> begin
790+ if ! rethrow_state_id = (- 1 ) then rethrow_state_id := get_next_state_id () ;
791+ ! rethrow_state_id;
792+ end
793+ in
794+
787795 let mk_continuation_call eresult p =
788796 let econtinuation = make_local vcontinuation p in
789797 mk (TCall (econtinuation, [eresult; make_null t_dynamic p])) com.basic.tvoid p
@@ -837,7 +845,7 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
837845
838846 (* TODO: maybe merge this into block_to_texpr somehow, and only introduce new states when there is a suspension point *)
839847 print_endline " ---" ;
840- let rec loop bb state_id back_state_id current_el while_loop =
848+ let rec loop bb state_id back_state_id current_el while_loop exc_state_id_getter =
841849 let p = bb.bb_pos in
842850 (* TODO: only do this in the end, avoid unnecessary List.rev *)
843851 let el = DynArray. to_list bb.bb_el in
@@ -853,7 +861,7 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
853861 | SESuspend (call , bb_next ) ->
854862 let next_state_id = get_next_state_id () in
855863 print_endline (Printf. sprintf " suspend cur:%d,next:%d,back:%d" state_id next_state_id back_state_id);
856- loop bb_next next_state_id back_state_id [] while_loop;
864+ loop bb_next next_state_id back_state_id [] while_loop exc_state_id_getter ;
857865 let ecallcoroutine = mk_suspending_call call in
858866 let esetstate = set_state next_state_id in
859867 add_state (current_el @ el @ [esetstate; ecallcoroutine; ereturn])
@@ -891,23 +899,23 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
891899
892900 | SEMerge bb_next ->
893901 print_endline (Printf. sprintf " merge cur:%d,back:%d" state_id back_state_id);
894- loop bb_next state_id back_state_id (current_el @ el) while_loop
902+ loop bb_next state_id back_state_id (current_el @ el) while_loop exc_state_id_getter
895903
896904 | SESubBlock (bb_sub ,bb_next ) ->
897905 let sub_state_id = get_next_state_id () in
898906 let next_state_id = get_next_state_id () in
899907 print_endline (Printf. sprintf " sub cur:%d,sub:%d,next:%d,back:%d" state_id sub_state_id next_state_id back_state_id);
900- loop bb_next next_state_id back_state_id [] while_loop;
901- loop bb_sub sub_state_id next_state_id [] while_loop;
908+ loop bb_next next_state_id back_state_id [] while_loop exc_state_id_getter ;
909+ loop bb_sub sub_state_id next_state_id [] while_loop exc_state_id_getter ;
902910 add_state (current_el @ el @ [set_state sub_state_id])
903911
904912 | SEIfThen (bb_then ,bb_next ,p ) ->
905913 let econd = get_cond_branch () in
906914 let then_state_id = get_next_state_id () in
907915 let next_state_id = get_next_state_id () in
908916 print_endline (Printf. sprintf " if-then cur:%d,then:%d,next:%d,back:%d" state_id then_state_id next_state_id back_state_id);
909- loop bb_then then_state_id next_state_id [] while_loop;
910- loop bb_next next_state_id back_state_id [] while_loop;
917+ loop bb_then then_state_id next_state_id [] while_loop exc_state_id_getter ;
918+ loop bb_next next_state_id back_state_id [] while_loop exc_state_id_getter ;
911919 let eif = mk (TIf (econd, set_state then_state_id, Some (set_state next_state_id))) com.basic.tint p in
912920 add_state (current_el @ el @ [eif])
913921
@@ -917,9 +925,9 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
917925 let else_state_id = get_next_state_id () in
918926 let next_state_id = get_next_state_id () in
919927 print_endline (Printf. sprintf " if-then-else cur:%d,then:%d,else:%d,next:%d,back:%d" state_id then_state_id else_state_id next_state_id back_state_id);
920- loop bb_then then_state_id next_state_id [] while_loop;
921- loop bb_else else_state_id next_state_id [] while_loop;
922- loop bb_next next_state_id back_state_id [] while_loop;
928+ loop bb_then then_state_id next_state_id [] while_loop exc_state_id_getter ;
929+ loop bb_else else_state_id next_state_id [] while_loop exc_state_id_getter ;
930+ loop bb_next next_state_id back_state_id [] while_loop exc_state_id_getter ;
923931 let eif = mk (TIf (econd, set_state then_state_id, Some (set_state else_state_id))) com.basic.tint p in
924932 add_state (current_el @ el @ [eif])
925933
@@ -931,20 +939,20 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
931939 (* TODO: variable capture and other fancy things O_o *)
932940 let case_state_id = get_next_state_id () in
933941 print_endline (Printf. sprintf " case %d" case_state_id);
934- loop bb case_state_id next_state_id [] while_loop;
942+ loop bb case_state_id next_state_id [] while_loop exc_state_id_getter ;
935943 patterns, set_state case_state_id
936944 ) cases in
937945 let default_state_id = match bb_default with
938946 | Some bb ->
939947 let default_state_id = get_next_state_id () in
940- loop bb default_state_id next_state_id [] while_loop;
948+ loop bb default_state_id next_state_id [] while_loop exc_state_id_getter ;
941949 default_state_id
942950 | None ->
943951 next_state_id
944952 in
945953 print_endline (Printf. sprintf " default %d" default_state_id);
946954 let eswitch = mk (TSwitch (esubj,ecases,Some (set_state default_state_id))) com.basic.tvoid p in
947- loop bb_next next_state_id back_state_id [] while_loop;
955+ loop bb_next next_state_id back_state_id [] while_loop exc_state_id_getter ;
948956 add_state (current_el @ el @ [eswitch])
949957
950958 | SEWhile (bb_body , bb_next , p ) ->
@@ -953,23 +961,24 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
953961 print_endline (Printf. sprintf " while cur:%d,body:%d,next:%d,back:%d" state_id body_state_id next_state_id back_state_id);
954962 let new_while_loop = Some (body_state_id,next_state_id) in
955963 (* TODO: next is empty? *)
956- loop bb_body body_state_id body_state_id [] new_while_loop;
957- loop bb_next next_state_id back_state_id [] while_loop;
964+ loop bb_body body_state_id body_state_id [] new_while_loop exc_state_id_getter ;
965+ loop bb_next next_state_id back_state_id [] while_loop exc_state_id_getter ;
958966 add_state (current_el @ el @ [set_state body_state_id]);
959967
960968 | SETry (bb_try ,_ ,catches ,bb_next ,p ) ->
961969 let try_state_id = get_next_state_id () in
962970 let new_exc_state_id = get_next_state_id () in
963971 let next_state_id = get_next_state_id () in
964972 print_endline (Printf. sprintf " try cur:%d,try:%d,catch:%d,next:%d,back:%d" state_id try_state_id new_exc_state_id next_state_id back_state_id);
965- loop bb_try try_state_id next_state_id [set_excstate new_exc_state_id] while_loop;
973+ loop bb_try try_state_id next_state_id [set_excstate new_exc_state_id] while_loop (fun () -> new_exc_state_id); (* TODO: add test for nested try/catch *)
974+ let esetexcstate = set_excstate (exc_state_id_getter () ) in
966975 let catch_case =
967976 let erethrow = mk (TThrow eerror) t_dynamic null_pos in
968977 let eif =
969978 List. fold_left (fun enext (vcatch ,bb_catch ) ->
970979 let catch_state_id = get_next_state_id () in
971980 let ecatchvar = mk (TVar (vcatch, Some eerror)) com.basic.tvoid null_pos in
972- loop bb_catch catch_state_id next_state_id [ecatchvar] while_loop;
981+ loop bb_catch catch_state_id next_state_id [esetexcstate; ecatchvar] while_loop exc_state_id_getter ;
973982
974983 (* TODO: exceptions filter... *)
975984 match follow vcatch.v_type with
@@ -983,21 +992,12 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
983992 (new_exc_state_id, eif)
984993 in
985994 exc_states := catch_case :: ! exc_states;
986- loop bb_next next_state_id back_state_id [(* TODO: set back to previous exc_state_id, which is not know atm *) ] while_loop;
995+ loop bb_next next_state_id back_state_id [esetexcstate (* TODO: test propagation after try/catch *) ] while_loop exc_state_id_getter ;
987996 add_state (current_el @ el @ [set_state try_state_id])
988997 in
989- loop bb (get_next_state_id () ) (- 1 ) [] None ;
990-
991- let rethrow_state_id = get_next_state_id () in
992-
993- (* prepend setting exceptionState to the rethrow one *)
994- let exc_states =
995- List. map (fun (id , e ) ->
996- id, mk (TBlock [set_excstate rethrow_state_id; e]) com.basic.tvoid null_pos
997- ) ! exc_states
998- in
998+ loop bb (get_next_state_id () ) (- 1 ) [] None get_rethrow_state_id;
999999
1000- let states = ! states @ exc_states in
1000+ let states = ! states @ ! exc_states in
10011001
10021002 (* TODO: this (and the coroutine transform in general) should probably be run before captured vars handling *)
10031003 (* very ugly, but seems to work: extract locals that are used across states *)
@@ -1062,6 +1062,7 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
10621062 - if there's only one state (no suspensions) - don't wrap into while/switch, don't introduce state var
10631063 *)
10641064
1065+ let rethrow_state_id = get_rethrow_state_id () in
10651066 let rethrow_state = (rethrow_state_id, mk (TThrow eerror) com.basic.tvoid null_pos) in
10661067 let states = states @ [rethrow_state] in
10671068
0 commit comments