1use bock_interp::{
9 BuiltinRegistry, IteratorKind, IteratorNext, IteratorValue, RuntimeError, TypeTag, Value,
10};
11
12pub fn register(registry: &mut BuiltinRegistry) {
14 registry.register(TypeTag::List, "iter", list_iter);
16 registry.register(TypeTag::Set, "iter", set_iter);
17 registry.register(TypeTag::Map, "iter", map_iter);
18 registry.register(TypeTag::Range, "iter", range_iter);
19
20 registry.register(TypeTag::Iterator, "next", iter_next);
22 registry.register(TypeTag::Iterator, "map", iter_map);
23 registry.register(TypeTag::Iterator, "filter", iter_filter);
24 registry.register(TypeTag::Iterator, "take", iter_take);
25 registry.register(TypeTag::Iterator, "skip", iter_skip);
26 registry.register(TypeTag::Iterator, "enumerate", iter_enumerate);
27 registry.register(TypeTag::Iterator, "zip", iter_zip);
28 registry.register(TypeTag::Iterator, "chain", iter_chain);
29 registry.register(TypeTag::Iterator, "collect", iter_collect);
30}
31
32fn expect_iterator(args: &[Value], method: &str) -> Result<IteratorValue, RuntimeError> {
35 match args.first() {
36 Some(Value::Iterator(it)) => Ok(it.clone()),
37 Some(other) => Err(RuntimeError::TypeError(format!(
38 "Iterator.{method} expects Iterator, got {other}"
39 ))),
40 None => Err(RuntimeError::ArityMismatch {
41 expected: 1,
42 got: 0,
43 }),
44 }
45}
46
47fn expect_int(args: &[Value], pos: usize, method: &str) -> Result<i64, RuntimeError> {
48 match args.get(pos) {
49 Some(Value::Int(v)) => Ok(*v),
50 Some(other) => Err(RuntimeError::TypeError(format!(
51 "Iterator.{method} expects Int, got {other}"
52 ))),
53 None => Err(RuntimeError::ArityMismatch {
54 expected: pos + 1,
55 got: args.len(),
56 }),
57 }
58}
59
60fn expect_fn_value(
61 args: &[Value],
62 pos: usize,
63 method: &str,
64) -> Result<bock_interp::FnValue, RuntimeError> {
65 match args.get(pos) {
66 Some(Value::Function(f)) => Ok(f.clone()),
67 Some(other) => Err(RuntimeError::TypeError(format!(
68 "Iterator.{method} expects Function, got {other}"
69 ))),
70 None => Err(RuntimeError::ArityMismatch {
71 expected: pos + 1,
72 got: args.len(),
73 }),
74 }
75}
76
77fn list_iter(args: &[Value]) -> Result<Value, RuntimeError> {
80 match args.first() {
81 Some(Value::List(items)) => Ok(Value::Iterator(IteratorValue::new(IteratorKind::List {
82 items: items.clone(),
83 pos: 0,
84 }))),
85 Some(other) => Err(RuntimeError::TypeError(format!(
86 "List.iter expects List, got {other}"
87 ))),
88 None => Err(RuntimeError::ArityMismatch {
89 expected: 1,
90 got: 0,
91 }),
92 }
93}
94
95fn set_iter(args: &[Value]) -> Result<Value, RuntimeError> {
96 match args.first() {
97 Some(Value::Set(set)) => {
98 let items: Vec<Value> = set.iter().cloned().collect();
99 Ok(Value::Iterator(IteratorValue::new(IteratorKind::Set {
100 items,
101 pos: 0,
102 })))
103 }
104 Some(other) => Err(RuntimeError::TypeError(format!(
105 "Set.iter expects Set, got {other}"
106 ))),
107 None => Err(RuntimeError::ArityMismatch {
108 expected: 1,
109 got: 0,
110 }),
111 }
112}
113
114fn map_iter(args: &[Value]) -> Result<Value, RuntimeError> {
115 match args.first() {
116 Some(Value::Map(map)) => {
117 let items: Vec<(Value, Value)> =
118 map.iter().map(|(k, v)| (k.clone(), v.clone())).collect();
119 Ok(Value::Iterator(IteratorValue::new(
120 IteratorKind::MapEntries { items, pos: 0 },
121 )))
122 }
123 Some(other) => Err(RuntimeError::TypeError(format!(
124 "Map.iter expects Map, got {other}"
125 ))),
126 None => Err(RuntimeError::ArityMismatch {
127 expected: 1,
128 got: 0,
129 }),
130 }
131}
132
133fn range_iter(args: &[Value]) -> Result<Value, RuntimeError> {
134 match args.first() {
135 Some(Value::Range {
136 start,
137 end,
138 inclusive,
139 step,
140 }) => Ok(Value::Iterator(IteratorValue::new(IteratorKind::Range {
141 current: *start,
142 end: *end,
143 inclusive: *inclusive,
144 step: *step,
145 }))),
146 Some(other) => Err(RuntimeError::TypeError(format!(
147 "Range.iter expects Range, got {other}"
148 ))),
149 None => Err(RuntimeError::ArityMismatch {
150 expected: 1,
151 got: 0,
152 }),
153 }
154}
155
156fn iter_next(args: &[Value]) -> Result<Value, RuntimeError> {
159 let it = expect_iterator(args, "next")?;
160 let mut kind = it.kind.lock().unwrap();
161 match kind.next() {
162 IteratorNext::Some(val) => Ok(Value::Optional(Some(Box::new(val)))),
163 IteratorNext::Done => Ok(Value::Optional(None)),
164 IteratorNext::NeedsMapCallback { .. } | IteratorNext::NeedsFilterCallback { .. } => {
165 Err(RuntimeError::TypeError(
166 "Iterator.next on map/filter combinator requires interpreter support \
167 (not available from builtin dispatch)"
168 .to_string(),
169 ))
170 }
171 }
172}
173
174fn iter_map(args: &[Value]) -> Result<Value, RuntimeError> {
175 let it = expect_iterator(args, "map")?;
176 let func = expect_fn_value(args, 1, "map")?;
177 Ok(Value::Iterator(IteratorValue::new(IteratorKind::Map {
178 source: it.kind.clone(),
179 func,
180 })))
181}
182
183fn iter_filter(args: &[Value]) -> Result<Value, RuntimeError> {
184 let it = expect_iterator(args, "filter")?;
185 let func = expect_fn_value(args, 1, "filter")?;
186 Ok(Value::Iterator(IteratorValue::new(IteratorKind::Filter {
187 source: it.kind.clone(),
188 pred: func,
189 })))
190}
191
192fn iter_take(args: &[Value]) -> Result<Value, RuntimeError> {
193 let it = expect_iterator(args, "take")?;
194 let n = expect_int(args, 1, "take")?;
195 let n = n.max(0) as usize;
196 Ok(Value::Iterator(IteratorValue::new(IteratorKind::Take {
197 source: it.kind.clone(),
198 remaining: n,
199 })))
200}
201
202fn iter_skip(args: &[Value]) -> Result<Value, RuntimeError> {
203 let it = expect_iterator(args, "skip")?;
204 let n = expect_int(args, 1, "skip")?;
205 let n = n.max(0) as usize;
206 Ok(Value::Iterator(IteratorValue::new(IteratorKind::Skip {
207 source: it.kind.clone(),
208 to_skip: n,
209 skipped: false,
210 })))
211}
212
213fn iter_enumerate(args: &[Value]) -> Result<Value, RuntimeError> {
214 let it = expect_iterator(args, "enumerate")?;
215 Ok(Value::Iterator(IteratorValue::new(
216 IteratorKind::Enumerate {
217 source: it.kind.clone(),
218 index: 0,
219 },
220 )))
221}
222
223fn iter_zip(args: &[Value]) -> Result<Value, RuntimeError> {
224 let it = expect_iterator(args, "zip")?;
225 let other = match args.get(1) {
226 Some(Value::Iterator(other)) => other.clone(),
227 Some(other) => {
228 return Err(RuntimeError::TypeError(format!(
229 "Iterator.zip expects Iterator, got {other}"
230 )))
231 }
232 None => {
233 return Err(RuntimeError::ArityMismatch {
234 expected: 2,
235 got: 1,
236 })
237 }
238 };
239 Ok(Value::Iterator(IteratorValue::new(IteratorKind::Zip {
240 a: it.kind.clone(),
241 b: other.kind.clone(),
242 })))
243}
244
245fn iter_chain(args: &[Value]) -> Result<Value, RuntimeError> {
246 let it = expect_iterator(args, "chain")?;
247 let other = match args.get(1) {
248 Some(Value::Iterator(other)) => other.clone(),
249 Some(other) => {
250 return Err(RuntimeError::TypeError(format!(
251 "Iterator.chain expects Iterator, got {other}"
252 )))
253 }
254 None => {
255 return Err(RuntimeError::ArityMismatch {
256 expected: 2,
257 got: 1,
258 })
259 }
260 };
261 Ok(Value::Iterator(IteratorValue::new(IteratorKind::Chain {
262 a: it.kind.clone(),
263 b: other.kind.clone(),
264 first_done: false,
265 })))
266}
267
268fn iter_collect(args: &[Value]) -> Result<Value, RuntimeError> {
269 let it = expect_iterator(args, "collect")?;
270 let mut result = Vec::new();
271 loop {
272 let mut kind = it.kind.lock().unwrap();
273 match kind.next() {
274 IteratorNext::Some(val) => result.push(val),
275 IteratorNext::Done => break,
276 IteratorNext::NeedsMapCallback { .. } | IteratorNext::NeedsFilterCallback { .. } => {
277 return Err(RuntimeError::TypeError(
278 "Iterator.collect on map/filter combinator requires interpreter support \
279 (not available from builtin dispatch)"
280 .to_string(),
281 ));
282 }
283 }
284 }
285 Ok(Value::List(result))
286}
287
288#[cfg(test)]
291mod tests {
292 use super::*;
293 use std::collections::{BTreeMap, BTreeSet};
294
295 fn reg() -> BuiltinRegistry {
296 let mut r = BuiltinRegistry::new();
297 register(&mut r);
298 r
299 }
300
301 fn list(vals: &[i64]) -> Value {
302 Value::List(vals.iter().map(|&v| Value::Int(v)).collect())
303 }
304
305 fn range(start: i64, end: i64, inclusive: bool) -> Value {
306 Value::Range {
307 start,
308 end,
309 inclusive,
310 step: 1,
311 }
312 }
313
314 #[test]
317 fn list_iter_creates_iterator() {
318 let r = reg();
319 let result = r.call(TypeTag::List, "iter", &[list(&[1, 2, 3])]);
320 assert!(matches!(result.unwrap().unwrap(), Value::Iterator(_)));
321 }
322
323 #[test]
324 fn range_iter_creates_iterator() {
325 let r = reg();
326 let result = r.call(TypeTag::Range, "iter", &[range(0, 3, false)]);
327 assert!(matches!(result.unwrap().unwrap(), Value::Iterator(_)));
328 }
329
330 #[test]
331 fn set_iter_creates_iterator() {
332 let r = reg();
333 let mut set = BTreeSet::new();
334 set.insert(Value::Int(1));
335 set.insert(Value::Int(2));
336 let result = r.call(TypeTag::Set, "iter", &[Value::Set(set)]);
337 assert!(matches!(result.unwrap().unwrap(), Value::Iterator(_)));
338 }
339
340 #[test]
341 fn map_iter_creates_iterator() {
342 let r = reg();
343 let mut map = BTreeMap::new();
344 map.insert(Value::Int(1), Value::Int(10));
345 let result = r.call(TypeTag::Map, "iter", &[Value::Map(map)]);
346 assert!(matches!(result.unwrap().unwrap(), Value::Iterator(_)));
347 }
348
349 #[test]
352 fn next_returns_elements_then_none() {
353 let r = reg();
354 let iter_val = r
355 .call(TypeTag::List, "iter", &[list(&[10, 20])])
356 .unwrap()
357 .unwrap();
358
359 let first = r
360 .call(TypeTag::Iterator, "next", &[iter_val.clone()])
361 .unwrap()
362 .unwrap();
363 assert_eq!(first, Value::Optional(Some(Box::new(Value::Int(10)))));
364
365 let second = r
366 .call(TypeTag::Iterator, "next", &[iter_val.clone()])
367 .unwrap()
368 .unwrap();
369 assert_eq!(second, Value::Optional(Some(Box::new(Value::Int(20)))));
370
371 let third = r
372 .call(TypeTag::Iterator, "next", &[iter_val])
373 .unwrap()
374 .unwrap();
375 assert_eq!(third, Value::Optional(None));
376 }
377
378 #[test]
379 fn range_iter_produces_values() {
380 let r = reg();
381 let iter_val = r
382 .call(TypeTag::Range, "iter", &[range(1, 4, false)])
383 .unwrap()
384 .unwrap();
385
386 let mut results = Vec::new();
387 loop {
388 let v = r
389 .call(TypeTag::Iterator, "next", &[iter_val.clone()])
390 .unwrap()
391 .unwrap();
392 match v {
393 Value::Optional(Some(val)) => results.push(*val),
394 Value::Optional(None) => break,
395 _ => panic!("unexpected"),
396 }
397 }
398 assert_eq!(results, vec![Value::Int(1), Value::Int(2), Value::Int(3)]);
399 }
400
401 #[test]
402 fn range_inclusive_iter() {
403 let r = reg();
404 let iter_val = r
405 .call(TypeTag::Range, "iter", &[range(1, 3, true)])
406 .unwrap()
407 .unwrap();
408
409 let mut results = Vec::new();
410 loop {
411 let v = r
412 .call(TypeTag::Iterator, "next", &[iter_val.clone()])
413 .unwrap()
414 .unwrap();
415 match v {
416 Value::Optional(Some(val)) => results.push(*val),
417 Value::Optional(None) => break,
418 _ => panic!("unexpected"),
419 }
420 }
421 assert_eq!(results, vec![Value::Int(1), Value::Int(2), Value::Int(3)]);
422 }
423
424 #[test]
427 fn collect_drains_into_list() {
428 let r = reg();
429 let iter_val = r
430 .call(TypeTag::List, "iter", &[list(&[1, 2, 3])])
431 .unwrap()
432 .unwrap();
433 let collected = r
434 .call(TypeTag::Iterator, "collect", &[iter_val])
435 .unwrap()
436 .unwrap();
437 assert_eq!(collected, list(&[1, 2, 3]));
438 }
439
440 #[test]
441 fn collect_range_iter() {
442 let r = reg();
443 let iter_val = r
444 .call(TypeTag::Range, "iter", &[range(0, 3, false)])
445 .unwrap()
446 .unwrap();
447 let collected = r
448 .call(TypeTag::Iterator, "collect", &[iter_val])
449 .unwrap()
450 .unwrap();
451 assert_eq!(collected, list(&[0, 1, 2]));
452 }
453
454 #[test]
457 fn take_limits_elements() {
458 let r = reg();
459 let iter_val = r
460 .call(TypeTag::List, "iter", &[list(&[1, 2, 3, 4, 5])])
461 .unwrap()
462 .unwrap();
463 let taken = r
464 .call(TypeTag::Iterator, "take", &[iter_val, Value::Int(3)])
465 .unwrap()
466 .unwrap();
467 let collected = r
468 .call(TypeTag::Iterator, "collect", &[taken])
469 .unwrap()
470 .unwrap();
471 assert_eq!(collected, list(&[1, 2, 3]));
472 }
473
474 #[test]
475 fn take_zero() {
476 let r = reg();
477 let iter_val = r
478 .call(TypeTag::List, "iter", &[list(&[1, 2])])
479 .unwrap()
480 .unwrap();
481 let taken = r
482 .call(TypeTag::Iterator, "take", &[iter_val, Value::Int(0)])
483 .unwrap()
484 .unwrap();
485 let collected = r
486 .call(TypeTag::Iterator, "collect", &[taken])
487 .unwrap()
488 .unwrap();
489 assert_eq!(collected, list(&[]));
490 }
491
492 #[test]
495 fn skip_elements() {
496 let r = reg();
497 let iter_val = r
498 .call(TypeTag::List, "iter", &[list(&[1, 2, 3, 4, 5])])
499 .unwrap()
500 .unwrap();
501 let skipped = r
502 .call(TypeTag::Iterator, "skip", &[iter_val, Value::Int(2)])
503 .unwrap()
504 .unwrap();
505 let collected = r
506 .call(TypeTag::Iterator, "collect", &[skipped])
507 .unwrap()
508 .unwrap();
509 assert_eq!(collected, list(&[3, 4, 5]));
510 }
511
512 #[test]
513 fn skip_all() {
514 let r = reg();
515 let iter_val = r
516 .call(TypeTag::List, "iter", &[list(&[1, 2])])
517 .unwrap()
518 .unwrap();
519 let skipped = r
520 .call(TypeTag::Iterator, "skip", &[iter_val, Value::Int(10)])
521 .unwrap()
522 .unwrap();
523 let collected = r
524 .call(TypeTag::Iterator, "collect", &[skipped])
525 .unwrap()
526 .unwrap();
527 assert_eq!(collected, list(&[]));
528 }
529
530 #[test]
533 fn enumerate_adds_index() {
534 let r = reg();
535 let iter_val = r
536 .call(TypeTag::List, "iter", &[list(&[10, 20, 30])])
537 .unwrap()
538 .unwrap();
539 let enumerated = r
540 .call(TypeTag::Iterator, "enumerate", &[iter_val])
541 .unwrap()
542 .unwrap();
543 let collected = r
544 .call(TypeTag::Iterator, "collect", &[enumerated])
545 .unwrap()
546 .unwrap();
547 let expected = Value::List(vec![
548 Value::Tuple(vec![Value::Int(0), Value::Int(10)]),
549 Value::Tuple(vec![Value::Int(1), Value::Int(20)]),
550 Value::Tuple(vec![Value::Int(2), Value::Int(30)]),
551 ]);
552 assert_eq!(collected, expected);
553 }
554
555 #[test]
558 fn zip_two_iterators() {
559 let r = reg();
560 let iter_a = r
561 .call(TypeTag::List, "iter", &[list(&[1, 2, 3])])
562 .unwrap()
563 .unwrap();
564 let iter_b = r
565 .call(TypeTag::List, "iter", &[list(&[10, 20])])
566 .unwrap()
567 .unwrap();
568 let zipped = r
569 .call(TypeTag::Iterator, "zip", &[iter_a, iter_b])
570 .unwrap()
571 .unwrap();
572 let collected = r
573 .call(TypeTag::Iterator, "collect", &[zipped])
574 .unwrap()
575 .unwrap();
576 let expected = Value::List(vec![
577 Value::Tuple(vec![Value::Int(1), Value::Int(10)]),
578 Value::Tuple(vec![Value::Int(2), Value::Int(20)]),
579 ]);
580 assert_eq!(collected, expected);
581 }
582
583 #[test]
586 fn chain_two_iterators() {
587 let r = reg();
588 let iter_a = r
589 .call(TypeTag::List, "iter", &[list(&[1, 2])])
590 .unwrap()
591 .unwrap();
592 let iter_b = r
593 .call(TypeTag::List, "iter", &[list(&[3, 4])])
594 .unwrap()
595 .unwrap();
596 let chained = r
597 .call(TypeTag::Iterator, "chain", &[iter_a, iter_b])
598 .unwrap()
599 .unwrap();
600 let collected = r
601 .call(TypeTag::Iterator, "collect", &[chained])
602 .unwrap()
603 .unwrap();
604 assert_eq!(collected, list(&[1, 2, 3, 4]));
605 }
606
607 #[test]
610 fn take_is_lazy_does_not_consume_all() {
611 let it = IteratorValue::new(IteratorKind::List {
614 items: vec![Value::Int(1), Value::Int(2), Value::Int(3), Value::Int(4)],
615 pos: 0,
616 });
617 let take_kind = IteratorKind::Take {
618 source: it.kind.clone(),
619 remaining: 2,
620 };
621 let take_it = IteratorValue::new(take_kind);
622
623 let r = reg();
625 let collected = r
626 .call(TypeTag::Iterator, "collect", &[Value::Iterator(take_it)])
627 .unwrap()
628 .unwrap();
629 assert_eq!(collected, list(&[1, 2]));
630
631 let remaining = r
633 .call(TypeTag::Iterator, "next", &[Value::Iterator(it)])
634 .unwrap()
635 .unwrap();
636 assert_eq!(remaining, Value::Optional(Some(Box::new(Value::Int(3)))));
637 }
638
639 #[test]
642 fn skip_then_take() {
643 let r = reg();
644 let iter_val = r
645 .call(TypeTag::List, "iter", &[list(&[1, 2, 3, 4, 5])])
646 .unwrap()
647 .unwrap();
648 let skipped = r
649 .call(TypeTag::Iterator, "skip", &[iter_val, Value::Int(1)])
650 .unwrap()
651 .unwrap();
652 let taken = r
653 .call(TypeTag::Iterator, "take", &[skipped, Value::Int(2)])
654 .unwrap()
655 .unwrap();
656 let collected = r
657 .call(TypeTag::Iterator, "collect", &[taken])
658 .unwrap()
659 .unwrap();
660 assert_eq!(collected, list(&[2, 3]));
661 }
662
663 #[test]
664 fn enumerate_then_take() {
665 let r = reg();
666 let iter_val = r
667 .call(TypeTag::List, "iter", &[list(&[10, 20, 30])])
668 .unwrap()
669 .unwrap();
670 let enumerated = r
671 .call(TypeTag::Iterator, "enumerate", &[iter_val])
672 .unwrap()
673 .unwrap();
674 let taken = r
675 .call(TypeTag::Iterator, "take", &[enumerated, Value::Int(2)])
676 .unwrap()
677 .unwrap();
678 let collected = r
679 .call(TypeTag::Iterator, "collect", &[taken])
680 .unwrap()
681 .unwrap();
682 let expected = Value::List(vec![
683 Value::Tuple(vec![Value::Int(0), Value::Int(10)]),
684 Value::Tuple(vec![Value::Int(1), Value::Int(20)]),
685 ]);
686 assert_eq!(collected, expected);
687 }
688
689 #[test]
692 fn map_creates_lazy_iterator() {
693 let r = reg();
694 let iter_val = r
695 .call(TypeTag::List, "iter", &[list(&[1, 2])])
696 .unwrap()
697 .unwrap();
698 let func = Value::Function(bock_interp::FnValue::new_named("double"));
699 let mapped = r
700 .call(TypeTag::Iterator, "map", &[iter_val, func])
701 .unwrap()
702 .unwrap();
703 assert!(matches!(mapped, Value::Iterator(_)));
705 }
706
707 #[test]
708 fn filter_creates_lazy_iterator() {
709 let r = reg();
710 let iter_val = r
711 .call(TypeTag::List, "iter", &[list(&[1, 2])])
712 .unwrap()
713 .unwrap();
714 let pred = Value::Function(bock_interp::FnValue::new_named("is_even"));
715 let filtered = r
716 .call(TypeTag::Iterator, "filter", &[iter_val, pred])
717 .unwrap()
718 .unwrap();
719 assert!(matches!(filtered, Value::Iterator(_)));
720 }
721
722 #[test]
725 fn map_entries_as_tuples() {
726 let r = reg();
727 let mut map = BTreeMap::new();
728 map.insert(Value::Int(1), Value::Int(10));
729 map.insert(Value::Int(2), Value::Int(20));
730 let iter_val = r
731 .call(TypeTag::Map, "iter", &[Value::Map(map)])
732 .unwrap()
733 .unwrap();
734 let collected = r
735 .call(TypeTag::Iterator, "collect", &[iter_val])
736 .unwrap()
737 .unwrap();
738 let expected = Value::List(vec![
739 Value::Tuple(vec![Value::Int(1), Value::Int(10)]),
740 Value::Tuple(vec![Value::Int(2), Value::Int(20)]),
741 ]);
742 assert_eq!(collected, expected);
743 }
744
745 #[test]
748 fn set_iter_collects_sorted() {
749 let r = reg();
750 let mut set = BTreeSet::new();
751 set.insert(Value::Int(3));
752 set.insert(Value::Int(1));
753 set.insert(Value::Int(2));
754 let iter_val = r
755 .call(TypeTag::Set, "iter", &[Value::Set(set)])
756 .unwrap()
757 .unwrap();
758 let collected = r
759 .call(TypeTag::Iterator, "collect", &[iter_val])
760 .unwrap()
761 .unwrap();
762 assert_eq!(collected, list(&[1, 2, 3]));
763 }
764
765 #[test]
768 fn map_requires_function() {
769 let r = reg();
770 let iter_val = r
771 .call(TypeTag::List, "iter", &[list(&[1])])
772 .unwrap()
773 .unwrap();
774 let result = r.call(TypeTag::Iterator, "map", &[iter_val, Value::Int(0)]);
775 assert!(matches!(result.unwrap(), Err(RuntimeError::TypeError(_))));
776 }
777
778 #[test]
779 fn filter_requires_function() {
780 let r = reg();
781 let iter_val = r
782 .call(TypeTag::List, "iter", &[list(&[1])])
783 .unwrap()
784 .unwrap();
785 let result = r.call(TypeTag::Iterator, "filter", &[iter_val, Value::Int(0)]);
786 assert!(matches!(result.unwrap(), Err(RuntimeError::TypeError(_))));
787 }
788
789 #[test]
790 fn zip_requires_iterator() {
791 let r = reg();
792 let iter_val = r
793 .call(TypeTag::List, "iter", &[list(&[1])])
794 .unwrap()
795 .unwrap();
796 let result = r.call(TypeTag::Iterator, "zip", &[iter_val, Value::Int(0)]);
797 assert!(matches!(result.unwrap(), Err(RuntimeError::TypeError(_))));
798 }
799
800 #[test]
801 fn chain_requires_iterator() {
802 let r = reg();
803 let iter_val = r
804 .call(TypeTag::List, "iter", &[list(&[1])])
805 .unwrap()
806 .unwrap();
807 let result = r.call(TypeTag::Iterator, "chain", &[iter_val, Value::Int(0)]);
808 assert!(matches!(result.unwrap(), Err(RuntimeError::TypeError(_))));
809 }
810}