Skip to content

Commit

Permalink
try a different input data design
Browse files Browse the repository at this point in the history
  • Loading branch information
Simn committed Feb 23, 2024
1 parent ba7604b commit 54dfcad
Show file tree
Hide file tree
Showing 12 changed files with 94 additions and 37 deletions.
4 changes: 3 additions & 1 deletion src/context/common.ml
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,7 @@ let create compilation_step cs version args display_mode =
tfloat = mk_mono();
tbool = mk_mono();
tstring = mk_mono();
tcoro_control = mk_mono();
tnull = (fun _ -> die "Could use locate abstract Null<T> (was it redefined?)" __LOC__);
tarray = (fun _ -> die "Could not locate class Array<T> (was it redefined?)" __LOC__);
tcoro = (fun _ -> die "Could not locate abstract Coroutine<T> (was it redefined?)" __LOC__);
Expand Down Expand Up @@ -878,6 +879,7 @@ let clone com is_macro_context =
tfloat = mk_mono();
tbool = mk_mono();
tstring = mk_mono();
tcoro_control = mk_mono();
};
main = {
main_class = None;
Expand Down Expand Up @@ -1224,5 +1226,5 @@ let expand_coro_type basic args ret =
let ret_type = if ExtType.is_void (follow ret) then t_dynamic else ret in
let tcontinuation = tfun [ret_type; t_dynamic] basic.tvoid in
let args = args @ [("_hx_continuation",false,tcontinuation)] in
let ret = tfun [t_dynamic; t_dynamic] basic.tvoid in
let ret = tfun [t_dynamic; basic.tcoro_control] basic.tvoid in
(args,ret)
1 change: 1 addition & 0 deletions src/core/tType.ml
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ type basic_types = {
mutable tstring : t;
mutable tarray : t -> t;
mutable tcoro : (string * bool * t) list -> t -> t;
mutable tcoro_control : t;
}

type class_field_scope =
Expand Down
6 changes: 3 additions & 3 deletions src/coro/coro.ml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ open CoroFunctions
let fun_to_coro ctx e tf =
let p = e.epos in
let v_result = alloc_var VGenerated "_hx_result" t_dynamic p in
let v_error = alloc_var VGenerated "_hx_error" t_dynamic p in
let v_control = alloc_var VGenerated "_hx_control" ctx.com.basic.tcoro_control p in
let cb_root = make_block ctx (Some(e.etype,p)) in
ignore(CoroFromTexpr.expr_to_coro ctx (v_result,v_error) cb_root tf.tf_expr);
ignore(CoroFromTexpr.expr_to_coro ctx (v_result,v_control) cb_root tf.tf_expr);
let ret_type = if ExtType.is_void (follow tf.tf_type) then t_dynamic else tf.tf_type in
let vcontinuation = alloc_var VGenerated "_hx_continuation" (tfun [ret_type; t_dynamic] ctx.com.basic.tvoid) p in
let tf_expr = CoroToTexpr.block_to_texpr_coroutine ctx cb_root vcontinuation v_result v_error e.epos in
let tf_expr = CoroToTexpr.block_to_texpr_coroutine ctx cb_root vcontinuation v_result v_control e.epos in
let tf_args = tf.tf_args @ [(vcontinuation,None)] in
let tf_type = tfun [t_dynamic; t_dynamic] ctx.com.basic.tvoid in
if ctx.coro_debug then begin
Expand Down
70 changes: 45 additions & 25 deletions src/coro/coroToTexpr.ml
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,57 @@ type coro_state = {
mutable cs_el : texpr list;
}

let block_to_texpr_coroutine ctx cb vcontinuation vresult verror p =
type coro_control =
| CoroNormal
| CoroError
| CoroSuspend

let mk_int com i = Texpr.Builder.make_int com.Common.basic i null_pos

let mk_control com (c : coro_control) = mk_int com (Obj.magic c)

let make_control_switch com e_subject e_normal e_error p =
let cases = [{
case_patterns = [mk_control com CoroNormal];
case_expr = e_normal;
}; {
case_patterns = [mk_control com CoroError];
case_expr = e_error;
}] in
let switch = {
switch_subject = e_subject;
switch_cases = cases;
switch_default = None;
switch_exhaustive = true;
} in
mk (TSwitch switch) com.basic.tvoid p

let block_to_texpr_coroutine ctx cb vcontinuation vresult vcontrol p =
let open Texpr.Builder in
let com = ctx.com in

let eerror = make_local verror null_pos in

let mk_int i = make_int com.basic i null_pos in
let eresult = make_local vresult vresult.v_pos in
let econtrol = make_local vcontrol vcontrol.v_pos in

let mk_assign estate eid =
mk (TBinop (OpAssign,estate,eid)) eid.etype null_pos
in

let vstate = alloc_var VGenerated "_hx_state" com.basic.tint p in
let estate = make_local vstate p in
let set_state id = mk_assign estate (mk_int id) in
let set_state id = mk_assign estate (mk_int com id) in

let tstatemachine = tfun [t_dynamic; t_dynamic] com.basic.tvoid in
let vstatemachine = alloc_var VGenerated "_hx_stateMachine" tstatemachine p in
let estatemachine = make_local vstatemachine p in

let mk_continuation_call eresult p =
let econtinuation = make_local vcontinuation p in
mk (TCall (econtinuation, [eresult; make_null t_dynamic p])) com.basic.tvoid p
mk (TCall (econtinuation, [eresult; mk_control com CoroNormal])) com.basic.tvoid p
in
let mk_continuation_call_error eerror p =
let econtinuation = make_local vcontinuation p in
mk (TCall (econtinuation, [make_null t_dynamic p; eerror])) com.basic.tvoid p
mk (TCall (econtinuation, [eerror; mk_control com CoroError])) com.basic.tvoid p
in

let cb_uncaught = CoroFunctions.make_block ctx None in
Expand All @@ -54,7 +78,7 @@ let block_to_texpr_coroutine ctx cb vcontinuation vresult verror p =
let args = call.cs_args @ [ estatemachine ] in
let ecreatecoroutine = mk (TCall (efun, args)) tcoroutine call.cs_pos in
let enull = make_null t_dynamic p in
mk (TCall (ecreatecoroutine, [enull; enull])) com.basic.tvoid call.cs_pos
mk (TCall (ecreatecoroutine, [enull; mk_control com CoroNormal])) com.basic.tvoid call.cs_pos
in

let std_is e t =
Expand Down Expand Up @@ -185,13 +209,13 @@ let block_to_texpr_coroutine ctx cb vcontinuation vresult verror p =
]) t_dynamic null_pos in
let eif =
List.fold_left (fun enext (vcatch,bb_catch) ->
let ecatchvar = mk (TVar (vcatch, Some eerror)) com.basic.tvoid null_pos in
let ecatchvar = mk (TVar (vcatch, Some eresult)) com.basic.tvoid null_pos in
let catch_state_id = loop bb_catch [ecatchvar] in
match follow vcatch.v_type with
| TDynamic _ ->
set_state catch_state_id (* no next *)
| t ->
let etypecheck = std_is (make_local verror null_pos) vcatch.v_type in
let etypecheck = std_is eresult vcatch.v_type in
mk (TIf (etypecheck, set_state catch_state_id, Some enext)) com.basic.tvoid null_pos
) erethrow (List.rev catch.cc_catches)
in
Expand Down Expand Up @@ -266,7 +290,7 @@ let block_to_texpr_coroutine ctx cb vcontinuation vresult verror p =
*)

let rethrow_state_id = cb_uncaught.cb_id in
let rethrow_state = make_state rethrow_state_id [mk (TThrow eerror) com.basic.tvoid null_pos] in
let rethrow_state = make_state rethrow_state_id [mk (TThrow eresult) com.basic.tvoid null_pos] in
let states = states @ [rethrow_state] in
let states = List.sort (fun state1 state2 -> state1.cs_id - state2.cs_id) states in

Expand All @@ -278,22 +302,18 @@ let block_to_texpr_coroutine ctx cb vcontinuation vresult verror p =

let switch =
let cases = List.map (fun state ->
{case_patterns = [mk_int state.cs_id];
{case_patterns = [mk_int com state.cs_id];
case_expr = mk (TBlock state.cs_el) ctx.com.basic.tvoid (punion_el null_pos state.cs_el);
}) states in
mk_switch estate cases (Some ethrow) true
in
let eswitch = mk (TSwitch switch) com.basic.tvoid p in

let eif = mk (TIf (
mk (TBinop (
OpNotEq,
eerror,
make_null verror.v_type p
)) com.basic.tbool p,
set_state cb_uncaught.cb_id,
None
)) com.basic.tvoid p in
let econtrolswitch =
let e_normal = mk (TBlock []) ctx.com.basic.tvoid p in
let e_error = set_state cb_uncaught.cb_id in
make_control_switch com econtrol e_normal e_error p
in

let etry = mk (TTry (
eswitch,
Expand All @@ -304,10 +324,10 @@ let block_to_texpr_coroutine ctx cb vcontinuation vresult verror p =
| [] ->
()
| l ->
let patterns = List.map mk_int l in
let patterns = List.map (mk_int com) l in
let expr = mk (TBlock [
set_state i;
Builder.binop OpAssign eerror (Builder.make_local vcaught null_pos) vcaught.v_type null_pos;
Builder.binop OpAssign eresult (Builder.make_local vcaught null_pos) vcaught.v_type null_pos;
]) ctx.com.basic.tvoid null_pos in
DynArray.add cases {case_patterns = patterns; case_expr = expr};
) exc_state_map;
Expand All @@ -334,9 +354,9 @@ let block_to_texpr_coroutine ctx cb vcontinuation vresult verror p =
let eloop = mk (TWhile (make_bool com.basic true p, etry, DoWhile)) com.basic.tvoid p in

let estatemachine_def = mk (TFunction {
tf_args = [(vresult,None); (verror,None)];
tf_args = [(vresult,None); (vcontrol,None)];
tf_type = com.basic.tvoid;
tf_expr = mk (TBlock [eif;eloop]) com.basic.tvoid null_pos
tf_expr = mk (TBlock [econtrolswitch;eloop]) com.basic.tvoid null_pos
}) tstatemachine p in

let state_var = mk (TVar (vstate, Some (make_int com.basic !init_state p))) com.basic.tvoid p in
Expand Down
21 changes: 20 additions & 1 deletion src/typing/typer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1735,6 +1735,25 @@ and type_call_builtin ctx e el mode with_type p =
let create_coroutine e args ret p =
let args,ret = expand_coro_type ctx.t args ret in
let el = unify_call_args ctx el args ctx.t.tvoid p false false false in
let el = match List.rev el with
| e_cb :: el ->
let v_result = alloc_var VGenerated "_hx_result" t_dynamic p in
let v_control = alloc_var VGenerated "_hx_control" ctx.com.basic.tcoro_control p in
let e_result = Texpr.Builder.make_local v_result p in
let e_null = Texpr.Builder.make_null t_dynamic p in
let e_normal = mk (TCall(e_cb,[e_result;e_null])) ctx.com.basic.tvoid p in
let e_error = mk (TCall(e_cb,[e_null;e_result])) ctx.com.basic.tvoid p in
let e_controlswitch = CoroToTexpr.make_control_switch ctx.com (Texpr.Builder.make_local v_control p) e_normal e_error p in
let tf = {
tf_args = [(v_result,None);(v_control,None)];
tf_expr = e_controlswitch;
tf_type = ctx.com.basic.tvoid;
} in
let e = mk (TFunction tf) (tfun [t_dynamic;ctx.com.basic.tcoro_control] ctx.com.basic.tvoid) p in
List.rev (e :: el)
| [] ->
die "" __LOC__
in
let e = mk e.eexpr (TFun(args,ret)) p in
mk (TCall (e, el)) ret p
in
Expand Down Expand Up @@ -1773,7 +1792,7 @@ and type_call_builtin ctx e el mode with_type p =
| Coro (args, ret) ->
let ecoro = create_coroutine e args ret p in
let enull = Builder.make_null t_dynamic p in
mk (TCall (ecoro, [enull; enull])) ctx.com.basic.tvoid p
mk (TCall (ecoro, [enull; CoroToTexpr.mk_control ctx.com CoroNormal])) ctx.com.basic.tvoid p
| _ -> raise Exit)
| (EField (e,"create",_),_), args ->
let e = type_expr ctx e WithType.value in
Expand Down
7 changes: 7 additions & 0 deletions src/typing/typerEntry.ml
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,13 @@ let create com macros =
| _ ->
()
) m.m_types;
let m = TypeloadModule.load_module ctx (["haxe";"coro"],"CoroutineControl") null_pos in
List.iter (function
| TAbstractDecl({a_path = (["haxe";"coro"],"CoroutineControl")} as a) ->
ctx.t.tcoro_control <- TAbstract(a,[])
| _ ->
()
) m.m_types;
ignore(TypeloadModule.load_module ctx (["haxe"],"Exception") null_pos);
ctx.g.complete <- true;
ctx
Expand Down
2 changes: 1 addition & 1 deletion std/haxe/coro/Continuation.hx
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package haxe.coro;

typedef Continuation<Result, Error> = (result:Result, error:Error) -> Void;
typedef Continuation<Result> = (result:Result, control:CoroutineControl) -> Void;
6 changes: 4 additions & 2 deletions std/haxe/coro/Coroutine.hx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package haxe.coro;

import haxe.coro.Continuation;

/**
Coroutine function.
**/
Expand All @@ -14,12 +16,12 @@ abstract Coroutine<T:haxe.Constraints.Function> {
#if cpp
@:native("::hx::Coroutine::suspend")
#end
public static extern function suspend<T>(f:(cont:Continuation<T, Null<Dynamic>>)->Void):T;
public static extern function suspend<T>(f:(cont:Continuation<T>) -> Void):T;

#if (jvm || eval)
@:native("suspend")
@:keep
static function nativeSuspend<T>(f, cont:Continuation<T, Null<Dynamic>>) {
static function nativeSuspend<T>(f, cont:Continuation<T>) {
return (_, _) -> f(cont);
}
#end
Expand Down
6 changes: 6 additions & 0 deletions std/haxe/coro/CoroutineControl.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package haxe.coro;

enum abstract CoroutineControl(Int) {
final Normal;
final Error;
}
2 changes: 1 addition & 1 deletion tests/misc/coroutines/src/TestBasic.hx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class TestBasic extends utest.Test {
Assert.equals(42, result);
async.done();
});
cont(null, null);
cont(null, Normal);
}

function testErrorDirect(async:Async) {
Expand Down
2 changes: 1 addition & 1 deletion tests/misc/coroutines/src/TestJsPromise.hx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import js.lib.Promise;

@:coroutine
private function await<T>(p:Promise<T>):T {
return Coroutine.suspend(cont -> p.then(r -> cont(r, null), e -> cont(null, e)));
return Coroutine.suspend(cont -> p.then(r -> cont(r, Normal), e -> cont(e, Error)));
}

private function promise<T>(c:Coroutine<()->T>):Promise<T> {
Expand Down
4 changes: 2 additions & 2 deletions tests/misc/coroutines/src/yield/Yield.hx
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ function sequence<T>(f:Coroutine<Yield<T>->Void>):Iterator<T> {
function hasNext():Bool {
if (nextStep == null) {
nextStep = f.create(yield, finish);
nextStep(null, null);
nextStep(null, Normal);
}
return !finished;
}

function next():T {
var value = nextValue;
nextStep(null, null);
nextStep(null, Normal);
return value;
}

Expand Down

0 comments on commit 54dfcad

Please sign in to comment.