1use std::collections::HashMap;
2use std::fmt::{Display, Formatter, Result};
3
4use itertools::Itertools;
5
6use super::{AnnotatedType, Offset, WindowReference};
7use crate::hir::expression::{ArithLogOp, Constant, Expression, Literal};
8use crate::hir::{FnExprKind, Inlined, StreamAccessKind, StreamReference, WidenExprKind};
9
10impl Expression {
11 pub(crate) fn pretty_string(&self, names: &HashMap<StreamReference, String>) -> String {
13 use crate::hir::expression::ExpressionKind::*;
14 match &self.kind {
15 StreamAccess(sref, kind, params) => {
16 format!(
17 "{}{}{}",
18 names[sref],
19 if !params.is_empty() {
20 format!(
21 "({})",
22 params.iter().map(|e| e.pretty_string(names)).join(", ")
23 )
24 } else {
25 "".into()
26 },
27 match kind {
28 StreamAccessKind::Offset(o) => format!(".offset(by: {o})"),
29 StreamAccessKind::Hold => ".hold()".into(),
30 StreamAccessKind::SlidingWindow(r)
31 | StreamAccessKind::DiscreteWindow(r)
32 | StreamAccessKind::InstanceAggregation(r) => {
33 format!(".aggregate(ref: {r})")
34 }
35 StreamAccessKind::Fresh => ".is_fresh()".into(),
36 StreamAccessKind::Get => ".get()".into(),
37 StreamAccessKind::Sync => "".into(),
38 }
39 )
40 }
41 LoadConstant(c) => format!("{c}"),
42 Function(FnExprKind { name, args, .. }) => {
43 format!(
44 "{}({})",
45 name,
46 args.iter().map(|e| e.pretty_string(names)).join(", ")
47 )
48 }
49 Tuple(elems) => format!(
50 "({})",
51 elems.iter().map(|e| e.pretty_string(names)).join(", ")
52 ),
53 Ite {
54 condition,
55 consequence,
56 alternative,
57 ..
58 } => {
59 format!(
60 "if {} then {} else {}",
61 condition.pretty_string(names),
62 consequence.pretty_string(names),
63 alternative.pretty_string(names)
64 )
65 }
66 ArithLog(op, args) => {
67 if args.len() == 1 {
68 format!("{}{}", op, args.first().unwrap().pretty_string(names))
69 } else {
70 format!(
71 "({})",
72 args.iter()
73 .map(|e| e.pretty_string(names))
74 .join(&format!(" {op} "))
75 )
76 }
77 }
78 Default { expr, default } => {
79 format!(
80 "{}.default({})",
81 expr.pretty_string(names),
82 default.pretty_string(names)
83 )
84 }
85 Widen(WidenExprKind { expr: e, ty }) => format!("{}({})", ty, e.pretty_string(names)),
86 TupleAccess(e, idx) => format!("{}.{}", e.pretty_string(names), idx),
87 ParameterAccess(sref, idx) => format!("Param({}, {})", names[sref], idx),
88 LambdaParameterAccess { wref, pref } => {
89 format!("LambdaParam{{wref:{wref}, pref:{pref}}}")
90 }
91 }
92 }
93}
94
95impl Display for Expression {
96 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
97 use crate::hir::expression::ExpressionKind::*;
98 match &self.kind {
99 LoadConstant(c) => write!(f, "{c}"),
100 Function(FnExprKind { name, args, .. }) => {
101 write!(
102 f,
103 "{}({})",
104 name,
105 args.iter().map(|e| format!("{e}")).join(", ")
106 )
107 }
108 Tuple(elems) => write!(f, "({})", elems.iter().map(|e| format!("{e}")).join(", ")),
109 Ite {
110 condition,
111 consequence,
112 alternative,
113 ..
114 } => {
115 write!(f, "if {condition} then {consequence} else {alternative}")
116 }
117 ArithLog(op, args) => {
118 if args.len() == 1 {
119 write!(f, "{}{}", op, args.first().unwrap())
120 } else {
121 write!(
122 f,
123 "({})",
124 args.iter().map(|e| format!("{e}")).join(&format!(" {op} "))
125 )
126 }
127 }
128 Default { expr, default: dft } => write!(f, "{expr}.default({dft})"),
129 Widen(WidenExprKind { expr: e, ty }) => write!(f, "{ty}({e})"),
130 TupleAccess(e, idx) => write!(f, "{e}.{idx}",),
131 ParameterAccess(sref, idx) => write!(f, "Param(ref: {sref}, idx: {idx})"),
132 LambdaParameterAccess { wref, pref } => {
133 write!(f, "LambdaParam{{ wref: {wref}, pref: {pref}}}")
134 }
135 StreamAccess(sref, kind, params) => {
136 write!(
137 f,
138 "Stream(ref: {}, params: ({}))",
139 sref,
140 params.iter().map(|e| format!("{e}")).join(", ")
141 )?;
142 match kind {
143 StreamAccessKind::Offset(o) => write!(f, ".offset(by: {o})"),
144 StreamAccessKind::Hold => write!(f, ".hold()"),
145 StreamAccessKind::SlidingWindow(r)
146 | StreamAccessKind::DiscreteWindow(r)
147 | StreamAccessKind::InstanceAggregation(r) => {
148 write!(f, ".aggregate(ref: {r})")
149 }
150 StreamAccessKind::Fresh => write!(f, ".is_fresh()"),
151 StreamAccessKind::Get => write!(f, ".get()"),
152 StreamAccessKind::Sync => Ok(()),
153 }
154 }
155 }
156 }
157}
158
159impl Display for Literal {
160 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
161 match self {
162 Literal::SInt(v) => write!(f, "{v}"),
163 Literal::Integer(v) => write!(f, "{v}"),
164 Literal::Decimal(v) => write!(f, "{v}"),
165 Literal::Bool(v) => write!(f, "{v}"),
166 Literal::Str(v) => write!(f, "{v}"),
167 }
168 }
169}
170
171impl Display for Constant {
172 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
173 let lit = match self {
174 Constant::Inlined(Inlined { lit, .. }) => lit,
175 Constant::Basic(c) => c,
176 };
177 write!(f, "{lit}")
178 }
179}
180
181impl Display for ArithLogOp {
182 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
183 use ArithLogOp::*;
184 match self {
185 Not => write!(f, "!"),
186 Neg => write!(f, "~"),
187 Add => write!(f, "+"),
188 Sub => write!(f, "-"),
189 Mul => write!(f, "*"),
190 Div => write!(f, "/"),
191 Rem => write!(f, "%"),
192 Pow => write!(f, "^"),
193 And => write!(f, "∧"),
194 Or => write!(f, "∨"),
195 Eq => write!(f, "="),
196 Lt => write!(f, "<"),
197 Le => write!(f, "≤"),
198 Ne => write!(f, "≠"),
199 Ge => write!(f, "≥"),
200 Gt => write!(f, ">"),
201 BitNot => write!(f, "~"),
202 BitAnd => write!(f, "&"),
203 BitOr => write!(f, "|"),
204 BitXor => write!(f, "^"),
205 Shl => write!(f, "<<"),
206 Shr => write!(f, ">>"),
207 }
208 }
209}
210
211impl Display for Offset {
212 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
213 match self {
214 Offset::PastDiscrete(u) => write!(f, "-{u}"),
215 _ => unimplemented!(),
216 }
217 }
218}
219
220impl Display for WindowReference {
221 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
222 match self {
223 WindowReference::Sliding(u) => write!(f, "SlidingWin({u})"),
224 WindowReference::Discrete(u) => write!(f, "DiscreteWin({u})"),
225 WindowReference::Instance(u) => write!(f, "InstanceAggr({u})"),
226 }
227 }
228}
229
230impl Display for StreamReference {
231 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
232 match self {
233 StreamReference::Out(ox) => write!(f, "Out({ox})"),
234 StreamReference::In(ix) => write!(f, "In({ix})"),
235 }
236 }
237}
238
239impl Display for AnnotatedType {
240 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
241 use AnnotatedType::*;
242 match self {
243 Int(s) => write!(f, "Int{s}"),
244 Float(s) => write!(f, "Float{s}"),
245 UInt(s) => write!(f, "UInt{s}"),
246 Bool => write!(f, "Bool"),
247 String => write!(f, "String"),
248 Bytes => write!(f, "Bytes"),
249 Option(t) => write!(f, "Option<{t}>"),
250 Tuple(tys) => write!(f, "({})", tys.iter().map(|t| format!("{t}")).join(",")),
251 Numeric => write!(f, "Numeric"),
253 Signed => write!(f, "Signed"),
254 Sequence => write!(f, "Sequence"),
255 Param(idx, name) => write!(f, "FunctionParam({idx}, {name})"),
256 Any => write!(f, "Any"),
257 Fixed(total, fractional) => write!(f, "Fixed{total}_{fractional}"),
258 UFixed(total, fractional) => write!(f, "UFixed{total}_{fractional}"),
259 Fractional => write!(f, "Fractional"),
260 }
261 }
262}