!7 p-experiment { callHibernatable(f normalFunction1); callHibernatable(f hibernatingFunction1); /*for (bool hibernate : ll(false, true)) { callHibernatable(curry(f aFunction, hibernate), voidfunc(S s) { print("Got result: " + finished); }); }*/ } // simple version with only one function and no return value static void callHibernatable(O f1) { try { callF(f1); } catch (RuntimeException e) { Throwable e2 = innerException(e); if (e2 instanceof HibernatingTheThread) ret; throw rethrow(e2); } } static O callHibernatable(O f1, O f2) { O result; try { result = callF(f1); } catch (RuntimeException e) { Throwable e2 = innerException(e); if (!e2 instanceof HibernatingTheThread) throw rethrow(e); HibernatingTheThread h = cast e2; throw HibernatingTheThread(func { }); } ret callF(f2, result); } svoid normalFunction1() { print("finished"); } svoid hibernatingFunction1() { HibernatingTheThread e = new(r { print("finished after hibernation"); }); doLater(1000, e); throw e; } sS aFunction(bool hibernate) { if (hibernate) { print("Hibernating for 1s..."); HibernatingTheThread e = new(func -> S { ret "finished"; }); doLater(1000, e); throw e; } else ret "hello"; } sclass HibernatingTheThread extends RuntimeException implements Runnable { O code; // runnable or F0 O continuation; // runnable or vf1 *() {} *(O *code) {} public void run() { callF(continuation, callF(code)); } }