1use std::fmt::{Display, Formatter, Result};
4
5use crate::ast::*;
6
7fn write_delim_list<T: Display>(f: &mut Formatter<'_>, v: &[T], pref: &str, suff: &str, join: &str) -> Result {
9 write!(f, "{pref}")?;
10 if let Some(e) = v.first() {
11 write!(f, "{e}")?;
12 for b in &v[1..] {
13 write!(f, "{join}{b}")?;
14 }
15 }
16 write!(f, "{suff}")?;
17 Ok(())
18}
19
20fn format_opt<T: Display>(opt: &Option<T>, pref: &str, suff: &str) -> String {
22 if let Some(ref e) = opt {
23 format!("{pref}{e}{suff}")
24 } else {
25 String::new()
26 }
27}
28
29fn format_type(ty: &Option<Type>) -> String {
31 format_opt(ty, ": ", "")
32}
33
34impl Display for Constant {
35 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
36 write!(f, "constant {}{} := {}", self.name, format_type(&self.ty), self.literal)
37 }
38}
39
40impl Display for Input {
41 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
42 write!(f, "input {}", self.name)?;
43 if !self.params.is_empty() {
44 write_delim_list(f, &self.params, " (", ")", ", ")?;
45 }
46 write!(f, ": {}", self.ty)
47 }
48}
49
50impl Display for Mirror {
51 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
52 write!(f, "output {} mirror {} when {}", self.name, self.target, self.filter)
53 }
54}
55
56impl Display for Output {
57 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
58 match &self.kind {
59 OutputKind::NamedOutput(name) => write!(f, "output {name}")?,
60 OutputKind::Trigger => write!(f, "trigger")?,
61 };
62 if !self.params.is_empty() {
63 write_delim_list(f, &self.params, " (", ")", ", ")?;
64 }
65 if let Some(ty) = &self.annotated_type {
66 write!(f, ": {ty}")?;
67 }
68 if let Some(spawn) = &self.spawn {
69 write!(f, " {spawn}")?;
70 }
71 for eval_spec in self.eval.iter() {
72 write!(f, " {eval_spec}")?;
73 }
74 if let Some(close) = &self.close {
75 write!(f, " {close}")?;
76 }
77 Ok(())
78 }
79}
80
81impl Display for Parameter {
82 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
83 match &self.ty {
84 None => write!(f, "{}", self.name),
85 Some(ty) => write!(f, "{}: {}", self.name, ty),
86 }
87 }
88}
89
90impl Display for AnnotatedPacingType {
91 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
92 match self {
93 AnnotatedPacingType::NotAnnotated => Ok(()),
94 AnnotatedPacingType::Global(freq) => write!(f, " @Global({freq})"),
95 AnnotatedPacingType::Local(freq) => write!(f, " @Local({freq})"),
96 AnnotatedPacingType::Unspecified(expr) => write!(f, " @{expr}"),
97 }
98 }
99}
100
101impl Display for SpawnSpec {
102 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
103 if self.expression.is_some() || self.condition.is_some() {
104 write!(f, "spawn")?;
105 }
106 write!(f, "{}", self.annotated_pacing)?;
107 if let Some(condition) = &self.condition {
108 write!(f, " when {condition}")?;
109 }
110 if let Some(expr) = &self.expression {
111 write!(f, " with {expr}")?;
112 }
113 Ok(())
114 }
115}
116
117impl Display for EvalSpec {
118 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
119 if self.condition.is_some()
120 || self.eval_expression.is_some()
121 || self.annotated_pacing != AnnotatedPacingType::NotAnnotated
122 {
123 write!(f, "eval")?;
124 }
125 write!(f, "{}", self.annotated_pacing)?;
126 if let Some(when) = &self.condition {
127 write!(f, " when {when}")?;
128 }
129 if let Some(exp) = &self.eval_expression {
130 write!(f, " with {exp}")?;
131 }
132 Ok(())
133 }
134}
135
136impl Display for CloseSpec {
137 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
138 write!(f, "close")?;
139 write!(f, "{}", self.annotated_pacing)?;
140 write!(f, " when {}", self.condition)
141 }
142}
143
144impl Display for Type {
145 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
146 write!(f, "{}", self.kind)
147 }
148}
149
150impl Display for TypeKind {
151 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
152 match &self {
153 TypeKind::Simple(name) => write!(f, "{name}"),
154 TypeKind::Tuple(types) => write_delim_list(f, types, "(", ")", ", "),
155 TypeKind::Optional(ty) => write!(f, "{ty}?"),
156 }
157 }
158}
159
160impl Display for TypeDeclField {
161 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
162 write!(f, "{}: {}", &self.name, &self.ty)
163 }
164}
165
166impl Display for TypeDeclaration {
167 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
168 write!(f, "type {}", format_opt(&self.name, "", ""))?;
169 write_delim_list(f, &self.fields, " { ", " }", ", ")
170 }
171}
172
173impl Display for Expression {
174 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
175 match &self.kind {
176 ExpressionKind::Lit(l) => write!(f, "{l}"),
177 ExpressionKind::Ident(ident) => write!(f, "{ident}"),
178 ExpressionKind::StreamAccess(expr, access) => {
179 match access {
180 StreamAccessKind::Sync => write!(f, "{expr}"),
181 StreamAccessKind::Hold => write!(f, "{expr}.hold()"),
182 StreamAccessKind::Get => write!(f, "{expr}.get()"),
183 StreamAccessKind::Fresh => write!(f, "{expr}.is_fresh()"),
184 }
185 },
186 ExpressionKind::Default(expr, val) => write!(f, "{expr}.defaults(to: {val})"),
187 ExpressionKind::Offset(expr, val) => write!(f, "{expr}.offset(by: {val})"),
188 ExpressionKind::DiscreteWindowAggregation {
189 expr,
190 duration,
191 wait,
192 aggregation,
193 } => {
194 match wait {
195 true => {
196 write!(
197 f,
198 "{expr}.aggregate(over_exactly_discrete: {duration}, using: {aggregation})"
199 )
200 },
201 false => {
202 write!(f, "{expr}.aggregate(over_discrete: {duration}, using: {aggregation})")
203 },
204 }
205 },
206 ExpressionKind::SlidingWindowAggregation {
207 expr,
208 duration,
209 wait,
210 aggregation,
211 } => {
212 match wait {
213 true => {
214 write!(f, "{expr}.aggregate(over_exactly: {duration}, using: {aggregation})")
215 },
216 false => write!(f, "{expr}.aggregate(over: {duration}, using: {aggregation})"),
217 }
218 },
219 ExpressionKind::InstanceAggregation {
220 expr,
221 selection,
222 aggregation,
223 } => write!(f, "{expr}.aggregate(over_instances: {selection}, using: {aggregation})"),
224 ExpressionKind::Binary(op, lhs, rhs) => write!(f, "{lhs} {op} {rhs}"),
225 ExpressionKind::Unary(operator, operand) => write!(f, "{operator}{operand}"),
226 ExpressionKind::Ite(cond, cons, alt) => {
227 write!(f, "if {cond} then {cons} else {alt}")
228 },
229 ExpressionKind::ParenthesizedExpression(left, expr, right) => {
230 write!(
231 f,
232 "{}{}{}",
233 if left.is_some() { "(" } else { "" },
234 expr,
235 if right.is_some() { ")" } else { "" }
236 )
237 },
238 ExpressionKind::MissingExpression => Ok(()),
239 ExpressionKind::Tuple(exprs) => write_delim_list(f, exprs, "(", ")", ", "),
240 ExpressionKind::Function(name, types, args) => {
241 write!(f, "{}", name.name)?;
242 if !types.is_empty() {
243 write_delim_list(f, types, "<", ">", ", ")?;
244 }
245 let args: Vec<String> = args
246 .iter()
247 .zip(&name.arg_names)
248 .map(|(arg, arg_name)| {
249 match arg_name {
250 None => format!("{arg}"),
251 Some(arg_name) => format!("{arg_name}: {arg}"),
252 }
253 })
254 .collect();
255 write_delim_list(f, &args, "(", ")", ", ")
256 },
257 ExpressionKind::Field(expr, ident) => write!(f, "{expr}.{ident}"),
258 ExpressionKind::Method(expr, name, types, args) => {
259 write!(f, "{}.{}", expr, name.name)?;
260 if !types.is_empty() {
261 write_delim_list(f, types, "<", ">", ", ")?;
262 }
263 let args: Vec<String> = args
264 .iter()
265 .zip(&name.arg_names)
266 .map(|(arg, arg_name)| {
267 match arg_name {
268 None => format!("{arg}"),
269 Some(arg_name) => format!("{arg_name}: {arg}"),
270 }
271 })
272 .collect();
273 write_delim_list(f, &args, "(", ")", ", ")
274 },
275 }
276 }
277}
278
279impl Display for FunctionName {
280 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
281 write!(f, "{}", self.name)?;
282 let args: Vec<String> = self
283 .arg_names
284 .iter()
285 .map(|arg_name| {
286 match arg_name {
287 None => String::from("_:"),
288 Some(arg_name) => format!("{arg_name}:"),
289 }
290 })
291 .collect();
292 write_delim_list(f, &args, "(", ")", "")
293 }
294}
295
296impl Display for Offset {
297 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
298 match self {
299 Offset::Discrete(val) => write!(f, "{val}"),
300 Offset::RealTime(val, unit) => write!(f, "{val}{unit}"),
301 }
302 }
303}
304
305impl Display for TimeUnit {
306 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
307 write!(
308 f,
309 "{}",
310 match self {
311 TimeUnit::Nanosecond => "ns",
312 TimeUnit::Microsecond => "μs",
313 TimeUnit::Millisecond => "ms",
314 TimeUnit::Second => "s",
315 TimeUnit::Minute => "min",
316 TimeUnit::Hour => "h",
317 TimeUnit::Day => "d",
318 TimeUnit::Week => "w",
319 TimeUnit::Year => "a",
320 }
321 )
322 }
323}
324
325impl Display for WindowOperation {
326 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
327 let op_str = match self {
328 WindowOperation::Sum => "Σ",
329 WindowOperation::Product => "Π",
330 WindowOperation::Average => "avg",
331 WindowOperation::Count => "#",
332 WindowOperation::Integral => "∫",
333 WindowOperation::Min => "min",
334 WindowOperation::Max => "max",
335 WindowOperation::Disjunction => "∃",
336 WindowOperation::Conjunction => "∀",
337 WindowOperation::Last => "last",
338 WindowOperation::Variance => "σ²",
339 WindowOperation::Covariance => "cov",
340 WindowOperation::StandardDeviation => "σ",
341 WindowOperation::NthPercentile(p) => return write!(f, "pctl{p}"),
342 };
343 write!(f, "{op_str}")
344 }
345}
346
347impl Display for UnOp {
348 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
349 write!(
350 f,
351 "{}",
352 match self {
353 UnOp::Not => "!",
354 UnOp::Neg => "-",
355 UnOp::BitNot => "~",
356 }
357 )
358 }
359}
360
361impl Display for Literal {
362 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
363 match &self.kind {
364 LitKind::Bool(val) => write!(f, "{val}"),
365 LitKind::Numeric(val, unit) => write!(f, "{}{}", val, unit.clone().unwrap_or_default()),
366 LitKind::Str(s) => write!(f, "\"{s}\""),
367 LitKind::RawStr(s) => {
368 let mut padding = 0;
370 while s.contains(&format!("{}\"", "#".repeat(padding))) {
371 padding += 1;
372 }
373 write!(f, "r{pad}\"{}\"{pad}", s, pad = "#".repeat(padding))
374 },
375 }
376 }
377}
378
379impl Display for Ident {
380 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
381 write!(f, "{}", self.name)
382 }
383}
384
385impl Display for InstanceSelection {
386 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
387 match self {
388 InstanceSelection::Fresh => write!(f, "fresh"),
389 InstanceSelection::All => write!(f, "all"),
390 }
391 }
392}
393
394impl Display for InstanceOperation {
395 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
396 let wo: WindowOperation = (*self).into();
397 wo.fmt(f)
398 }
399}
400
401impl Display for BinOp {
402 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
403 use BinOp::*;
404 match &self {
405 Add => write!(f, "+"),
407 Sub => write!(f, "-"),
408 Mul => write!(f, "*"),
409 Div => write!(f, "/"),
410 Rem => write!(f, "%"),
411 Pow => write!(f, "**"),
412 And => write!(f, "∧"),
414 Or => write!(f, "∨"),
415 Implies => write!(f, "->"),
416 Eq => write!(f, "="),
418 Lt => write!(f, "<"),
419 Le => write!(f, "≤"),
420 Ne => write!(f, "≠"),
421 Gt => write!(f, ">"),
422 Ge => write!(f, "≥"),
423 BitAnd => write!(f, "&"),
425 BitOr => write!(f, "|"),
426 BitXor => write!(f, "^"),
427 Shl => write!(f, "<<"),
428 Shr => write!(f, ">>"),
429 }
430 }
431}
432
433impl Display for Import {
434 fn fmt(&self, f: &mut Formatter) -> Result {
435 write!(f, "import {}", self.name)
436 }
437}
438
439impl Display for RtLolaAst {
440 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
441 for import in &self.imports {
442 writeln!(f, "{import}")?;
443 }
444 for decl in &self.type_declarations {
445 writeln!(f, "{decl}")?;
446 }
447 for constant in &self.constants {
448 writeln!(f, "{constant}")?;
449 }
450 for input in &self.inputs {
451 writeln!(f, "{input}")?;
452 }
453 for output in &self.outputs {
454 writeln!(f, "{output}")?;
455 }
456 for mirror in &self.mirrors {
457 writeln!(f, "{mirror}")?;
458 }
459 Ok(())
460 }
461}
462
463impl Display for NodeId {
464 fn fmt(&self, f: &mut Formatter) -> Result {
465 write!(f, "{}{}", self.id, "'".repeat(self.prime_counter as usize))
466 }
467}