1use crate::mappers::CachedMapper;
22use crate::primitives::{BinaryOpType, Expression, LiteralT, SmallVecExprT, UnaryOpType};
23use crate::utils::ExpressionRawPointer;
24use std::rc::Rc;
25
26pub trait UncachedWalkMapper {
29 fn should_walk(&self, _expr: &Expression) -> bool {
30 true
31 }
32
33 fn post_walk(&self, _expr: &Expression) {}
34
35 fn visit(&self, expr: &Expression) {
36 if self.should_walk(expr) {
37 match expr {
38 Expression::Scalar(s) => self.map_scalar(&s),
39 Expression::Variable(name) => self.map_variable(name.to_string()),
40 Expression::UnaryOp(op, x) => self.map_unary_op(op.clone(), &x),
41 Expression::BinaryOp(l, op, r) => self.map_binary_op(&l, op.clone(), &r),
42 Expression::Call(call, params) => self.map_call(&call, ¶ms),
43 Expression::Subscript(agg, indices) => self.map_subscript(&agg, &indices),
44 Expression::If(cond, then, else_) => self.map_if(&cond, &then, &else_),
45 };
46 self.post_walk(expr);
47 }
48 }
49
50 fn map_scalar(&self, _value: &LiteralT) {}
51
52 fn map_variable(&self, _name: String) {}
53
54 fn map_unary_op(&self, _op: UnaryOpType, x: &Expression) {
55 self.visit(x);
56 }
57
58 fn map_binary_op(&self, left: &Expression, _op: BinaryOpType, right: &Expression) {
59 self.visit(left);
60 self.visit(right);
61 }
62
63 fn map_call(&self, call: &Expression, params: &SmallVecExprT) {
64 self.visit(call);
65 for param in params {
66 self.visit(param);
67 }
68 }
69
70 fn map_subscript(&self, agg: &Expression, indices: &SmallVecExprT) {
71 self.visit(agg);
72 for idx in indices {
73 self.visit(idx);
74 }
75 }
76
77 fn map_if(&self, cond: &Expression, then: &Expression, else_: &Expression) {
78 self.visit(cond);
79 self.visit(then);
80 self.visit(else_);
81 }
82}
83
84pub trait WalkMapperWithContext {
89 type Context;
90
91 fn should_walk(&self, _expr: &Expression, _context: &Self::Context) -> bool {
92 true
93 }
94
95 fn post_walk(&self, _expr: &Expression, _context: &Self::Context) {}
96
97 fn visit(&self, expr: &Expression, context: &Self::Context) {
98 if self.should_walk(expr, context) {
99 match expr {
100 Expression::Scalar(s) => self.map_scalar(&s, context),
101 Expression::Variable(name) => self.map_variable(name.to_string(), context),
102 Expression::UnaryOp(op, x) => self.map_unary_op(op.clone(), &x, context),
103 Expression::BinaryOp(l, op, r) => self.map_binary_op(&l, op.clone(), &r, context),
104 Expression::Call(call, params) => self.map_call(&call, ¶ms, context),
105 Expression::Subscript(agg, indices) => self.map_subscript(&agg, &indices, context),
106 Expression::If(cond, then, else_) => self.map_if(&cond, &then, &else_, context),
107 };
108 self.post_walk(expr, context);
109 }
110 }
111
112 fn map_scalar(&self, _value: &LiteralT, _context: &Self::Context) {}
113
114 fn map_variable(&self, _name: String, _context: &Self::Context) {}
115
116 fn map_unary_op(&self, _op: UnaryOpType, x: &Expression, context: &Self::Context) {
117 self.visit(x, context);
118 }
119
120 fn map_binary_op(&self, left: &Expression, _op: BinaryOpType, right: &Expression,
121 context: &Self::Context) {
122 self.visit(left, context);
123 self.visit(right, context);
124 }
125
126 fn map_call(&self, call: &Expression, params: &SmallVecExprT, context: &Self::Context) {
127 self.visit(call, context);
128 for param in params {
129 self.visit(param, context);
130 }
131 }
132
133 fn map_subscript(&self, agg: &Expression, indices: &SmallVecExprT, context: &Self::Context) {
134 self.visit(agg, context);
135 for idx in indices {
136 self.visit(idx, context);
137 }
138 }
139
140 fn map_if(&self, cond: &Expression, then: &Expression, else_: &Expression,
141 context: &Self::Context) {
142 self.visit(cond, context);
143 self.visit(then, context);
144 self.visit(else_, context);
145 }
146}
147
148pub trait WalkMapper: CachedMapper<ExpressionRawPointer, bool> {
153 fn should_walk(&self, _expr: &Expression) -> bool {
154 true
155 }
156
157 fn post_walk(&mut self, _expr: &Expression) {}
158
159 fn visit(&mut self, expr: &Rc<Expression>) {
160 let cache_key = ExpressionRawPointer(expr.clone());
161
162 match self.query_cache(&cache_key) {
163 Some(true) => {}
164 None => {
165 if self.should_walk(&expr) {
166 match &*expr.clone() {
167 Expression::Scalar(s) => self.map_scalar(&s),
168 Expression::Variable(name) => self.map_variable(name.to_string()),
169 Expression::UnaryOp(op, x) => self.map_unary_op(op.clone(), x),
170 Expression::BinaryOp(l, op, r) => self.map_binary_op(l, op.clone(), r),
171 Expression::Call(call, params) => self.map_call(call, ¶ms),
172 Expression::Subscript(agg, indices) => self.map_subscript(agg, &indices),
173 Expression::If(cond, then, else_) => self.map_if(cond, then, else_),
174 };
175 self.post_walk(&expr);
176 };
177 self.add_to_cache(cache_key, true);
178 }
179 _ => unreachable!(),
180 }
181 }
182
183 fn map_scalar(&mut self, _value: &LiteralT) {}
184
185 fn map_variable(&mut self, _name: String) {}
186
187 fn map_unary_op(&mut self, _op: UnaryOpType, x: &Rc<Expression>) {
188 self.visit(x);
189 }
190
191 fn map_binary_op(&mut self, left: &Rc<Expression>, _op: BinaryOpType, right: &Rc<Expression>) {
192 self.visit(left);
193 self.visit(right);
194 }
195
196 fn map_call(&mut self, call: &Rc<Expression>, params: &SmallVecExprT) {
197 self.visit(call);
198 for param in params {
199 self.visit(param);
200 }
201 }
202
203 fn map_subscript(&mut self, agg: &Rc<Expression>, indices: &SmallVecExprT) {
204 self.visit(agg);
205 for idx in indices {
206 self.visit(idx);
207 }
208 }
209
210 fn map_if(&mut self, cond: &Rc<Expression>, then: &Rc<Expression>, else_: &Rc<Expression>) {
211 self.visit(cond);
212 self.visit(then);
213 self.visit(else_);
214 }
215}
216
217