rtlola_parser/
ast.rs

1//! This module contains the [RtLolaAst] data structures for the RTLola Language.
2//!
3//! Every node in the abstract syntax tree is assigned a unique id and has a span referencing the node's location in the specification.
4
5use std::cell::RefCell;
6use std::convert::TryFrom;
7use std::hash::Hash;
8
9use serde::{Deserialize, Serialize};
10
11mod conversion;
12mod print;
13
14use std::rc::Rc;
15
16use num::rational::Rational64 as Rational;
17use rtlola_reporting::Span;
18
19/// The root of a RTLola specification, consisting of stream and trigger declarations.
20/// Each declaration contains the id of the Ast node, a span, and declaration-specific components.
21///
22/// # Ast Node Kinds
23/// * [Import] represents an import statement for a module.
24/// * [Constant] represents a constant stream.
25/// * [Input] represents an input stream.
26/// * [Output] represents an regular output stream or trigger.
27/// * [Mirror] represents mirror streams, a syntactic sugar for an output stream.
28/// * [TypeDeclaration] captures a user given type declaration.
29///
30/// # Related Data Structures
31/// * A [NodeId] is a unique identifier given to every node of the [RtLolaAst]
32/// * A [Span] links an Ast node to its code location.
33#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
34pub struct RtLolaAst {
35    /// The imports of additional modules
36    pub imports: Vec<Import>,
37    /// The constant stream declarations
38    pub constants: Vec<Rc<Constant>>,
39    /// The input stream declarations
40    pub inputs: Vec<Rc<Input>>,
41    /// The output stream declarations
42    pub outputs: Vec<Rc<Output>>,
43    /// The mirror stream declarations
44    pub mirrors: Vec<Rc<Mirror>>,
45    /// The user-defined type declarations
46    pub type_declarations: Vec<TypeDeclaration>,
47    /// Next highest NodeId
48    pub next_node_id: RefCell<NodeId>,
49    /// The global tags of the specification
50    pub global_tags: Vec<Tag>,
51}
52
53impl RtLolaAst {
54    /// Creates a new and empty [RtLolaAst]
55    pub(crate) fn empty() -> RtLolaAst {
56        RtLolaAst {
57            imports: Vec::new(),
58            constants: Vec::new(),
59            inputs: Vec::new(),
60            outputs: Vec::new(),
61            mirrors: Vec::new(),
62            type_declarations: Vec::new(),
63            next_node_id: RefCell::new(NodeId::default()),
64            global_tags: Vec::new(),
65        }
66    }
67
68    pub(crate) fn next_id(&self) -> NodeId {
69        let res = *self.next_node_id.borrow();
70        self.next_node_id.borrow_mut().0 += 1;
71        res
72    }
73
74    /// Creates a deep clone of the Ast. I.e. clones the underlying data not the RCs.
75    pub fn clone_deep(&self) -> RtLolaAst {
76        let RtLolaAst {
77            imports,
78            constants,
79            inputs,
80            outputs,
81            mirrors,
82            type_declarations,
83            next_node_id,
84            global_tags,
85        } = self;
86
87        RtLolaAst {
88            imports: imports.clone(),
89            constants: constants
90                .iter()
91                .map(|c| Rc::new(c.as_ref().clone()))
92                .collect(),
93            inputs: inputs.iter().map(|c| Rc::new(c.as_ref().clone())).collect(),
94            outputs: outputs
95                .iter()
96                .map(|c| Rc::new(c.as_ref().clone()))
97                .collect(),
98            mirrors: mirrors
99                .iter()
100                .map(|c| Rc::new(c.as_ref().clone()))
101                .collect(),
102            type_declarations: type_declarations.clone(),
103            next_node_id: next_node_id.clone(),
104            global_tags: global_tags.clone(),
105        }
106    }
107
108    pub(crate) fn primed_name(&self, name: &str) -> String {
109        let streams = self
110            .inputs
111            .iter()
112            .map(|i| &i.name)
113            .chain(self.outputs.iter().filter_map(|o| o.name()))
114            .collect::<Vec<_>>();
115        let mut name = format!("{name}\'");
116        loop {
117            if !streams.iter().any(|s| s.name == name) {
118                return name;
119            }
120            name = format!("{name}\'")
121        }
122    }
123}
124
125/// An Ast node representing the import of a module, which brings additional implemented functionality to a specification.
126/// The 'math' module, for example, adds pre-defined mathematical functions as the sine or cosine function.
127#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
128pub struct Import {
129    /// The name of the module
130    pub name: Ident,
131    /// The id of the node in the Ast
132    pub id: NodeId,
133    /// The span in the specification declaring the module
134    pub span: Span,
135}
136
137/// An Ast node representing the declaration of a constant.
138#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
139pub struct Constant {
140    /// The name of the constant stream
141    pub name: Ident,
142    /// The value type of the constant stream
143    pub ty: Option<Type>,
144    /// The literal defining the constant
145    pub literal: Literal,
146    /// The id of the node in the Ast
147    pub id: NodeId,
148    /// The span in the specification declaring the constant stream
149    pub span: Span,
150}
151
152/// An Ast node representing the declaration of an input stream.
153#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
154pub struct Input {
155    /// The name of the input stream
156    pub name: Ident,
157    ///  The value type of the input stream
158    pub ty: Type,
159    /// The parameters of a parameterized input stream; The vector is empty in non-parametrized streams.
160    pub params: Vec<Rc<Parameter>>,
161    /// The tags annotated to that input
162    pub tags: TagList,
163    /// The id of the node in the Ast
164    pub id: NodeId,
165    /// The span in the specification declaring the input stream
166    pub span: Span,
167}
168
169/// The kind of an output stream
170/// Can be either a regular output stream with a name or a trigger
171#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
172pub enum OutputKind {
173    /// The output stream represents a regular named output stream
174    NamedOutput(Ident),
175    /// The output stream represents a trigger
176    Trigger,
177}
178
179/// An Ast node representing the declaration of an output stream.
180#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
181pub struct Output {
182    /// The kind of the output stream
183    pub kind: OutputKind,
184    /// An optional value type annotation of the output stream
185    pub annotated_type: Option<Type>,
186    /// The parameters of a parameterized output stream; The vector is empty in non-parametrized streams
187    pub params: Vec<Rc<Parameter>>,
188    /// The spawn declaration of a parameterized stream
189    pub spawn: Option<SpawnSpec>,
190    /// The eval declaration of a stream,
191    pub eval: Vec<EvalSpec>,
192    ///  The close declaration of parametrized stream
193    pub close: Option<CloseSpec>,
194    /// The tags annotated to that input
195    pub tags: TagList,
196    /// The id of the node in the Ast
197    pub id: NodeId,
198    /// The span in the specification declaring the output stream
199    pub span: Span,
200}
201
202impl Output {
203    /// Returns the name of the output stream if it has any
204    pub fn name(&self) -> Option<&Ident> {
205        match &self.kind {
206            OutputKind::NamedOutput(n) => Some(n),
207            OutputKind::Trigger => None,
208        }
209    }
210}
211
212/// Represents an output stream that mirrors another but filters them.
213#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
214pub struct Mirror {
215    /// The name of the mirror stream.
216    pub name: Ident,
217    /// The condition under which values of the target will be propagated.
218    pub filter: Expression,
219    /// The stream that is supposed to be mirrored.
220    pub target: Ident,
221    /// The id of the node in the Ast
222    pub id: NodeId,
223    /// The span in the specification declaring the parameter
224    pub span: Span,
225}
226
227/// An Ast node representing the declaration of a parameter of a parametrized stream.
228#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
229pub struct Parameter {
230    /// The name of the parameter
231    pub name: Ident,
232    /// An optional value type annotation of the parameter
233    pub ty: Option<Type>,
234    /// The index of this parameter in the list of parameter of the respective output stream
235    pub param_idx: usize,
236    /// The id of the node in the Ast
237    pub id: NodeId,
238    /// The span in the specification declaring the parameter
239    pub span: Span,
240}
241
242/// An Ast node representing the declaration of a spawn condition and expression of a stream.
243#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
244pub struct SpawnSpec {
245    /// The expression defining the parameter instances. If the stream has more than one parameter, the expression needs to return a tuple, with one element for each parameter
246    pub expression: Option<Expression>,
247    /// The pacing type describing when a new instance is created.
248    pub annotated_pacing: AnnotatedPacingType,
249    /// An additional condition for the creation of an instance, i.e., an instance is only created if the condition is true.
250    pub condition: Option<Expression>,
251    /// The id of the node in the Ast
252    pub id: NodeId,
253    /// The span in the specification declaring the invoke declaration
254    pub span: Span,
255}
256
257/// An Ast node representing the evaluation condition and expression of a stream
258#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
259pub struct EvalSpec {
260    /// The pacing type describing when a new value is computed.
261    pub annotated_pacing: AnnotatedPacingType,
262    /// The boolean expression defining the condition, if a stream instance is evaluated.
263    pub condition: Option<Expression>,
264    /// The evaluated expression, defining the value of the stream.
265    pub eval_expression: Option<Expression>,
266    /// The id of the node in the Ast
267    pub id: NodeId,
268    /// The span in the specification declaring the extend declaration
269    pub span: Span,
270}
271
272/// An Ast node representing the declaration of a close condition of a stream
273#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
274pub struct CloseSpec {
275    /// The boolean expression defining the condition, if a stream instance is closed.
276    pub condition: Expression,
277    /// The pacing type describing when the close condition is evaluated.
278    pub annotated_pacing: AnnotatedPacingType,
279    /// The id of the node in the Ast
280    pub id: NodeId,
281    /// The span in the specification declaring the extend declaration
282    pub span: Span,
283}
284
285/// An Ast node representing the declaration of a user-defined type.
286#[allow(clippy::vec_box)]
287#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
288pub struct TypeDeclaration {
289    /// The name of the new type.
290    pub name: Option<Ident>,
291    /// The components of the new type, e.g. a GPS type might consist of a type for the latitude and for the longitude
292    pub fields: Vec<Box<TypeDeclField>>,
293    /// The id of the node in the Ast
294    pub id: NodeId,
295    /// The span in the specification declaring the type declaration
296    pub span: Span,
297}
298
299type TagList = Vec<Tag>;
300
301/// An annotation of a stream.
302#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
303pub struct Tag {
304    /// The key of the annotation.
305    pub key: String,
306    /// The value of the annotation (if any).
307    pub value: Option<String>,
308    /// The span of the annotation.
309    pub span: Span,
310}
311
312/// An Ast node representing the declaration of a field of a user-defined type.
313#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
314pub struct TypeDeclField {
315    /// The type of a field of a user-defined type
316    pub ty: Type,
317    /// The name of a field of a user-defined type
318    pub name: String,
319    /// The id of the node in the Ast
320    pub id: NodeId,
321    /// The span in the specification declaring the type declaration
322    pub span: Span,
323}
324
325/// An Ast node representing the declaration of a value type
326#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Hash, PartialOrd, Ord)]
327pub struct Type {
328    /// The kind of the type, e.g., a tuple
329    pub kind: TypeKind,
330    /// The id of the node in the Ast
331    pub id: NodeId,
332    /// The span in the specification declaring the extend declaration
333    pub span: Span,
334}
335
336impl Type {
337    /// Creates a new non-recursive type like `Int` or `Bool`
338    pub(crate) fn new_simple(id: NodeId, name: String, span: Span) -> Type {
339        Type {
340            id,
341            kind: TypeKind::Simple(name),
342            span,
343        }
344    }
345
346    /// Creates a new tuple type
347    pub(crate) fn new_tuple(id: NodeId, tuple: Vec<Type>, span: Span) -> Type {
348        Type {
349            id,
350            kind: TypeKind::Tuple(tuple),
351            span,
352        }
353    }
354
355    /// Creates a new optional type
356    pub(crate) fn new_optional(id: NodeId, name: Type, span: Span) -> Type {
357        Type {
358            id,
359            kind: TypeKind::Optional(name.into()),
360            span,
361        }
362    }
363}
364
365/// Ast representation of the value type of a stream
366#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq, Hash, PartialOrd, Ord)]
367pub enum TypeKind {
368    /// A simple type, e.g., `Int`
369    Simple(String),
370    /// A tuple type, e.g., `(Int32, Float32)`
371    Tuple(Vec<Type>),
372    /// An optional type, e.g., `Int?`
373    Optional(Box<Type>),
374}
375
376/// The Ast representation of a stream expression
377#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
378pub struct Expression {
379    /// The kind of the root expression, e.g., stream access
380    pub kind: ExpressionKind,
381    /// The id of the node in the Ast
382    pub id: NodeId,
383    /// The span in the specification declaring the extend declaration
384    pub span: Span,
385}
386
387impl Expression {
388    /// Creates a new expression
389    pub(crate) fn new(id: NodeId, kind: ExpressionKind, span: Span) -> Expression {
390        Expression { kind, id, span }
391    }
392}
393
394#[allow(clippy::large_enum_variant, clippy::vec_box)]
395#[derive(Debug, Clone, Hash, Eq, PartialEq, PartialOrd, Ord)]
396/// The Ast representation of a single expression
397pub enum ExpressionKind {
398    /// A literal, e.g., `1`, `"foo"`
399    Lit(Literal),
400    /// An identifier, e.g., `foo`
401    Ident(Ident),
402    /// Accessing a stream
403    StreamAccess(Box<Expression>, StreamAccessKind),
404    /// A default expression, e.g., `a.defaults(to: 0) `
405    Default(Box<Expression>, Box<Expression>),
406    /// An offset expression, e.g., `a.offset(by: -1)`
407    Offset(Box<Expression>, Offset),
408    /// A discrete window with a duration `duration` as an integer constant and aggregation function `aggregation`
409    DiscreteWindowAggregation {
410        /// The accesses stream
411        expr: Box<Expression>,
412        /// The duration of the window
413        duration: Box<Expression>,
414        /// Flag to mark that the window returns only a value if the complete duration has passed
415        wait: bool,
416        /// The aggregation function
417        aggregation: WindowOperation,
418    },
419    /// A sliding window with duration `duration` and aggregation function `aggregation`
420    SlidingWindowAggregation {
421        /// The accesses stream
422        expr: Box<Expression>,
423        /// The duration of the window
424        duration: Box<Expression>,
425        /// Flag to mark that the window returns only a value if the complete duration has passed
426        wait: bool,
427        /// The aggregation function
428        aggregation: WindowOperation,
429    },
430    /// A aggregation over stream-instances with instances `instances` and aggregation function `aggregation`
431    InstanceAggregation {
432        /// The accesses stream
433        expr: Box<Expression>,
434        /// Flag to indicate which instances are part of the aggregation
435        selection: InstanceSelection,
436        /// The aggregation function
437        aggregation: InstanceOperation,
438    },
439    /// A binary operation (For example: `a + b`, `a * b`)
440    Binary(BinOp, Box<Expression>, Box<Expression>),
441    /// A unary operation (For example: `!x`, `*x`)
442    Unary(UnOp, Box<Expression>),
443    /// An if-then-else expression
444    Ite(Box<Expression>, Box<Expression>, Box<Expression>),
445    /// An expression enveloped in parentheses
446    ParenthesizedExpression(Box<Expression>),
447    /// An expression was expected, e.g., after an operator like `*`
448    MissingExpression,
449    /// A tuple expression
450    Tuple(Vec<Expression>),
451    /// Access of a named (`obj.foo`) or unnamed (`obj.0`) struct field
452    Field(Box<Expression>, Ident),
453    /// A method call, e.g., `foo.bar(-1)`
454    Method(Box<Expression>, FunctionName, Vec<Type>, Vec<Expression>),
455    /// A function call
456    Function(FunctionName, Vec<Type>, Vec<Expression>),
457    /// A lambda expression used in filtered instance aggregations
458    Lambda(LambdaExpr),
459}
460
461#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, PartialOrd, Ord)]
462/// The Ast representation of the different aggregation functions
463pub enum WindowOperation {
464    /// Aggregation function to count the number of updated values on the accessed stream
465    Count,
466    /// Aggregation function to return the minimum
467    Min,
468    /// Aggregation function to return the minimum
469    Max,
470    /// Aggregation function to return the addition
471    Sum,
472    /// Aggregation function to return the product
473    Product,
474    /// Aggregation function to return the average
475    Average,
476    /// Aggregation function to return the integral
477    Integral,
478    /// Aggregation function to return the conjunction, i.e., the sliding window returns true iff ALL values on the accessed stream inside a window are assigned to true
479    Conjunction,
480    /// Aggregation function to return the disjunction, i.e., the sliding window returns true iff AT LEAst ONE value on the accessed stream inside a window is assigned to true
481    Disjunction,
482    /// Aggregation function to return the last value, a time bounded hold
483    Last,
484    /// Aggregation function to return the variance of all values, assumes equal probability.
485    Variance,
486    /// Aggregation function to return the covariance of all values in a tuple stream, assumes equal probability.
487    Covariance,
488    /// Aggregation function to return the standard deviation of all values, assumes equal probability.
489    StandardDeviation,
490    /// Aggregation function to return the Nth-Percentile
491    NthPercentile(u8),
492    /// Aggregation function to return the true ratio
493    TrueRatio,
494}
495
496#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, PartialOrd, Ord)]
497/// A subset of the window operations that are suitable to be performed over a set of instances.
498pub enum InstanceOperation {
499    /// Aggregation function to count the number of instances of the accessed stream
500    Count,
501    /// Aggregation function to return the minimum
502    Min,
503    /// Aggregation function to return the minimum
504    Max,
505    /// Aggregation function to return the addition
506    Sum,
507    /// Aggregation function to return the product
508    Product,
509    /// Aggregation function to return the average
510    Average,
511    /// Aggregation function to return the conjunction, i.e., the instances aggregation returns true iff ALL current values of the instances of the accessed stream are assigned to true
512    Conjunction,
513    /// Aggregation function to return the disjunction, i.e., the instances aggregation returns true iff ANY current values of the instances of the accessed stream are assigned to true
514    Disjunction,
515    /// Aggregation function to return the variance of all values, assumes equal probability.
516    Variance,
517    /// Aggregation function to return the covariance of all values in a tuple stream, assumes equal probability.
518    Covariance,
519    /// Aggregation function to return the standard deviation of all values, assumes equal probability.
520    StandardDeviation,
521    /// Aggregation function to return the Nth-Percentile
522    NthPercentile(u8),
523    /// Aggregation function to return the true ratio
524    TrueRatio,
525}
526
527impl TryFrom<WindowOperation> for InstanceOperation {
528    type Error = String;
529
530    fn try_from(value: WindowOperation) -> Result<Self, Self::Error> {
531        match value {
532            WindowOperation::Count => Ok(InstanceOperation::Count),
533            WindowOperation::Min => Ok(InstanceOperation::Min),
534            WindowOperation::Max => Ok(InstanceOperation::Max),
535            WindowOperation::Sum => Ok(InstanceOperation::Sum),
536            WindowOperation::Product => Ok(InstanceOperation::Product),
537            WindowOperation::Average => Ok(InstanceOperation::Average),
538            WindowOperation::Conjunction => Ok(InstanceOperation::Conjunction),
539            WindowOperation::Disjunction => Ok(InstanceOperation::Disjunction),
540            WindowOperation::Variance => Ok(InstanceOperation::Variance),
541            WindowOperation::Covariance => Ok(InstanceOperation::Covariance),
542            WindowOperation::StandardDeviation => Ok(InstanceOperation::StandardDeviation),
543            WindowOperation::NthPercentile(x) => Ok(InstanceOperation::NthPercentile(x)),
544            WindowOperation::TrueRatio => Ok(InstanceOperation::TrueRatio),
545            WindowOperation::Integral | WindowOperation::Last => {
546                Err(format!("Operation {value} not supported over instances."))
547            }
548        }
549    }
550}
551
552impl From<InstanceOperation> for WindowOperation {
553    fn from(val: InstanceOperation) -> Self {
554        match val {
555            InstanceOperation::Count => WindowOperation::Count,
556            InstanceOperation::Min => WindowOperation::Min,
557            InstanceOperation::Max => WindowOperation::Max,
558            InstanceOperation::Sum => WindowOperation::Sum,
559            InstanceOperation::Product => WindowOperation::Product,
560            InstanceOperation::Average => WindowOperation::Average,
561            InstanceOperation::Conjunction => WindowOperation::Conjunction,
562            InstanceOperation::Disjunction => WindowOperation::Disjunction,
563            InstanceOperation::Variance => WindowOperation::Variance,
564            InstanceOperation::Covariance => WindowOperation::Covariance,
565            InstanceOperation::StandardDeviation => WindowOperation::StandardDeviation,
566            InstanceOperation::NthPercentile(x) => WindowOperation::NthPercentile(x),
567            InstanceOperation::TrueRatio => WindowOperation::TrueRatio,
568        }
569    }
570}
571
572/// Describes the operation used to access a stream
573#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, PartialOrd, Ord)]
574pub enum StreamAccessKind {
575    /// Synchronous access
576    Sync,
577    /// Hold access for *incompatible* stream types, returns previous known value
578    Hold,
579    /// Optional access, returns value if it exists, called by `.get()`
580    Get,
581    /// Boolean Typed access, returning true if the target stream received a new value at the current timestamp. Called with `.is_fresh()`.
582    Fresh,
583}
584
585/// Describes the operation used to access a stream with a offset
586#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
587pub enum Offset {
588    /// Discrete offset
589    Discrete(i16),
590    /// Real-time offset
591    RealTime(Rational, TimeUnit),
592}
593
594/// Supported time unit for real time expressions
595#[allow(missing_docs)]
596#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
597pub enum TimeUnit {
598    Nanosecond,
599    Microsecond,
600    Millisecond,
601    Second,
602    Minute,
603    Hour,
604    Day,
605    Week,
606    /// Note: A year is always, *always*, 365 days long.
607    Year,
608}
609
610/// An Ast node representing the declaration of a literal
611#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
612pub struct Literal {
613    /// The kind of the literal, e.g., boolean, string, numeric, ...
614    pub kind: LitKind,
615    /// The id of the node in the Ast
616    pub id: NodeId,
617    /// The span in the specification declaring the extend declaration
618    pub span: Span,
619}
620
621impl Literal {
622    /// Creates a new bool literal
623    pub(crate) fn new_bool(id: NodeId, val: bool, span: Span) -> Literal {
624        Literal {
625            id,
626            kind: LitKind::Bool(val),
627            span,
628        }
629    }
630
631    /// Creates a new numeric literal
632    pub(crate) fn new_numeric(id: NodeId, val: &str, unit: Option<String>, span: Span) -> Literal {
633        Literal {
634            id,
635            kind: LitKind::Numeric(val.to_string(), unit),
636            span,
637        }
638    }
639
640    /// Creates a new string literal
641    pub(crate) fn new_str(id: NodeId, val: &str, span: Span) -> Literal {
642        Literal {
643            id,
644            kind: LitKind::Str(val.to_string()),
645            span,
646        }
647    }
648
649    /// Creates a new raw string literal
650    pub(crate) fn new_raw_str(id: NodeId, val: &str, span: Span) -> Literal {
651        Literal {
652            id,
653            kind: LitKind::RawStr(val.to_string()),
654            span,
655        }
656    }
657
658    /// Creates a new tuple literal
659    pub(crate) fn new_tuple(id: NodeId, val: Vec<Literal>, span: Span) -> Literal {
660        Literal {
661            id,
662            kind: LitKind::Tuple(val),
663            span,
664        }
665    }
666}
667
668#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
669/// The Ast representation of literals
670pub enum LitKind {
671    /// A string literal (`"foo"`)
672    Str(String),
673    /// A raw string literal (`r#" x " a \ff "#`)
674    RawStr(String),
675    /// A numeric value with optional postfix part (`42`, `1.3`, `1Hz`, `100sec`)
676    /// Stores as a string to have lossless representation
677    Numeric(String, Option<String>),
678    /// A boolean literal (`true`)
679    Bool(bool),
680    /// A tuple of literal values
681    Tuple(Vec<Literal>),
682}
683
684/// An Ast node representing a binary operator.
685#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
686pub enum BinOp {
687    /// The `+` operator (addition)
688    Add,
689    /// The `-` operator (subtraction)
690    Sub,
691    /// The `*` operator (multiplication)
692    Mul,
693    /// The `/` operator (division)
694    Div,
695    /// The `%` operator (modulus)
696    Rem,
697    /// The `**` operator (power)
698    Pow,
699    /// The `&&` operator (logical and)
700    And,
701    /// The `||` operator (logical or)
702    Or,
703    /// The `->` operator (logical implication)
704    Implies,
705    /// The `^` operator (bitwise xor)
706    BitXor,
707    /// The `&` operator (bitwise and)
708    BitAnd,
709    /// The `|` operator (bitwise or)
710    BitOr,
711    /// The `<<` operator (shift left)
712    Shl,
713    /// The `>>` operator (shift right)
714    Shr,
715    /// The `==` operator (equality)
716    Eq,
717    /// The `<` operator (less than)
718    Lt,
719    /// The `<=` operator (less than or equal to)
720    Le,
721    /// The `!=` operator (not equal to)
722    Ne,
723    /// The `>=` operator (greater than or equal to)
724    Ge,
725    /// The `>` operator (greater than)
726    Gt,
727}
728
729/// An Ast node representing an unary operator.
730#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord)]
731pub enum UnOp {
732    /// The `!` operator for logical inversion
733    Not,
734    /// The `-` operator for negation
735    Neg,
736    /// The `~` operator for one's complement
737    BitNot,
738}
739
740/// An Ast node representing the name of a called function and also the names of the arguments.
741#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Hash, PartialOrd, Ord)]
742pub struct FunctionName {
743    /// The name of the function
744    pub name: Ident,
745    /// A list containing the name of each argument.  If the argument is unnamed, it is represented by `None`.
746    pub arg_names: Vec<Option<Ident>>,
747}
748
749#[derive(Debug, Clone, Eq, Serialize, Deserialize, PartialOrd, Ord)]
750/// This struct represents an identifier in the specification.
751/// For example the name of an [Output] or [Input].
752pub struct Ident {
753    /// The name of the identifier
754    pub name: String,
755    /// The span in the specification declaring the identifier
756    pub span: Span,
757}
758
759impl Ident {
760    /// Creates a new identifier.
761    pub(crate) fn new(name: String, span: Span) -> Ident {
762        Ident { name, span }
763    }
764}
765
766/// In the equality definition of `Ident`, we only compare the string values
767/// and ignore the `Span` info
768impl PartialEq for Ident {
769    fn eq(&self, other: &Self) -> bool {
770        self.name == other.name
771    }
772}
773
774impl Hash for Ident {
775    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
776        self.name.hash(state);
777    }
778}
779
780#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
781/// Struct to represent a lambda expression in the specification
782/// Can currently only occur inside instance aggregation conditions
783pub struct LambdaExpr {
784    /// The names of the parameters of the stream instance
785    pub parameters: Vec<Rc<Parameter>>,
786    /// The condition that needs to be satisfied
787    pub expr: Box<Expression>,
788}
789
790#[derive(Debug, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
791/// Enum to indicate which instances are part of the aggregation
792pub enum InstanceSelection {
793    /// Only instances that are updated in this evaluation cycle are part of the aggregation
794    Fresh,
795    /// All instances are part of the aggregation
796    All,
797    /// Only instances that are updated in this evaluation cycle are part of the aggregation and satisfy the condition
798    FilteredFresh(LambdaExpr),
799    /// All instances that satisfy the condition are part of the aggregation
800    FilteredAll(LambdaExpr),
801}
802
803#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
804/// Enum to indicate which annotated pacing type the stream has
805pub enum AnnotatedPacingType {
806    /// No annotated Pacing
807    /// Includes the span where the annotation would be.
808    NotAnnotated(Span),
809    /// Annotated Pacing refers to the global clock
810    Global(Expression),
811    /// Annotated Pacing refers to the local clock
812    Local(Expression),
813    /// Annotated Pacing is unspecified if it refers the local or global clock
814    Unspecified(Expression),
815}
816
817#[derive(
818    Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
819)]
820/// Every node in the Ast gets a unique id, represented by a 32bit unsigned integer.
821/// They are used in the later analysis phases to store information about Ast nodes.
822/// The actual unique id.
823pub struct NodeId(u32);
824
825impl NodeId {
826    /// Creates a new NodeId
827    pub fn new(x: usize) -> NodeId {
828        assert!(x < (u32::MAX as usize));
829        NodeId(x as u32)
830    }
831}