1use crate::{
95 env::Local,
96 exceptions::{Exception, raise},
97 gc::{Gc, GcInner, Trace},
98 lists::{self, Pair, list_to_vec},
99 ports::{BufferMode, Port, Transcoder},
100 records::{Record, RecordTypeDescriptor, SchemeCompatible, rtd},
101 registry::BridgeFnDebugInfo,
102 runtime::{Runtime, RuntimeInner},
103 symbols::Symbol,
104 syntax::Span,
105 value::Value,
106 vectors::Vector,
107};
108use parking_lot::RwLock;
109use scheme_rs_macros::{cps_bridge, maybe_async, maybe_await};
110use std::{
111 any::Any,
112 collections::HashMap,
113 fmt,
114 ops::DerefMut,
115 sync::{
116 Arc, OnceLock,
117 atomic::{AtomicUsize, Ordering},
118 },
119};
120
121pub(crate) type ContinuationPtr = unsafe extern "C" fn(
123 runtime: *mut GcInner<RwLock<RuntimeInner>>,
124 env: *const Value,
125 args: *const Value,
126 barrier: *mut ContBarrier<'_>,
127) -> *mut Application;
128
129pub(crate) type UserPtr = unsafe extern "C" fn(
131 runtime: *mut GcInner<RwLock<RuntimeInner>>,
132 env: *const Value,
133 args: *const Value,
134 barrier: *mut ContBarrier<'_>,
135 k: Value,
136) -> *mut Application;
137
138pub type BridgePtr = fn(
140 runtime: &Runtime,
141 env: &[Value],
142 args: &[Value],
143 rest_args: &[Value],
144 barrier: &mut ContBarrier<'_>,
145 k: Value,
146) -> Application;
147
148#[cfg(feature = "async")]
150pub type AsyncBridgePtr = for<'a> fn(
151 runtime: &'a Runtime,
152 env: &'a [Value],
153 args: &'a [Value],
154 rest_args: &'a [Value],
155 barrier: &'a mut ContBarrier<'_>,
156 k: Value,
157) -> futures::future::BoxFuture<'a, Application>;
158
159#[derive(Copy, Clone, Debug)]
160pub(crate) enum FuncPtr {
161 Bridge(BridgePtr),
163 #[cfg(feature = "async")]
164 AsyncBridge(AsyncBridgePtr),
166 User(UserPtr),
168 Continuation(ContinuationPtr),
170 PromptBarrier {
172 barrier_id: usize,
173 k: ContinuationPtr,
174 },
175}
176
177impl From<BridgePtr> for FuncPtr {
178 fn from(ptr: BridgePtr) -> Self {
179 Self::Bridge(ptr)
180 }
181}
182
183#[cfg(feature = "async")]
184impl From<AsyncBridgePtr> for FuncPtr {
185 fn from(ptr: AsyncBridgePtr) -> Self {
186 Self::AsyncBridge(ptr)
187 }
188}
189
190impl From<UserPtr> for FuncPtr {
191 fn from(ptr: UserPtr) -> Self {
192 Self::User(ptr)
193 }
194}
195
196enum JitFuncPtr {
197 Continuation(ContinuationPtr),
198 User(UserPtr),
199}
200
201#[derive(Clone, Trace)]
202#[repr(align(16))]
203pub(crate) struct ProcedureInner {
204 pub(crate) runtime: Runtime,
209 pub(crate) env: Vec<Value>,
211 #[trace(skip)]
213 pub(crate) func: FuncPtr,
214 pub(crate) num_required_args: usize,
216 pub(crate) variadic: bool,
218 pub(crate) is_variable_transformer: bool,
220 pub(crate) debug_info: Option<Arc<ProcDebugInfo>>,
223}
224
225impl ProcedureInner {
226 pub(crate) fn new(
227 runtime: Runtime,
228 env: Vec<Value>,
229 func: FuncPtr,
230 num_required_args: usize,
231 variadic: bool,
232 debug_info: Option<Arc<ProcDebugInfo>>,
233 ) -> Self {
234 Self {
235 runtime,
236 env,
237 func,
238 num_required_args,
239 variadic,
240 is_variable_transformer: false,
241 debug_info,
242 }
243 }
244
245 pub fn is_continuation(&self) -> bool {
246 matches!(
247 self.func,
248 FuncPtr::Continuation(_) | FuncPtr::PromptBarrier { .. }
249 )
250 }
251
252 pub(crate) fn prepare_args(
253 &self,
254 mut args: Vec<Value>,
255 barrier: &mut ContBarrier,
256 ) -> Result<(Vec<Value>, Option<Value>), Application> {
257 let cont = (!self.is_continuation()).then(|| args.pop().unwrap());
259
260 if args.len() < self.num_required_args {
262 return Err(raise(
263 self.runtime.clone(),
264 Exception::wrong_num_of_args(self.num_required_args, args.len()).into(),
265 barrier,
266 ));
267 }
268
269 if !self.variadic && args.len() > self.num_required_args {
270 return Err(raise(
271 self.runtime.clone(),
272 Exception::wrong_num_of_args(self.num_required_args, args.len()).into(),
273 barrier,
274 ));
275 }
276
277 Ok((args, cont))
278 }
279
280 #[cfg(feature = "async")]
281 async fn apply_async_bridge(
282 &self,
283 func: AsyncBridgePtr,
284 args: &[Value],
285 barrier: &mut ContBarrier<'_>,
286 k: Value,
287 ) -> Application {
288 let (args, rest_args) = if self.variadic {
289 args.split_at(self.num_required_args)
290 } else {
291 (args, &[] as &[Value])
292 };
293
294 (func)(&self.runtime, &self.env, args, rest_args, barrier, k).await
295 }
296
297 fn apply_sync_bridge(
298 &self,
299 func: BridgePtr,
300 args: &[Value],
301 barrier: &mut ContBarrier,
302 k: Value,
303 ) -> Application {
304 let (args, rest_args) = if self.variadic {
305 args.split_at(self.num_required_args)
306 } else {
307 (args, &[] as &[Value])
308 };
309
310 (func)(&self.runtime, &self.env, args, rest_args, barrier, k)
311 }
312
313 fn apply_jit(
314 &self,
315 func: JitFuncPtr,
316 mut args: Vec<Value>,
317 barrier: &mut ContBarrier,
318 k: Option<Value>,
319 ) -> Application {
320 if self.variadic {
321 let mut rest_args = Value::null();
322 let extra_args = args.len() - self.num_required_args;
323 for _ in 0..extra_args {
324 rest_args = Value::from(Pair::immutable(args.pop().unwrap(), rest_args));
325 }
326 args.push(rest_args);
327 }
328
329 let app = match func {
330 JitFuncPtr::Continuation(sync_fn) => unsafe {
331 (sync_fn)(
332 Gc::as_ptr(&self.runtime.0),
333 self.env.as_ptr(),
334 args.as_ptr(),
335 barrier as *mut ContBarrier<'_>,
336 )
337 },
338 JitFuncPtr::User(sync_fn) => unsafe {
339 (sync_fn)(
340 Gc::as_ptr(&self.runtime.0),
341 self.env.as_ptr(),
342 args.as_ptr(),
343 barrier as *mut ContBarrier<'_>,
344 Value::from_raw(Value::as_raw(k.as_ref().unwrap())),
345 )
346 },
347 };
348
349 unsafe { *Box::from_raw(app) }
350 }
351
352 #[maybe_async]
354 pub fn apply(&self, args: Vec<Value>, barrier: &mut ContBarrier<'_>) -> Application {
355 if let FuncPtr::PromptBarrier { barrier_id: id, .. } = self.func {
356 barrier.pop_marks();
357 match barrier.pop_dyn_stack() {
358 Some(DynStackElem::PromptBarrier(PromptBarrier {
359 barrier_id,
360 replaced_k,
361 })) if barrier_id == id => {
362 let (args, _) = match replaced_k.0.prepare_args(args, barrier) {
363 Ok(args) => args,
364 Err(raised) => return raised,
365 };
366 return Application::new(replaced_k, args);
367 }
368 Some(other) => barrier.push_dyn_stack(other),
369 _ => (),
370 }
371 }
372
373 let (args, k) = match self.prepare_args(args, barrier) {
374 Ok(args) => args,
375 Err(raised) => return raised,
376 };
377
378 match self.func {
379 FuncPtr::Bridge(sbridge) => self.apply_sync_bridge(sbridge, &args, barrier, k.unwrap()),
380 #[cfg(feature = "async")]
381 FuncPtr::AsyncBridge(abridge) => {
382 self.apply_async_bridge(abridge, &args, barrier, k.unwrap())
383 .await
384 }
385 FuncPtr::User(user) => self.apply_jit(JitFuncPtr::User(user), args, barrier, k),
386 FuncPtr::Continuation(k) => {
387 barrier.pop_marks();
388 self.apply_jit(JitFuncPtr::Continuation(k), args, barrier, None)
389 }
390 FuncPtr::PromptBarrier { k, .. } => {
391 self.apply_jit(JitFuncPtr::Continuation(k), args, barrier, None)
392 }
393 }
394 }
395
396 #[cfg(feature = "async")]
397 pub fn apply_sync(&self, args: Vec<Value>, barrier: &mut ContBarrier) -> Application {
399 if let FuncPtr::PromptBarrier { barrier_id: id, .. } = self.func {
400 barrier.pop_marks();
401 match barrier.pop_dyn_stack() {
402 Some(DynStackElem::PromptBarrier(PromptBarrier {
403 barrier_id,
404 replaced_k,
405 })) if barrier_id == id => {
406 let (args, _) = match replaced_k.0.prepare_args(args, barrier) {
407 Ok(args) => args,
408 Err(raised) => return raised,
409 };
410 return Application::new(replaced_k, args);
411 }
412 Some(other) => barrier.push_dyn_stack(other),
413 _ => (),
414 }
415 }
416
417 let (args, k) = match self.prepare_args(args, barrier) {
418 Ok(args) => args,
419 Err(raised) => return raised,
420 };
421
422 match self.func {
423 FuncPtr::Bridge(sbridge) => self.apply_sync_bridge(sbridge, &args, barrier, k.unwrap()),
424 FuncPtr::AsyncBridge(_) => raise(
425 self.runtime.clone(),
426 Exception::error("attempt to apply async function in a sync-only context").into(),
427 barrier,
428 ),
429 FuncPtr::User(user) => self.apply_jit(JitFuncPtr::User(user), args, barrier, k),
430 FuncPtr::Continuation(k) => {
431 barrier.pop_marks();
432 self.apply_jit(JitFuncPtr::Continuation(k), args, barrier, None)
433 }
434 FuncPtr::PromptBarrier { k, .. } => {
435 self.apply_jit(JitFuncPtr::Continuation(k), args, barrier, None)
436 }
437 }
438 }
439}
440
441impl fmt::Debug for ProcedureInner {
442 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
443 if self.is_continuation() {
444 return write!(f, "continuation");
445 }
446
447 let Some(ref debug_info) = self.debug_info else {
448 write!(f, "(<lambda>")?;
449 for i in 0..self.num_required_args {
450 write!(f, " ${i}")?;
451 }
452 if self.variadic {
453 write!(f, " . ${}", self.num_required_args)?;
454 }
455 return write!(f, ")");
456 };
457
458 write!(f, "({}", debug_info.name)?;
459
460 if let Some((last, args)) = debug_info.args.split_last() {
461 for arg in args {
462 write!(f, " {arg}")?;
463 }
464 if self.variadic {
465 write!(f, " .")?;
466 }
467 write!(f, " {last}")?;
468 }
469
470 write!(f, ") at {}", debug_info.location)
471 }
472}
473
474#[derive(Clone, Trace)]
479pub struct Procedure(pub(crate) Gc<ProcedureInner>);
480
481impl Procedure {
482 #[allow(private_bounds)]
483 pub fn new(
486 runtime: Runtime,
487 env: Vec<Value>,
488 func: impl Into<FuncPtr>,
489 num_required_args: usize,
490 variadic: bool,
491 ) -> Self {
492 Self::with_debug_info(runtime, env, func.into(), num_required_args, variadic, None)
493 }
494
495 pub(crate) fn with_debug_info(
496 runtime: Runtime,
497 env: Vec<Value>,
498 func: FuncPtr,
499 num_required_args: usize,
500 variadic: bool,
501 debug_info: Option<Arc<ProcDebugInfo>>,
502 ) -> Self {
503 Self(Gc::new(ProcedureInner {
504 runtime,
505 env,
506 func,
507 num_required_args,
508 variadic,
509 is_variable_transformer: false,
510 debug_info,
511 }))
512 }
513
514 pub fn get_runtime(&self) -> Runtime {
516 self.0.runtime.clone()
517 }
518
519 pub fn get_formals(&self) -> (usize, bool) {
522 (self.0.num_required_args, self.0.variadic)
523 }
524
525 pub fn get_debug_info(&self) -> Option<Arc<ProcDebugInfo>> {
527 self.0.debug_info.clone()
528 }
529
530 pub(crate) unsafe fn collect_args(&self, args: *const Value) -> Vec<Value> {
533 let (num_required_args, variadic) = self.get_formals();
535
536 unsafe {
537 let mut collected_args: Vec<_> = (0..num_required_args)
538 .map(|i| args.add(i).as_ref().unwrap().clone())
539 .collect();
540
541 if variadic {
542 let rest_args = args.add(num_required_args).as_ref().unwrap().clone();
543 let mut vec = Vec::new();
544 lists::list_to_vec(&rest_args, &mut vec);
545 collected_args.extend(vec);
546 }
547
548 collected_args
549 }
550 }
551
552 pub fn is_variable_transformer(&self) -> bool {
553 self.0.is_variable_transformer
554 }
555
556 pub fn is_continuation(&self) -> bool {
558 self.0.is_continuation()
559 }
560
561 #[maybe_async]
563 pub fn call(
564 &self,
565 args: &[Value],
566 barrier: &mut ContBarrier<'_>,
567 ) -> Result<Vec<Value>, Exception> {
568 let mut args = args.to_vec();
569
570 args.push(halt_continuation(self.get_runtime()));
571
572 maybe_await!(Application::new(self.clone(), args).eval(barrier))
573 }
574
575 #[cfg(feature = "async")]
576 pub fn call_sync(
577 &self,
578 args: &[Value],
579 barrier: &mut ContBarrier<'_>,
580 ) -> Result<Vec<Value>, Exception> {
581 let mut args = args.to_vec();
582
583 args.push(halt_continuation(self.get_runtime()));
584
585 Application::new(self.clone(), args).eval_sync(barrier)
586 }
587}
588
589static HALT_CONTINUATION: OnceLock<Value> = OnceLock::new();
590
591pub fn halt_continuation(runtime: Runtime) -> Value {
593 unsafe extern "C" fn halt(
594 _runtime: *mut GcInner<RwLock<RuntimeInner>>,
595 _env: *const Value,
596 args: *const Value,
597 _barrier: *mut ContBarrier,
598 ) -> *mut Application {
599 unsafe { crate::runtime::halt(Value::into_raw(args.read())) }
600 }
601
602 HALT_CONTINUATION
603 .get_or_init(move || {
604 Value::from(Procedure(Gc::new(ProcedureInner::new(
605 runtime,
606 Vec::new(),
607 FuncPtr::Continuation(halt),
608 0,
609 true,
610 None,
611 ))))
612 })
613 .clone()
614}
615
616impl fmt::Debug for Procedure {
617 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
618 self.0.fmt(f)
619 }
620}
621
622impl PartialEq for Procedure {
623 fn eq(&self, rhs: &Procedure) -> bool {
624 Gc::ptr_eq(&self.0, &rhs.0)
625 }
626}
627
628pub(crate) enum OpType {
629 Proc(Procedure),
630 HaltOk,
631 HaltErr,
632}
633
634pub struct Application {
636 op: OpType,
638 args: Vec<Value>,
640}
641
642impl Application {
643 pub fn new(op: Procedure, args: Vec<Value>) -> Self {
644 Self {
645 op: OpType::Proc(op),
646 args,
647 }
648 }
649
650 pub fn halt_ok(args: Vec<Value>) -> Self {
651 Self {
652 op: OpType::HaltOk,
653 args,
654 }
655 }
656
657 pub fn halt_err(arg: Value) -> Self {
658 Self {
659 op: OpType::HaltErr,
660 args: vec![arg],
661 }
662 }
663
664 #[maybe_async]
667 pub fn eval(mut self, barrier: &mut ContBarrier<'_>) -> Result<Vec<Value>, Exception> {
668 loop {
669 let op = match self.op {
670 OpType::Proc(proc) => proc,
671 OpType::HaltOk => return Ok(self.args),
672 OpType::HaltErr => {
673 return Err(Exception(self.args.pop().unwrap()));
674 }
675 };
676 self = maybe_await!(op.0.apply(self.args, barrier));
677 }
678 }
679
680 #[cfg(feature = "async")]
681 pub fn eval_sync(mut self, barrier: &mut ContBarrier) -> Result<Vec<Value>, Exception> {
683 loop {
684 let op = match self.op {
685 OpType::Proc(proc) => proc,
686 OpType::HaltOk => return Ok(self.args),
687 OpType::HaltErr => {
688 return Err(Exception(self.args.pop().unwrap()));
689 }
690 };
691 self = op.0.apply_sync(self.args, barrier);
692 }
693 }
694}
695
696#[derive(Debug)]
699pub struct ProcDebugInfo {
700 pub name: Symbol,
702 pub args: Vec<Local>,
704 pub location: Span,
706}
707
708impl ProcDebugInfo {
709 pub fn new(name: Option<Symbol>, args: Vec<Local>, location: Span) -> Self {
710 Self {
711 name: name.unwrap_or_else(|| Symbol::intern("<lambda>")),
712 args,
713 location,
714 }
715 }
716
717 pub fn from_bridge_fn(name: &'static str, debug_info: BridgeFnDebugInfo) -> Self {
718 Self {
719 name: Symbol::intern(name),
720 args: debug_info
721 .args
722 .iter()
723 .map(|arg| Local::gensym_with_name(Symbol::intern(arg)))
724 .collect(),
725 location: Span {
726 line: debug_info.line,
727 column: debug_info.column as usize,
728 offset: debug_info.offset,
729 file: std::sync::Arc::from(debug_info.file.to_string()),
730 },
731 }
732 }
733}
734
735#[cps_bridge(def = "apply arg1 . args", lib = "(rnrs base builtins (6))")]
736pub fn apply(
737 _runtime: &Runtime,
738 _env: &[Value],
739 args: &[Value],
740 rest_args: &[Value],
741 _barrier: &mut ContBarrier,
742 k: Value,
743) -> Result<Application, Exception> {
744 if rest_args.is_empty() {
745 return Err(Exception::wrong_num_of_args(2, args.len()));
746 }
747 let op: Procedure = args[0].clone().try_into()?;
748 let (last, args) = rest_args.split_last().unwrap();
749 let mut args = args.to_vec();
750 list_to_vec(last, &mut args);
751 args.push(k);
752 Ok(Application::new(op.clone(), args))
753}
754
755#[cfg(feature = "async")]
761type Param<'a> = &'a mut (dyn Any + Send + Sync);
762
763#[cfg(not(feature = "async"))]
764type Param<'a> = &'a mut dyn Any;
765
766pub struct ContBarrier<'a> {
772 id: usize,
774 dyn_stack: Vec<DynStackElem>,
776 cont_marks: Vec<HashMap<Symbol, Value>>,
778 params: HashMap<Symbol, Param<'a>>,
780}
781
782impl<'a> ContBarrier<'a> {
783 pub fn new() -> Self {
784 static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
785
786 Self {
787 id: NEXT_ID.fetch_add(1, Ordering::Relaxed),
788 dyn_stack: Vec::new(),
789 cont_marks: vec![HashMap::new()],
794 params: HashMap::new(),
795 }
796 }
797
798 pub(crate) fn new_k(
802 &mut self,
803 runtime: Runtime,
804 env: Vec<Value>,
805 k: ContinuationPtr,
806 num_required_args: usize,
807 variadic: bool,
808 ) -> Procedure {
809 self.push_marks();
810 Procedure::with_debug_info(
811 runtime,
812 env,
813 FuncPtr::Continuation(k),
814 num_required_args,
815 variadic,
816 None,
817 )
818 }
819
820 pub fn save(&self) -> SavedDynamicState {
821 SavedDynamicState {
822 id: self.id,
823 dyn_stack: self.dyn_stack.clone(),
824 cont_marks: self.cont_marks.clone(),
825 }
826 }
827
828 pub fn add_param(
829 &mut self,
830 key: impl Into<Symbol>,
831 #[cfg(feature = "async")] val: &'a mut (impl Any + Send + Sync),
832 #[cfg(not(feature = "async"))] val: &'a mut impl Any,
833 ) {
834 self.params.insert(key.into(), val);
835 }
836
837 pub fn get_param<'b>(&'b mut self, key: impl Into<Symbol>) -> Option<Param<'b>> {
838 self.params.get_mut(&key.into()).map(|v| v.deref_mut())
839 }
840
841 pub fn get_params_disjoint<'b, const N: usize>(
842 &'b mut self,
843 keys: [&Symbol; N],
844 ) -> [Option<Param<'b>>; N] {
845 self.params
846 .get_disjoint_mut(keys)
847 .map(|v| v.map(|v| v.deref_mut()))
848 }
849
850 pub fn iter_params<'b>(&'b mut self) -> impl Iterator<Item = (Symbol, Param<'b>)> {
851 self.params.iter_mut().map(|(k, v)| (*k, v.deref_mut()))
852 }
853
854 pub fn child_barrier<'b, 'c, const N: usize>(
857 &'b mut self,
858 params: [impl Into<Symbol>; N],
859 ) -> ([Option<Param<'b>>; N], ContBarrier<'c>)
860 where
861 'b: 'c,
862 {
863 let param_to_index = params
864 .into_iter()
865 .enumerate()
866 .map(|(idx, param)| (param.into(), idx))
867 .collect::<HashMap<_, _>>();
868 let mut params = [const { None }; N];
869 let mut child_barrier = ContBarrier::from(self.save());
870 for (key, value) in self.params.iter_mut() {
871 let value = value.deref_mut();
872 if let Some(idx) = param_to_index.get(key) {
873 params[*idx] = Some(value);
874 } else {
875 child_barrier.params.insert(*key, value);
876 }
877 }
878 (params, child_barrier)
879 }
880
881 pub(crate) fn push_marks(&mut self) {
882 self.cont_marks.push(HashMap::new());
883 }
884
885 pub(crate) fn pop_marks(&mut self) {
886 self.cont_marks.pop();
887 }
888
889 pub(crate) fn current_marks(&self, tag: Symbol) -> Vec<Value> {
890 self.cont_marks
891 .iter()
892 .rev()
893 .flat_map(|marks| marks.get(&tag).cloned())
894 .collect()
895 }
896
897 pub(crate) fn set_continuation_mark(&mut self, tag: Symbol, val: Value) {
898 self.cont_marks.last_mut().unwrap().insert(tag, val);
899 }
900
901 pub fn current_exception_handler(&self) -> Option<Procedure> {
906 self.dyn_stack.iter().rev().find_map(|elem| match elem {
907 DynStackElem::ExceptionHandler(proc) => Some(proc.clone()),
908 _ => None,
909 })
910 }
911
912 pub fn current_input_port(&self) -> Port {
913 self.dyn_stack
914 .iter()
915 .rev()
916 .find_map(|elem| match elem {
917 DynStackElem::CurrentInputPort(port) => Some(port.clone()),
918 _ => None,
919 })
920 .unwrap_or_else(|| {
921 Port::new(
922 "<stdin>",
923 #[cfg(not(feature = "async"))]
924 std::io::stdin(),
925 #[cfg(feature = "tokio")]
926 tokio::io::stdin(),
927 BufferMode::Line,
928 Some(Transcoder::native()),
929 )
930 })
931 }
932
933 pub fn current_output_port(&self) -> Port {
934 self.dyn_stack
935 .iter()
936 .rev()
937 .find_map(|elem| match elem {
938 DynStackElem::CurrentOutputPort(port) => Some(port.clone()),
939 _ => None,
940 })
941 .unwrap_or_else(|| {
942 Port::new(
943 "<stdout>",
944 #[cfg(not(feature = "async"))]
945 std::io::stdout(),
946 #[cfg(feature = "tokio")]
947 tokio::io::stdout(),
948 BufferMode::None,
951 Some(Transcoder::native()),
952 )
953 })
954 }
955
956 pub(crate) fn push_dyn_stack(&mut self, elem: DynStackElem) {
957 self.dyn_stack.push(elem);
958 }
959
960 pub(crate) fn pop_dyn_stack(&mut self) -> Option<DynStackElem> {
961 self.dyn_stack.pop()
962 }
963
964 pub(crate) fn dyn_stack_last(&self) -> Option<&DynStackElem> {
965 self.dyn_stack.last()
966 }
967
968 pub(crate) fn dyn_stack_len(&self) -> usize {
969 self.dyn_stack.len()
970 }
971
972 pub(crate) fn dyn_stack_is_empty(&self) -> bool {
973 self.dyn_stack.is_empty()
974 }
975}
976
977impl Default for ContBarrier<'_> {
978 fn default() -> Self {
979 Self::new()
980 }
981}
982
983impl<'a, 'b, 'c> From<&'b mut ContBarrier<'a>> for ContBarrier<'c>
984where
985 'b: 'c,
986{
987 fn from(value: &'b mut ContBarrier<'a>) -> Self {
988 let mut new_barrier = ContBarrier::from(value.save());
989 for (key, value) in value.params.iter_mut() {
990 new_barrier.params.insert(*key, value.deref_mut());
991 }
992 new_barrier
993 }
994}
995
996#[derive(Clone, Debug, Trace)]
998pub struct SavedDynamicState {
999 id: usize,
1000 dyn_stack: Vec<DynStackElem>,
1001 cont_marks: Vec<HashMap<Symbol, Value>>,
1002}
1003
1004impl SavedDynamicState {
1005 pub(crate) fn dyn_stack_get(&self, idx: usize) -> Option<&DynStackElem> {
1006 self.dyn_stack.get(idx)
1007 }
1008
1009 pub(crate) fn dyn_stack_last(&self) -> Option<&DynStackElem> {
1010 self.dyn_stack.last()
1011 }
1012
1013 pub(crate) fn dyn_stack_len(&self) -> usize {
1014 self.dyn_stack.len()
1015 }
1016
1017 pub(crate) fn dyn_stack_is_empty(&self) -> bool {
1018 self.dyn_stack.is_empty()
1019 }
1020}
1021
1022impl From<SavedDynamicState> for ContBarrier<'_> {
1023 fn from(value: SavedDynamicState) -> Self {
1024 ContBarrier {
1025 dyn_stack: value.dyn_stack,
1026 cont_marks: value.cont_marks,
1027 ..Default::default()
1028 }
1029 }
1030}
1031
1032impl SchemeCompatible for SavedDynamicState {
1033 fn rtd() -> Arc<RecordTypeDescriptor> {
1034 rtd!(name: "$dynamic-state", sealed: true, opaque: true)
1035 }
1036}
1037
1038#[derive(Clone, Debug, PartialEq, Trace)]
1039pub(crate) enum DynStackElem {
1040 Prompt(Prompt),
1041 PromptBarrier(PromptBarrier),
1042 Winder(Winder),
1043 ExceptionHandler(Procedure),
1044 CurrentInputPort(Port),
1045 CurrentOutputPort(Port),
1046}
1047
1048pub(crate) unsafe extern "C" fn pop_dyn_stack(
1049 _runtime: *mut GcInner<RwLock<RuntimeInner>>,
1050 env: *const Value,
1051 args: *const Value,
1052 barrier: *mut ContBarrier,
1053) -> *mut Application {
1054 unsafe {
1055 let k: Procedure = env.as_ref().unwrap().clone().try_into().unwrap();
1057
1058 barrier.as_mut().unwrap_unchecked().pop_dyn_stack();
1059
1060 let args = k.collect_args(args);
1061 let app = Application::new(k, args);
1062
1063 Box::into_raw(Box::new(app))
1064 }
1065}
1066
1067#[cps_bridge(def = "print-trace", lib = "(rnrs base builtins (6))")]
1068pub fn print_trace(
1069 _runtime: &Runtime,
1070 _env: &[Value],
1071 _args: &[Value],
1072 _rest_args: &[Value],
1073 barrier: &mut ContBarrier,
1074 k: Value,
1075) -> Result<Application, Exception> {
1076 println!(
1077 "trace: {:#?}",
1078 barrier.current_marks(Symbol::intern("trace"))
1079 );
1080 Ok(Application::new(k.try_into()?, vec![]))
1081}
1082
1083#[cps_bridge(
1089 def = "call-with-current-continuation proc",
1090 lib = "(rnrs base builtins (6))"
1091)]
1092pub fn call_with_current_continuation(
1093 runtime: &Runtime,
1094 _env: &[Value],
1095 args: &[Value],
1096 _rest_args: &[Value],
1097 barrier: &mut ContBarrier,
1098 k: Value,
1099) -> Result<Application, Exception> {
1100 let [proc] = args else { unreachable!() };
1101 let proc: Procedure = proc.clone().try_into()?;
1102
1103 let (req_args, variadic) = {
1104 let k: Procedure = k.clone().try_into()?;
1105 k.get_formals()
1106 };
1107
1108 let barrier = Value::from(Record::from_rust_type(barrier.save()));
1109
1110 let escape_procedure = Procedure::new(
1111 runtime.clone(),
1112 vec![k.clone(), barrier],
1113 FuncPtr::Bridge(escape_procedure),
1114 req_args,
1115 variadic,
1116 );
1117
1118 let app = Application::new(proc, vec![Value::from(escape_procedure), k]);
1119
1120 Ok(app)
1121}
1122
1123#[cps_bridge]
1126fn escape_procedure(
1127 runtime: &Runtime,
1128 env: &[Value],
1129 args: &[Value],
1130 rest_args: &[Value],
1131 barrier: &mut ContBarrier,
1132 _k: Value,
1133) -> Result<Application, Exception> {
1134 let k = env[0].clone();
1136
1137 let saved_barrier_val = env[1].clone();
1139 let saved_barrier = saved_barrier_val
1140 .try_to_rust_type::<SavedDynamicState>()
1141 .unwrap();
1142 let saved_barrier_read = saved_barrier.as_ref();
1143
1144 if saved_barrier_read.id != barrier.id {
1145 return Err(Exception::error("attempt to cross continuation barrier"));
1146 }
1147
1148 barrier.cont_marks = saved_barrier_read.cont_marks.clone();
1149
1150 let k: Procedure = k.try_into().unwrap();
1152
1153 let args = args.iter().chain(rest_args).cloned().collect::<Vec<_>>();
1154
1155 if barrier.dyn_stack_len() == saved_barrier_read.dyn_stack_len()
1157 && barrier.dyn_stack_last() == saved_barrier_read.dyn_stack_last()
1158 {
1159 Ok(Application::new(k, args))
1160 } else {
1161 let args = Value::from(args);
1162 let k = barrier.new_k(
1163 runtime.clone(),
1164 vec![Value::from(k), args, saved_barrier_val],
1165 unwind,
1166 0,
1167 false,
1168 );
1169 Ok(Application::new(k, Vec::new()))
1170 }
1171}
1172
1173unsafe extern "C" fn unwind(
1174 runtime: *mut GcInner<RwLock<RuntimeInner>>,
1175 env: *const Value,
1176 _args: *const Value,
1177 barrier: *mut ContBarrier,
1178) -> *mut Application {
1179 unsafe {
1180 let k = env.as_ref().unwrap().clone();
1182
1183 let args = env.add(1).as_ref().unwrap().clone();
1185
1186 let dest_stack_val = env.add(2).as_ref().unwrap().clone();
1188 let dest_stack = dest_stack_val
1189 .clone()
1190 .try_to_rust_type::<SavedDynamicState>()
1191 .unwrap();
1192 let dest_stack_read = dest_stack.as_ref();
1193
1194 let barrier = barrier.as_mut().unwrap_unchecked();
1195
1196 while !barrier.dyn_stack_is_empty()
1197 && (barrier.dyn_stack_len() > dest_stack_read.dyn_stack_len()
1198 || barrier.dyn_stack_last()
1199 != dest_stack_read.dyn_stack_get(barrier.dyn_stack_len() - 1))
1200 {
1201 match barrier.pop_dyn_stack() {
1202 None => {
1203 break;
1204 }
1205 Some(DynStackElem::Winder(winder)) => {
1206 let app = Application::new(
1208 winder.out_thunk,
1209 vec![Value::from(barrier.new_k(
1210 Runtime::from_raw_inc_rc(runtime),
1211 vec![k, args, dest_stack_val],
1212 unwind,
1213 0,
1214 false,
1215 ))],
1216 );
1217 return Box::into_raw(Box::new(app));
1218 }
1219 _ => (),
1220 };
1221 }
1222
1223 let app = Application::new(
1225 barrier.new_k(
1226 Runtime::from_raw_inc_rc(runtime),
1227 vec![k, args, dest_stack_val, Value::from(false)],
1228 wind,
1229 0,
1230 false,
1231 ),
1232 Vec::new(),
1233 );
1234
1235 Box::into_raw(Box::new(app))
1236 }
1237}
1238
1239unsafe extern "C" fn wind(
1240 runtime: *mut GcInner<RwLock<RuntimeInner>>,
1241 env: *const Value,
1242 _args: *const Value,
1243 barrier: *mut ContBarrier,
1244) -> *mut Application {
1245 unsafe {
1246 let k = env.as_ref().unwrap().clone();
1248
1249 let args = env.add(1).as_ref().unwrap().clone();
1251
1252 let dest_stack_val = env.add(2).as_ref().unwrap().clone();
1254 let dest_stack = dest_stack_val
1255 .try_to_rust_type::<SavedDynamicState>()
1256 .unwrap();
1257 let dest_stack_read = dest_stack.as_ref();
1258
1259 let barrier = barrier.as_mut().unwrap_unchecked();
1260
1261 let winder = env.add(3).as_ref().unwrap().clone();
1263 if winder.is_true() {
1264 let winder = winder.try_to_rust_type::<Winder>().unwrap();
1265 barrier.push_dyn_stack(DynStackElem::Winder(winder.as_ref().clone()));
1266 }
1267
1268 while barrier.dyn_stack_len() < dest_stack_read.dyn_stack_len() {
1269 match dest_stack_read
1270 .dyn_stack_get(barrier.dyn_stack_len())
1271 .cloned()
1272 {
1273 None => {
1274 break;
1275 }
1276 Some(DynStackElem::Winder(winder)) => {
1277 let app = Application::new(
1279 winder.in_thunk.clone(),
1280 vec![Value::from(barrier.new_k(
1281 Runtime::from_raw_inc_rc(runtime),
1282 vec![
1283 k,
1284 args,
1285 dest_stack_val,
1286 Value::from(Record::from_rust_type(winder)),
1287 ],
1288 wind,
1289 0,
1290 false,
1291 ))],
1292 );
1293 return Box::into_raw(Box::new(app));
1294 }
1295 Some(elem) => barrier.push_dyn_stack(elem),
1296 }
1297 }
1298
1299 let args: Vector = args.try_into().unwrap();
1300 let args = args.0.vec.read().to_vec();
1301
1302 Box::into_raw(Box::new(Application::new(k.try_into().unwrap(), args)))
1303 }
1304}
1305
1306unsafe extern "C" fn call_consumer_with_values(
1307 runtime: *mut GcInner<RwLock<RuntimeInner>>,
1308 env: *const Value,
1309 args: *const Value,
1310 barrier: *mut ContBarrier,
1311) -> *mut Application {
1312 unsafe {
1313 let consumer = env.as_ref().unwrap().clone();
1315 let type_name = consumer.type_name();
1316
1317 let consumer: Procedure = match consumer.try_into() {
1318 Ok(consumer) => consumer,
1319 _ => {
1320 let raised = raise(
1321 Runtime::from_raw_inc_rc(runtime),
1322 Exception::invalid_operator(type_name).into(),
1323 barrier.as_mut().unwrap_unchecked(),
1324 );
1325 return Box::into_raw(Box::new(raised));
1326 }
1327 };
1328
1329 let k = env.add(1).as_ref().unwrap().clone();
1331
1332 let mut collected_args: Vec<_> = (0..consumer.0.num_required_args)
1333 .map(|i| args.add(i).as_ref().unwrap().clone())
1334 .collect();
1335
1336 if consumer.0.variadic {
1339 let rest_args = args
1340 .add(consumer.0.num_required_args)
1341 .as_ref()
1342 .unwrap()
1343 .clone();
1344 let mut vec = Vec::new();
1345 list_to_vec(&rest_args, &mut vec);
1346 collected_args.extend(vec);
1347 }
1348
1349 collected_args.push(k);
1350
1351 Box::into_raw(Box::new(Application::new(consumer.clone(), collected_args)))
1352 }
1353}
1354
1355#[cps_bridge(
1356 def = "call-with-values producer consumer",
1357 lib = "(rnrs base builtins (6))"
1358)]
1359pub fn call_with_values(
1360 runtime: &Runtime,
1361 _env: &[Value],
1362 args: &[Value],
1363 _rest_args: &[Value],
1364 barrier: &mut ContBarrier,
1365 k: Value,
1366) -> Result<Application, Exception> {
1367 let [producer, consumer] = args else {
1368 return Err(Exception::wrong_num_of_args(2, args.len()));
1369 };
1370
1371 let producer: Procedure = producer.clone().try_into()?;
1372 let consumer: Procedure = consumer.clone().try_into()?;
1373
1374 let (num_required_args, variadic) = { (consumer.0.num_required_args, consumer.0.variadic) };
1376
1377 let call_consumer_closure = barrier.new_k(
1378 runtime.clone(),
1379 vec![Value::from(consumer), k],
1380 call_consumer_with_values,
1381 num_required_args,
1382 variadic,
1383 );
1384
1385 Ok(Application::new(
1386 producer,
1387 vec![Value::from(call_consumer_closure)],
1388 ))
1389}
1390
1391#[derive(Clone, Debug, Trace, PartialEq)]
1397pub(crate) struct Winder {
1398 pub(crate) in_thunk: Procedure,
1399 pub(crate) out_thunk: Procedure,
1400}
1401
1402impl SchemeCompatible for Winder {
1403 fn rtd() -> Arc<RecordTypeDescriptor> {
1404 rtd!(name: "$winder", sealed: true, opaque: true)
1405 }
1406}
1407
1408#[cps_bridge(def = "dynamic-wind in body out", lib = "(rnrs base builtins (6))")]
1409pub fn dynamic_wind(
1410 runtime: &Runtime,
1411 _env: &[Value],
1412 args: &[Value],
1413 _rest_args: &[Value],
1414 barrier: &mut ContBarrier,
1415 k: Value,
1416) -> Result<Application, Exception> {
1417 let [in_thunk_val, body_thunk_val, out_thunk_val] = args else {
1418 return Err(Exception::wrong_num_of_args(3, args.len()));
1419 };
1420
1421 let in_thunk: Procedure = in_thunk_val.clone().try_into()?;
1422 let _: Procedure = body_thunk_val.clone().try_into()?;
1423
1424 let call_body_thunk_cont = barrier.new_k(
1425 runtime.clone(),
1426 vec![
1427 in_thunk_val.clone(),
1428 body_thunk_val.clone(),
1429 out_thunk_val.clone(),
1430 k,
1431 ],
1432 call_body_thunk,
1433 0,
1434 true,
1435 );
1436
1437 Ok(Application::new(
1438 in_thunk,
1439 vec![Value::from(call_body_thunk_cont)],
1440 ))
1441}
1442
1443pub(crate) unsafe extern "C" fn call_body_thunk(
1444 runtime: *mut GcInner<RwLock<RuntimeInner>>,
1445 env: *const Value,
1446 _args: *const Value,
1447 barrier: *mut ContBarrier,
1448) -> *mut Application {
1449 unsafe {
1450 let in_thunk = env.as_ref().unwrap().clone();
1452
1453 let body_thunk: Procedure = env.add(1).as_ref().unwrap().clone().try_into().unwrap();
1455
1456 let out_thunk = env.add(2).as_ref().unwrap().clone();
1458
1459 let k = env.add(3).as_ref().unwrap().clone();
1461
1462 let barrier = barrier.as_mut().unwrap_unchecked();
1463
1464 barrier.push_dyn_stack(DynStackElem::Winder(Winder {
1465 in_thunk: in_thunk.clone().try_into().unwrap(),
1466 out_thunk: out_thunk.clone().try_into().unwrap(),
1467 }));
1468
1469 let k = barrier.new_k(
1470 Runtime::from_raw_inc_rc(runtime),
1471 vec![out_thunk, k],
1472 call_out_thunks,
1473 0,
1474 true,
1475 );
1476
1477 let app = Application::new(body_thunk, vec![Value::from(k)]);
1478
1479 Box::into_raw(Box::new(app))
1480 }
1481}
1482
1483pub(crate) unsafe extern "C" fn call_out_thunks(
1484 runtime: *mut GcInner<RwLock<RuntimeInner>>,
1485 env: *const Value,
1486 args: *const Value,
1487 barrier: *mut ContBarrier,
1488) -> *mut Application {
1489 unsafe {
1490 let out_thunk: Procedure = env.as_ref().unwrap().clone().try_into().unwrap();
1492
1493 let k = env.add(1).as_ref().unwrap().clone();
1495
1496 let body_thunk_res = args.as_ref().unwrap().clone();
1498
1499 let barrier = barrier.as_mut().unwrap_unchecked();
1500 barrier.pop_dyn_stack();
1501
1502 let cont = barrier.new_k(
1503 Runtime::from_raw_inc_rc(runtime),
1504 vec![body_thunk_res, k],
1505 forward_body_thunk_result,
1506 0,
1507 true,
1508 );
1509
1510 let app = Application::new(out_thunk, vec![Value::from(cont)]);
1511
1512 Box::into_raw(Box::new(app))
1513 }
1514}
1515
1516unsafe extern "C" fn forward_body_thunk_result(
1517 _runtime: *mut GcInner<RwLock<RuntimeInner>>,
1518 env: *const Value,
1519 _args: *const Value,
1520 _barrier: *mut ContBarrier,
1521) -> *mut Application {
1522 unsafe {
1523 let body_thunk_res = env.as_ref().unwrap().clone();
1525 let k: Procedure = env.add(1).as_ref().unwrap().clone().try_into().unwrap();
1527
1528 let mut args = Vec::new();
1529 list_to_vec(&body_thunk_res, &mut args);
1530
1531 Box::into_raw(Box::new(Application::new(k, args)))
1532 }
1533}
1534
1535#[derive(Clone, Debug, PartialEq, Trace)]
1541pub(crate) struct Prompt {
1542 tag: Symbol,
1543 barrier_id: usize,
1544 handler: Procedure,
1545 handler_k: Procedure,
1546}
1547
1548#[derive(Clone, Debug, PartialEq, Trace)]
1549pub(crate) struct PromptBarrier {
1550 barrier_id: usize,
1551 replaced_k: Procedure,
1552}
1553
1554static BARRIER_ID: AtomicUsize = AtomicUsize::new(0);
1555
1556#[cps_bridge(def = "call-with-prompt tag thunk handler", lib = "(prompts)")]
1557pub fn call_with_prompt(
1558 runtime: &Runtime,
1559 _env: &[Value],
1560 args: &[Value],
1561 _rest_args: &[Value],
1562 barrier: &mut ContBarrier,
1563 k: Value,
1564) -> Result<Application, Exception> {
1565 let [tag, thunk, handler] = args else {
1566 unreachable!()
1567 };
1568
1569 let k_proc: Procedure = k.clone().try_into().unwrap();
1570 let (req_args, variadic) = k_proc.get_formals();
1571 let tag: Symbol = tag.clone().try_into().unwrap();
1572
1573 let barrier_id = BARRIER_ID.fetch_add(1, Ordering::Relaxed);
1574
1575 barrier.push_dyn_stack(DynStackElem::Prompt(Prompt {
1576 tag,
1577 handler: handler.clone().try_into().unwrap(),
1578 barrier_id,
1579 handler_k: k.clone().try_into()?,
1580 }));
1581
1582 barrier.push_marks();
1583
1584 let prompt_barrier = Procedure::new(
1585 runtime.clone(),
1586 vec![k],
1587 FuncPtr::PromptBarrier {
1588 barrier_id,
1589 k: pop_dyn_stack,
1590 },
1591 req_args,
1592 variadic,
1593 );
1594
1595 Ok(Application::new(
1596 thunk.clone().try_into().unwrap(),
1597 vec![Value::from(prompt_barrier)],
1598 ))
1599}
1600
1601#[cps_bridge(def = "abort-to-prompt tag . values", lib = "(prompts)")]
1602pub fn abort_to_prompt(
1603 runtime: &Runtime,
1604 _env: &[Value],
1605 args: &[Value],
1606 rest_args: &[Value],
1607 barrier: &mut ContBarrier,
1608 k: Value,
1609) -> Result<Application, Exception> {
1610 let [tag] = args else { unreachable!() };
1611
1612 let unwind_to_prompt = barrier.new_k(
1613 runtime.clone(),
1614 vec![
1615 k,
1616 Value::from(rest_args.to_vec()),
1617 tag.clone(),
1618 Value::from_rust_type(barrier.save()),
1619 ],
1620 unwind_to_prompt,
1621 0,
1622 false,
1623 );
1624
1625 Ok(Application::new(unwind_to_prompt, Vec::new()))
1626}
1627
1628unsafe extern "C" fn unwind_to_prompt(
1629 runtime: *mut GcInner<RwLock<RuntimeInner>>,
1630 env: *const Value,
1631 _args: *const Value,
1632 barrier: *mut ContBarrier,
1633) -> *mut Application {
1634 unsafe {
1635 let k = env.as_ref().unwrap().clone();
1637 let args = env.add(1).as_ref().unwrap().clone();
1639 let tag: Symbol = env.add(2).as_ref().unwrap().clone().try_into().unwrap();
1641 let saved_barrier = env.add(3).as_ref().unwrap().clone();
1643
1644 let barrier = barrier.as_mut().unwrap_unchecked();
1645
1646 loop {
1647 let app = match barrier.pop_dyn_stack() {
1648 None => {
1649 Application::halt_err(Value::from(Exception::error(format!(
1651 "no prompt tag {tag} found"
1652 ))))
1653 }
1654 Some(DynStackElem::Prompt(Prompt {
1655 tag: prompt_tag,
1656 barrier_id,
1657 handler,
1658 handler_k,
1659 })) if prompt_tag == tag => {
1660 let saved_barrier = saved_barrier
1661 .try_to_rust_type::<SavedDynamicState>()
1662 .unwrap();
1663 let prompt_delimited_barrier = SavedDynamicState {
1664 id: saved_barrier.id,
1665 dyn_stack: saved_barrier.as_ref().dyn_stack[barrier.dyn_stack_len() + 1..]
1666 .to_vec(),
1667 cont_marks: saved_barrier.cont_marks.clone(),
1668 };
1669 let (req_args, var) = {
1670 let k_proc: Procedure = k.clone().try_into().unwrap();
1671 k_proc.get_formals()
1672 };
1673 let mut handler_args = vec![Value::from(Procedure::new(
1675 Runtime::from_raw_inc_rc(runtime),
1676 vec![
1677 k,
1678 Value::from(barrier_id),
1679 Value::from_rust_type(prompt_delimited_barrier),
1680 ],
1681 FuncPtr::Bridge(delimited_continuation),
1682 req_args,
1683 var,
1684 ))];
1685 handler_args.extend(args.cast_to_scheme_type::<Vector>().unwrap().iter());
1686 handler_args.push(Value::from(handler_k));
1687 Application::new(handler, handler_args)
1688 }
1689 Some(DynStackElem::Winder(winder)) => {
1690 Application::new(
1692 winder.out_thunk,
1693 vec![Value::from(barrier.new_k(
1694 Runtime::from_raw_inc_rc(runtime),
1695 vec![k, args, Value::from(tag), saved_barrier],
1696 unwind_to_prompt,
1697 0,
1698 false,
1699 ))],
1700 )
1701 }
1702 _ => continue,
1703 };
1704 return Box::into_raw(Box::new(app));
1705 }
1706 }
1707}
1708
1709#[cps_bridge]
1710fn delimited_continuation(
1711 runtime: &Runtime,
1712 env: &[Value],
1713 args: &[Value],
1714 rest_args: &[Value],
1715 barrier: &mut ContBarrier,
1716 k: Value,
1717) -> Result<Application, Exception> {
1718 let dk = env[0].clone();
1720
1721 let barrier_id: usize = env[1].try_to_scheme_type()?;
1723
1724 let saved_barrier_val = env[2].clone();
1726 let saved_barrier = saved_barrier_val
1727 .try_to_rust_type::<SavedDynamicState>()
1728 .unwrap();
1729 let saved_barrier_read = saved_barrier.as_ref();
1730 barrier.cont_marks = saved_barrier_read.cont_marks.clone();
1732
1733 let args = args.iter().chain(rest_args).cloned().collect::<Vec<_>>();
1734
1735 barrier.push_dyn_stack(DynStackElem::PromptBarrier(PromptBarrier {
1736 barrier_id,
1737 replaced_k: k.try_into()?,
1738 }));
1739
1740 if saved_barrier_read.dyn_stack_is_empty() {
1743 Ok(Application::new(dk.try_into()?, args))
1744 } else {
1745 let args = Value::from(args);
1746 let k = barrier.new_k(
1747 runtime.clone(),
1748 vec![
1749 dk,
1750 args,
1751 saved_barrier_val,
1752 Value::from(0),
1753 Value::from(false),
1754 ],
1755 wind_delim,
1756 0,
1757 false,
1758 );
1759 Ok(Application::new(k, Vec::new()))
1760 }
1761}
1762
1763unsafe extern "C" fn wind_delim(
1764 runtime: *mut GcInner<RwLock<RuntimeInner>>,
1765 env: *const Value,
1766 _args: *const Value,
1767 barrier: *mut ContBarrier,
1768) -> *mut Application {
1769 unsafe {
1770 let k = env.as_ref().unwrap().clone();
1772
1773 let args = env.add(1).as_ref().unwrap().clone();
1775
1776 let dest_stack_val = env.add(2).as_ref().unwrap().clone();
1778 let dest_stack = dest_stack_val
1779 .try_to_rust_type::<SavedDynamicState>()
1780 .unwrap();
1781 let dest_stack_read = dest_stack.as_ref();
1782
1783 let mut idx: usize = env.add(3).as_ref().unwrap().cast_to_scheme_type().unwrap();
1785
1786 let barrier = barrier.as_mut().unwrap_unchecked();
1787
1788 let winder = env.add(4).as_ref().unwrap().clone();
1790 if winder.is_true() {
1791 let winder = winder.try_to_rust_type::<Winder>().unwrap();
1792 barrier.push_dyn_stack(DynStackElem::Winder(winder.as_ref().clone()));
1793 }
1794
1795 while let Some(elem) = dest_stack_read.dyn_stack_get(idx) {
1796 idx += 1;
1797
1798 if let DynStackElem::Winder(winder) = elem {
1799 let app = Application::new(
1801 winder.in_thunk.clone(),
1802 vec![Value::from(barrier.new_k(
1803 Runtime::from_raw_inc_rc(runtime),
1804 vec![
1805 k,
1806 args,
1807 dest_stack_val,
1808 Value::from(Record::from_rust_type(winder.clone())),
1809 ],
1810 wind,
1811 0,
1812 false,
1813 ))],
1814 );
1815 return Box::into_raw(Box::new(app));
1816 }
1817 barrier.push_dyn_stack(elem.clone());
1818 }
1819
1820 let args: Vector = args.try_into().unwrap();
1821 let args = args.0.vec.read().to_vec();
1822
1823 Box::into_raw(Box::new(Application::new(k.try_into().unwrap(), args)))
1824 }
1825}