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