1use hashbrown::HashSet;
4use indexmap::IndexMap;
5use parking_lot::RwLock;
6
7use crate::{
8 exceptions::Exception,
9 gc::{Gc, GcInner, Trace},
10 proc::{Application, DynamicState, Procedure},
11 registry::{bridge, cps_bridge},
12 runtime::{Runtime, RuntimeInner},
13 strings::WideString,
14 value::{UnpackedValue, Value, ValueType, write_value},
15 vectors::Vector,
16};
17use std::fmt;
18
19#[derive(Trace)]
20#[repr(align(16))]
21pub(crate) struct PairInner {
22 car: RwLock<Value>,
24 cdr: RwLock<Value>,
26 mutable: bool,
28}
29
30#[derive(Clone, Trace)]
33pub struct Pair(pub(crate) Gc<PairInner>);
34
35impl Pair {
36 pub fn new(car: Value, cdr: Value, mutable: bool) -> Self {
38 Self(Gc::new(PairInner {
39 car: RwLock::new(car),
40 cdr: RwLock::new(cdr),
41 mutable,
42 }))
43 }
44
45 pub fn car(&self) -> Value {
47 self.0.car.read().clone()
48 }
49
50 pub fn head(&self) -> Value {
52 self.car()
53 }
54
55 pub fn cdr(&self) -> Value {
57 self.0.cdr.read().clone()
58 }
59
60 pub fn tail(&self) -> Value {
62 self.cdr()
63 }
64
65 pub fn set_car(&self, new_car: Value) -> Result<(), Exception> {
67 if self.0.mutable {
68 *self.0.car.write() = new_car;
69 Ok(())
70 } else {
71 Err(Exception::error("pair is not mutable"))
72 }
73 }
74
75 pub fn set_cdr(&self, new_cdr: Value) -> Result<(), Exception> {
77 if self.0.mutable {
78 *self.0.cdr.write() = new_cdr;
79 Ok(())
80 } else {
81 Err(Exception::error("pair is not mutable"))
82 }
83 }
84}
85
86impl From<Pair> for (Value, Value) {
87 fn from(value: Pair) -> Self {
88 (value.car(), value.cdr())
89 }
90}
91
92pub(crate) fn write_list(
93 car: &Value,
94 cdr: &Value,
95 fmt: fn(&Value, &mut IndexMap<Value, bool>, &mut fmt::Formatter<'_>) -> fmt::Result,
96 circular_values: &mut IndexMap<Value, bool>,
97 f: &mut fmt::Formatter<'_>,
98) -> fmt::Result {
99 match cdr.type_of() {
100 ValueType::Pair | ValueType::Null => (),
101 _ => {
102 write!(f, "(")?;
104 write_value(car, fmt, circular_values, f)?;
105 write!(f, " . ")?;
106 write_value(cdr, fmt, circular_values, f)?;
107 write!(f, ")")?;
108 return Ok(());
109 }
110 }
111
112 write!(f, "(")?;
113 write_value(car, fmt, circular_values, f)?;
114 let mut stack = vec![cdr.clone()];
115
116 while let Some(head) = stack.pop() {
117 if let Some((idx, _, seen)) = circular_values.get_full_mut(&head) {
118 if *seen {
119 write!(f, " . #{idx}#")?;
120 continue;
121 } else {
122 write!(f, " #{idx}=")?;
123 *seen = true;
124 }
125 }
126 match &*head.unpacked_ref() {
127 UnpackedValue::Null => {
128 if !stack.is_empty() {
129 write!(f, " ()")?;
130 }
131 }
132 UnpackedValue::Pair(pair) => {
133 let (car, cdr) = pair.clone().into();
134 write!(f, " ")?;
135 write_value(&car, fmt, circular_values, f)?;
136 stack.push(cdr);
137 }
138 x => {
139 let val = x.clone().into_value();
140 write!(f, " ")?;
141 if stack.is_empty() {
142 write!(f, ". ")?;
143 }
144 write_value(&val, fmt, circular_values, f)?;
145 }
146 }
147 }
148
149 write!(f, ")")
150}
151
152pub struct List {
162 head: Value,
163 items: Vec<Value>,
164}
165
166impl List {
167 pub fn as_slice(&self) -> &[Value] {
168 self.items.as_slice()
169 }
170
171 pub fn into_vec(self) -> Vec<Value> {
172 self.items
173 }
174}
175
176impl IntoIterator for List {
177 type Item = Value;
178 type IntoIter = std::vec::IntoIter<Value>;
179
180 fn into_iter(self) -> Self::IntoIter {
181 self.items.into_iter()
182 }
183}
184
185impl From<List> for Value {
186 fn from(value: List) -> Self {
187 value.head
188 }
189}
190
191impl From<&Value> for Option<List> {
192 fn from(value: &Value) -> Self {
193 let mut seen = HashSet::new();
194 let mut cdr = value.clone();
195 let mut items = Vec::new();
196 while !cdr.is_null() {
197 if !seen.insert(cdr.clone()) {
198 return None;
199 }
200 let (car, new_cdr) = cdr.cast_to_scheme_type()?;
201 items.push(car);
202 cdr = new_cdr;
203 }
204 Some(List {
205 head: value.clone(),
206 items,
207 })
208 }
209}
210
211impl TryFrom<&Value> for List {
212 type Error = Exception;
213
214 fn try_from(value: &Value) -> Result<Self, Self::Error> {
215 value
216 .cast_to_scheme_type::<List>()
217 .ok_or_else(|| Exception::error("value is not a proper list"))
218 }
219}
220
221pub fn slice_to_list(items: &[Value]) -> Value {
223 match items {
224 [] => Value::null(),
225 [head, tail @ ..] => Value::from(Pair::new(head.clone(), slice_to_list(tail), false)),
226 }
227}
228
229pub fn list_to_vec(curr: &Value, out: &mut Vec<Value>) {
230 match &*curr.unpacked_ref() {
231 UnpackedValue::Pair(pair) => {
232 let (car, cdr) = pair.clone().into();
233 out.push(car);
234 list_to_vec(&cdr, out);
235 }
236 UnpackedValue::Null => (),
237 _ => out.push(curr.clone()),
238 }
239}
240
241pub fn list_to_vec_with_null(curr: &Value, out: &mut Vec<Value>) {
242 match &*curr.unpacked_ref() {
243 UnpackedValue::Pair(pair) => {
244 let (car, cdr) = pair.clone().into();
245 out.push(car);
246 list_to_vec_with_null(&cdr, out);
247 }
248 _ => out.push(curr.clone()),
249 }
250}
251
252pub fn is_list(curr: &Value, seen: &mut HashSet<Value>) -> bool {
253 if curr.is_null() {
254 return true;
255 }
256
257 if !seen.insert(curr.clone()) {
258 return false;
259 }
260
261 let Some(curr) = curr.cast_to_scheme_type::<Pair>() else {
262 return false;
263 };
264
265 is_list(&curr.cdr(), seen)
266}
267
268#[bridge(name = "list?", lib = "(rnrs base builtins (6))")]
269pub fn list_pred(arg: &Value) -> Result<Vec<Value>, Exception> {
270 Ok(vec![Value::from(is_list(arg, &mut HashSet::default()))])
271}
272
273#[bridge(name = "list", lib = "(rnrs base builtins (6))")]
274pub fn list(args: &[Value]) -> Result<Vec<Value>, Exception> {
275 let mut cdr = Value::null();
277 for arg in args.iter().rev() {
278 cdr = Value::from(Pair::new(arg.clone(), cdr, true));
279 }
280 Ok(vec![cdr])
281}
282
283#[bridge(name = "cons", lib = "(rnrs base builtins (6))")]
284pub fn cons(car: &Value, cdr: &Value) -> Result<Vec<Value>, Exception> {
285 Ok(vec![Value::from(Pair::new(car.clone(), cdr.clone(), true))])
286}
287
288#[bridge(name = "car", lib = "(rnrs base builtins (6))")]
289pub fn car(val: &Value) -> Result<Vec<Value>, Exception> {
290 Ok(vec![val.try_to_scheme_type::<Pair>()?.car()])
291}
292
293#[bridge(name = "cdr", lib = "(rnrs base builtins (6))")]
294pub fn cdr(val: &Value) -> Result<Vec<Value>, Exception> {
295 Ok(vec![val.try_to_scheme_type::<Pair>()?.cdr()])
296}
297
298#[bridge(name = "set-car!", lib = "(rnrs mutable-pairs (6))")]
299pub fn set_car(var: &Value, val: &Value) -> Result<Vec<Value>, Exception> {
300 let pair: Pair = var.clone().try_into()?;
301 pair.set_car(val.clone())?;
302 Ok(Vec::new())
303}
304
305#[bridge(name = "set-cdr!", lib = "(rnrs mutable-pairs (6))")]
306pub fn set_cdr(var: &Value, val: &Value) -> Result<Vec<Value>, Exception> {
307 let pair: Pair = var.clone().try_into()?;
308 pair.set_cdr(val.clone())?;
309 Ok(Vec::new())
310}
311
312#[bridge(name = "length", lib = "(rnrs base builtins (6))")]
313pub fn length_builtin(arg: &Value) -> Result<Vec<Value>, Exception> {
314 Ok(vec![Value::from(length(arg)?)])
315}
316
317pub fn length(arg: &Value) -> Result<usize, Exception> {
318 let mut length = 0usize;
319 let mut arg = arg.clone();
320 loop {
321 arg = {
322 match &*arg.unpacked_ref() {
323 UnpackedValue::Pair(pair) => pair.cdr(),
324 UnpackedValue::Null => break,
325 _ => return Err(Exception::error("list must be proper".to_string())),
326 }
327 };
328 length += 1;
329 }
330 Ok(length)
331}
332
333#[bridge(name = "list->vector", lib = "(rnrs base builtins (6))")]
334pub fn list_to_vector(list: &Value) -> Result<Vec<Value>, Exception> {
335 let List { items, .. } = list.try_to_scheme_type()?;
336 Ok(vec![Value::from(items)])
337}
338
339#[bridge(name = "list->string", lib = "(rnrs base builtins (6))")]
340pub fn list_to_string(List { items, .. }: List) -> Result<Vec<Value>, Exception> {
341 let chars = items
342 .into_iter()
343 .map(char::try_from)
344 .collect::<Result<Vec<_>, _>>()?;
345 Ok(vec![Value::from(WideString::new_mutable(chars))])
346}
347
348#[bridge(name = "append", lib = "(rnrs base builtins (6))")]
349pub fn append(list: &Value, to_append: &Value) -> Result<Vec<Value>, Exception> {
350 let mut vec = Vec::new();
351 list_to_vec(list, &mut vec);
352 let mut list = to_append.clone();
353 for item in vec.into_iter().rev() {
354 list = Value::from(Pair::new(item, list, true));
355 }
356 Ok(vec![list])
357}
358
359#[cps_bridge(def = "map proc list1 . listn", lib = "(rnrs base builtins (6))")]
360pub fn map(
361 runtime: &Runtime,
362 _env: &[Value],
363 args: &[Value],
364 list_n: &[Value],
365 dyn_state: &mut DynamicState,
366 k: Value,
367) -> Result<Application, Exception> {
368 let [mapper, list_1] = args else {
369 unreachable!()
370 };
371 let mapper_proc: Procedure = mapper.clone().try_into()?;
372 let mut inputs = Some(list_1.clone())
373 .into_iter()
374 .chain(list_n.iter().cloned())
375 .collect::<Vec<_>>();
376 let mut args = Vec::new();
377
378 for input in inputs.iter_mut() {
379 if input.type_of() == ValueType::Null {
380 return Ok(Application::new(k.try_into()?, vec![Value::null()]));
382 }
383
384 let (car, cdr) = input.try_to_scheme_type::<Pair>()?.into();
385
386 args.push(car);
387 *input = cdr;
388 }
389
390 let map_k = dyn_state.new_k(
391 runtime.clone(),
392 vec![
393 Value::from(Vec::<Value>::new()),
394 Value::from(inputs),
395 mapper.clone(),
396 k,
397 ],
398 map_k,
399 1,
400 false,
401 );
402
403 args.push(Value::from(map_k));
404
405 Ok(Application::new(mapper_proc, args))
406}
407
408unsafe extern "C" fn map_k(
409 runtime: *mut GcInner<RwLock<RuntimeInner>>,
410 env: *const Value,
411 args: *const Value,
412 dyn_state: *mut DynamicState,
413) -> *mut Application {
414 unsafe {
415 let output: Vector = env.as_ref().unwrap().clone().try_into().unwrap();
419
420 output.0.vec.write().push(args.as_ref().unwrap().clone());
421
422 let inputs: Vector = env.add(1).as_ref().unwrap().clone().try_into().unwrap();
424
425 let mapper: Procedure = env.add(2).as_ref().unwrap().clone().try_into().unwrap();
427
428 let k: Procedure = env.add(3).as_ref().unwrap().clone().try_into().unwrap();
430
431 let mut args = Vec::new();
432
433 for input in inputs.0.vec.write().iter_mut() {
435 if input.type_of() == ValueType::Null {
436 let output = slice_to_list(&output.0.vec.read());
438 let app = Application::new(k, vec![output]);
439 return Box::into_raw(Box::new(app));
440 }
441
442 let (car, cdr) = input.cast_to_scheme_type::<Pair>().unwrap().into();
443 args.push(car);
444 *input = cdr;
445 }
446
447 let map_k = dyn_state.as_mut().unwrap().new_k(
448 Runtime::from_raw_inc_rc(runtime),
449 vec![
450 Value::from(output),
451 Value::from(inputs),
452 Value::from(mapper.clone()),
453 Value::from(k),
454 ],
455 map_k,
456 1,
457 false,
458 );
459
460 args.push(Value::from(map_k));
461
462 Box::into_raw(Box::new(Application::new(mapper, args)))
463 }
464}
465
466#[bridge(name = "zip", lib = "(rnrs base builtins (6))")]
467pub fn zip(list1: &Value, listn: &[Value]) -> Result<Vec<Value>, Exception> {
468 let mut output: Option<Vec<Value>> = None;
469 for list in Some(list1).into_iter().chain(listn.iter()).rev() {
470 let List { items, .. } = list.try_to_scheme_type()?;
471 if let Some(output) = &output {
472 if output.len() != items.len() {
473 return Err(Exception::error("lists do not have the same length"));
474 }
475 } else {
476 output = Some(vec![Value::null(); items.len()]);
477 }
478
479 let output = output.as_mut().unwrap();
480 for (i, item) in items.into_iter().enumerate() {
481 output[i] = Value::from((item, output[i].clone()));
482 }
483 }
484
485 if let Some(output) = output {
486 Ok(vec![slice_to_list(&output)])
487 } else {
488 Ok(vec![Value::null()])
489 }
490}