1use crate::error::StdlibError;
58use crate::module::StdlibModule;
59use crate::value::Value;
60
61pub struct ListModule;
63
64impl ListModule {
65 pub fn new() -> Self {
66 Self
67 }
68}
69
70impl Default for ListModule {
71 fn default() -> Self {
72 Self::new()
73 }
74}
75
76impl StdlibModule for ListModule {
77 fn name(&self) -> &'static str {
78 "list"
79 }
80
81 fn has_function(&self, function: &str) -> bool {
82 matches!(
83 function,
84 "empty" | "of" | "repeat" | "range"
86 | "length" | "get" | "first" | "last" | "index_of"
88 | "append" | "prepend" | "insert" | "remove" | "update" | "set"
90 | "slice" | "concat" | "reverse" | "flatten" | "unique"
91 | "map" | "filter" | "reduce" | "find" | "find_index"
93 | "every" | "any" | "some" | "sort" | "count"
94 | "contains" | "zip" | "take" | "drop"
96 )
97 }
98
99 fn call(&self, function: &str, args: Vec<Value>) -> Result<Value, StdlibError> {
100 match function {
101 "empty" => self.empty(args),
103 "of" => self.of(args),
104 "repeat" => self.repeat(args),
105 "range" => self.range(args),
106 "length" => self.length(args),
108 "get" => self.get(args),
109 "first" => self.first(args),
110 "last" => self.last(args),
111 "index_of" => self.index_of(args),
112 "append" => self.append(args),
114 "prepend" => self.prepend(args),
115 "insert" => self.insert(args),
116 "remove" => self.remove(args),
117 "update" | "set" => self.update(args),
118 "slice" => self.slice(args),
119 "concat" => self.concat(args),
120 "reverse" => self.reverse(args),
121 "flatten" => self.flatten(args),
122 "unique" => self.unique(args),
123 "map" => self.map(args),
125 "filter" => self.filter(args),
126 "reduce" => self.reduce(args),
127 "find" => self.find(args),
128 "find_index" => self.find_index(args),
129 "every" => self.every(args),
130 "any" | "some" => self.any(args),
131 "sort" => self.sort(args),
132 "count" => self.count(args),
133 "contains" => self.contains(args),
135 "zip" => self.zip(args),
136 "take" => self.take(args),
137 "drop" => self.drop_fn(args),
138 _ => Err(StdlibError::unknown_function("list", function)),
139 }
140 }
141}
142
143fn expect_list(fn_name: &str, args: &[Value]) -> Result<Vec<Value>, StdlibError> {
147 if args.len() != 1 {
148 return Err(StdlibError::wrong_args(fn_name, 1, args.len()));
149 }
150 match &args[0] {
151 Value::List(items) => Ok(items.clone()),
152 other => Err(StdlibError::type_mismatch(fn_name, 1, "list", other.type_name())),
153 }
154}
155
156fn extract_list(fn_name: &str, val: &Value) -> Result<Vec<Value>, StdlibError> {
158 match val {
159 Value::List(items) => Ok(items.clone()),
160 other => Err(StdlibError::type_mismatch(fn_name, 1, "list", other.type_name())),
161 }
162}
163
164fn extract_index(fn_name: &str, val: &Value, position: usize) -> Result<i64, StdlibError> {
166 match val {
167 Value::Number(n) => {
168 if n.fract() != 0.0 || !n.is_finite() {
169 return Err(StdlibError::RuntimeError(format!(
170 "{fn_name}: index must be a whole number, got {n}"
171 )));
172 }
173 Ok(*n as i64)
174 }
175 other => Err(StdlibError::type_mismatch(fn_name, position, "number", other.type_name())),
176 }
177}
178
179fn extract_number(fn_name: &str, val: &Value, position: usize) -> Result<f64, StdlibError> {
181 match val {
182 Value::Number(n) => Ok(*n),
183 other => Err(StdlibError::type_mismatch(fn_name, position, "number", other.type_name())),
184 }
185}
186
187fn extract_function(
189 fn_name: &str,
190 val: &Value,
191 position: usize,
192) -> Result<crate::value::StdlibFn, StdlibError> {
193 match val {
194 Value::Function(f) => Ok(f.clone()),
195 other => Err(StdlibError::type_mismatch(
196 fn_name,
197 position,
198 "function",
199 other.type_name(),
200 )),
201 }
202}
203
204impl ListModule {
207 fn empty(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
209 if !args.is_empty() {
210 return Err(StdlibError::wrong_args("list.empty", 0, args.len()));
211 }
212 Ok(Value::List(vec![]))
213 }
214
215 fn of(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
217 Ok(Value::List(args))
218 }
219
220 fn repeat(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
222 if args.len() != 2 {
223 return Err(StdlibError::wrong_args("list.repeat", 2, args.len()));
224 }
225 let count = extract_number("list.repeat", &args[1], 2)?;
226 if count.fract() != 0.0 || !count.is_finite() || count < 0.0 {
227 return Err(StdlibError::RuntimeError(
228 "list.repeat: count must be a non-negative integer".to_string(),
229 ));
230 }
231 let count = count as usize;
232 let item = args[0].clone();
233 Ok(Value::List(vec![item; count]))
234 }
235
236 fn range(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
238 if args.len() != 2 {
239 return Err(StdlibError::wrong_args("list.range", 2, args.len()));
240 }
241 let start = extract_number("list.range", &args[0], 1)?;
242 let end = extract_number("list.range", &args[1], 2)?;
243 if start.fract() != 0.0 || end.fract() != 0.0 || !start.is_finite() || !end.is_finite() {
244 return Err(StdlibError::RuntimeError(
245 "list.range: start and end must be integers".to_string(),
246 ));
247 }
248 let start = start as i64;
249 let end = end as i64;
250 if end < start {
251 return Ok(Value::List(vec![]));
252 }
253 let len = (end - start) as usize;
255 if len > 10_000_000 {
256 return Err(StdlibError::RuntimeError(
257 "list.range: range too large (max 10,000,000 elements)".to_string(),
258 ));
259 }
260 let items: Vec<Value> = (start..end).map(|i| Value::Number(i as f64)).collect();
261 Ok(Value::List(items))
262 }
263
264 fn length(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
268 let items = expect_list("list.length", &args)?;
269 Ok(Value::Number(items.len() as f64))
270 }
271
272 fn get(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
274 if args.len() != 2 {
275 return Err(StdlibError::wrong_args("list.get", 2, args.len()));
276 }
277 let items = extract_list("list.get", &args[0])?;
278 let index = extract_index("list.get", &args[1], 2)?;
279 if index < 0 || index as usize >= items.len() {
280 Ok(Value::Nil)
281 } else {
282 Ok(items[index as usize].clone())
283 }
284 }
285
286 fn first(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
288 let items = expect_list("list.first", &args)?;
289 Ok(items.first().cloned().unwrap_or(Value::Nil))
290 }
291
292 fn last(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
294 let items = expect_list("list.last", &args)?;
295 Ok(items.last().cloned().unwrap_or(Value::Nil))
296 }
297
298 fn index_of(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
300 if args.len() != 2 {
301 return Err(StdlibError::wrong_args("list.index_of", 2, args.len()));
302 }
303 let items = extract_list("list.index_of", &args[0])?;
304 let needle = &args[1];
305 let index = items
306 .iter()
307 .position(|v| v == needle)
308 .map(|i| i as f64)
309 .unwrap_or(-1.0);
310 Ok(Value::Number(index))
311 }
312
313 fn append(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
317 if args.len() != 2 {
318 return Err(StdlibError::wrong_args("list.append", 2, args.len()));
319 }
320 let mut items = extract_list("list.append", &args[0])?;
321 items.push(args[1].clone());
322 Ok(Value::List(items))
323 }
324
325 fn prepend(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
327 if args.len() != 2 {
328 return Err(StdlibError::wrong_args("list.prepend", 2, args.len()));
329 }
330 let mut items = extract_list("list.prepend", &args[0])?;
331 items.insert(0, args[1].clone());
332 Ok(Value::List(items))
333 }
334
335 fn insert(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
337 if args.len() != 3 {
338 return Err(StdlibError::wrong_args("list.insert", 3, args.len()));
339 }
340 let mut items = extract_list("list.insert", &args[0])?;
341 let index = extract_index("list.insert", &args[1], 2)?;
342 if index < 0 || index as usize > items.len() {
343 return Err(StdlibError::RuntimeError(format!(
344 "list.insert: index {} out of bounds for list of length {}",
345 index,
346 items.len()
347 )));
348 }
349 items.insert(index as usize, args[2].clone());
350 Ok(Value::List(items))
351 }
352
353 fn remove(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
355 if args.len() != 2 {
356 return Err(StdlibError::wrong_args("list.remove", 2, args.len()));
357 }
358 let mut items = extract_list("list.remove", &args[0])?;
359 let index = extract_index("list.remove", &args[1], 2)?;
360 if index < 0 || index as usize >= items.len() {
361 return Err(StdlibError::RuntimeError(format!(
362 "list.remove: index {} out of bounds for list of length {}",
363 index,
364 items.len()
365 )));
366 }
367 items.remove(index as usize);
368 Ok(Value::List(items))
369 }
370
371 fn update(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
373 if args.len() != 3 {
374 return Err(StdlibError::wrong_args("list.update", 3, args.len()));
375 }
376 let mut items = extract_list("list.update", &args[0])?;
377 let index = extract_index("list.update", &args[1], 2)?;
378 if index < 0 || index as usize >= items.len() {
379 return Err(StdlibError::RuntimeError(format!(
380 "list.update: index {} out of bounds for list of length {}",
381 index,
382 items.len()
383 )));
384 }
385 items[index as usize] = args[2].clone();
386 Ok(Value::List(items))
387 }
388
389 fn slice(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
391 if args.len() != 3 {
392 return Err(StdlibError::wrong_args("list.slice", 3, args.len()));
393 }
394 let items = extract_list("list.slice", &args[0])?;
395 let start = extract_index("list.slice", &args[1], 2)?;
396 let end = extract_index("list.slice", &args[2], 3)?;
397 let len = items.len() as i64;
398 let start = start.clamp(0, len) as usize;
400 let end = end.clamp(0, len) as usize;
401 if start >= end {
402 return Ok(Value::List(vec![]));
403 }
404 Ok(Value::List(items[start..end].to_vec()))
405 }
406
407 fn concat(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
409 if args.len() != 2 {
410 return Err(StdlibError::wrong_args("list.concat", 2, args.len()));
411 }
412 let mut a = extract_list("list.concat", &args[0])?;
413 let b = match &args[1] {
414 Value::List(items) => items.clone(),
415 other => {
416 return Err(StdlibError::type_mismatch(
417 "list.concat",
418 2,
419 "list",
420 other.type_name(),
421 ))
422 }
423 };
424 a.extend(b);
425 Ok(Value::List(a))
426 }
427
428 fn reverse(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
430 let mut items = expect_list("list.reverse", &args)?;
431 items.reverse();
432 Ok(Value::List(items))
433 }
434
435 fn flatten(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
437 let items = expect_list("list.flatten", &args)?;
438 let mut result = Vec::new();
439 for item in items {
440 match item {
441 Value::List(inner) => result.extend(inner),
442 other => result.push(other),
443 }
444 }
445 Ok(Value::List(result))
446 }
447
448 fn unique(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
450 let items = expect_list("list.unique", &args)?;
451 let mut seen = Vec::new();
452 let mut result = Vec::new();
453 for item in items {
454 if !seen.contains(&item) {
455 seen.push(item.clone());
456 result.push(item);
457 }
458 }
459 Ok(Value::List(result))
460 }
461
462 fn map(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
466 if args.len() != 2 {
467 return Err(StdlibError::wrong_args("list.map", 2, args.len()));
468 }
469 let items = extract_list("list.map", &args[0])?;
470 let f = extract_function("list.map", &args[1], 2)?;
471 let mut result = Vec::with_capacity(items.len());
472 for item in items {
473 result.push(f.call(vec![item])?);
474 }
475 Ok(Value::List(result))
476 }
477
478 fn filter(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
480 if args.len() != 2 {
481 return Err(StdlibError::wrong_args("list.filter", 2, args.len()));
482 }
483 let items = extract_list("list.filter", &args[0])?;
484 let pred = extract_function("list.filter", &args[1], 2)?;
485 let mut result = Vec::new();
486 for item in items {
487 let keep = pred.call(vec![item.clone()])?;
488 if keep.is_truthy() {
489 result.push(item);
490 }
491 }
492 Ok(Value::List(result))
493 }
494
495 fn reduce(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
497 if args.len() != 3 {
498 return Err(StdlibError::wrong_args("list.reduce", 3, args.len()));
499 }
500 let items = extract_list("list.reduce", &args[0])?;
501 let mut acc = args[1].clone();
502 let f = extract_function("list.reduce", &args[2], 3)?;
503 for item in items {
504 acc = f.call(vec![acc, item])?;
505 }
506 Ok(acc)
507 }
508
509 fn find(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
511 if args.len() != 2 {
512 return Err(StdlibError::wrong_args("list.find", 2, args.len()));
513 }
514 let items = extract_list("list.find", &args[0])?;
515 let pred = extract_function("list.find", &args[1], 2)?;
516 for item in items {
517 let matches = pred.call(vec![item.clone()])?;
518 if matches.is_truthy() {
519 return Ok(item);
520 }
521 }
522 Ok(Value::Nil)
523 }
524
525 fn find_index(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
527 if args.len() != 2 {
528 return Err(StdlibError::wrong_args("list.find_index", 2, args.len()));
529 }
530 let items = extract_list("list.find_index", &args[0])?;
531 let pred = extract_function("list.find_index", &args[1], 2)?;
532 for (i, item) in items.into_iter().enumerate() {
533 let matches = pred.call(vec![item])?;
534 if matches.is_truthy() {
535 return Ok(Value::Number(i as f64));
536 }
537 }
538 Ok(Value::Number(-1.0))
539 }
540
541 fn every(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
543 if args.len() != 2 {
544 return Err(StdlibError::wrong_args("list.every", 2, args.len()));
545 }
546 let items = extract_list("list.every", &args[0])?;
547 let pred = extract_function("list.every", &args[1], 2)?;
548 for item in items {
549 let result = pred.call(vec![item])?;
550 if !result.is_truthy() {
551 return Ok(Value::Bool(false));
552 }
553 }
554 Ok(Value::Bool(true))
555 }
556
557 fn any(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
560 if args.len() != 2 {
561 return Err(StdlibError::wrong_args("list.any", 2, args.len()));
562 }
563 let items = extract_list("list.any", &args[0])?;
564 let pred = extract_function("list.any", &args[1], 2)?;
565 for item in items {
566 let result = pred.call(vec![item])?;
567 if result.is_truthy() {
568 return Ok(Value::Bool(true));
569 }
570 }
571 Ok(Value::Bool(false))
572 }
573
574 fn sort(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
581 if args.len() != 2 {
582 return Err(StdlibError::wrong_args("list.sort", 2, args.len()));
583 }
584 let mut items = extract_list("list.sort", &args[0])?;
585 let cmp = extract_function("list.sort", &args[1], 2)?;
586
587 let mut sort_error: Option<StdlibError> = None;
590
591 items.sort_by(|a, b| {
592 if sort_error.is_some() {
593 return std::cmp::Ordering::Equal;
594 }
595 match cmp.call(vec![a.clone(), b.clone()]) {
596 Ok(Value::Number(n)) => {
597 if n < 0.0 {
598 std::cmp::Ordering::Less
599 } else if n > 0.0 {
600 std::cmp::Ordering::Greater
601 } else {
602 std::cmp::Ordering::Equal
603 }
604 }
605 Ok(other) => {
606 sort_error = Some(StdlibError::RuntimeError(format!(
607 "list.sort: comparator must return a number, got {}",
608 other.type_name()
609 )));
610 std::cmp::Ordering::Equal
611 }
612 Err(e) => {
613 sort_error = Some(e);
614 std::cmp::Ordering::Equal
615 }
616 }
617 });
618
619 if let Some(e) = sort_error {
620 return Err(e);
621 }
622 Ok(Value::List(items))
623 }
624
625 fn count(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
627 if args.len() != 2 {
628 return Err(StdlibError::wrong_args("list.count", 2, args.len()));
629 }
630 let items = extract_list("list.count", &args[0])?;
631 let pred = extract_function("list.count", &args[1], 2)?;
632 let mut n = 0usize;
633 for item in items {
634 let result = pred.call(vec![item])?;
635 if result.is_truthy() {
636 n += 1;
637 }
638 }
639 Ok(Value::Number(n as f64))
640 }
641
642 fn contains(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
646 if args.len() != 2 {
647 return Err(StdlibError::wrong_args("list.contains", 2, args.len()));
648 }
649 let items = extract_list("list.contains", &args[0])?;
650 let needle = &args[1];
651 Ok(Value::Bool(items.contains(needle)))
652 }
653
654 fn zip(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
659 if args.len() != 2 {
660 return Err(StdlibError::wrong_args("list.zip", 2, args.len()));
661 }
662 let a = extract_list("list.zip", &args[0])?;
663 let b = match &args[1] {
664 Value::List(items) => items.clone(),
665 other => {
666 return Err(StdlibError::type_mismatch(
667 "list.zip",
668 2,
669 "list",
670 other.type_name(),
671 ))
672 }
673 };
674 let result: Vec<Value> = a
675 .into_iter()
676 .zip(b)
677 .map(|(first, second)| {
678 let mut fields = std::collections::BTreeMap::new();
679 fields.insert("first".to_string(), first);
680 fields.insert("second".to_string(), second);
681 Value::record(fields)
682 })
683 .collect();
684 Ok(Value::List(result))
685 }
686
687 fn take(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
689 if args.len() != 2 {
690 return Err(StdlibError::wrong_args("list.take", 2, args.len()));
691 }
692 let items = extract_list("list.take", &args[0])?;
693 let n = extract_number("list.take", &args[1], 2)?;
694 if n.fract() != 0.0 || !n.is_finite() || n < 0.0 {
695 return Err(StdlibError::RuntimeError(
696 "list.take: count must be a non-negative integer".to_string(),
697 ));
698 }
699 let n = (n as usize).min(items.len());
700 Ok(Value::List(items[..n].to_vec()))
701 }
702
703 fn drop_fn(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
708 if args.len() != 2 {
709 return Err(StdlibError::wrong_args("list.drop", 2, args.len()));
710 }
711 let items = extract_list("list.drop", &args[0])?;
712 let n = extract_number("list.drop", &args[1], 2)?;
713 if n.fract() != 0.0 || !n.is_finite() || n < 0.0 {
714 return Err(StdlibError::RuntimeError(
715 "list.drop: count must be a non-negative integer".to_string(),
716 ));
717 }
718 let n = (n as usize).min(items.len());
719 Ok(Value::List(items[n..].to_vec()))
720 }
721}