rtlola_parser/ast/
print.rs

1//! This module contains `Display` implementations for the AST.
2
3use std::fmt::{Display, Formatter, Result};
4
5use crate::ast::*;
6
7/// Writes out the joined vector `v`, enclosed by the given strings `pref` and `suff`.
8fn 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
20/// Helper to format an Optional
21fn 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
29/// Formats an optional type
30fn 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                // need to determine padding with `#`
369                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            // Arithmetic
406            Add => write!(f, "+"),
407            Sub => write!(f, "-"),
408            Mul => write!(f, "*"),
409            Div => write!(f, "/"),
410            Rem => write!(f, "%"),
411            Pow => write!(f, "**"),
412            // Logical
413            And => write!(f, "∧"),
414            Or => write!(f, "∨"),
415            Implies => write!(f, "->"),
416            // Comparison
417            Eq => write!(f, "="),
418            Lt => write!(f, "<"),
419            Le => write!(f, "≤"),
420            Ne => write!(f, "≠"),
421            Gt => write!(f, ">"),
422            Ge => write!(f, "≥"),
423            // Bitwise
424            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}