polydat_core/iteration/comprehension/surfaces/
polydat_kernel.rs1use std::sync::Arc;
18
19use crate::ast::Value;
20use crate::iteration::comprehension::strategies::{Tuple, TupleValue};
21use crate::kernel::PolydatKernel;
22
23use super::instance::KernelScope;
24
25#[derive(Debug, Clone)]
39pub struct PolydatKernelScope {
40 canonical: Arc<PolydatKernel>,
41 parent: Arc<PolydatKernel>,
42}
43
44impl PolydatKernelScope {
45 pub fn new(canonical: Arc<PolydatKernel>, parent: Arc<PolydatKernel>) -> Self {
48 Self { canonical, parent }
49 }
50
51 pub fn canonical(&self) -> &Arc<PolydatKernel> {
55 &self.canonical
56 }
57
58 pub fn parent(&self) -> &Arc<PolydatKernel> {
60 &self.parent
61 }
62}
63
64impl KernelScope for PolydatKernelScope {
65 type Scoped = Arc<PolydatKernel>;
69
70 fn scope(&self, coords: &Tuple) -> Arc<PolydatKernel> {
71 let bindings: Vec<(String, Value)> = coords
72 .bindings
73 .iter()
74 .map(|(name, val)| (name.clone(), tuple_value_to_polydat_value(val)))
75 .collect();
76 PolydatKernel::for_iteration(&self.canonical, &self.parent, &bindings)
77 }
78}
79
80pub fn tuple_value_to_polydat_value(val: &TupleValue) -> Value {
91 match val {
92 TupleValue::U64(n) => Value::U64(*n),
93 TupleValue::I64(n) => Value::U64(*n as u64),
94 TupleValue::F64(f) => Value::F64(*f),
95 TupleValue::Str(s) => Value::Str(Arc::from(s.as_str())),
96 TupleValue::Bool(b) => Value::Bool(*b),
97 }
98}
99
100pub fn polydat_value_to_tuple_value(val: &Value) -> Option<TupleValue> {
107 match val {
108 Value::U64(n) => Some(TupleValue::U64(*n)),
109 Value::F64(f) => Some(TupleValue::F64(*f)),
110 Value::Bool(b) => Some(TupleValue::Bool(*b)),
111 Value::Str(s) => Some(TupleValue::Str(s.to_string())),
112 _ => None,
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119
120 #[test]
121 fn tuple_value_to_polydat_round_trips_u64() {
122 let tv = TupleValue::U64(42);
123 let pv = tuple_value_to_polydat_value(&tv);
124 let back = polydat_value_to_tuple_value(&pv).unwrap();
125 assert_eq!(tv, back);
126 }
127
128 #[test]
129 fn tuple_value_to_polydat_round_trips_f64() {
130 let tv = TupleValue::F64(3.14);
131 let pv = tuple_value_to_polydat_value(&tv);
132 let back = polydat_value_to_tuple_value(&pv).unwrap();
133 assert_eq!(tv, back);
134 }
135
136 #[test]
137 fn tuple_value_to_polydat_round_trips_string() {
138 let tv = TupleValue::Str("hello".into());
139 let pv = tuple_value_to_polydat_value(&tv);
140 let back = polydat_value_to_tuple_value(&pv).unwrap();
141 assert_eq!(tv, back);
142 }
143
144 #[test]
145 fn tuple_value_to_polydat_round_trips_bool() {
146 let tv = TupleValue::Bool(true);
147 let pv = tuple_value_to_polydat_value(&tv);
148 let back = polydat_value_to_tuple_value(&pv).unwrap();
149 assert_eq!(tv, back);
150 }
151
152 #[test]
153 fn i64_converts_via_bitcast() {
154 let tv = TupleValue::I64(123);
155 let pv = tuple_value_to_polydat_value(&tv);
156 match pv {
157 Value::U64(n) => assert_eq!(n, 123u64),
158 other => panic!("expected U64, got {other:?}"),
159 }
160 }
161
162 #[test]
163 fn polydat_value_returns_none_for_unsupported_variants() {
164 let pv = Value::Bytes(Arc::from(&b"abc"[..]));
165 assert!(polydat_value_to_tuple_value(&pv).is_none());
166 }
167}