1use crate::{library::closure::Closure, Array, Boolean, Function, Integer, Map, Reference};
2use intuicio_core::{context::Context, registry::Registry, IntuicioStruct};
3use intuicio_derive::{intuicio_function, intuicio_method, intuicio_methods, IntuicioStruct};
4
5const GENERATOR: &str = "next";
6
7#[intuicio_function(module_name = "iter", use_context, use_registry)]
8pub fn next(context: &mut Context, registry: &Registry, iterator: Reference) -> Reference {
9 let iter = iterator.clone();
10 if let Some(closure) = iterator.read::<Closure>() {
11 closure.invoke(context, registry, &[iter])
12 } else if let Some(map) = iterator.read::<Map>() {
13 map.get(GENERATOR)
14 .unwrap()
15 .read::<Closure>()
16 .unwrap()
17 .invoke(context, registry, &[iter])
18 } else {
19 let closure = {
20 let iterator = iterator.read_object().unwrap();
21 iterator.read_field::<Reference>(GENERATOR).unwrap().clone()
22 };
23 let closure = closure.read::<Closure>().unwrap();
24 closure.invoke(context, registry, &[iter])
25 }
26}
27
28pub fn build_impl(
29 context: &mut Context,
30 registry: &Registry,
31 previous: Option<Reference>,
32 next: &[Reference],
33) -> Reference {
34 if next.is_empty() {
35 return previous.unwrap_or_default();
36 }
37 let current = &next[0];
38 if let Some(current) = current.read::<Array>() {
39 let function = current[0].read::<Function>().unwrap();
40 for argument in current[1..].iter().rev() {
41 context.stack().push(argument.to_owned());
42 }
43 if let Some(previous) = previous {
44 context.stack().push(previous);
45 }
46 function.handle().unwrap().invoke(context, registry);
47 let previous = context.stack().pop::<Reference>().unwrap();
48 build_impl(context, registry, Some(previous), &next[1..])
49 } else {
50 build_impl(context, registry, Some(current.clone()), &next[1..])
51 }
52}
53
54#[intuicio_function(module_name = "iter", use_context, use_registry)]
55pub fn build(context: &mut Context, registry: &Registry, iterators: Reference) -> Reference {
56 let iterators = iterators.read::<Array>().unwrap();
57 build_impl(context, registry, None, &iterators)
58}
59
60#[intuicio_function(module_name = "iter", use_registry)]
61pub fn enumerate(registry: &Registry, iterator: Reference) -> Reference {
62 Reference::new(
63 IterEnumerate {
64 iterator,
65 index: 0,
66 next: Reference::new(
67 Closure {
68 function: Function::by_name("next", "iter_enumerate", registry).unwrap(),
69 captured: vec![],
70 },
71 registry,
72 ),
73 },
74 registry,
75 )
76}
77
78#[intuicio_function(module_name = "iter", use_registry)]
79pub fn walk(registry: &Registry, start: Reference, steps: Reference) -> Reference {
80 Reference::new(
81 IterWalk {
82 current: *start.read::<Integer>().unwrap(),
83 steps: *steps.read::<Integer>().unwrap(),
84 next: Reference::new(
85 Closure {
86 function: Function::by_name("next", "iter_walk", registry).unwrap(),
87 captured: vec![],
88 },
89 registry,
90 ),
91 },
92 registry,
93 )
94}
95
96#[intuicio_function(module_name = "iter", use_registry)]
97pub fn range(registry: &Registry, from: Reference, to: Reference) -> Reference {
98 let from = *from.read::<Integer>().unwrap();
99 let to = *to.read::<Integer>().unwrap();
100 Reference::new(
101 IterWalk {
102 current: from,
103 steps: to - from,
104 next: Reference::new(
105 Closure {
106 function: Function::by_name("next", "iter_walk", registry).unwrap(),
107 captured: vec![],
108 },
109 registry,
110 ),
111 },
112 registry,
113 )
114}
115
116#[intuicio_function(module_name = "iter", use_registry)]
117pub fn range_inclusive(registry: &Registry, from: Reference, to: Reference) -> Reference {
118 let from = *from.read::<Integer>().unwrap();
119 let to = *to.read::<Integer>().unwrap();
120 let steps = to - from;
121 Reference::new(
122 IterWalk {
123 current: from,
124 steps: steps + steps.signum(),
125 next: Reference::new(
126 Closure {
127 function: Function::by_name("next", "iter_walk", registry).unwrap(),
128 captured: vec![],
129 },
130 registry,
131 ),
132 },
133 registry,
134 )
135}
136
137#[intuicio_function(module_name = "iter", use_registry)]
138pub fn filter(registry: &Registry, iterator: Reference, closure: Reference) -> Reference {
139 Reference::new(
140 IterFilter {
141 iterator,
142 closure,
143 next: Reference::new(
144 Closure {
145 function: Function::by_name("next", "iter_filter", registry).unwrap(),
146 captured: vec![],
147 },
148 registry,
149 ),
150 },
151 registry,
152 )
153}
154
155#[intuicio_function(module_name = "iter", use_registry)]
156pub fn map(registry: &Registry, iterator: Reference, closure: Reference) -> Reference {
157 Reference::new(
158 IterMap {
159 iterator,
160 closure,
161 next: Reference::new(
162 Closure {
163 function: Function::by_name("next", "iter_map", registry).unwrap(),
164 captured: vec![],
165 },
166 registry,
167 ),
168 },
169 registry,
170 )
171}
172
173#[intuicio_function(module_name = "iter", use_registry)]
174pub fn filter_map(registry: &Registry, iterator: Reference, closure: Reference) -> Reference {
175 Reference::new(
176 IterFilterMap {
177 iterator,
178 closure,
179 next: Reference::new(
180 Closure {
181 function: Function::by_name("next", "iter_filter_map", registry).unwrap(),
182 captured: vec![],
183 },
184 registry,
185 ),
186 },
187 registry,
188 )
189}
190
191#[intuicio_function(module_name = "iter", use_registry)]
192pub fn flatten(registry: &Registry, iterator: Reference) -> Reference {
193 Reference::new(
194 IterFlatten {
195 iterator,
196 current: Reference::null(),
197 next: Reference::new(
198 Closure {
199 function: Function::by_name("next", "iter_flatten", registry).unwrap(),
200 captured: vec![],
201 },
202 registry,
203 ),
204 },
205 registry,
206 )
207}
208
209#[intuicio_function(module_name = "iter", use_registry)]
210pub fn chain(registry: &Registry, iterators: Reference) -> Reference {
211 Reference::new(
212 IterChain {
213 iterators: iterators.read::<Array>().unwrap().clone(),
214 current: 0,
215 next: Reference::new(
216 Closure {
217 function: Function::by_name("next", "iter_chain", registry).unwrap(),
218 captured: vec![],
219 },
220 registry,
221 ),
222 },
223 registry,
224 )
225}
226
227#[intuicio_function(module_name = "iter", use_registry)]
228pub fn zip(registry: &Registry, iterators: Reference) -> Reference {
229 Reference::new(
230 IterZip {
231 iterators: iterators.read::<Array>().unwrap().clone(),
232 next: Reference::new(
233 Closure {
234 function: Function::by_name("next", "iter_zip", registry).unwrap(),
235 captured: vec![],
236 },
237 registry,
238 ),
239 },
240 registry,
241 )
242}
243
244#[intuicio_function(module_name = "iter", use_registry)]
245pub fn chunks(registry: &Registry, iterator: Reference, count: Reference) -> Reference {
246 Reference::new(
247 IterChunks {
248 iterator,
249 count,
250 next: Reference::new(
251 Closure {
252 function: Function::by_name("next", "iter_chunks", registry).unwrap(),
253 captured: vec![],
254 },
255 registry,
256 ),
257 },
258 registry,
259 )
260}
261
262#[intuicio_function(module_name = "iter", use_context, use_registry)]
263pub fn fold(
264 context: &mut Context,
265 registry: &Registry,
266 iterator: Reference,
267 mut start: Reference,
268 closure: Reference,
269) -> Reference {
270 loop {
271 let value = crate::library::iter::next(context, registry, iterator.clone());
272 if value.is_null() {
273 return start;
274 }
275 let closure = closure.read::<Closure>().unwrap();
276 start = closure.invoke(context, registry, &[start.clone(), value]);
277 }
278}
279
280#[intuicio_function(module_name = "iter", use_context, use_registry)]
281pub fn find(
282 context: &mut Context,
283 registry: &Registry,
284 iterator: Reference,
285 closure: Reference,
286) -> Reference {
287 loop {
288 let value = crate::library::iter::next(context, registry, iterator.clone());
289 if value.is_null() {
290 return value;
291 }
292 let closure = closure.read::<Closure>().unwrap();
293 let result = closure.invoke(context, registry, &[value.clone()]);
294 if *result.read::<Boolean>().unwrap() {
295 return value;
296 }
297 }
298}
299
300#[intuicio_function(module_name = "iter", use_context, use_registry)]
301pub fn find_map(
302 context: &mut Context,
303 registry: &Registry,
304 iterator: Reference,
305 closure: Reference,
306) -> Reference {
307 loop {
308 let value = crate::library::iter::next(context, registry, iterator.clone());
309 if value.is_null() {
310 return value;
311 }
312 let closure = closure.read::<Closure>().unwrap();
313 let result = closure.invoke(context, registry, &[value]);
314 if !result.is_null() {
315 return result;
316 }
317 }
318}
319
320#[intuicio_function(module_name = "iter", use_context, use_registry)]
321pub fn position(
322 context: &mut Context,
323 registry: &Registry,
324 iterator: Reference,
325 closure: Reference,
326) -> Reference {
327 let mut index = 0;
328 loop {
329 let value = crate::library::iter::next(context, registry, iterator.clone());
330 if value.is_null() {
331 return value;
332 }
333 let closure = closure.read::<Closure>().unwrap();
334 let result = closure.invoke(context, registry, &[value]);
335 if *result.read::<Boolean>().unwrap() {
336 return Reference::new_integer(index, registry);
337 }
338 index += 1;
339 }
340}
341
342#[intuicio_function(module_name = "iter", use_context, use_registry)]
343pub fn any(
344 context: &mut Context,
345 registry: &Registry,
346 iterator: Reference,
347 closure: Reference,
348) -> Reference {
349 loop {
350 let value = crate::library::iter::next(context, registry, iterator.clone());
351 if value.is_null() {
352 return Reference::new_boolean(false, registry);
353 }
354 let closure = closure.read::<Closure>().unwrap();
355 let result = closure.invoke(context, registry, &[value]);
356 if *result.read::<Boolean>().unwrap() {
357 return Reference::new_boolean(true, registry);
358 }
359 }
360}
361
362#[intuicio_function(module_name = "iter", use_context, use_registry)]
363pub fn all(
364 context: &mut Context,
365 registry: &Registry,
366 iterator: Reference,
367 closure: Reference,
368) -> Reference {
369 loop {
370 let value = crate::library::iter::next(context, registry, iterator.clone());
371 if value.is_null() {
372 return Reference::new_boolean(true, registry);
373 }
374 let closure = closure.read::<Closure>().unwrap();
375 let result = closure.invoke(context, registry, &[value]);
376 if !*result.read::<Boolean>().unwrap() {
377 return Reference::new_boolean(false, registry);
378 }
379 }
380}
381
382#[intuicio_function(module_name = "iter", use_context, use_registry)]
383pub fn count(context: &mut Context, registry: &Registry, iterator: Reference) -> Reference {
384 let mut result = 0;
385 loop {
386 let value = crate::library::iter::next(context, registry, iterator.clone());
387 if value.is_null() {
388 return Reference::new_integer(result, registry);
389 }
390 result += 1;
391 }
392}
393
394#[intuicio_function(module_name = "iter", use_context, use_registry)]
395pub fn compared_by(
396 context: &mut Context,
397 registry: &Registry,
398 iterator: Reference,
399 closure: Reference,
400) -> Reference {
401 let mut found = crate::library::iter::next(context, registry, iterator.clone());
402 if found.is_null() {
403 return Reference::null();
404 }
405 loop {
406 let value = crate::library::iter::next(context, registry, iterator.clone());
407 if value.is_null() {
408 return found;
409 }
410 let closure = closure.read::<Closure>().unwrap();
411 let result = closure.invoke(context, registry, &[value.clone(), found.clone()]);
412 if *result.read::<Boolean>().unwrap() {
413 found = value;
414 }
415 }
416}
417
418#[derive(IntuicioStruct, Default)]
419#[intuicio(name = "IterWalk", module_name = "iter_walk")]
420pub struct IterWalk {
421 #[intuicio(ignore)]
422 pub current: Integer,
423 #[intuicio(ignore)]
424 pub steps: Integer,
425 pub next: Reference,
426}
427
428#[intuicio_methods(module_name = "iter_walk")]
429impl IterWalk {
430 #[intuicio_method(use_registry)]
431 pub fn next(registry: &Registry, mut iterator: Reference) -> Reference {
432 let mut iterator = iterator.write::<IterWalk>().unwrap();
433 if iterator.steps.abs() == 0 {
434 return Reference::null();
435 }
436 let value = iterator.current;
437 let step = iterator.steps.signum();
438 iterator.current += step;
439 iterator.steps -= step;
440 Reference::new_integer(value, registry)
441 }
442}
443
444#[derive(IntuicioStruct, Default)]
445#[intuicio(name = "Enumeration", module_name = "iter")]
446pub struct Enumeration {
447 pub index: Reference,
448 pub value: Reference,
449}
450
451#[derive(IntuicioStruct, Default)]
452#[intuicio(name = "IterEnumerate", module_name = "iter_enumerate")]
453pub struct IterEnumerate {
454 #[intuicio(ignore)]
455 pub iterator: Reference,
456 #[intuicio(ignore)]
457 pub index: usize,
458 pub next: Reference,
459}
460
461#[intuicio_methods(module_name = "iter_enumerate")]
462impl IterEnumerate {
463 #[intuicio_method(use_context, use_registry)]
464 pub fn next(context: &mut Context, registry: &Registry, mut iterator: Reference) -> Reference {
465 let mut iterator = iterator.write::<IterEnumerate>().unwrap();
466 let value = next(context, registry, iterator.iterator.clone());
467 if value.is_null() {
468 return Reference::null();
469 }
470 let index = iterator.index;
471 iterator.index += 1;
472 Reference::new(
473 Enumeration {
474 index: Reference::new_integer(index as Integer, registry),
475 value,
476 },
477 registry,
478 )
479 }
480}
481
482#[derive(IntuicioStruct, Default)]
483#[intuicio(name = "IterFilter", module_name = "iter_filter")]
484pub struct IterFilter {
485 #[intuicio(ignore)]
486 pub iterator: Reference,
487 #[intuicio(ignore)]
488 pub closure: Reference,
489 pub next: Reference,
490}
491
492#[intuicio_methods(module_name = "iter_filter")]
493impl IterFilter {
494 #[intuicio_method(use_context, use_registry)]
495 pub fn next(context: &mut Context, registry: &Registry, iterator: Reference) -> Reference {
496 let iterator = iterator.read::<IterFilter>().unwrap();
497 loop {
498 let value = next(context, registry, iterator.iterator.clone());
499 if value.is_null() {
500 return value;
501 }
502 let closure = iterator.closure.read::<Closure>().unwrap();
503 let result = closure.invoke(context, registry, &[value.clone()]);
504 if *result.read::<Boolean>().unwrap() {
505 return value;
506 }
507 }
508 }
509}
510
511#[derive(IntuicioStruct, Default)]
512#[intuicio(name = "IterMap", module_name = "iter_map")]
513pub struct IterMap {
514 #[intuicio(ignore)]
515 pub iterator: Reference,
516 #[intuicio(ignore)]
517 pub closure: Reference,
518 pub next: Reference,
519}
520
521#[intuicio_methods(module_name = "iter_map")]
522impl IterMap {
523 #[intuicio_method(use_context, use_registry)]
524 pub fn next(context: &mut Context, registry: &Registry, iterator: Reference) -> Reference {
525 let iterator = iterator.read::<IterMap>().unwrap();
526 let value = next(context, registry, iterator.iterator.clone());
527 if value.is_null() {
528 value
529 } else {
530 let closure = iterator.closure.read::<Closure>().unwrap();
531 closure.invoke(context, registry, &[value])
532 }
533 }
534}
535
536#[derive(IntuicioStruct, Default)]
537#[intuicio(name = "IterMap", module_name = "iter_filter_map")]
538pub struct IterFilterMap {
539 #[intuicio(ignore)]
540 pub iterator: Reference,
541 #[intuicio(ignore)]
542 pub closure: Reference,
543 pub next: Reference,
544}
545
546#[intuicio_methods(module_name = "iter_filter_map")]
547impl IterFilterMap {
548 #[intuicio_method(use_context, use_registry)]
549 pub fn next(context: &mut Context, registry: &Registry, iterator: Reference) -> Reference {
550 let iterator = iterator.read::<IterFilterMap>().unwrap();
551 loop {
552 let value = next(context, registry, iterator.iterator.clone());
553 if value.is_null() {
554 return value;
555 }
556 let closure = iterator.closure.read::<Closure>().unwrap();
557 let result = closure.invoke(context, registry, &[value]);
558 if !result.is_null() {
559 return result;
560 }
561 }
562 }
563}
564
565#[derive(IntuicioStruct, Default)]
566#[intuicio(name = "IterFlatten", module_name = "iter_flatten")]
567pub struct IterFlatten {
568 #[intuicio(ignore)]
569 pub iterator: Reference,
570 #[intuicio(ignore)]
571 pub current: Reference,
572 pub next: Reference,
573}
574
575#[intuicio_methods(module_name = "iter_flatten")]
576impl IterFlatten {
577 #[intuicio_method(use_context, use_registry)]
578 pub fn next(context: &mut Context, registry: &Registry, mut iterator: Reference) -> Reference {
579 let mut iterator = iterator.write::<IterFlatten>().unwrap();
580 loop {
581 if iterator.current.is_null() {
582 iterator.current = next(context, registry, iterator.iterator.clone());
583 if iterator.current.is_null() {
584 return Reference::null();
585 }
586 }
587 let value = next(context, registry, iterator.current.clone());
588 if value.is_null() {
589 iterator.current = Reference::null()
590 } else {
591 return value;
592 }
593 }
594 }
595}
596
597#[derive(IntuicioStruct, Default)]
598#[intuicio(name = "IterChain", module_name = "iter_chain")]
599pub struct IterChain {
600 #[intuicio(ignore)]
601 pub iterators: Array,
602 #[intuicio(ignore)]
603 pub current: usize,
604 pub next: Reference,
605}
606
607#[intuicio_methods(module_name = "iter_chain")]
608impl IterChain {
609 #[intuicio_method(use_context, use_registry)]
610 pub fn next(context: &mut Context, registry: &Registry, mut iterator: Reference) -> Reference {
611 let mut iterator = iterator.write::<IterChain>().unwrap();
612 while let Some(current) = iterator.iterators.get(iterator.current) {
613 let value = next(context, registry, current.clone());
614 if value.is_null() {
615 iterator.current += 1;
616 } else {
617 return value;
618 }
619 }
620 Reference::null()
621 }
622}
623
624#[derive(IntuicioStruct, Default)]
625#[intuicio(name = "IterZip", module_name = "iter_zip")]
626pub struct IterZip {
627 #[intuicio(ignore)]
628 pub iterators: Array,
629 pub next: Reference,
630}
631
632#[intuicio_methods(module_name = "iter_zip")]
633impl IterZip {
634 #[intuicio_method(use_context, use_registry)]
635 pub fn next(context: &mut Context, registry: &Registry, iterator: Reference) -> Reference {
636 let iterator = iterator.read::<IterZip>().unwrap();
637 let result = iterator
638 .iterators
639 .iter()
640 .map(|iterator| next(context, registry, iterator.clone()))
641 .collect::<Array>();
642 if result.iter().any(|value| value.is_null()) {
643 Reference::null()
644 } else {
645 Reference::new_array(result, registry)
646 }
647 }
648}
649
650#[derive(IntuicioStruct, Default)]
651#[intuicio(name = "IterChunks", module_name = "iter_chunks")]
652pub struct IterChunks {
653 #[intuicio(ignore)]
654 pub iterator: Reference,
655 #[intuicio(ignore)]
656 pub count: Reference,
657 pub next: Reference,
658}
659
660#[intuicio_methods(module_name = "iter_chunks")]
661impl IterChunks {
662 #[intuicio_method(use_context, use_registry)]
663 pub fn next(context: &mut Context, registry: &Registry, iterator: Reference) -> Reference {
664 let iterator = iterator.read::<IterChunks>().unwrap();
665 let count = *iterator.count.read::<Integer>().unwrap() as usize;
666 if count == 0 {
667 return Reference::null();
668 }
669 let mut result = Vec::with_capacity(count);
670 for _ in 0..count {
671 let value = next(context, registry, iterator.iterator.clone());
672 if value.is_null() {
673 return Reference::null();
674 }
675 result.push(value);
676 }
677 Reference::new_array(result, registry)
678 }
679}
680
681pub fn install(registry: &mut Registry) {
682 registry.add_function(next::define_function(registry));
683 registry.add_function(build::define_function(registry));
684 registry.add_function(walk::define_function(registry));
685 registry.add_function(range::define_function(registry));
686 registry.add_function(range_inclusive::define_function(registry));
687 registry.add_function(enumerate::define_function(registry));
688 registry.add_function(filter::define_function(registry));
689 registry.add_function(map::define_function(registry));
690 registry.add_function(filter_map::define_function(registry));
691 registry.add_function(flatten::define_function(registry));
692 registry.add_function(chain::define_function(registry));
693 registry.add_function(zip::define_function(registry));
694 registry.add_function(chunks::define_function(registry));
695 registry.add_function(fold::define_function(registry));
696 registry.add_function(find::define_function(registry));
697 registry.add_function(find_map::define_function(registry));
698 registry.add_function(position::define_function(registry));
699 registry.add_function(any::define_function(registry));
700 registry.add_function(all::define_function(registry));
701 registry.add_function(count::define_function(registry));
702 registry.add_function(compared_by::define_function(registry));
703 registry.add_type(IterWalk::define_struct(registry));
704 registry.add_function(IterWalk::next__define_function(registry));
705 registry.add_type(Enumeration::define_struct(registry));
706 registry.add_type(IterEnumerate::define_struct(registry));
707 registry.add_function(IterEnumerate::next__define_function(registry));
708 registry.add_type(IterFilter::define_struct(registry));
709 registry.add_function(IterFilter::next__define_function(registry));
710 registry.add_type(IterMap::define_struct(registry));
711 registry.add_function(IterMap::next__define_function(registry));
712 registry.add_type(IterFilterMap::define_struct(registry));
713 registry.add_function(IterFilterMap::next__define_function(registry));
714 registry.add_type(IterFlatten::define_struct(registry));
715 registry.add_function(IterFlatten::next__define_function(registry));
716 registry.add_type(IterChain::define_struct(registry));
717 registry.add_function(IterChain::next__define_function(registry));
718 registry.add_type(IterZip::define_struct(registry));
719 registry.add_function(IterZip::next__define_function(registry));
720 registry.add_type(IterChunks::define_struct(registry));
721 registry.add_function(IterChunks::next__define_function(registry));
722}