diff --git a/src/continuation.rs b/src/continuation.rs index 17ab8d4..3773863 100644 --- a/src/continuation.rs +++ b/src/continuation.rs @@ -1,4 +1,5 @@ use async_trait::async_trait; +use futures::future::BoxFuture; use proc_macros::builtin; use crate::{ @@ -31,6 +32,8 @@ pub trait Resumable: Trace + Send + Sync { args: Vec>, cont: &Option>, ) -> Result>, RuntimeError>; + + async fn clone_stack(&self) -> Arc; } #[derive(Clone, Trace)] @@ -46,6 +49,19 @@ impl Continuation { remaining: remaining.clone(), } } + + fn clone_stack(&self) -> BoxFuture<'_, Arc> { + Box::pin(async move { + Arc::new(Self { + resume_point: self.resume_point.clone_stack().await, + remaining: if let Some(ref cont) = self.remaining { + Some(cont.clone_stack().await) + } else { + None + }, + }) + }) + } } #[async_trait] @@ -63,6 +79,10 @@ impl Resumable for Continuation { self.resume_point.resume(args, cont).await } } + + async fn clone_stack(&self) -> Arc { + self.clone_stack().await + } } #[async_trait] @@ -128,7 +148,7 @@ impl Eval for CatchContinuationCall { } } -#[derive(Trace)] +#[derive(Trace, Clone)] pub struct ResumableBody { env: Env, remaining: ArcSlice>, @@ -162,6 +182,19 @@ impl Resumable for ResumableBody { } last.eval(&self.env, cont).await } + + async fn clone_stack(&self) -> Arc { + Arc::new(Self { + env: self.env.deep_clone().await, + remaining: self.remaining.clone(), + }) + } + + /* + async fn clone_stack(&self) -> Arc { + Arc::new(self.clone()) + } + */ } #[derive(Trace)] @@ -200,6 +233,13 @@ impl Resumable for ResumableSyntaxCase { _ => todo!(), } } + + async fn clone_stack(&self) -> Arc { + Arc::new(Self { + env: self.env.deep_clone().await, + transformer: self.transformer.clone(), + }) + } } #[derive(Trace)] @@ -236,6 +276,13 @@ impl Resumable for ResumableSet { .await = val; Ok(vec![Gc::new(Value::Null)]) } + + async fn clone_stack(&self) -> Arc { + Arc::new(Self { + env: self.env.deep_clone().await, + var: self.var.clone(), + }) + } } #[derive(Trace)] @@ -287,6 +334,13 @@ impl Resumable for ResumableAnd { } last.eval(&self.env, cont).await } + + async fn clone_stack(&self) -> Arc { + Arc::new(Self { + env: self.env.deep_clone().await, + args: self.args.clone(), + }) + } } #[derive(Trace)] @@ -338,6 +392,13 @@ impl Resumable for ResumableOr { } last.eval(&self.env, cont).await } + + async fn clone_stack(&self) -> Arc { + Arc::new(Self { + env: self.env.deep_clone().await, + args: self.args.clone(), + }) + } } #[derive(Trace)] @@ -387,6 +448,15 @@ impl Resumable for ResumableLet { } self.body.eval(&Env::from(self.scope.clone()), cont).await } + + async fn clone_stack(&self) -> Arc { + Arc::new(Self { + scope: Gc::new(self.scope.read().await.deep_clone().await), + curr: self.curr.clone(), + remaining_bindings: self.remaining_bindings.clone(), + body: self.body.clone(), + }) + } } #[derive(Trace)] @@ -422,6 +492,14 @@ impl Resumable for ResumableIf { Ok(vec![Gc::new(Value::Null)]) } } + + async fn clone_stack(&self) -> Arc { + Arc::new(Self { + env: self.env.deep_clone().await, + success: self.success.clone(), + failure: self.failure.clone(), + }) + } } #[derive(Trace)] @@ -450,6 +528,13 @@ impl Resumable for ResumableDefineVar { self.env.def_var(&self.name, arg).await; Ok(vec![Gc::new(Value::Null)]) } + + async fn clone_stack(&self) -> Arc { + Arc::new(Self { + env: self.env.deep_clone().await, + name: self.name.clone(), + }) + } } #[derive(Trace)] @@ -516,6 +601,16 @@ impl Resumable for ResumableCall { .eval(cont) .await } + + async fn clone_stack(&self) -> Arc { + Arc::new(Self { + env: self.env.deep_clone().await, + collected: self.collected.clone(), + remaining: self.remaining.clone(), + proc_name: self.proc_name.clone(), + location: self.location.clone(), + }) + } } #[derive(Trace)] @@ -602,6 +697,25 @@ impl Resumable for ResumableApply { .eval(cont) .await } + + async fn clone_stack(&self) -> Arc { + Arc::new(Self { + env: self.env.deep_clone().await, + collected: self.collected.clone(), + remaining: self.remaining.clone(), + rest_args: self.rest_args.clone(), + proc_name: self.proc_name.clone(), + location: self.location.clone(), + }) + } +} + +async fn clone_cont_stack(cont: &Option>) -> Option> { + if let Some(ref cont) = cont { + Some(cont.clone_stack().await) + } else { + None + } } #[builtin("call/cc")] @@ -615,13 +729,16 @@ pub async fn call_cc( .ok_or_else(|| RuntimeError::invalid_type("procedure", proc.type_name()))? }; callable - .call(vec![Gc::new(Value::Continuation(cont.clone()))], cont) + .call( + vec![Gc::new(Value::Continuation(clone_cont_stack(cont).await))], + cont, + ) .await? .eval(cont) .await } -#[derive(Trace)] +#[derive(Trace, Clone)] pub struct CallWithValues { min_args: usize, max_args: Option, @@ -649,6 +766,10 @@ impl Resumable for CallWithValues { }; callable.call(args, cont).await?.eval(cont).await } + + async fn clone_stack(&self) -> Arc { + Arc::new(self.clone()) + } } #[builtin("call-with-values")] @@ -673,7 +794,7 @@ pub async fn call_with_values( max_args: consumer_callable.max_args(), consumer: consumer.clone(), }), - cont, + &clone_cont_stack(cont).await, )); let producer_result = producer_callable diff --git a/src/env.rs b/src/env.rs index 4864228..83b6ba1 100644 --- a/src/env.rs +++ b/src/env.rs @@ -72,6 +72,16 @@ impl LexicalContour { } self.macros.insert(ident.clone(), value); } + + pub fn deep_clone(&self) -> BoxFuture<'_, Self> { + Box::pin(async move { + Self { + up: self.up.deep_clone().await, + vars: self.vars.clone(), + macros: self.macros.clone(), + } + }) + } } #[derive(derive_more::Debug, Trace)] @@ -124,6 +134,16 @@ impl ExpansionContext { } }) } + + pub fn deep_clone(&self) -> BoxFuture<'_, Self> { + Box::pin(async move { + Self { + up: self.up.deep_clone().await, + mark: self.mark, + macro_env: self.macro_env.deep_clone().await, + } + }) + } } #[derive(Clone, Trace, derive_more::Debug)] @@ -219,6 +239,18 @@ impl Env { }) } + pub async fn deep_clone(&self) -> Self { + match self { + Self::Top => Self::Top, + Self::Expansion(expansion) => { + Self::Expansion(Gc::new(expansion.read().await.deep_clone().await)) + } + Self::LexicalContour(env) => { + Self::LexicalContour(Gc::new(env.read().await.deep_clone().await)) + } + } + } + /// Evaluate a string, returning all of the results in a Vec pub async fn eval<'e>(&self, exprs: &'e str) -> Result>>, EvalError<'e>> { let tokens = Token::tokenize_str(exprs)?; diff --git a/src/value.rs b/src/value.rs index d3cde1b..27d6cb6 100644 --- a/src/value.rs +++ b/src/value.rs @@ -360,6 +360,6 @@ pub async fn disp( _cont: &Option>, arg: &Gc, ) -> Result>, RuntimeError> { - println!("{}", arg.read().await.fmt().await); + print!("{}", arg.read().await.fmt().await); Ok(vec![Gc::new(Value::Null)]) }