polydat_core/iteration/comprehension/ir/
program.rs1use serde::{Deserialize, Serialize};
14
15use super::op::Op;
16
17#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
25#[non_exhaustive]
26pub struct Program {
27 ops: Vec<Op>,
28}
29
30impl Program {
31 pub fn new(ops: Vec<Op>) -> Self {
35 Self { ops }
36 }
37
38 pub fn ops(&self) -> &[Op] {
41 &self.ops
42 }
43
44 pub fn len(&self) -> usize {
46 self.ops.len()
47 }
48
49 pub fn is_empty(&self) -> bool {
51 self.ops.is_empty()
52 }
53
54 pub fn stack_depth(&self) -> usize {
58 let mut depth: i64 = 0;
59 let mut max_depth: i64 = 0;
60 for op in &self.ops {
61 let (pop, push) = op.stack_effect();
62 depth -= pop as i64;
63 depth += push as i64;
64 if depth > max_depth {
65 max_depth = depth;
66 }
67 }
68 max_depth as usize
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75 use crate::iteration::comprehension::source::Source;
76 use crate::iteration::comprehension::strategy::ZipMode;
77
78 fn push_clause(name: &str) -> Op {
79 Op::PushClause {
80 name: name.into(),
81 source: Source::Literal { values: vec![] },
82 }
83 }
84
85 #[test]
86 fn stack_depth_simple() {
87 let p = Program::new(vec![
89 push_clause("a"),
90 push_clause("b"),
91 Op::Cartesian { n: 2 },
92 Op::Dispense,
93 ]);
94 assert_eq!(p.stack_depth(), 2);
95 }
96
97 #[test]
98 fn stack_depth_nested() {
99 let p = Program::new(vec![
101 push_clause("a"),
102 push_clause("b"),
103 push_clause("c"),
104 Op::Cartesian { n: 3 },
105 Op::Dispense,
106 ]);
107 assert_eq!(p.stack_depth(), 3);
108 }
109
110 #[test]
111 fn stack_depth_zip_then_cartesian() {
112 let p = Program::new(vec![
114 push_clause("a"),
115 push_clause("b"),
116 Op::Zip {
117 n: 2,
118 mode: ZipMode::Strict,
119 },
120 push_clause("c"),
121 Op::Cartesian { n: 2 },
122 Op::Dispense,
123 ]);
124 assert_eq!(p.stack_depth(), 2);
125 }
126
127 #[test]
128 fn round_trip_serde() {
129 let p = Program::new(vec![push_clause("a"), Op::Dispense]);
130 let json = serde_json::to_string(&p).unwrap();
131 let back: Program = serde_json::from_str(&json).unwrap();
132 assert_eq!(p, back);
133 }
134}