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