1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/// Values are rose trees.
/// Node labeled 'Arr', leaves labeled 'Obj'.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Tree<Leaf, Node> {
// Variable name and its type
Empty,
Leaf(usize, Leaf),
Node(Node, usize, Vec<Tree<Leaf, Node>>),
}
impl<Leaf, Node: std::fmt::Display> Tree<Leaf, Node> {
pub fn try_pretty<E>(
&self,
coarity: Option<&dyn Fn(&Node) -> Result<usize, E>>,
) -> Result<String, E> {
match self {
Tree::Empty => Ok("empty".to_string()),
Tree::Leaf(i, _) => Ok(format!("x{i}")),
Tree::Node(op, target_idx, children) => {
let inner = match children.len() {
0 => Ok(format!("{op}")),
1 => Ok(format!("{op}({})", children[0].try_pretty(coarity)?)),
2 => {
let op_str = format!("{op}");
if op_str.starts_with(|c: char| c.is_alphanumeric()) {
Ok(format!(
"{op}({}, {})",
children[0].try_pretty(coarity)?,
children[1].try_pretty(coarity)?
))
} else {
Ok(format!(
"{} {op} {}",
children[0].try_pretty(coarity)?,
children[1].try_pretty(coarity)?
))
}
}
_ => {
let args: Vec<String> = children
.iter()
.map(|c| c.try_pretty(coarity))
.collect::<Result<_, _>>()?;
Ok(format!("{op}({})", args.join(", ")))
}
}?;
let show_proj = match coarity {
Some(f) => f(op)? > 1,
None => true,
};
if show_proj {
Ok(format!("π{target_idx}({inner})"))
} else {
Ok(inner)
}
}
}
}
}