Skip to content

Commit

Permalink
Clone stack on-demand
Browse files Browse the repository at this point in the history
  • Loading branch information
maplant committed Dec 4, 2024
1 parent 8645a60 commit 2fb91d9
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 5 deletions.
129 changes: 125 additions & 4 deletions src/continuation.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use async_trait::async_trait;
use futures::future::BoxFuture;
use proc_macros::builtin;

use crate::{
Expand Down Expand Up @@ -31,6 +32,8 @@ pub trait Resumable: Trace + Send + Sync {
args: Vec<Gc<Value>>,
cont: &Option<Arc<Continuation>>,
) -> Result<Vec<Gc<Value>>, RuntimeError>;

async fn clone_stack(&self) -> Arc<dyn Resumable>;
}

#[derive(Clone, Trace)]
Expand All @@ -46,6 +49,19 @@ impl Continuation {
remaining: remaining.clone(),
}
}

fn clone_stack(&self) -> BoxFuture<'_, Arc<Self>> {
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]
Expand All @@ -63,6 +79,10 @@ impl Resumable for Continuation {
self.resume_point.resume(args, cont).await
}
}

async fn clone_stack(&self) -> Arc<dyn Resumable> {
self.clone_stack().await
}
}

#[async_trait]
Expand Down Expand Up @@ -128,7 +148,7 @@ impl Eval for CatchContinuationCall {
}
}

#[derive(Trace)]
#[derive(Trace, Clone)]
pub struct ResumableBody {
env: Env,
remaining: ArcSlice<Arc<dyn Eval>>,
Expand Down Expand Up @@ -162,6 +182,19 @@ impl Resumable for ResumableBody {
}
last.eval(&self.env, cont).await
}

async fn clone_stack(&self) -> Arc<dyn Resumable> {
Arc::new(Self {
env: self.env.deep_clone().await,
remaining: self.remaining.clone(),
})
}

/*
async fn clone_stack(&self) -> Arc<dyn Resumable> {
Arc::new(self.clone())
}
*/
}

#[derive(Trace)]
Expand Down Expand Up @@ -200,6 +233,13 @@ impl Resumable for ResumableSyntaxCase {
_ => todo!(),
}
}

async fn clone_stack(&self) -> Arc<dyn Resumable> {
Arc::new(Self {
env: self.env.deep_clone().await,
transformer: self.transformer.clone(),
})
}
}

#[derive(Trace)]
Expand Down Expand Up @@ -236,6 +276,13 @@ impl Resumable for ResumableSet {
.await = val;
Ok(vec![Gc::new(Value::Null)])
}

async fn clone_stack(&self) -> Arc<dyn Resumable> {
Arc::new(Self {
env: self.env.deep_clone().await,
var: self.var.clone(),
})
}
}

#[derive(Trace)]
Expand Down Expand Up @@ -287,6 +334,13 @@ impl Resumable for ResumableAnd {
}
last.eval(&self.env, cont).await
}

async fn clone_stack(&self) -> Arc<dyn Resumable> {
Arc::new(Self {
env: self.env.deep_clone().await,
args: self.args.clone(),
})
}
}

#[derive(Trace)]
Expand Down Expand Up @@ -338,6 +392,13 @@ impl Resumable for ResumableOr {
}
last.eval(&self.env, cont).await
}

async fn clone_stack(&self) -> Arc<dyn Resumable> {
Arc::new(Self {
env: self.env.deep_clone().await,
args: self.args.clone(),
})
}
}

#[derive(Trace)]
Expand Down Expand Up @@ -387,6 +448,15 @@ impl Resumable for ResumableLet {
}
self.body.eval(&Env::from(self.scope.clone()), cont).await
}

async fn clone_stack(&self) -> Arc<dyn Resumable> {
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)]
Expand Down Expand Up @@ -422,6 +492,14 @@ impl Resumable for ResumableIf {
Ok(vec![Gc::new(Value::Null)])
}
}

async fn clone_stack(&self) -> Arc<dyn Resumable> {
Arc::new(Self {
env: self.env.deep_clone().await,
success: self.success.clone(),
failure: self.failure.clone(),
})
}
}

#[derive(Trace)]
Expand Down Expand Up @@ -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<dyn Resumable> {
Arc::new(Self {
env: self.env.deep_clone().await,
name: self.name.clone(),
})
}
}

#[derive(Trace)]
Expand Down Expand Up @@ -516,6 +601,16 @@ impl Resumable for ResumableCall {
.eval(cont)
.await
}

async fn clone_stack(&self) -> Arc<dyn Resumable> {
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)]
Expand Down Expand Up @@ -602,6 +697,25 @@ impl Resumable for ResumableApply {
.eval(cont)
.await
}

async fn clone_stack(&self) -> Arc<dyn Resumable> {
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<Arc<Continuation>>) -> Option<Arc<Continuation>> {
if let Some(ref cont) = cont {
Some(cont.clone_stack().await)
} else {
None
}
}

#[builtin("call/cc")]
Expand All @@ -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<usize>,
Expand Down Expand Up @@ -649,6 +766,10 @@ impl Resumable for CallWithValues {
};
callable.call(args, cont).await?.eval(cont).await
}

async fn clone_stack(&self) -> Arc<dyn Resumable> {
Arc::new(self.clone())
}
}

#[builtin("call-with-values")]
Expand All @@ -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
Expand Down
32 changes: 32 additions & 0 deletions src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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)]
Expand Down Expand Up @@ -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<Vec<Vec<Gc<Value>>>, EvalError<'e>> {
let tokens = Token::tokenize_str(exprs)?;
Expand Down
2 changes: 1 addition & 1 deletion src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,6 @@ pub async fn disp(
_cont: &Option<Arc<Continuation>>,
arg: &Gc<Value>,
) -> Result<Vec<Gc<Value>>, RuntimeError> {
println!("{}", arg.read().await.fmt().await);
print!("{}", arg.read().await.fmt().await);
Ok(vec![Gc::new(Value::Null)])
}

0 comments on commit 2fb91d9

Please sign in to comment.