polydat_core/iteration/comprehension/surfaces/
scoped_stream.rs1use std::sync::Arc;
19
20use crate::iteration::comprehension::ir::Program;
21
22use super::coord_stream::CoordinateStream;
23use super::instance::{KernelScope, ScopedKernelInstance};
24use super::scope_once::scope_once_with;
25
26pub struct ScopedKernelStream<K: KernelScope> {
31 coord_stream: CoordinateStream,
34 parent: K,
37}
38
39impl<K: KernelScope> ScopedKernelStream<K> {
40 pub(crate) fn new(program: Arc<Program>, parent: K) -> Self {
41 let coord_stream = CoordinateStream::new(program);
42 Self {
43 coord_stream,
44 parent,
45 }
46 }
47
48 pub fn advance(&mut self) -> Option<ScopedKernelInstance<K::Scoped>> {
55 let coords = self.coord_stream.advance()?;
56 let instance = scope_once_with(&self.parent, &coords);
57 Some(instance)
58 }
59}
60
61impl<K: KernelScope> Iterator for ScopedKernelStream<K> {
62 type Item = ScopedKernelInstance<K::Scoped>;
63 fn next(&mut self) -> Option<Self::Item> {
64 self.advance()
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71 use crate::iteration::comprehension::ast::Comprehension;
72 use crate::iteration::comprehension::source::{LiteralValue, Source};
73 use crate::iteration::comprehension::strategies::{Tuple, TupleValue};
74 use crate::iteration::comprehension::surfaces::compile;
75
76 #[derive(Debug, Clone)]
77 struct MockKernel(String);
78
79 impl KernelScope for MockKernel {
80 type Scoped = (String, Vec<(String, TupleValue)>);
81 fn scope(&self, coords: &Tuple) -> Self::Scoped {
82 (self.0.clone(), coords.bindings.clone())
83 }
84 }
85
86 fn clause(name: &str, vs: &[i64]) -> Comprehension {
87 Comprehension::clause(
88 name,
89 Source::Literal {
90 values: vs.iter().map(|n| LiteralValue::Int(*n)).collect(),
91 },
92 )
93 }
94
95 #[test]
96 fn advance_produces_scoped_instances() {
97 let compiled = compile(&clause("k", &[1, 2, 3]));
98 let parent = MockKernel("p".into());
99 let mut stream = compiled.scoped_kernel_stream(parent);
100 let mut count = 0;
101 while let Some(inst) = stream.advance() {
102 assert_eq!(inst.scoped.0, "p");
103 assert_eq!(inst.coords.bindings.len(), 1);
104 count += 1;
105 }
106 assert_eq!(count, 3);
107 }
108
109 #[test]
110 fn dispense_order_matches_coord_stream() {
111 let compiled = compile(&clause("k", &[10, 20, 30]));
112 let parent = MockKernel("p".into());
113 let coord_values: Vec<TupleValue> = compiled
114 .coordinate_stream()
115 .map(|t| t.bindings[0].1.clone())
116 .collect();
117 let scoped_values: Vec<TupleValue> = compiled
118 .scoped_kernel_stream(parent)
119 .map(|inst| inst.coords.bindings[0].1.clone())
120 .collect();
121 assert_eq!(coord_values, scoped_values);
122 }
123}