1use crate::{continuation::Continuation, error::RuntimeError, gc::Gc, num::Number, value::Value};
2use futures::future::BoxFuture;
3use scheme_rs_macros::builtin;
4use std::sync::Arc;
5
6pub fn fmt_list<'a>(car: &'a Gc<Value>, cdr: &'a Gc<Value>) -> BoxFuture<'a, String> {
7 Box::pin(async move {
9 match &*cdr.read().await {
10 Value::Pair(_, _) | Value::Null => (),
11 cdr => {
12 let car = car.read().await.fmt().await;
14 let cdr = cdr.fmt().await;
15 return format!("({car} . {cdr})");
16 }
17 }
18
19 let mut output = String::from("(");
20 output.push_str(&car.read().await.fmt().await);
21
22 let mut stack = vec![cdr.clone()];
23
24 while let Some(head) = stack.pop() {
25 match &*head.read().await {
26 Value::Null => {
27 if !stack.is_empty() {
28 output.push_str(" ()");
29 }
30 }
31 Value::Pair(car, cdr) => {
32 output.push(' ');
33 output.push_str(&car.read().await.fmt().await);
34 stack.push(cdr.clone());
35 }
36 x => {
37 output.push(' ');
38 output.push_str(&x.fmt().await)
39 }
40 }
41 }
42
43 output.push(')');
44 output
45 })
46}
47
48pub fn list_to_vec<'a>(curr: &'a Gc<Value>, out: &'a mut Vec<Gc<Value>>) -> BoxFuture<'a, ()> {
49 Box::pin(async move {
50 let val = curr.read().await;
51 match &*val {
52 Value::Pair(a, b) => {
53 out.push(a.clone());
54 list_to_vec(b, out).await;
55 }
56 Value::Null => (),
57 _ => out.push(curr.clone()),
58 }
59 })
60}
61
62#[builtin("list")]
63pub async fn list(
64 _cont: &Option<Arc<Continuation>>,
65 args: Vec<Gc<Value>>,
66) -> Result<Vec<Gc<Value>>, RuntimeError> {
67 let mut cdr = Gc::new(Value::Null);
69 for arg in args.into_iter().rev() {
70 cdr = Gc::new(Value::Pair(arg, cdr.clone()));
71 }
72 Ok(vec![cdr])
73}
74
75#[builtin("cons")]
76pub async fn cons(
77 _cont: &Option<Arc<Continuation>>,
78 car: &Gc<Value>,
79 cdr: &Gc<Value>,
80) -> Result<Vec<Gc<Value>>, RuntimeError> {
81 Ok(vec![Gc::new(Value::Pair(car.clone(), cdr.clone()))])
82}
83
84#[builtin("car")]
85pub async fn car(
86 _cont: &Option<Arc<Continuation>>,
87 val: &Gc<Value>,
88) -> Result<Vec<Gc<Value>>, RuntimeError> {
89 let val = val.read().await;
90 match &*val {
91 Value::Pair(car, _cdr) => Ok(vec![car.clone()]),
92 _ => Err(RuntimeError::invalid_type("pair", val.type_name())),
93 }
94}
95
96#[builtin("cdr")]
97pub async fn cdr(
98 _cont: &Option<Arc<Continuation>>,
99 val: &Gc<Value>,
100) -> Result<Vec<Gc<Value>>, RuntimeError> {
101 let val = val.read().await;
102 match &*val {
103 Value::Pair(_car, cdr) => Ok(vec![cdr.clone()]),
104 _ => Err(RuntimeError::invalid_type("pair", val.type_name())),
105 }
106}
107
108#[builtin("set-car!")]
109pub async fn set_car(
110 _cont: &Option<Arc<Continuation>>,
111 var: &Gc<Value>,
112 val: &Gc<Value>,
113) -> Result<Vec<Gc<Value>>, RuntimeError> {
114 let mut var = var.write().await;
115 match &mut *var {
116 Value::Pair(ref mut car, _cdr) => *car = val.clone(),
117 _ => todo!(),
118 }
119 Ok(vec![Gc::new(Value::Null)])
120}
121
122#[builtin("length")]
123pub async fn length(
124 _cont: &Option<Arc<Continuation>>,
125 arg: &Gc<Value>,
126) -> Result<Vec<Gc<Value>>, RuntimeError> {
127 let mut length = 0;
128 let mut arg = arg.clone();
129 loop {
130 arg = {
131 let val = arg.read().await;
132 match &*val {
133 Value::Pair(_, cdr) => cdr.clone(),
134 _ => break,
135 }
136 };
137 length += 1;
138 }
139 Ok(vec![Gc::new(Value::Number(Number::from(length)))])
140}