1use async_trait::async_trait;
2use scheme_rs_macros::builtin;
3
4use crate::{
5 ast,
6 env::{Env, LexicalContour},
7 error::{RuntimeError, RuntimeErrorKind},
8 eval::{Eval, ValuesOrPreparedCall},
9 expand::Transformer,
10 gc::{Gc, Trace},
11 lists::list_to_vec,
12 proc::{Callable, PreparedCall},
13 syntax::{Identifier, Span},
14 util::{ArcSlice, RequireOne},
15 value::Value,
16};
17use std::sync::Arc;
18
19#[async_trait]
20pub trait Resumable: Trace + Send + Sync {
21 fn min_args(&self) -> usize {
22 1
23 }
24
25 fn max_args(&self) -> Option<usize> {
26 Some(1)
27 }
28
29 async fn resume(
30 &self,
31 args: Vec<Gc<Value>>,
32 cont: &Option<Arc<Continuation>>,
33 ) -> Result<Vec<Gc<Value>>, RuntimeError>;
34}
35
36#[derive(Clone, Trace)]
37pub struct Continuation {
38 resume_point: Arc<dyn Resumable>,
39 remaining: Option<Arc<Continuation>>,
40}
41
42impl Continuation {
43 pub fn new(resume_point: Arc<dyn Resumable>, remaining: &Option<Arc<Continuation>>) -> Self {
44 Self {
45 resume_point,
46 remaining: remaining.clone(),
47 }
48 }
49}
50
51#[async_trait]
52impl Resumable for Continuation {
53 async fn resume(
54 &self,
55 args: Vec<Gc<Value>>,
56 cont: &Option<Arc<Continuation>>,
57 ) -> Result<Vec<Gc<Value>>, RuntimeError> {
58 if let Some(ref remaining) = self.remaining {
59 let new_cont = Some(Arc::new(Continuation::new(remaining.clone(), cont)));
60 let resume_result = self.resume_point.resume(args, &new_cont).await?;
61 remaining.resume(resume_result, cont).await
62 } else {
63 self.resume_point.resume(args, cont).await
64 }
65 }
66}
67
68#[async_trait]
69impl Callable for Option<Arc<Continuation>> {
70 fn min_args(&self) -> usize {
71 self.as_ref()
72 .map(|x| x.resume_point.min_args())
73 .unwrap_or(1)
74 }
75
76 fn max_args(&self) -> Option<usize> {
77 self.as_ref()
78 .map(|x| x.resume_point.max_args())
79 .unwrap_or(None)
80 }
81
82 async fn call(
83 &self,
84 args: Vec<Gc<Value>>,
85 _calling_cont: &Self,
86 ) -> Result<ValuesOrPreparedCall, RuntimeError> {
87 Err(RuntimeError::abandon_current_continuation(
88 args,
89 self.clone(),
90 ))
91 }
92}
93
94#[derive(Trace)]
95pub struct CatchContinuationCall {
96 inner: Arc<dyn Eval>,
97}
98
99impl CatchContinuationCall {
100 pub fn new(inner: Arc<dyn Eval>) -> Self {
101 Self { inner }
102 }
103}
104
105#[async_trait]
106impl Eval for CatchContinuationCall {
107 async fn eval(
108 &self,
109 env: &Env,
110 cont: &Option<Arc<Continuation>>,
111 ) -> Result<Vec<Gc<Value>>, RuntimeError> {
112 let mut inner = self.inner.eval(env, cont).await;
113 while let Err(RuntimeError {
114 kind: RuntimeErrorKind::AbandonCurrentContinuation { args, new_cont },
115 ..
116 }) = inner
117 {
118 if let Some(new_cont) = new_cont {
122 inner = new_cont.resume(args, cont).await;
123 } else {
124 return Ok(args);
125 }
126 }
127 inner
128 }
129}
130
131#[derive(Trace)]
132pub struct ResumableBody {
133 env: Env,
134 remaining: ArcSlice<Arc<dyn Eval>>,
135}
136
137impl ResumableBody {
138 pub fn new(env: &Env, remaining: &ArcSlice<Arc<dyn Eval>>) -> Self {
139 Self {
140 env: env.clone(),
141 remaining: remaining.clone(),
142 }
143 }
144}
145
146#[async_trait]
147impl Resumable for ResumableBody {
148 async fn resume(
149 &self,
150 args: Vec<Gc<Value>>,
151 cont: &Option<Arc<Continuation>>,
152 ) -> Result<Vec<Gc<Value>>, RuntimeError> {
153 let Some(last) = self.remaining.last() else {
154 return Ok(args);
155 };
156 for (expr, tail) in self.remaining.skip_last() {
157 let cont = Some(Arc::new(Continuation::new(
158 Arc::new(ResumableBody::new(&self.env, &tail)),
159 cont,
160 )));
161 expr.eval(&self.env, &cont).await?;
162 }
163 last.eval(&self.env, cont).await
164 }
165}
166
167#[derive(Trace)]
168pub struct ResumableSyntaxCase {
169 env: Env,
170 transformer: Transformer,
171}
172
173impl ResumableSyntaxCase {
174 pub fn new(env: &Env, transformer: &Transformer) -> Self {
175 Self {
176 env: env.clone(),
177 transformer: transformer.clone(),
178 }
179 }
180}
181
182#[async_trait]
183impl Resumable for ResumableSyntaxCase {
184 async fn resume(
185 &self,
186 args: Vec<Gc<Value>>,
187 cont: &Option<Arc<Continuation>>,
188 ) -> Result<Vec<Gc<Value>>, RuntimeError> {
189 let arg = args.require_one()?;
190 let arg = arg.read().await;
191 match &*arg {
192 Value::Syntax(syntax) => {
193 let result = self.transformer.expand(syntax).unwrap();
194 result
195 .compile(&self.env, cont)
196 .await?
197 .eval(&self.env, cont)
198 .await
199 }
200 _ => todo!(),
201 }
202 }
203}
204
205#[derive(Trace)]
206pub struct ResumableSet {
207 env: Env,
208 var: Identifier,
209}
210
211impl ResumableSet {
212 pub fn new(env: &Env, var: &Identifier) -> Self {
213 Self {
214 env: env.clone(),
215 var: var.clone(),
216 }
217 }
218}
219
220#[async_trait]
221impl Resumable for ResumableSet {
222 async fn resume(
223 &self,
224 args: Vec<Gc<Value>>,
225 _cont: &Option<Arc<Continuation>>,
226 ) -> Result<Vec<Gc<Value>>, RuntimeError> {
227 let arg = args.require_one()?;
229 let val = arg.read().await.clone();
230 *self
231 .env
232 .fetch_var(&self.var)
233 .await
234 .ok_or_else(|| RuntimeError::undefined_variable(self.var.clone()))?
235 .write()
236 .await = val;
237 Ok(vec![Gc::new(Value::Null)])
238 }
239}
240
241#[derive(Trace)]
242pub struct ResumableAnd {
243 env: Env,
244 args: ArcSlice<Arc<dyn Eval>>,
245}
246
247impl ResumableAnd {
248 pub fn new(env: &Env, args: &ArcSlice<Arc<dyn Eval>>) -> Self {
249 Self {
250 env: env.clone(),
251 args: args.clone(),
252 }
253 }
254}
255
256#[async_trait]
257impl Resumable for ResumableAnd {
258 async fn resume(
259 &self,
260 args: Vec<Gc<Value>>,
261 cont: &Option<Arc<Continuation>>,
262 ) -> Result<Vec<Gc<Value>>, RuntimeError> {
263 let Some(last) = self.args.last() else {
266 return Ok(args);
267 };
268 let arg = args.require_one()?;
269 if !arg.read().await.is_true() {
270 return Ok(vec![Gc::new(Value::Boolean(false))]);
271 }
272 for (arg, tail) in self.args.skip_last() {
273 let cont = Arc::new(Continuation::new(
274 Arc::new(ResumableAnd::new(&self.env, &tail)),
275 cont,
276 ));
277 if !arg
278 .eval(&self.env, &Some(cont))
279 .await?
280 .require_one()?
281 .read()
282 .await
283 .is_true()
284 {
285 return Ok(vec![Gc::new(Value::Boolean(false))]);
286 }
287 }
288 last.eval(&self.env, cont).await
289 }
290}
291
292#[derive(Trace)]
293pub struct ResumableOr {
294 env: Env,
295 args: ArcSlice<Arc<dyn Eval>>,
296}
297
298impl ResumableOr {
299 pub fn new(env: &Env, args: &ArcSlice<Arc<dyn Eval>>) -> Self {
300 Self {
301 env: env.clone(),
302 args: args.clone(),
303 }
304 }
305}
306
307#[async_trait]
308impl Resumable for ResumableOr {
309 async fn resume(
310 &self,
311 args: Vec<Gc<Value>>,
312 cont: &Option<Arc<Continuation>>,
313 ) -> Result<Vec<Gc<Value>>, RuntimeError> {
314 let Some(last) = self.args.last() else {
317 return Ok(args);
318 };
319 let arg = args.require_one()?;
320 if arg.read().await.is_true() {
321 return Ok(vec![Gc::new(Value::Boolean(true))]);
322 }
323 for (arg, tail) in self.args.skip_last() {
324 let cont = Arc::new(Continuation::new(
325 Arc::new(ResumableAnd::new(&self.env, &tail)),
326 cont,
327 ));
328 if arg
329 .eval(&self.env, &Some(cont))
330 .await?
331 .require_one()?
332 .read()
333 .await
334 .is_true()
335 {
336 return Ok(vec![Gc::new(Value::Boolean(true))]);
337 }
338 }
339 last.eval(&self.env, cont).await
340 }
341}
342
343#[derive(Trace)]
344pub struct ResumableLet {
345 scope: Gc<LexicalContour>,
346 curr: Identifier,
347 remaining_bindings: ArcSlice<(Identifier, Arc<dyn Eval>)>,
348 body: ast::Body,
349}
350
351impl ResumableLet {
352 pub fn new(
353 scope: &Gc<LexicalContour>,
354 curr: &Identifier,
355 remaining_bindings: ArcSlice<(Identifier, Arc<dyn Eval>)>,
356 body: &ast::Body,
357 ) -> Self {
358 Self {
359 scope: scope.clone(),
360 curr: curr.clone(),
361 remaining_bindings,
362 body: body.clone(),
363 }
364 }
365}
366
367#[async_trait]
368impl Resumable for ResumableLet {
369 async fn resume(
370 &self,
371 args: Vec<Gc<Value>>,
372 cont: &Option<Arc<Continuation>>,
373 ) -> Result<Vec<Gc<Value>>, RuntimeError> {
374 let arg = args.require_one()?;
375 let up = {
376 let mut scope = self.scope.write().await;
377 scope.def_var(&self.curr, arg);
378 scope.up.clone()
379 };
380 for ((ident, expr), remaining) in self.remaining_bindings.iter() {
381 let cont = Arc::new(Continuation::new(
382 Arc::new(ResumableLet::new(&self.scope, ident, remaining, &self.body)),
383 cont,
384 ));
385 let val = expr.eval(&up, &Some(cont)).await?.require_one()?;
386 self.scope.write().await.def_var(ident, val);
387 }
388 self.body.eval(&Env::from(self.scope.clone()), cont).await
389 }
390}
391
392#[derive(Trace)]
393pub struct ResumableIf {
394 env: Env,
395 success: Arc<dyn Eval>,
396 failure: Option<Arc<dyn Eval>>,
397}
398
399impl ResumableIf {
400 pub fn new(env: &Env, success: &Arc<dyn Eval>, failure: &Option<Arc<dyn Eval>>) -> Self {
401 Self {
402 env: env.clone(),
403 success: success.clone(),
404 failure: failure.clone(),
405 }
406 }
407}
408
409#[async_trait]
410impl Resumable for ResumableIf {
411 async fn resume(
412 &self,
413 args: Vec<Gc<Value>>,
414 cont: &Option<Arc<Continuation>>,
415 ) -> Result<Vec<Gc<Value>>, RuntimeError> {
416 let arg = args.require_one()?;
417 if arg.read().await.is_true() {
418 self.success.eval(&self.env, cont).await
419 } else if let Some(ref failure) = self.failure {
420 failure.eval(&self.env, cont).await
421 } else {
422 Ok(vec![Gc::new(Value::Null)])
423 }
424 }
425}
426
427#[derive(Trace)]
428pub struct ResumableDefineVar {
429 env: Env,
430 name: Identifier,
431}
432
433impl ResumableDefineVar {
434 pub fn new(env: &Env, name: &Identifier) -> Self {
435 Self {
436 env: env.clone(),
437 name: name.clone(),
438 }
439 }
440}
441
442#[async_trait]
443impl Resumable for ResumableDefineVar {
444 async fn resume(
445 &self,
446 args: Vec<Gc<Value>>,
447 _cont: &Option<Arc<Continuation>>,
448 ) -> Result<Vec<Gc<Value>>, RuntimeError> {
449 let arg = args.require_one()?;
450 self.env.def_var(&self.name, arg).await;
451 Ok(vec![Gc::new(Value::Null)])
452 }
453}
454
455#[derive(Trace)]
456pub struct ResumableCall {
457 env: Env,
458 collected: Vec<Gc<Value>>,
461 remaining: ArcSlice<Arc<dyn Eval>>,
462 proc_name: String,
463 location: Span,
464}
465
466impl ResumableCall {
467 pub fn new(
468 proc_name: &str,
469 location: &Span,
470 env: &Env,
471 collected: &[Gc<Value>],
472 remaining: ArcSlice<Arc<dyn Eval>>,
473 ) -> Self {
474 Self {
475 env: env.clone(),
476 collected: collected.to_owned(),
477 remaining,
478 proc_name: proc_name.to_string(),
479 location: location.clone(),
480 }
481 }
482}
483
484#[async_trait]
485impl Resumable for ResumableCall {
486 async fn resume(
487 &self,
488 args: Vec<Gc<Value>>,
489 cont: &Option<Arc<Continuation>>,
490 ) -> Result<Vec<Gc<Value>>, RuntimeError> {
491 let arg = args.require_one()?;
492 let mut collected = self.collected.clone();
493 collected.push(arg);
494 for (arg, remaining) in self.remaining.iter() {
495 let cont = Arc::new(Continuation::new(
496 Arc::new(ResumableCall::new(
497 &self.proc_name,
498 &self.location,
499 &self.env,
500 &collected,
501 remaining,
502 )),
503 cont,
504 ));
505 let arg = arg
506 .eval(&self.env, &Some(cont))
507 .await
508 .map_err(|mut err| {
509 err.push_frame(self.proc_name.clone(), self.location.clone());
510 err
511 })?
512 .require_one()?;
513 collected.push(arg);
514 }
515 PreparedCall::prepare(&self.proc_name, &self.location, collected)
516 .eval(cont)
517 .await
518 }
519}
520
521#[derive(Trace)]
522pub struct ResumableApply {
523 env: Env,
524 collected: Vec<Gc<Value>>,
525 remaining: ArcSlice<Arc<dyn Eval>>,
526 rest_args: Option<Arc<dyn Eval>>,
527 proc_name: String,
528 location: Span,
529}
530
531impl ResumableApply {
532 pub fn new(
533 proc_name: &str,
534 location: &Span,
535 env: &Env,
536 collected: &[Gc<Value>],
537 remaining: ArcSlice<Arc<dyn Eval>>,
538 rest_args: Option<Arc<dyn Eval>>,
539 ) -> Self {
540 Self {
541 proc_name: proc_name.to_string(),
542 location: location.clone(),
543 env: env.clone(),
544 collected: collected.to_owned(),
545 remaining,
546 rest_args,
547 }
548 }
549}
550
551#[async_trait]
552impl Resumable for ResumableApply {
553 async fn resume(
554 &self,
555 args: Vec<Gc<Value>>,
556 cont: &Option<Arc<Continuation>>,
557 ) -> Result<Vec<Gc<Value>>, RuntimeError> {
558 let arg = args.require_one()?;
559 let mut collected = self.collected.clone();
560 if let Some(ref rest_args) = self.rest_args {
561 collected.push(arg);
562
563 for (arg, remaining) in self.remaining.iter() {
564 let cont = Arc::new(Continuation::new(
565 Arc::new(ResumableApply::new(
566 &self.proc_name,
567 &self.location,
568 &self.env,
569 &collected,
570 remaining,
571 Some(rest_args.clone()),
572 )),
573 cont,
574 ));
575 let arg = arg.eval(&self.env, &Some(cont)).await?.require_one()?;
576 collected.push(arg);
577 }
578
579 let cont = Arc::new(Continuation::new(
580 Arc::new(ResumableApply::new(
581 &self.proc_name,
582 &self.location,
583 &self.env,
584 &collected,
585 ArcSlice::empty(),
586 None,
587 )),
588 cont,
589 ));
590 let rest_args = rest_args
591 .eval(&self.env, &Some(cont))
592 .await?
593 .require_one()?;
594 list_to_vec(&rest_args, &mut collected).await;
596 } else {
597 list_to_vec(&arg, &mut collected).await;
599 }
600
601 PreparedCall::prepare(&self.proc_name, &self.location, collected)
602 .eval(cont)
603 .await
604 }
605}
606
607#[builtin("call/cc")]
608pub async fn call_cc(
609 cont: &Option<Arc<Continuation>>,
610 proc: &Gc<Value>,
611) -> Result<Vec<Gc<Value>>, RuntimeError> {
612 let callable = {
613 let proc = proc.read().await;
614 proc.as_callable()
615 .ok_or_else(|| RuntimeError::invalid_type("procedure", proc.type_name()))?
616 };
617 callable
618 .call(vec![Gc::new(Value::Continuation(cont.clone()))], cont)
619 .await?
620 .eval(cont)
621 .await
622}
623
624#[derive(Trace)]
625pub struct CallWithValues {
626 min_args: usize,
627 max_args: Option<usize>,
628 consumer: Gc<Value>,
629}
630
631#[async_trait]
632impl Resumable for CallWithValues {
633 fn min_args(&self) -> usize {
634 self.min_args
635 }
636
637 fn max_args(&self) -> Option<usize> {
638 self.max_args
639 }
640
641 async fn resume(
642 &self,
643 args: Vec<Gc<Value>>,
644 cont: &Option<Arc<Continuation>>,
645 ) -> Result<Vec<Gc<Value>>, RuntimeError> {
646 let callable = {
647 let proc = self.consumer.read().await;
648 proc.as_callable().unwrap()
649 };
650 callable.call(args, cont).await?.eval(cont).await
651 }
652}
653
654#[builtin("call-with-values")]
655pub async fn call_with_values(
656 cont: &Option<Arc<Continuation>>,
657 producer: &Gc<Value>,
658 consumer: &Gc<Value>,
659) -> Result<Vec<Gc<Value>>, RuntimeError> {
660 let producer_callable = {
661 let proc = producer.read().await;
662 proc.as_callable()
663 .ok_or_else(|| RuntimeError::invalid_type("procedure", proc.type_name()))?
664 };
665 let consumer_callable = {
666 let proc = consumer.read().await;
667 proc.as_callable()
668 .ok_or_else(|| RuntimeError::invalid_type("procedure", proc.type_name()))?
669 };
670 let producer_cont = Arc::new(Continuation::new(
671 Arc::new(CallWithValues {
672 min_args: consumer_callable.min_args(),
673 max_args: consumer_callable.max_args(),
674 consumer: consumer.clone(),
675 }),
676 cont,
677 ));
678
679 let producer_result = producer_callable
680 .call(Vec::new(), &Some(producer_cont.clone()))
681 .await?
682 .eval(&Some(producer_cont))
683 .await?;
684
685 consumer_callable
687 .call(producer_result, cont)
688 .await?
689 .eval(cont)
690 .await
691}