1
//! Functions for pretty printing Conjure models.
2
//!
3
//! Most things can be pretty printed using `Display`; however some, notably collections
4
//! can not, for example, Vec<Expression>
5

            
6
use std::fmt::Display;
7

            
8
use itertools::Itertools;
9

            
10
use super::{Expression, Name, SymbolTable};
11

            
12
/// Pretty prints a `Vec<Expression>` as if it were a top level constraint list in a `such that`.
13
///
14
/// Each expression is printed on a new line, and expressions are delimited by commas.
15
///
16
/// For some input expressions A,B,C:
17
/// ```text
18
/// A,
19
/// B,
20
/// C
21
/// ```
22
///
23
/// Each `Expression` is printed using its underlying `Display` implementation.
24
15742
pub fn pretty_expressions_as_top_level(expressions: &[Expression]) -> String {
25
66623
    expressions.iter().map(|x| format!("{}", x)).join(",\n")
26
15742
}
27

            
28
/// Pretty prints a `Vec<Expression>` as if it were a conjunction.
29
///
30
/// For some input expressions A,B,C:
31
///
32
/// ```text
33
/// (A /\ B /\ C)
34
/// ```
35
///
36
/// Each `Expression` is printed using its underlying `Display` implementation.
37
pub fn pretty_expressions_as_conjunction(expressions: &[Expression]) -> String {
38
    let mut str = expressions.iter().map(|x| format!("{}", x)).join(" /\\ ");
39

            
40
    str.insert(0, '(');
41
    str.push(')');
42

            
43
    str
44
}
45

            
46
/// Pretty prints a `Vec<T>` in a vector like syntax.
47
///
48
/// For some input values A,B,C:
49
///
50
/// ```text
51
/// [A,B,C]
52
/// ````
53
///
54
/// Each element is printed using its underlying `Display` implementation.
55
79322
pub fn pretty_vec<T: Display>(elems: &[T]) -> String {
56
158474
    let mut str = elems.iter().map(|x| format!("{}", x)).join(", ");
57
79322
    str.insert(0, '[');
58
79322
    str.push(']');
59
79322

            
60
79322
    str
61
79322
}
62

            
63
/// Pretty prints, in essence syntax, the variable declaration for the given symbol.
64
///
65
/// E.g.
66
///
67
/// ```text
68
/// find a: int(1..5)
69
/// ```
70
///
71
/// Returns None if the symbol is not in the symbol table, or if it is not a variable.
72
100215
pub fn pretty_variable_declaration(symbol_table: &SymbolTable, var_name: &Name) -> Option<String> {
73
100215
    let decl = symbol_table.lookup(var_name)?;
74
100215
    let var = decl.as_var()?;
75
100215
    let domain = &var.domain;
76
100215
    Some(format!("find {var_name}: {domain}"))
77
100215
}
78

            
79
/// Pretty prints, in essence syntax, the declaration for the given value letting.
80
///
81
/// E.g.
82
///
83
/// ```text
84
/// letting A be 1+2+3
85
/// ```
86
///
87
/// Returns None if the symbol is not in the symbol table, or if it is not a value letting.
88
561
pub fn pretty_value_letting_declaration(symbol_table: &SymbolTable, name: &Name) -> Option<String> {
89
561
    let decl = symbol_table.lookup(name)?;
90
561
    let letting = decl.as_value_letting()?;
91
561
    Some(format!("letting {name} be {letting}"))
92
561
}
93

            
94
/// Pretty prints, in essence syntax, the declaration for the given domain letting.
95
///
96
/// E.g.
97
///
98
/// ```text
99
/// letting A be domain bool
100
/// ```
101
///
102
/// Returns None if the symbol is not in the symbol table, or if it is not a domain letting.
103
238
pub fn pretty_domain_letting_declaration(
104
238
    symbol_table: &SymbolTable,
105
238
    name: &Name,
106
238
) -> Option<String> {
107
238
    let decl = symbol_table.lookup(name)?;
108
238
    let letting = decl.as_domain_letting()?;
109
238
    Some(format!("letting {name} be domain {letting}"))
110
238
}