@@ -45,7 +45,10 @@ let rec func ctx bb tf t p =
4545 let bb_root = create_node (BKFunctionBegin tf) tf.tf_expr.etype tf.tf_expr.epos in
4646 let bb_exit = create_node BKFunctionEnd tf.tf_expr.etype tf.tf_expr.epos in
4747 let coroutine = match follow t with
48- | TAbstract ({a_path =[] ,"Coroutine" } , _ ) -> Some (alloc_var VGenerated " _hx_result" t_dynamic p)
48+ | TAbstract ({a_path =[] ,"Coroutine" } , _ ) -> Some (
49+ alloc_var VGenerated " _hx_result" t_dynamic p,
50+ alloc_var VGenerated " _hx_error" t_dynamic p
51+ )
4952 | _ -> None
5053 in
5154 add_function g tf t p bb_root coroutine;
@@ -329,7 +332,7 @@ let rec func ctx bb tf t p =
329332 | _ -> false
330333 in
331334 (match coroutine with
332- | Some vresult when is_coroutine efun ->
335+ | Some ( vresult , _ ) when is_coroutine efun ->
333336 let bb_next = create_node BKNormal e1.etype e1.epos in
334337 add_cfg_edge bb bb_next CFGGoto ;
335338 let syntax_edge = SESuspend (
@@ -745,13 +748,14 @@ and block_to_texpr ctx bb =
745748 let e = mk (TBlock el) bb.bb_type bb.bb_pos in
746749 e
747750
748- and block_to_texpr_coroutine ctx bb vcontinuation vresult p =
751+ and block_to_texpr_coroutine ctx bb vcontinuation vresult verror p =
749752 assert (bb.bb_closed);
750753
751754 let open Texpr.Builder in
752755 let com = ctx.com in
753756
754757 declare_var ctx.graph vresult bb;
758+ declare_var ctx.graph verror bb;
755759
756760 let vstate = alloc_var VGenerated " _hx_state" com.basic.tint p in
757761 declare_var ctx.graph vstate bb;
@@ -769,7 +773,11 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult p =
769773
770774 let mk_continuation_call eresult p =
771775 let econtinuation = make_local vcontinuation p in
772- mk (TCall (econtinuation, [eresult])) com.basic.tvoid p
776+ mk (TCall (econtinuation, [eresult; make_null t_dynamic p])) com.basic.tvoid p
777+ in
778+ let mk_continuation_call_error eerror p =
779+ let econtinuation = make_local vcontinuation p in
780+ mk (TCall (econtinuation, [make_null t_dynamic p; eerror])) com.basic.tvoid p
773781 in
774782
775783 (* TODO: maybe merge this into block_to_texpr somehow, and only introduce new states when there is a suspension point *)
@@ -832,8 +840,8 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult p =
832840 mk_case (current_el @ el @ [esetstate; ecallcontinuation; ereturn]) :: statecases
833841 | TermNone ->
834842 mk_case (current_el @ el @ [set_state back_state_id]) :: statecases
835- | TermThrow (_ ,p ) ->
836- Error. error " throw is currently not supported in coroutines " p
843+ | TermThrow (e ,p ) ->
844+ mk_case (current_el @ el @ [set_state ( - 1 ); mk_continuation_call_error e p; ereturn]) :: statecases
837845 | TermCondBranch _ ->
838846 die " unexpected TermCondBranch" __LOC__)
839847
@@ -982,10 +990,25 @@ and block_to_texpr_coroutine ctx bb vcontinuation vresult p =
982990 let eswitch = mk (TSwitch (estate, statecases, Some ethrow)) com.basic.tvoid p in
983991 let eloop = mk (TWhile (make_bool com.basic true p, eswitch, DoWhile )) com.basic.tvoid p in
984992
993+ (* TODO: this has to be much more complicated, unfortunately, we need a try/catch around the state machine to catch errors from
994+ synchronous throws and then we need to propagate properly and then we need to support try/catch inside coroutines etc etc.
995+ maybe while implementing support for all this, we can as well look into adding COROUTINE_SUSPEND markers and separate coroutine
996+ and non-coroutine worlds a bit more *)
997+ let eerror = make_local verror p in
998+ let eif = mk (TIf (
999+ mk (TBinop (
1000+ OpNotEq ,
1001+ eerror,
1002+ make_null verror.v_type p (* TODO: throw null should work *)
1003+ )) com.basic.tbool p,
1004+ mk_continuation_call_error eerror p,
1005+ Some eloop
1006+ )) com.basic.tvoid p in
1007+
9851008 let estatemachine_def = mk (TFunction {
986- tf_args = [(vresult,None )];
1009+ tf_args = [(vresult,None ); (verror, None ) ];
9871010 tf_type = com.basic.tvoid;
988- tf_expr = eloop ;
1011+ tf_expr = eif ;
9891012 }) tstatemachine p in
9901013
9911014 let state_var = mk (TVar (vstate, Some (make_int com.basic 0 p))) com.basic.tvoid p in
@@ -1001,10 +1024,10 @@ and func ctx i =
10011024 let bb,t,p,tf,coroutine = Hashtbl. find ctx.graph.g_functions i in
10021025 let e,tf_args,tf_type =
10031026 match coroutine with
1004- | Some vresult ->
1027+ | Some ( vresult , verror ) ->
10051028 let vcontinuation = alloc_var VGenerated " _hx_continuation" (tfun [t_dynamic] ctx.com.basic.tvoid) p in
10061029 declare_var ctx.graph vcontinuation bb;
1007- let e = block_to_texpr_coroutine ctx bb vcontinuation vresult p in
1030+ let e = block_to_texpr_coroutine ctx bb vcontinuation vresult verror p in
10081031 let tf_args = tf.tf_args @ [(vcontinuation,None )] in
10091032 e, tf_args, tf.tf_type
10101033 | None ->
0 commit comments