Skip to content

Commit b621f2b

Browse files
SimnAidan63yuxiaomaoRblSbkLabz
authored
Coroutines (#12479)
* clean up a bit * let's see if we can run HL * expand coroutine function types for proper forward declarations * add @:coroutine.transformed (#39) * add delay test closes #34 * get neko working * make test output file consistent * apparently python just works * Run tests on php and lua (#43) * try php * and lua * remove invalid extra type parameter * Make coros exception-free (#40) * make coros exception-free * avoid double looping if there's no catch * add more exception tests * add test for nested try-catch * try to get exce[topm value management right * port remaining YieldTryCatch cases * make nested test even crazier * change throw to break to avoid inner exceptions * fix indentation * also test throw from child coro * ignore some tests on lua because there's a codegen issue * lua isn't ready for this * try again * Move recursion tests back to flow control suite * Fix missing import --------- Co-authored-by: Aidan Lee <[email protected]> * Add type parameters to BaseContinuation and ContinuationResult (#45) * make coros exception-free * avoid double looping if there's no catch * add more exception tests * add test for nested try-catch * try to get exce[topm value management right * port remaining YieldTryCatch cases * make nested test even crazier * change throw to break to avoid inner exceptions * fix indentation * also test throw from child coro * ignore some tests on lua because there's a codegen issue * lua isn't ready for this * try again * it works I guess * also add to BlockingContinuation to lose the casts * run JVM tests through hxb roundtrip * be more accurate * deal with LocalFunc type paramters too * use more precise type on suspend * T for all * Copy js' custom event loop, but add mutexes * cache continuation_api on typer globals * remove some API types that we don't need * pass texprs as record type The reason I prefer this is because it prevents us from accidentally messing up the order. * clean up some outdated comments * remove some unused internal data * Optimize CFG a bit (#48) * optimize * another flag * add missing catch handling, enable reindexing * remove inner recursion from texpr transformer * move functions to where they should be * implement TCO (#49) * add _hx_tmp local to deal with intermediate values (#53) * don't forward blocks if their cb_catch differs * rework error resume, again closes #54 * actually we don't need the cb_catch check now, I think * Add -D coroutine.throw for eager throws (#52) * implement TCO * add -D coroutine.throw for eager throws * adjust * Keep waiting if we haven't got a result but the loop reports no more events. * set next state later closes #55 * use Unit instead of Void closes #56 * change how we run JVM tests on CI * try a new way of expression building * move local handling to own function this should probably actually move to coro.ml because the only thing it needs from here are the states * rename some things * update resume-flag when forwarding blocks closes #59 * Remove unreachable block (#60) * remove cb_unreachable, use options instead * add -D coroutine.noopt * test all combinations * nobody saw that * pull structural changes from call-stacks branch * pull null_pos changes from call-stacks branch * always use the mangled name with the variable id * no more _hx_ prefixes for core classes / interfaces * Call stacks (#50) * Update stack item just before suspension * class field and local func stack items * wrap thrown exceptions in a CoroutineException * bung the exception stack in the result field * remove commented out code * move buildCallStack to end of function * add takeExceptionCallStack * unbreak CI * fix some types * don't let null_pos mess up JVM codegen positions * change while to if * ignore for now broken by the CoroutineException wrapping * get it working on JVM * how could I forget about Flash * coroStack can be null * make it work on eval * apparently that can raise * move top stack handling to BlockingContinuation this way it works for immediate exceptions too * remove _hx_stackItem, work with _hx_result directly * remove CoroutineException, modify error.stack directly * move texpr builder to context * embrace the builder * even more builder * update __exceptionStack when setting the stack this should allow reentrancy with regards to exceptions * add something resembling a test * overdesign test case * disable hxb roundtrip for now because that must be an unrelated haxe problem * this won't work in throw-mode * make call stack tests print more info on failures * add __customStack assignment to HL * remove null_pos from our lives * cpp setting custom stack * Add forgotten actual stack setting * hack around top stack problem a bit to test cpp and eval * Revert "disable hxb roundtrip for now because that must be an unrelated haxe problem" This reverts commit d78590d. --------- Co-authored-by: Simon Krajewski <[email protected]> * interfaces seemingly working * Add test * number issue properly * Add an assert.pass we just want to know if this even compiles * Fix coroutine overload resolution in jvm * Expand coroutine arguments for php * [std/hl] move some position for customStack and set_stack (#12217) * send all types to analyzer for purity inference see #12224 * Test for #12224 (#12227) * Test for #11909 (#12218) * [nullsafety] Allow statics init in main (#12211) * [nullsafety] Allow statics init in main * usage before init check * Update TestStrict.hx (#12228) * 4.3.7 changelog * get call stack test passing on HL * fix test * rename state to gotoLabel and control to state (#73) * never mind * haxe/coro: add Mutex typedef for threaded targets, and stub for non (#72) * haxe/coro: add Mutex typedef for threaded targets, and stub for non threaded targets * haxe/coro: add body to Mutex stub constructor * tests: add TestMutex * more publicity * fix package * try to make doc gen happy --------- Co-authored-by: Simon Krajewski <[email protected]> * don't try to optimize resume states closes #75 * avoid null issue see #75 * also avoid JVM issue * use ctx.type_params for type params closes #77 * Extensible context (#78) * get started on extensible contexts (again) * introduce Element after all * more API * use BalancedTree instead of Array * assign value blocks to temp var closes #79 * change Element to IElement (#80) * be more diligent with positions * fix more optimization problems * [WIP] Stack traces continued (#82) * improve stack traces again * rework it again * Try a new stack trace approach (#84) * good start potentially * more hacks required * remove wonky sync stack handling * don't try to manage stack traces on JS because we can't * avoid cpp test problem * Make Context immutable (#87) * make context immutable * actually make it immutable * remove -D coroutine.throw (#89) * disable optimizations for now too many distractions, will revisit this later * deal with branching expressions in value places closes #90 * assign suspension calls in value places to local closes #93 * Revert "assign suspension calls in value places to local" This reverts commit cc67f42. * awkwardly deal with stack suspend problem * Don't use the typers current module for manged class names * per class anon function counter * fix transformer bug and add more tests * change context data structure to linked list (#100) * Structured Concurrency with Task/Scope (#97) * try yet another approach * factor out startChildren * Explicit type hint to make cpp generator happy * adjust hierarchy once more * bring back scope.with I didn't notice the test was missing * change entry point handling to support Coroutine.with * add more tests and align with structured branch some more * rework cancellation * add wasResumed instead * remove join, move loop handling back to entrypoint * remove completion callbacks, instead store continuations directly * adjust to feedback * Add catch segv define to see if we get a stack trace in the future * organize and document a bit * refactor some more * move scope addChild to its constructor * support Coroutine.with().create That's a neat looking API! * scheduler experiments ported to new structured branch * fix wasResume handling * don't get distracted by optimization test insanity * start children when beginning completion This is much faster, but we should go back to counting completed children to make it faster still. * fix wasResume handling * work on event loop linked list from both ends * go back to counting children to determine completion * child scope test class uses virtual time scheduler * optimize ms == 0 cases * Other tests involving delay go through the virtual time scheduler * make CI green because I want to see if PHP still explodes * Try a double buffer for zero events * switch schedule arguments around * Make virtual time scheduler work how you'd expect it to work * rename Scope to Node * Move functions out of haxe.coro.Coroutine (#102) * move coro API to hxcoro.Coro * missed one * move coro runner API to hxcoro.CoroRun * missed another one * change context to property closes #101 * remove double allocation from suspend closes #103 --------- Co-authored-by: Aidan Lee <[email protected]> Co-authored-by: Aidan Lee <[email protected]> * unset children when they completed closes #105 * add some micro benchmarks * Add some virtual time scheduler tests * scheduler functions can be cancelled * fix complex wrapper expressions * Callback on abstract task for cancellation * handle for stopping cancellation callback * Cancellation token approach * add Context.add * walk event loop from both ends * Cancellation token key * static no-op cancellation handle * lazy initialise cancellation callback and children array * lets get fancy after all * Add hxcoro.ds.Channel (#107) * add hxcoro.ds.Channel * maybe that's too much for some targets * remove mutex * fix wonky logic * fix wonky logic differently and test with random delays * change underlying data structure to paged deque * move PagedDeque to its own file * clean up a little and document random things * document new interfaces * timeout implementation * Add some tests * separate (#117) * generate continuation stack traces only in debug mode * avoid more array allocations * Extra test * Document timeout * Bring back the event loop mutexes * implement awaitChildren (#123) * release future lock before calling the function * don't hold onto zeroMutex while we're running * also remove double loop because run itself is run in a loop * Don't reschedule BaseContinuation.resume (#118) * don't reschedule BaseContinuation.resume * go back to scheduling somewhat * disable linux lua because this is annoying * even less lua * go away... * move task stuff to hxcoro.task * add some API to PagedDeque * add produce sample as a test because it happens to work right now see #124 * Don't have RacingContinuation hold onto its mutex for so long (#127) * don't have RacingContinuation hold onto its mutex for so long also avoid some unnecessary scheduling * go for yet another approach * inline by hand because HL hates me * avoid capturing `this` * Add CoroMutex (#112) * start over without task ID * move to hxcoro.concurrent * change API to match haxe.atomic.AtomicInt * move to own file * use native implementations where possible * fixes and tests * make task context lazy and avoid some retention * add CoroTask.putOnHold and call it from CoroSemaphore * make some more context retention adjustments * enable optimizations again to see if we have broken anything in the meantime * ignoring failing eval call stack test * fix some potential null problems * Cancelling suspend (#129) * first pass at cancelling suspend * tests * Close handle on resuming Otherwise callback could be invoked later on * bounce continuation call through the scheduler * Work with ICancellationHandle instead of its closure (#131) * work with ICancellationHandle directly instead of closures * rename to ICancellationCallback.onCancellation * adjust to changes awkwardly * add mutex cancellation test * is it really that easy? * add more elaborate semaphore cancelling test * Immediate invoke callback if already cancelled * Disallow multiple assignment of the callback * flip the words * change to cancellable * I think this atomic state makes sense * Interface name change for consistency * document * let's play sure it's not about this... * less handle terminology --------- Co-authored-by: Simon Krajewski <[email protected]> * Prompt channels (#126) * prompt write cancellation * Use AssertAsync class I added a while back * FIFO suspended writes * prompt read cancellation * actually assert the promptness of cancellations also expected is actually actual * go back to PagedDeque * remove unintended double resume curious that this doesn't cause anything to fail * adapt * Failing junction test (#128) * add funny test that fails on some targets * adapt * fix order of operations * change producer example to infinite loops * use static extensions and port prime example * change to bufferSize --------- Co-authored-by: Simon Krajewski <[email protected]> * finally add an id to tasks * optimize common CancellationHandle.close case * make Key interface nicer * don't use @:native * add hxcoro.components.CoroName closes #67 * get the old generator tests working see #5 * add Coro.supervisor * add C type parameter to tasks (#135) * move parent back to AbstractTask * Add INodeStrategy (#136) * add INodeStrategy, favor composition over inheritance * use concrete parameters after all * Revert "use concrete parameters after all" This reverts commit 2e7ff68. * revert type param changes * split up CoroTask * Add hxcoro.util.Convenience (#134) * add hxcoro.Convenience * adapt * adapt more * refine some toString * fix double suspension_result wrapping see #139 * fix some field hosts see #139 * Schedulers use Int64 ms everywhere * Change float literal * Int64 literal to make some targets happy * i64 literal here as well, for paranoia's sake * Private access Int64.toString to make some targets happy * spell things out for HL * spell it out for every other target too * Add ILocalContext (#137) * add ILocalContext * use for awaitingChildContinuation * add initialState to AbstractTask constructor and `start` automatically if Running closes #124 * [mad science] Get rid of explicit .key expressions (#141) * add Key.fromClass to get rid of explicit .key expressions * we actually don't care about the class itself at all * add Channel benchmark * remove expression mapping that doesn't seem to be needed anymore * bring back some mapping that was needed after all * re-enabled virtual time scheduler tests * Implement yield as delay 0 * don't ignore RLocal when mapping complex expressions closes #146 * Remove private access int64 workaround * Clean up _hx_tmp handling (#145) * split up hx_tmp for result/error * try to get error wrapping under control * add surprisingly simple tests * clean up result handling a little * make most Context functions inline * add missing return * Add IScheduleObject (#143) * add IScheduleObject * use for continuations * use for async * also use for CancellationContinuation * implement suspendCancellable directly closes #138 * avoid some double-scheduling * use AtomicInt instead of simon-mutexes for RacingContinuation too * factor out delayImpl so both delay and yield can call it This avoids the double suspension call from yield to delay, which I noticed in the yield benchmarks. * go back to Array context because that's simply faster * reduce BaseContinuation data a little more * eval has atomics now * Change isCancellationRequested to cancellationException (#147) * change isCancellationRequested to cancellationException * bring back isCancellationRequested as a convenience method * Make internal coroutine initialization lazy (#151) * start moving some types to continuation api * more * more * don't load exception twice * be lazier * be even lazier * fix * ignore that * Add PagedDeque.remove (#154) * support element deletion in Page * get cpp green even though this seems weird * add some more tests * fix isEmpty but find more problems * fix isEmpty resetting * don't blit with length 0 * use ArraySort for stability * change API to something that might actually be sound * test middle page deletion * move tests to TestPagedDeque * Follow away abstracts before getting the default value * Add test * Add an assert * treat {} as the special case that it is * haxelib * [tests] fix server tests (#164) * [tests] fix server tests builder * WIP fix server tests with coro * [CI] enable server tests.. * Use promise wrapper instead of blocking run * point to my updated utest coro branch * Fix server display tests --------- Co-authored-by: Aidan Lee <[email protected]> * support static extensions closes #167 * Add default value int64 test * Fix scheduled events not being ordered by time * Manual Int64 equality check * Spilling (#152) * Some initial work on variable spilling * skip restoring with the first state * bodge saving and restoring * make arguments appear in the first state usage table * Don't restore variables in their defined state * Add loop iteration hoisting test * another attempt * sort out arguments they're always a pain * round and round we go... Back to per state vars, was hoping the "tmp used without being initialised" would magically solve itself, but no. Might be related to TVar exprs * give some vars default type expressions * bodge it * disable hanging test so we can look at actual failures * hack it even more * Add some comments so I don't forget what this all is again * attempt at avoiding double wrapping seems to work on some targets... * mark them as captured as well * don't duplicate half of capturedVars * Fix dodgy merge * Need to follow abstracts away before getting default values Not sure why I need to do this now --------- Co-authored-by: Simon Krajewski <[email protected]> * Spilling Reads and Writes (#170) * track local read and writes for states * Use Texpr.skip * Channel API (#150) * add tryRead * progress so far * work around variance problem * apply variance to bounded reader as well * Add reader wakeup tests * add write tests * adjust * generic createUnbounded * load of bounded reader tests * Remove test which I think we don't need * channel kind enum * add reader tests to main * work around weird paged dequeue issue * channel tests updated and passing * bring back all tests * Add basic creation tests * add writer closing tests * remove some unused imports * reader cancellation * async success, but immediate scheduler in tests * Fix missing var * Move existing tests into the bounded test class * Writer sets out closed object * Add another tests which includes the wait for read and channel closing * use PagedDeque.remove * go back to the dequeue tryPop loop * add concurrent circular buffer * configurable write behaviour when buffer is full * experiments with single reader and writer combo * drop callbacks * Quickly thrown together and untested ubbounded channel * prompt cancellation waitForWrite * throw channel closed when writing to a closed channel * Add unbounded writer tests * work around weird issue * disable single producer consumer implementation will revisit at a later time * Work around weird python issue by breaking these out into variables * unbounded reader tests * Add tryPeek to channel reader * Have bounded channel use a circular buffer instead of an array --------- Co-authored-by: Aidan Lee <[email protected]> * Add thread pool scheduler (#159) * Add thread pool scheduler * Use event loop now * Make negative time exception message consistent * try sys wrap * fix thread dodge --------- Co-authored-by: Simon Krajewski <[email protected]> * [std] move hxcoro package to hxcoro And add basic 3rd party tests (eval only for now) * [tests] remove tests moved to hxcoro * Move continuations to be the leading argument * Use the hxcoro branch * remove ThreadPoolScheduler * avoid default_value problem for now * bring back double-ended list walking in scheduler see HaxeFoundation/hxcoro#18 * Remove scheduler implementations They have moved to hxcoro * document things * remove leading-completion references * reset some things * update Coro benchmark * use real utest * remove unused file * fix bad control flow handling with empty blocks * Don't try and wedge variable saving in between the last expr Properly track the trailing return expr and inject before that one * deal with mono default value --------- Co-authored-by: Aidan Lee <[email protected]> Co-authored-by: Aidan Lee <[email protected]> Co-authored-by: Yuxiao Mao <[email protected]> Co-authored-by: RblSb <[email protected]> Co-authored-by: Rudy Ges <[email protected]> Co-authored-by: Joey <[email protected]> Co-authored-by: Rudy Ges <[email protected]>
1 parent be20311 commit b621f2b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+3587
-391
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,4 @@ lib.sexp
133133
src/compiler/version.ml
134134
tests/party
135135
tests/misc/projects/Issue10863/error.log
136+
tests/misc/coroutines/dump

src-json/meta.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,18 @@
142142
"targets": ["TAbstract"],
143143
"links": ["https://haxe.org/manual/types-abstract-core-type.html"]
144144
},
145+
{
146+
"name": "Coroutine",
147+
"metadata": ":coroutine",
148+
"doc": "Transform function into a coroutine",
149+
"targets": ["TClassField"]
150+
},
151+
{
152+
"name": "CoroutineTransformed",
153+
"metadata": ":coroutine.transformed",
154+
"doc": "Marks a field as being a coroutine that has already been transformed",
155+
"targets": ["TClassField"]
156+
},
145157
{
146158
"name": "CppFileCode",
147159
"metadata": ":cppFileCode",

src/codegen/fixOverrides.ml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@ let fix_override com c f fd =
4141
let f2 = (try Some (find_field com c f) with Not_found -> None) in
4242
match f2,fd with
4343
| Some (f2), Some(fd) ->
44-
let targs, tret = (match follow f2.cf_type with TFun (args,ret) -> args, ret | _ -> die "" __LOC__) in
44+
let targs, tret =
45+
match follow_with_coro f2.cf_type with
46+
| Coro (args,ret) -> Common.expand_coro_type com.basic args ret
47+
| NotCoro (TFun(args, ret)) -> args, ret
48+
| _ -> die "" __LOC__ in
4549
let changed_args = ref [] in
4650
let prefix = "_tmp_" in
4751
let nargs = List.map2 (fun ((v,ct) as cur) (_,_,t2) ->
@@ -86,7 +90,11 @@ let fix_override com c f fd =
8690
f.cf_expr <- Some { fde with eexpr = TFunction fd2 };
8791
f.cf_type <- TFun(targs,tret);
8892
| Some(f2), None when (has_class_flag c CInterface) ->
89-
let targs, tret = (match follow f2.cf_type with TFun (args,ret) -> args, ret | _ -> die "" __LOC__) in
93+
let targs, tret =
94+
match follow_with_coro f2.cf_type with
95+
| Coro (args,ret) -> Common.expand_coro_type com.basic args ret
96+
| NotCoro (TFun(args, ret)) -> args, ret
97+
| _ -> die "" __LOC__ in
9098
f.cf_type <- TFun(targs,tret)
9199
| _ ->
92100
()

src/context/common.ml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,9 +795,16 @@ let create timer_ctx compilation_step cs version args display_mode =
795795
tfloat = mk_mono();
796796
tbool = mk_mono();
797797
tstring = mk_mono();
798+
texception = mk_mono();
798799
tnull = (fun _ -> die "Could use locate abstract Null<T> (was it redefined?)" __LOC__);
799800
tarray = (fun _ -> die "Could not locate class Array<T> (was it redefined?)" __LOC__);
800801
titerator = (fun _ -> die "Could not locate typedef Iterator<T> (was it redefined?)" __LOC__);
802+
tunit = mk_mono();
803+
tcoro = {
804+
tcoro = lazy (fun _ -> die "Could not locate abstract Coroutine<T> (was it redefined?)" __LOC__);
805+
continuation = lazy (mk_mono());
806+
suspension_result_class = lazy null_class;
807+
}
801808
};
802809
std = null_class;
803810
file_keys = new file_keys;
@@ -929,6 +936,13 @@ let clone com is_macro_context =
929936
tnull = (fun _ -> die "Could use locate abstract Null<T> (was it redefined?)" __LOC__);
930937
tarray = (fun _ -> die "Could not locate class Array<T> (was it redefined?)" __LOC__);
931938
titerator = (fun _ -> die "Could not locate typedef Iterator<T> (was it redefined?)" __LOC__);
939+
texception = mk_mono();
940+
tunit = mk_mono();
941+
tcoro = {
942+
tcoro = lazy (fun _ -> die "Could not locate abstract Coroutine<T> (was it redefined?)" __LOC__);
943+
continuation = lazy (mk_mono());
944+
suspension_result_class = lazy null_class;
945+
};
932946
};
933947
local_wrapper = LocalWrapper.null_wrapper;
934948
std = null_class;
@@ -1140,6 +1154,12 @@ let get_entry_point com =
11401154
(snd path, c, e)
11411155
) com.main.main_path
11421156

1157+
let expand_coro_type basic args ret =
1158+
let args = ("_hx_continuation",false,Lazy.force basic.tcoro.continuation) :: args in
1159+
let ret = if ExtType.is_void (follow ret) then basic.tunit else ret in
1160+
let c = Lazy.force basic.tcoro.suspension_result_class in
1161+
(args,TInst(c,[ret]))
1162+
11431163
let make_unforced_lazy t_proc f where =
11441164
let r = ref (lazy_available t_dynamic) in
11451165
r := lazy_wait (fun() ->

src/context/typecore.ml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ type typer_pass_tasks = {
9292

9393
type function_mode =
9494
| FunFunction
95+
| FunCoroutine
9596
| FunNotFunction
9697

9798
type typer_globals = {
@@ -113,6 +114,7 @@ type typer_globals = {
113114
mutable delayed_display : DisplayTypes.display_exception_kind option;
114115
root_typer : typer;
115116
(* api *)
117+
mutable continuation_api : ContTypes.continuation_api option;
116118
do_macro : typer -> macro_mode -> path -> string -> expr list -> pos -> macro_result;
117119
do_load_macro : typer -> bool -> path -> string -> pos -> ((string * bool * t) list * t * tclass * Type.tclass_field);
118120
do_load_module : ?origin:module_dep_origin -> typer -> path -> pos -> module_def;
@@ -288,8 +290,11 @@ module TyperManager = struct
288290
let e = create_ctx_e ctx.e.curfun FunNotFunction in
289291
create ctx ctx.m ctx.c f e PTypeField ctx.type_params
290292

293+
let is_coroutine_context ctx =
294+
ctx.e.function_mode = FunCoroutine
295+
291296
let is_function_context ctx = match ctx.e.function_mode with
292-
| FunFunction ->
297+
| FunFunction | FunCoroutine ->
293298
true
294299
| FunNotFunction ->
295300
false

src/core/tFunctions.ml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,21 @@ let rec follow_lazy_and_mono t = match t with
649649
| _ ->
650650
t
651651

652+
type maybe_coro =
653+
| Coro of tsignature
654+
| NotCoro of t
655+
656+
let follow_with_coro t = match follow t with
657+
| TAbstract({a_path = (["haxe";"coro"],"Coroutine")},[t]) ->
658+
begin match follow t with
659+
| TFun(args,ret) ->
660+
Coro (args,ret)
661+
| t ->
662+
NotCoro t
663+
end
664+
| t ->
665+
NotCoro t
666+
652667
let rec ambiguate_funs t =
653668
match follow t with
654669
| TFun _ -> TFun ([], t_dynamic)

src/core/tType.ml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,12 @@ and build_state =
482482

483483
exception Type_exception of t
484484

485+
type coro_types = {
486+
mutable tcoro : ((string * bool * t) list -> t -> t) Lazy.t;
487+
mutable continuation : t Lazy.t;
488+
mutable suspension_result_class : tclass Lazy.t;
489+
}
490+
485491
type basic_types = {
486492
mutable tvoid : t;
487493
mutable tany : t;
@@ -491,7 +497,10 @@ type basic_types = {
491497
mutable tnull : t -> t;
492498
mutable tstring : t;
493499
mutable tarray : t -> t;
494-
mutable titerator : t -> t
500+
mutable texception : t;
501+
mutable titerator : t -> t;
502+
mutable tunit : t;
503+
mutable tcoro : coro_types;
495504
}
496505

497506
type class_field_scope =
@@ -549,6 +558,7 @@ type flag_tvar =
549558
| VStatic
550559
| VUsedByTyper (* Set if the typer looked up this variable *)
551560
| VHxb (* Flag used by hxb *)
561+
| VCoroCaptured
552562

553563
let flag_tvar_names = [
554564
"VCaptured";"VFinal";"VAnalyzed";"VAssigned";"VCaught";"VStatic";"VUsedByTyper"

src/core/texpr.ml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,24 @@ let for_remap basic v etype e1 e2 p =
639639
mk (TWhile((mk (TParenthesis ehasnext) ehasnext.etype ehasnext.epos),ebody,NormalWhile)) basic.tvoid e1.epos;
640640
]) basic.tvoid p
641641

642+
let not_while_true_to_while_true basic e1 e2 flag t p =
643+
let e_break = mk TBreak t_dynamic p in
644+
let e_not = mk (TUnop(Not,Prefix,Builder.mk_parent e1)) e1.etype e1.epos in
645+
let e_if eo = mk (TIf(e_not,e_break,eo)) basic.tvoid p in
646+
let rec map_continue e = match e.eexpr with
647+
| TContinue ->
648+
duplicate_tvars e_identity (e_if (Some e))
649+
| TWhile _ ->
650+
e
651+
| _ ->
652+
map_expr map_continue e
653+
in
654+
let e2 = if flag = NormalWhile then e2 else map_continue e2 in
655+
let e_if = e_if None in
656+
let e_block = if flag = NormalWhile then concat e_if e2 else concat e2 e_if in
657+
let e_true = mk (TConst (TBool true)) basic.tbool p in
658+
mk (TWhile(e_true,e_block,NormalWhile)) t p
659+
642660
(* -------------------------------------------------------------------------- *)
643661
(* BUILD META DATA OBJECT *)
644662

src/coro/contTypes.ml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
open Type
2+
3+
type continuation_api = {
4+
base_continuation_class : tclass;
5+
immediate_suspension_result_class : tclass;
6+
suspension_state : Type.t;
7+
suspension_result : t -> t;
8+
suspension_result_class : tclass;
9+
continuation : Type.t;
10+
state : tclass_field;
11+
result : tclass_field;
12+
error : tclass_field;
13+
completion : tclass_field;
14+
context : tclass_field;
15+
goto_label : tclass_field;
16+
recursing : tclass_field;
17+
immediate_result : texpr -> texpr;
18+
immediate_error : texpr -> Type.t -> texpr;
19+
}
20+
21+
let create_continuation_api base_continuation_class immediate_suspension_result_class suspension_state suspension_result_class continuation immediate_result immediate_error state result error completion context goto_label recursing = {
22+
base_continuation_class;
23+
immediate_suspension_result_class;
24+
suspension_state;
25+
suspension_result = (fun t -> TInst(suspension_result_class,[t]));
26+
suspension_result_class;
27+
continuation;
28+
immediate_result;
29+
immediate_error;
30+
state;
31+
result;
32+
error;
33+
completion;
34+
context;
35+
goto_label;
36+
recursing;
37+
}

0 commit comments

Comments
 (0)