symoxide/mappers/
identity.rs

1// Copyright (c) 2022 Kaushik Kulkarni
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21use crate::mappers::CachedMapper;
22use crate::utils::ExpressionRawPointer;
23use crate::{BinaryOpType, Expression, LiteralT, SmallVecExprT, UnaryOpType};
24use std::rc::Rc;
25
26// {{{ IdentityMapper
27
28pub trait IdentityMapper: CachedMapper<ExpressionRawPointer, Rc<Expression>> {
29    fn visit(&mut self, expr: Rc<Expression>) -> Rc<Expression> {
30        let cache_key = ExpressionRawPointer(expr.clone());
31        match self.query_cache(&cache_key) {
32            Some(x) => x.clone(),
33            None => {
34                let result = match &*expr {
35                    Expression::Scalar(s) => self.map_scalar(&s),
36                    Expression::Variable(name) => self.map_variable(name.to_string()),
37                    Expression::UnaryOp(op, x) => self.map_unary_op(op.clone(), &x),
38                    Expression::BinaryOp(l, op, r) => self.map_binary_op(&l, op.clone(), &r),
39                    Expression::Call(call, params) => self.map_call(&call, &params),
40                    Expression::Subscript(agg, indices) => self.map_subscript(&agg, &indices),
41                    Expression::If(cond, then, else_) => self.map_if(&cond, &then, &else_),
42                };
43                self.add_to_cache(cache_key, result.clone());
44                result
45            }
46        }
47    }
48
49    fn map_scalar(&mut self, value: &LiteralT) -> Rc<Expression> {
50        Rc::new(Expression::Scalar(value.clone()))
51    }
52
53    fn map_variable(&mut self, name: String) -> Rc<Expression> {
54        Rc::new(Expression::Variable(name))
55    }
56
57    fn map_unary_op(&mut self, op: UnaryOpType, x: &Rc<Expression>) -> Rc<Expression> {
58        Rc::new(Expression::UnaryOp(op, self.visit(x.clone())))
59    }
60
61    fn map_binary_op(&mut self, left: &Rc<Expression>, op: BinaryOpType, right: &Rc<Expression>)
62                     -> Rc<Expression> {
63        Rc::new(Expression::BinaryOp(self.visit(left.clone()), op, self.visit(right.clone())))
64    }
65
66    fn map_call(&mut self, call: &Rc<Expression>, params: &SmallVecExprT) -> Rc<Expression> {
67        Rc::new(Expression::Call(self.visit(call.clone()),
68                                 params.iter()
69                                       .map(|param| self.visit(param.clone()))
70                                       .collect()))
71    }
72
73    fn map_subscript(&mut self, agg: &Rc<Expression>, indices: &SmallVecExprT) -> Rc<Expression> {
74        Rc::new(Expression::Subscript(self.visit(agg.clone()),
75                                      indices.iter().map(|idx| self.visit(idx.clone())).collect()))
76    }
77
78    fn map_if(&mut self, cond: &Rc<Expression>, then: &Rc<Expression>, else_: &Rc<Expression>)
79              -> Rc<Expression> {
80        Rc::new(Expression::If(self.visit(cond.clone()),
81                               self.visit(then.clone()),
82                               self.visit(else_.clone())))
83    }
84}
85
86// }}}
87
88// {{{ UncachedIdentityMapper
89
90pub trait UncachedIdentityMapper {
91    fn visit(&self, expr: &Expression) -> Rc<Expression> {
92        match expr {
93            Expression::Scalar(s) => self.map_scalar(&s),
94            Expression::Variable(name) => self.map_variable(name.to_string()),
95            Expression::UnaryOp(op, x) => self.map_unary_op(op.clone(), &x),
96            Expression::BinaryOp(l, op, r) => self.map_binary_op(&l, op.clone(), &r),
97            Expression::Call(call, params) => self.map_call(&call, &params),
98            Expression::Subscript(agg, indices) => self.map_subscript(&agg, &indices),
99            Expression::If(cond, then, else_) => self.map_if(&cond, &then, &else_),
100        }
101    }
102
103    fn map_scalar(&self, value: &LiteralT) -> Rc<Expression> {
104        Rc::new(Expression::Scalar(value.clone()))
105    }
106
107    fn map_variable(&self, name: String) -> Rc<Expression> {
108        Rc::new(Expression::Variable(name))
109    }
110
111    fn map_unary_op(&self, op: UnaryOpType, x: &Rc<Expression>) -> Rc<Expression> {
112        Rc::new(Expression::UnaryOp(op, self.visit(x)))
113    }
114
115    fn map_binary_op(&self, left: &Rc<Expression>, op: BinaryOpType, right: &Rc<Expression>)
116                     -> Rc<Expression> {
117        Rc::new(Expression::BinaryOp(self.visit(left), op, self.visit(right)))
118    }
119
120    fn map_call(&self, call: &Rc<Expression>, params: &SmallVecExprT) -> Rc<Expression> {
121        Rc::new(Expression::Call(self.visit(call),
122                                 params.iter().map(|param| self.visit(param)).collect()))
123    }
124
125    fn map_subscript(&self, agg: &Rc<Expression>, indices: &SmallVecExprT) -> Rc<Expression> {
126        Rc::new(Expression::Subscript(self.visit(agg),
127                                      indices.iter().map(|idx| self.visit(idx)).collect()))
128    }
129
130    fn map_if(&self, cond: &Rc<Expression>, then: &Rc<Expression>, else_: &Rc<Expression>)
131              -> Rc<Expression> {
132        Rc::new(Expression::If(self.visit(cond), self.visit(then), self.visit(else_)))
133    }
134}
135
136// }}}
137
138// {{{ IdentityMapperWithContext
139
140pub trait IdentityMapperWithContext {
141    type Context;
142
143    fn visit(&self, expr: &Expression, context: &Self::Context) -> Rc<Expression> {
144        match expr {
145            Expression::Scalar(s) => self.map_scalar(&s, context),
146            Expression::Variable(name) => self.map_variable(name.to_string(), context),
147            Expression::UnaryOp(op, x) => self.map_unary_op(op.clone(), &x, context),
148            Expression::BinaryOp(l, op, r) => self.map_binary_op(&l, op.clone(), &r, context),
149            Expression::Call(call, params) => self.map_call(&call, &params, context),
150            Expression::Subscript(agg, indices) => self.map_subscript(&agg, &indices, context),
151            Expression::If(cond, then, else_) => self.map_if(&cond, &then, &else_, context),
152        }
153    }
154
155    fn map_scalar(&self, value: &LiteralT, _context: &Self::Context) -> Rc<Expression> {
156        Rc::new(Expression::Scalar(value.clone()))
157    }
158
159    fn map_variable(&self, name: String, _context: &Self::Context) -> Rc<Expression> {
160        Rc::new(Expression::Variable(name))
161    }
162
163    fn map_unary_op(&self, op: UnaryOpType, x: &Rc<Expression>, context: &Self::Context)
164                    -> Rc<Expression> {
165        Rc::new(Expression::UnaryOp(op, self.visit(x, context)))
166    }
167
168    fn map_binary_op(&self, left: &Rc<Expression>, op: BinaryOpType, right: &Rc<Expression>,
169                     context: &Self::Context)
170                     -> Rc<Expression> {
171        Rc::new(Expression::BinaryOp(self.visit(left, context), op, self.visit(right, context)))
172    }
173
174    fn map_call(&self, call: &Rc<Expression>, params: &SmallVecExprT, context: &Self::Context)
175                -> Rc<Expression> {
176        Rc::new(Expression::Call(self.visit(call, context),
177                                 params.iter()
178                                       .map(|param| self.visit(param, context))
179                                       .collect()))
180    }
181
182    fn map_subscript(&self, agg: &Rc<Expression>, indices: &SmallVecExprT,
183                     context: &Self::Context)
184                     -> Rc<Expression> {
185        Rc::new(Expression::Subscript(self.visit(agg, context),
186                                      indices.iter().map(|idx| self.visit(idx, context)).collect()))
187    }
188
189    fn map_if(&self, cond: &Rc<Expression>, then: &Rc<Expression>, else_: &Rc<Expression>,
190              context: &Self::Context)
191              -> Rc<Expression> {
192        Rc::new(Expression::If(self.visit(cond, context),
193                               self.visit(then, context),
194                               self.visit(else_, context)))
195    }
196}
197
198// }}}
199
200// {{{ IdentityMapperWithCustomCacheKey
201
202pub trait IdentityMapperWithCustomCacheKey: CachedMapper<Self::CacheKey, Rc<Expression>> {
203    type CacheKey;
204
205    fn get_cache_key(&self, expr: Rc<Expression>) -> Self::CacheKey;
206
207    fn visit(&mut self, expr: Rc<Expression>) -> Rc<Expression> {
208        let cache_key = self.get_cache_key(expr.clone());
209        match self.query_cache(&cache_key) {
210            Some(x) => x.clone(),
211            None => {
212                let result = match &*expr {
213                    Expression::Scalar(s) => self.map_scalar(&s),
214                    Expression::Variable(name) => self.map_variable(name.to_string()),
215                    Expression::UnaryOp(op, x) => self.map_unary_op(op.clone(), &x),
216                    Expression::BinaryOp(l, op, r) => self.map_binary_op(&l, op.clone(), &r),
217                    Expression::Call(call, params) => self.map_call(&call, &params),
218                    Expression::Subscript(agg, indices) => self.map_subscript(&agg, &indices),
219                    Expression::If(cond, then, else_) => self.map_if(&cond, &then, &else_),
220                };
221                self.add_to_cache(cache_key, result.clone());
222                result
223            }
224        }
225    }
226
227    fn map_scalar(&mut self, value: &LiteralT) -> Rc<Expression> {
228        Rc::new(Expression::Scalar(value.clone()))
229    }
230
231    fn map_variable(&mut self, name: String) -> Rc<Expression> {
232        Rc::new(Expression::Variable(name))
233    }
234
235    fn map_unary_op(&mut self, op: UnaryOpType, x: &Rc<Expression>) -> Rc<Expression> {
236        Rc::new(Expression::UnaryOp(op, self.visit(x.clone())))
237    }
238
239    fn map_binary_op(&mut self, left: &Rc<Expression>, op: BinaryOpType, right: &Rc<Expression>)
240                     -> Rc<Expression> {
241        Rc::new(Expression::BinaryOp(self.visit(left.clone()), op, self.visit(right.clone())))
242    }
243
244    fn map_call(&mut self, call: &Rc<Expression>, params: &SmallVecExprT) -> Rc<Expression> {
245        Rc::new(Expression::Call(self.visit(call.clone()),
246                                 params.iter()
247                                       .map(|param| self.visit(param.clone()))
248                                       .collect()))
249    }
250
251    fn map_subscript(&mut self, agg: &Rc<Expression>, indices: &SmallVecExprT) -> Rc<Expression> {
252        Rc::new(Expression::Subscript(self.visit(agg.clone()),
253                                      indices.iter().map(|idx| self.visit(idx.clone())).collect()))
254    }
255
256    fn map_if(&mut self, cond: &Rc<Expression>, then: &Rc<Expression>, else_: &Rc<Expression>)
257              -> Rc<Expression> {
258        Rc::new(Expression::If(self.visit(cond.clone()),
259                               self.visit(then.clone()),
260                               self.visit(else_.clone())))
261    }
262}
263
264// }}}