1use super::{BinaryOperator, Expr, Literal, TemporalKeyword, UnaryOperator};
7
8pub trait Visitor<T> {
33 fn visit_expr(&mut self, expr: &Expr) -> T;
35
36 fn visit_literal(&mut self, lit: &Literal) -> T;
38
39 fn visit_null(&mut self) -> T;
41
42 fn visit_identifier(&mut self, name: &str) -> T;
44
45 fn visit_field_access(&mut self, receiver: &Expr, field: &str) -> T;
47
48 fn visit_binary_op(&mut self, op: BinaryOperator, left: &Expr, right: &Expr) -> T;
50
51 fn visit_unary_op(&mut self, op: UnaryOperator, operand: &Expr) -> T;
53
54 fn visit_function_call(&mut self, name: &str, args: &[Expr]) -> T;
56
57 fn visit_lambda(&mut self, param: &str, body: &Expr) -> T;
59
60 fn visit_let(&mut self, name: &str, value: &Expr, body: &Expr) -> T;
62
63 fn visit_if(&mut self, condition: &Expr, then_branch: &Expr, else_branch: &Expr) -> T;
65
66 fn visit_array(&mut self, elements: &[Expr]) -> T;
68
69 fn visit_object(&mut self, fields: &[(String, Expr)]) -> T;
71
72 fn visit_pipe(&mut self, value: &Expr, functions: &[Expr]) -> T;
74
75 fn visit_alternative(&mut self, primary: &Expr, alternative: &Expr) -> T;
77
78 fn visit_guard(&mut self, condition: &Expr, body: &Expr) -> T;
80
81 fn visit_date(&mut self, date: &str) -> T;
83
84 fn visit_datetime(&mut self, datetime: &str) -> T;
86
87 fn visit_duration(&mut self, duration: &str) -> T;
89
90 fn visit_temporal_keyword(&mut self, keyword: TemporalKeyword) -> T;
92
93 fn visit_string(&mut self, value: &str) -> T;
95}
96
97pub trait DefaultVisitor<T>: Visitor<T> {
102 fn default_visit_expr(&mut self, expr: &Expr) -> T {
104 match expr {
105 Expr::Literal(lit) => self.visit_literal(lit),
106 Expr::Null => self.visit_null(),
107 Expr::Identifier(name) => self.visit_identifier(name),
108 Expr::String(value) => self.visit_string(value),
109 Expr::FieldAccess { receiver, field } => self.visit_field_access(receiver, field),
110 Expr::BinaryOp { op, left, right } => self.visit_binary_op(*op, left, right),
111 Expr::UnaryOp { op, operand } => self.visit_unary_op(*op, operand),
112 Expr::FunctionCall { name, args } => self.visit_function_call(name, args),
113 Expr::Lambda { param, body } => self.visit_lambda(param, body),
114 Expr::Let { name, value, body } => self.visit_let(name, value, body),
115 Expr::If {
116 condition,
117 then_branch,
118 else_branch,
119 } => self.visit_if(condition, then_branch, else_branch),
120 Expr::Array(elements) => self.visit_array(elements),
121 Expr::Object(fields) => self.visit_object(fields),
122 Expr::Pipe { value, functions } => self.visit_pipe(value, functions),
123 Expr::Alternative {
124 primary,
125 alternative,
126 } => self.visit_alternative(primary, alternative),
127 Expr::Guard { condition, body } => self.visit_guard(condition, body),
128 Expr::Date(date) => self.visit_date(date),
129 Expr::DateTime(datetime) => self.visit_datetime(datetime),
130 Expr::Duration(duration) => self.visit_duration(duration),
131 Expr::TemporalKeyword(keyword) => self.visit_temporal_keyword(*keyword),
132 }
133 }
134}
135
136#[cfg(test)]
137mod tests {
138 use super::*;
139 use std::cell::RefCell;
140 use std::rc::Rc;
141
142 struct CountingVisitor {
143 count: Rc<RefCell<usize>>,
144 }
145
146 impl Visitor<()> for CountingVisitor {
147 fn visit_expr(&mut self, expr: &Expr) {
148 *self.count.borrow_mut() += 1;
149 match expr {
150 Expr::BinaryOp { left, right, .. } => {
151 self.visit_expr(left);
152 self.visit_expr(right);
153 }
154 Expr::UnaryOp { operand, .. } => {
155 self.visit_expr(operand);
156 }
157 Expr::FieldAccess { receiver, .. } => {
158 self.visit_expr(receiver);
159 }
160 _ => {}
161 }
162 }
163
164 fn visit_literal(&mut self, _lit: &Literal) {}
165 fn visit_null(&mut self) {}
166 fn visit_identifier(&mut self, _name: &str) {}
167 fn visit_field_access(&mut self, _receiver: &Expr, _field: &str) {}
168 fn visit_binary_op(&mut self, _op: BinaryOperator, _left: &Expr, _right: &Expr) {}
169 fn visit_unary_op(&mut self, _op: UnaryOperator, _operand: &Expr) {}
170 fn visit_function_call(&mut self, _name: &str, _args: &[Expr]) {}
171 fn visit_lambda(&mut self, _param: &str, _body: &Expr) {}
172 fn visit_let(&mut self, _name: &str, _value: &Expr, _body: &Expr) {}
173 fn visit_if(&mut self, _condition: &Expr, _then_branch: &Expr, _else_branch: &Expr) {}
174 fn visit_array(&mut self, _elements: &[Expr]) {}
175 fn visit_object(&mut self, _fields: &[(String, Expr)]) {}
176 fn visit_pipe(&mut self, _value: &Expr, _functions: &[Expr]) {}
177 fn visit_alternative(&mut self, _primary: &Expr, _alternative: &Expr) {}
178 fn visit_guard(&mut self, _condition: &Expr, _body: &Expr) {}
179 fn visit_date(&mut self, _date: &str) {}
180 fn visit_datetime(&mut self, _datetime: &str) {}
181 fn visit_duration(&mut self, _duration: &str) {}
182 fn visit_temporal_keyword(&mut self, _keyword: TemporalKeyword) {}
183 fn visit_string(&mut self, _value: &str) {}
184 }
185
186 #[test]
187 fn test_visitor_basic() {
188 let expr = Expr::Literal(Literal::Integer(42));
189 let mut visitor = CountingVisitor {
190 count: Rc::new(RefCell::new(0)),
191 };
192 visitor.visit_expr(&expr);
193 assert_eq!(*visitor.count.borrow(), 1);
194 }
195
196 #[test]
197 fn test_visitor_traversal() {
198 let expr = Expr::BinaryOp {
199 op: BinaryOperator::Add,
200 left: Box::new(Expr::Literal(Literal::Integer(1))),
201 right: Box::new(Expr::Literal(Literal::Integer(2))),
202 };
203 let mut visitor = CountingVisitor {
204 count: Rc::new(RefCell::new(0)),
205 };
206 visitor.visit_expr(&expr);
207 assert_eq!(*visitor.count.borrow(), 3); }
209}