use serde::{Deserialize, Serialize};
use crate::iteration::comprehension::source::Source;
use crate::iteration::comprehension::strategy::{StrategyName, ZipMode};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "op", rename_all = "snake_case")]
pub enum Op {
PushClause {
name: String,
source: Source,
},
Cartesian {
n: usize,
},
Zip {
n: usize,
mode: ZipMode,
},
Union {
n: usize,
},
Filter {
predicate: String,
},
OrderStreaming {
kind: OrderStreamingKind,
truncation: Option<u64>,
},
OrderMaterialize {
strategy: StrategyName,
truncation: Option<u64>,
indexed: bool,
input_index_fn: Option<crate::iteration::comprehension::metadata::IndexFn>,
},
Dispense,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum OrderStreamingKind {
Lex,
}
impl Op {
pub fn stack_effect(&self) -> (usize, usize) {
match self {
Op::PushClause { .. } => (0, 1),
Op::Cartesian { n } => (*n, 1),
Op::Zip { n, .. } => (*n, 1),
Op::Union { n } => (*n, 1),
Op::Filter { .. } => (1, 1),
Op::OrderStreaming { .. } => (1, 1),
Op::OrderMaterialize { .. } => (1, 1),
Op::Dispense => (1, 0),
}
}
pub fn is_barrier(&self) -> bool {
matches!(
self,
Op::OrderMaterialize { .. }
| Op::Zip {
mode: ZipMode::Cycle,
..
}
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn stack_effect_basics() {
assert_eq!(
Op::PushClause {
name: "k".into(),
source: Source::Literal { values: vec![] },
}
.stack_effect(),
(0, 1)
);
assert_eq!(Op::Cartesian { n: 3 }.stack_effect(), (3, 1));
assert_eq!(Op::Dispense.stack_effect(), (1, 0));
}
#[test]
fn barrier_classification() {
assert!(
Op::OrderMaterialize {
strategy: StrategyName::Halton,
truncation: Some(10),
indexed: true,
input_index_fn: None,
}
.is_barrier()
);
assert!(
Op::Zip {
n: 2,
mode: ZipMode::Cycle
}
.is_barrier()
);
assert!(
!Op::Zip {
n: 2,
mode: ZipMode::Strict
}
.is_barrier()
);
assert!(
!Op::OrderStreaming {
kind: OrderStreamingKind::Lex,
truncation: None,
}
.is_barrier()
);
}
#[test]
fn serde_round_trip() {
let op = Op::OrderMaterialize {
strategy: StrategyName::Halton,
truncation: Some(50),
indexed: true,
input_index_fn: Some(
crate::iteration::comprehension::metadata::IndexFn::Lattice {
axis_sizes: vec![10, 5],
},
),
};
let json = serde_json::to_string(&op).unwrap();
let back: Op = serde_json::from_str(&json).unwrap();
assert_eq!(op, back);
}
}