import Std::Io::{PrintLine, PrintInt};

extern func bux_async_yield();
extern func bux_async_run();
extern func bux_async_spawn(fn: *void) -> *void;
extern func bux_async_await(handle: *void) -> *void;
extern func bux_async_return(value: *void, size: int64);
extern func bux_async_sleep(ms: int64);

async func Compute() -> int {
    PrintLine("Compute: start");
    bux_async_sleep(100);
    PrintLine("Compute: after 100ms");
    let result: int = 42;
    bux_async_return((&result) as *void, sizeof(int));
    return result;
}

async func Double() -> int {
    PrintLine("Double: start");
    bux_async_sleep(50);
    PrintLine("Double: after 50ms");
    let result: int = 84;
    bux_async_return((&result) as *void, sizeof(int));
    return result;
}

func Main() -> int {
    PrintLine("Main: start");
    let h1: *void = spawn Compute();
    let h2: *void = spawn Double();
    let r1Ptr: *int = h1.await as *int;
    let r2Ptr: *int = h2.await as *int;
    let r1: int = *r1Ptr;
    let r2: int = *r2Ptr;
    PrintLine("Results:");
    PrintInt(r1);
    PrintLine("");
    PrintInt(r2);
    PrintLine("");
    PrintLine("Main: done");
    return 0;
}
