use std::sync::Arc;
use crate::iteration::comprehension::strategies::{Tuple, TupleValue};
use crate::kernel::PolydatKernel;
use crate::ast::Value;
use super::instance::KernelScope;
#[derive(Debug, Clone)]
pub struct PolydatKernelScope {
canonical: Arc<PolydatKernel>,
parent: Arc<PolydatKernel>,
}
impl PolydatKernelScope {
pub fn new(canonical: Arc<PolydatKernel>, parent: Arc<PolydatKernel>) -> Self {
Self { canonical, parent }
}
pub fn canonical(&self) -> &Arc<PolydatKernel> {
&self.canonical
}
pub fn parent(&self) -> &Arc<PolydatKernel> {
&self.parent
}
}
impl KernelScope for PolydatKernelScope {
type Scoped = Arc<PolydatKernel>;
fn scope(&self, coords: &Tuple) -> Arc<PolydatKernel> {
let bindings: Vec<(String, Value)> = coords
.bindings
.iter()
.map(|(name, val)| (name.clone(), tuple_value_to_polydat_value(val)))
.collect();
PolydatKernel::for_iteration(&self.canonical, &self.parent, &bindings)
}
}
pub fn tuple_value_to_polydat_value(val: &TupleValue) -> Value {
match val {
TupleValue::U64(n) => Value::U64(*n),
TupleValue::I64(n) => Value::U64(*n as u64),
TupleValue::F64(f) => Value::F64(*f),
TupleValue::Str(s) => Value::Str(Arc::from(s.as_str())),
TupleValue::Bool(b) => Value::Bool(*b),
}
}
pub fn polydat_value_to_tuple_value(val: &Value) -> Option<TupleValue> {
match val {
Value::U64(n) => Some(TupleValue::U64(*n)),
Value::F64(f) => Some(TupleValue::F64(*f)),
Value::Bool(b) => Some(TupleValue::Bool(*b)),
Value::Str(s) => Some(TupleValue::Str(s.to_string())),
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn tuple_value_to_polydat_round_trips_u64() {
let tv = TupleValue::U64(42);
let pv = tuple_value_to_polydat_value(&tv);
let back = polydat_value_to_tuple_value(&pv).unwrap();
assert_eq!(tv, back);
}
#[test]
fn tuple_value_to_polydat_round_trips_f64() {
let tv = TupleValue::F64(3.14);
let pv = tuple_value_to_polydat_value(&tv);
let back = polydat_value_to_tuple_value(&pv).unwrap();
assert_eq!(tv, back);
}
#[test]
fn tuple_value_to_polydat_round_trips_string() {
let tv = TupleValue::Str("hello".into());
let pv = tuple_value_to_polydat_value(&tv);
let back = polydat_value_to_tuple_value(&pv).unwrap();
assert_eq!(tv, back);
}
#[test]
fn tuple_value_to_polydat_round_trips_bool() {
let tv = TupleValue::Bool(true);
let pv = tuple_value_to_polydat_value(&tv);
let back = polydat_value_to_tuple_value(&pv).unwrap();
assert_eq!(tv, back);
}
#[test]
fn i64_converts_via_bitcast() {
let tv = TupleValue::I64(123);
let pv = tuple_value_to_polydat_value(&tv);
match pv {
Value::U64(n) => assert_eq!(n, 123u64),
other => panic!("expected U64, got {other:?}"),
}
}
#[test]
fn polydat_value_returns_none_for_unsupported_variants() {
let pv = Value::Bytes(Arc::from(&b"abc"[..]));
assert!(polydat_value_to_tuple_value(&pv).is_none());
}
}