1use crate::{continuation::Continuation, error::RuntimeError, gc::Gc, num::Number, value::Value};
2use futures::{future::try_join_all, FutureExt};
3use scheme_rs_macros::builtin;
4use std::{sync::Arc, time::Duration};
5
6#[builtin("spawn")]
7pub async fn spawn(
8 _cont: &Option<Arc<Continuation>>,
9 arg: &Gc<Value>,
10) -> Result<Vec<Gc<Value>>, RuntimeError> {
11 let value = arg.read().await;
12 let callable = value
13 .as_callable()
14 .ok_or_else(|| RuntimeError::invalid_type("callable", value.type_name()))?;
15 let task = tokio::task::spawn(async move {
21 let val = callable.call(Vec::new(), &None).await?;
22 val.eval(&None).await
23 });
24 let future = async move { task.await.unwrap() }.boxed().shared();
25 Ok(vec![Gc::new(Value::Future(future))])
26}
27
28#[builtin("sleep")]
29pub async fn sleep(
30 _cont: &Option<Arc<Continuation>>,
31 arg: &Gc<Value>,
32) -> Result<Vec<Gc<Value>>, RuntimeError> {
33 let value = arg.read().await;
34 let time: &Number = value.as_ref().try_into()?;
35 let millis = time.to_u64();
36 let future = async move {
37 tokio::time::sleep(Duration::from_millis(millis)).await;
38 Ok(vec![Gc::new(Value::Null)])
39 }
40 .boxed()
41 .shared();
42 Ok(vec![Gc::new(Value::Future(future))])
43}
44
45#[builtin("await")]
46pub async fn await_value(
47 _cont: &Option<Arc<Continuation>>,
48 arg: &Gc<Value>,
49) -> Result<Vec<Gc<Value>>, RuntimeError> {
50 let value = arg.read().await;
51 match &*value {
52 Value::Future(fut) => fut.clone().await,
53 _ => Ok(vec![arg.clone()]),
54 }
55}
56
57#[builtin("join")]
58pub async fn join(
59 _cont: &Option<Arc<Continuation>>,
60 args: Vec<Gc<Value>>,
61) -> Result<Vec<Gc<Value>>, RuntimeError> {
62 let mut futs = Vec::new();
63 for arg in args.into_iter() {
64 let value = arg.read().await;
65 let fut = match &*value {
66 Value::Future(fut) => fut.clone(),
67 _ => {
68 let arg = arg.clone();
71 async move { Ok(vec![arg]) }.boxed().shared()
72 }
73 };
74 futs.push(fut);
75 }
76 let future = async move {
77 let results = try_join_all(futs)
78 .await?
79 .into_iter()
80 .flatten()
81 .collect::<Vec<_>>();
82 Ok(vec![Gc::new(Value::from(results))])
83 }
84 .boxed()
85 .shared();
86 Ok(vec![Gc::new(Value::Future(future))])
87}