use crate::mappers::fold::FoldMapperWithContext;
use crate::mappers::CachedMapper;
use crate::primitives::{BinaryOpType, Expression, LiteralT, SmallVecExprT, UnaryOpType};
use crate::utils::ExpressionRawPointer;
use crate::CachedMapper;
use hashbrown::HashMap;
use std::fmt;
use std::rc::Rc;
#[derive(CachedMapper)]
pub struct Reprifier {
truncation_level: u32,
cache: HashMap<(ExpressionRawPointer, u32), String>,
}
impl FoldMapperWithContext for Reprifier {
type Context = u32;
type Output = String;
type CacheKey = (ExpressionRawPointer, u32);
fn get_cache_key(&self, expr: &Rc<Expression>, context: &Self::Context) -> Self::CacheKey {
(ExpressionRawPointer(expr.clone()), *context)
}
fn map_scalar(&mut self, value: &LiteralT, level: &Self::Context) -> Self::Output {
if *level < self.truncation_level {
format!("{:?}", value)
} else {
format!("(...)")
}
}
fn map_variable(&mut self, name: String, level: &Self::Context) -> Self::Output {
if *level < self.truncation_level {
format!("Variable(\"{}\"))", name)
} else {
format!("(...)")
}
}
fn map_unary_op(&mut self, op: UnaryOpType, x: &Rc<Expression>, level: &Self::Context)
-> Self::Output {
if *level < self.truncation_level {
let new_level: u32 = level + 1;
format!("UnaryOp({}, {}))", op, self.visit(x, &new_level))
} else {
format!("(...)")
}
}
fn map_binary_op(&mut self, left: &Rc<Expression>, op: BinaryOpType, right: &Rc<Expression>,
level: &Self::Context)
-> Self::Output {
if *level < self.truncation_level {
let new_level: u32 = level + 1;
format!("BinaryOp({}, {}, {}))",
self.visit(left, &new_level),
op,
self.visit(right, &new_level))
} else {
format!("(...)")
}
}
fn map_call(&mut self, call: &Rc<Expression>, params: &SmallVecExprT, level: &Self::Context)
-> Self::Output {
if *level < self.truncation_level {
let new_level: u32 = level + 1;
let mut param_str = format!("");
for (iparam, param) in params.iter().enumerate() {
param_str = if iparam == 0 {
format!("{}", param)
} else {
format!("{}, {}", param_str, self.visit(param, &new_level))
};
}
format!("Call({}, [{}]))", self.visit(call, &new_level), param_str)
} else {
format!("(...)")
}
}
fn map_subscript(&mut self, agg: &Rc<Expression>, indices: &SmallVecExprT,
level: &Self::Context)
-> Self::Output {
if *level < self.truncation_level {
let new_level: u32 = level + 1;
let mut indices_str = format!("");
for (i_idx, idx) in indices.iter().enumerate() {
indices_str = if i_idx == 0 {
format!("{}", idx)
} else {
format!("{}, {}", indices_str, self.visit(idx, &new_level))
};
}
format!("Subscript({}, [{}]))",
self.visit(agg, &new_level),
indices_str)
} else {
format!("(...)")
}
}
fn map_if(&mut self, cond: &Rc<Expression>, then: &Rc<Expression>, else_: &Rc<Expression>,
level: &Self::Context)
-> Self::Output {
if *level < self.truncation_level {
let new_level: u32 = level + 1;
format!("If({}, {}, {}))",
self.visit(cond, &new_level),
self.visit(then, &new_level),
self.visit(else_, &new_level))
} else {
format!("(...)")
}
}
}
impl fmt::Debug for Expression {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut mapper = Reprifier { truncation_level: 3,
cache: HashMap::new() };
let start_level = 0;
write!(f, "{}", mapper.visit(&Rc::new(self.clone()), &start_level))
}
}