1use tan::{
2 context::Context,
3 error::Error,
4 eval::{invoke, invoke_func},
5 expr::{expr_clone, format_value, Expr},
6 util::{
7 args::{unpack_arg, unpack_array_arg, unpack_array_mut_arg, unpack_int_arg},
8 module_util::require_module,
9 },
10};
11
12use super::cmp::rust_ordering_from_tan_ordering;
13
14pub fn list_cons(args: &[Expr]) -> Result<Expr, Error> {
21 let [head, tail] = args else {
22 return Err(Error::invalid_arguments(
23 "requires `head` and `tail` arguments",
24 None,
25 ));
26 };
27
28 let Some(tail) = tail.as_list() else {
29 return Err(Error::invalid_arguments(
30 "`tail` argument should be a List",
31 tail.range(),
32 ));
33 };
34
35 let mut cons_items = vec![expr_clone(head.unpack())];
37 for expr in tail {
38 cons_items.push(expr_clone(expr));
39 }
40
41 Ok(Expr::List(cons_items))
42}
43
44pub fn list_count(args: &[Expr]) -> Result<Expr, Error> {
46 let [list, ..] = args else {
47 return Err(Error::invalid_arguments("requires `list` argument", None));
48 };
49
50 let Some(list) = list.as_list() else {
51 return Err(Error::invalid_arguments(
52 "`list` argument should be a List",
53 list.range(),
54 ));
55 };
56
57 Ok(Expr::Int(list.len() as i64))
58}
59
60pub fn array_eq(args: &[Expr]) -> Result<Expr, Error> {
68 let a = unpack_array_arg(args, 0, "a")?;
73 let b = unpack_array_arg(args, 1, "b")?;
74
75 Ok(Expr::Bool(*a == *b))
76}
77
78pub fn array_push(args: &[Expr]) -> Result<Expr, Error> {
82 let [array, element] = args else {
83 return Err(Error::invalid_arguments(
84 "requires `this` and `element` argument",
85 None,
86 ));
87 };
88
89 let Some(mut elements) = array.as_array_mut() else {
90 return Err(Error::invalid_arguments(
91 "`array` argument should be a Array",
92 array.range(),
93 ));
94 };
95
96 elements.push(element.unpack().clone()); Ok(Expr::None)
100}
101
102pub fn array_put(args: &[Expr]) -> Result<Expr, Error> {
105 let mut array = unpack_array_mut_arg(args, 0, "array")?;
106 let index = unpack_int_arg(args, 1, "index")?;
107 let element = unpack_arg(args, 2, "element")?;
108
109 array[index as usize] = element.clone();
111
112 Ok(Expr::None)
114}
115
116pub fn array_concat_mut(args: &[Expr]) -> Result<Expr, Error> {
121 let [array1, array2] = args else {
122 return Err(Error::invalid_arguments("requires two arguments", None));
123 };
124
125 let Some(mut array1) = array1.as_array_mut() else {
126 return Err(Error::invalid_arguments(
127 "`array1` argument should be a Array",
128 array1.range(),
129 ));
130 };
131
132 let Some(mut array2) = array2.as_array_mut() else {
133 return Err(Error::invalid_arguments(
134 "`array2` argument should be a Array",
135 array2.range(),
136 ));
137 };
138
139 array1.append(&mut array2);
140
141 Ok(Expr::None)
143}
144
145pub fn array_concat(args: &[Expr]) -> Result<Expr, Error> {
146 let a = unpack_array_arg(args, 0, "a")?;
147 let b = unpack_array_arg(args, 1, "b")?;
148
149 let c: Vec<Expr> = a.iter().chain(b.iter()).cloned().collect();
152
153 Ok(Expr::array(c))
154}
155
156pub fn array_join(args: &[Expr]) -> Result<Expr, Error> {
161 let Some(array) = args.first() else {
162 return Err(Error::invalid_arguments("requires `array` argument", None));
163 };
164
165 let separator = args.get(1);
166 let separator = if separator.is_some() {
167 let Some(str) = separator.unwrap().as_stringable() else {
168 return Err(Error::invalid_arguments(
169 "the `separator` should be a Stringable",
170 None,
171 ));
172 };
173 str
174 } else {
175 ""
176 };
177
178 let Some(array) = array.as_array() else {
179 return Err(Error::invalid_arguments(
180 "`array` argument should be a Array",
181 array.range(),
182 ));
183 };
184
185 let elements: Vec<String> = array.iter().map(format_value).collect();
186
187 Ok(Expr::String(elements.join(separator)))
188}
189
190pub fn array_skip(args: &[Expr]) -> Result<Expr, Error> {
194 let Some(array) = args.first() else {
198 return Err(Error::invalid_arguments("requires `array` argument", None));
199 };
200
201 let n = args.get(1);
202 let n = if n.is_some() {
203 let Some(n) = n.unwrap().as_int() else {
204 return Err(Error::invalid_arguments("`n` should be an Int", None));
205 };
206 n
207 } else {
208 1
209 };
210
211 let Some(array) = array.as_array() else {
212 return Err(Error::invalid_arguments(
213 "`array` argument should be a Array",
214 array.range(),
215 ));
216 };
217
218 let elements: Vec<Expr> = array.iter().skip(n as usize).cloned().collect();
219
220 Ok(Expr::array(elements))
221}
222
223pub fn array_count(args: &[Expr]) -> Result<Expr, Error> {
230 let [array, ..] = args else {
231 return Err(Error::invalid_arguments("requires `array` argument", None));
232 };
233
234 let Some(array) = array.as_array() else {
235 return Err(Error::invalid_arguments(
236 "`array` argument should be a Array",
237 array.range(),
238 ));
239 };
240
241 Ok(Expr::Int(array.len() as i64))
242}
243
244pub fn array_is_empty(args: &[Expr]) -> Result<Expr, Error> {
246 let [array, ..] = args else {
247 return Err(Error::invalid_arguments("requires `array` argument", None));
248 };
249
250 let Some(array) = array.as_array() else {
251 return Err(Error::invalid_arguments(
252 "`array` argument should be a Array",
253 array.range(),
254 ));
255 };
256
257 Ok(Expr::Bool(array.len() == 0))
258}
259
260pub fn array_contains(args: &[Expr]) -> Result<Expr, Error> {
261 let [array, element] = args else {
262 return Err(Error::invalid_arguments(
263 "requires `this` and `element` argument",
264 None,
265 ));
266 };
267
268 let Some(elements) = array.as_array_mut() else {
269 return Err(Error::invalid_arguments(
270 "`array` argument should be a Array",
271 array.range(),
272 ));
273 };
274
275 Ok(Expr::Bool(elements.contains(element.unpack())))
276}
277
278pub fn array_map(args: &[Expr], context: &mut Context) -> Result<Expr, Error> {
280 let [seq, func] = args else {
281 return Err(Error::invalid_arguments(
282 "requires `array` and `func` arguments",
283 None,
284 ));
285 };
286
287 let Some(input_values) = seq.as_array() else {
289 return Err(Error::invalid_arguments(
290 "`seq` must be an `Array`",
291 seq.range(),
292 ));
293 };
294
295 let mut output_values: Vec<Expr> = Vec::new();
298
299 for x in input_values.iter() {
302 let args = vec![expr_clone(x)];
304 output_values.push(invoke(func, args, context)?);
307 }
308
309 Ok(Expr::array(output_values))
310}
311
312pub fn array_filter(_args: &[Expr]) -> Result<Expr, Error> {
315 todo!();
316
317 }
352
353#[inline]
356fn sort_array_items(array_items: &mut [Expr], func: &Expr, context: &mut Context) {
357 array_items.sort_by(|x, y| {
364 let args = vec![x.clone(), y.clone()];
369 let tan_ordering = invoke_func(func, args, context).unwrap();
370 rust_ordering_from_tan_ordering(&tan_ordering).unwrap()
371 });
372}
373
374pub fn array_sort(args: &[Expr], context: &mut Context) -> Result<Expr, Error> {
375 let xs = unpack_array_arg(args, 0, "xs")?;
377 let func = unpack_arg(args, 1, "func")?;
378
379 let mut xs_sorted = xs.clone();
380
381 sort_array_items(&mut xs_sorted, func, context);
382
383 Ok(Expr::array(xs_sorted))
384}
385
386pub fn array_sort_mut(args: &[Expr], context: &mut Context) -> Result<Expr, Error> {
393 let [array, func] = args else {
394 return Err(Error::invalid_arguments(
395 "requires `array` and `func` arguments",
396 None,
397 ));
398 };
399
400 let Some(mut array_items) = array.as_array_mut() else {
401 return Err(Error::invalid_arguments(
402 "`array` argument should be a Array",
403 array.range(),
404 ));
405 };
406
407 sort_array_items(&mut array_items, func, context);
408
409 Ok(array.clone())
415}
416
417pub fn array_slice(args: &[Expr]) -> Result<Expr, Error> {
427 let [this, start, ..] = args else {
428 return Err(Error::invalid_arguments(
429 "requires `this` and start arguments",
430 None,
431 ));
432 };
433
434 let Some(elements) = this.as_array() else {
435 return Err(Error::invalid_arguments(
436 "`this` argument should be an Array",
437 this.range(),
438 ));
439 };
440
441 let Some(start) = start.as_int() else {
442 return Err(Error::invalid_arguments(
443 "`start` argument should be an Int",
444 this.range(),
445 ));
446 };
447
448 let end = if let Some(end) = args.get(2) {
449 let Some(end) = end.as_int() else {
450 return Err(Error::invalid_arguments(
451 "`end` argument should be an Int",
452 this.range(),
453 ));
454 };
455 end
456 } else {
457 elements.len() as i64
458 };
459
460 let start = start as usize;
461 let end = if end < 0 {
462 (elements.len() as i64 + end) as usize
466 } else {
467 end as usize
468 };
469
470 let slice = &elements[start..end];
471
472 Ok(Expr::array(slice))
473}
474
475pub fn array_roll(args: &[Expr]) -> Result<Expr, Error> {
479 let window_size = unpack_int_arg(args, 0, "window-size")?;
480 let items = unpack_array_arg(args, 1, "items")?;
481
482 let windows = items.windows(window_size as usize);
483
484 let mut rolled_items = Vec::new();
485 for window in windows {
486 rolled_items.push(Expr::array(window));
487 }
488
489 Ok(Expr::array(rolled_items))
490}
491
492pub fn setup_lib_seq(context: &mut Context) {
493 let module = require_module("prelude", context);
495
496 module.insert_invocable("=$$Array$$Array", Expr::foreign_func(&array_eq));
497
498 module.insert_invocable("cons", Expr::foreign_func(&list_cons));
500 module.insert_invocable("count", Expr::foreign_func(&list_count));
501 module.insert_invocable("count$$List", Expr::foreign_func(&list_count));
502
503 module.insert_invocable("push", Expr::foreign_func(&array_push));
505 module.insert_invocable("put$$Array$$Int$$Int", Expr::foreign_func(&array_put));
507 module.insert_invocable("put$$Array$$Int$$Float", Expr::foreign_func(&array_put));
508 module.insert_invocable("concat!", Expr::foreign_func(&array_concat_mut));
512
513 module.insert_invocable("concat", Expr::foreign_func(&array_concat));
514 module.insert_invocable("++", Expr::foreign_func(&array_concat));
515
516 module.insert_invocable("map", Expr::foreign_func_mut_context(&array_map));
521
522 module.insert_invocable("join", Expr::foreign_func(&array_join));
523 module.insert_invocable("skip", Expr::foreign_func(&array_skip));
524 module.insert_invocable("count", Expr::foreign_func(&array_count));
526 module.insert_invocable("count$$Array", Expr::foreign_func(&array_count));
527 module.insert_invocable("contains?", Expr::foreign_func(&array_contains));
529 module.insert_invocable("contains?$$Array$$Int", Expr::foreign_func(&array_contains));
530 module.insert_invocable(
531 "contains?$$Array$$String",
532 Expr::foreign_func(&array_contains),
533 );
534 module.insert_invocable("is-empty?", Expr::foreign_func(&array_is_empty));
535 module.insert_invocable("sort", Expr::foreign_func_mut_context(&array_sort));
536 module.insert_invocable("sort!", Expr::foreign_func_mut_context(&array_sort_mut));
537
538 module.insert_invocable("slice$$Array$$Int", Expr::foreign_func(&array_slice));
542 module.insert_invocable("slice$$Array$$Int$$Int", Expr::foreign_func(&array_slice));
543
544 module.insert_invocable("roll", Expr::foreign_func(&array_roll));
545
546 }
555
556