symoxide/mapper_impls/
reprifier.rs1use crate::mappers::fold::FoldMapperWithContext;
2use crate::mappers::CachedMapper;
3use crate::primitives::{BinaryOpType, Expression, LiteralT, SmallVecExprT, UnaryOpType};
4use crate::utils::ExpressionRawPointer;
5use crate::CachedMapper;
6use hashbrown::HashMap;
7use std::fmt;
8use std::rc::Rc;
9
10#[derive(CachedMapper)]
13pub struct Reprifier {
14 truncation_level: u32,
15 cache: HashMap<(ExpressionRawPointer, u32), String>,
16}
17
18impl FoldMapperWithContext for Reprifier {
19 type Context = u32;
20 type Output = String;
21 type CacheKey = (ExpressionRawPointer, u32);
22
23 fn get_cache_key(&self, expr: &Rc<Expression>, context: &Self::Context) -> Self::CacheKey {
24 (ExpressionRawPointer(expr.clone()), *context)
25 }
26
27 fn map_scalar(&mut self, value: &LiteralT, level: &Self::Context) -> Self::Output {
28 if *level < self.truncation_level {
29 format!("{:?}", value)
30 } else {
31 format!("(...)")
32 }
33 }
34 fn map_variable(&mut self, name: String, level: &Self::Context) -> Self::Output {
35 if *level < self.truncation_level {
36 format!("Variable(\"{}\"))", name)
37 } else {
38 format!("(...)")
39 }
40 }
41 fn map_unary_op(&mut self, op: UnaryOpType, x: &Rc<Expression>, level: &Self::Context)
42 -> Self::Output {
43 if *level < self.truncation_level {
44 let new_level: u32 = level + 1;
45 format!("UnaryOp({}, {}))", op, self.visit(x, &new_level))
46 } else {
47 format!("(...)")
48 }
49 }
50 fn map_binary_op(&mut self, left: &Rc<Expression>, op: BinaryOpType, right: &Rc<Expression>,
51 level: &Self::Context)
52 -> Self::Output {
53 if *level < self.truncation_level {
54 let new_level: u32 = level + 1;
55 format!("BinaryOp({}, {}, {}))",
56 self.visit(left, &new_level),
57 op,
58 self.visit(right, &new_level))
59 } else {
60 format!("(...)")
61 }
62 }
63 fn map_call(&mut self, call: &Rc<Expression>, params: &SmallVecExprT, level: &Self::Context)
64 -> Self::Output {
65 if *level < self.truncation_level {
66 let new_level: u32 = level + 1;
67 let mut param_str = format!("");
68 for (iparam, param) in params.iter().enumerate() {
70 param_str = if iparam == 0 {
71 format!("{}", param)
72 } else {
73 format!("{}, {}", param_str, self.visit(param, &new_level))
74 };
75 }
76
77 format!("Call({}, [{}]))", self.visit(call, &new_level), param_str)
78 } else {
79 format!("(...)")
80 }
81 }
82 fn map_subscript(&mut self, agg: &Rc<Expression>, indices: &SmallVecExprT,
83 level: &Self::Context)
84 -> Self::Output {
85 if *level < self.truncation_level {
86 let new_level: u32 = level + 1;
87 let mut indices_str = format!("");
88 for (i_idx, idx) in indices.iter().enumerate() {
90 indices_str = if i_idx == 0 {
91 format!("{}", idx)
92 } else {
93 format!("{}, {}", indices_str, self.visit(idx, &new_level))
94 };
95 }
96
97 format!("Subscript({}, [{}]))",
98 self.visit(agg, &new_level),
99 indices_str)
100 } else {
101 format!("(...)")
102 }
103 }
104 fn map_if(&mut self, cond: &Rc<Expression>, then: &Rc<Expression>, else_: &Rc<Expression>,
105 level: &Self::Context)
106 -> Self::Output {
107 if *level < self.truncation_level {
108 let new_level: u32 = level + 1;
109 format!("If({}, {}, {}))",
110 self.visit(cond, &new_level),
111 self.visit(then, &new_level),
112 self.visit(else_, &new_level))
113 } else {
114 format!("(...)")
115 }
116 }
117}
118
119impl fmt::Debug for Expression {
120 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
121 let mut mapper = Reprifier { truncation_level: 3,
122 cache: HashMap::new() };
123 let start_level = 0;
124 write!(f, "{}", mapper.visit(&Rc::new(self.clone()), &start_level))
125 }
126}