rimu_ast/
expression.rs

1use rimu_meta::Spanned;
2use rust_decimal::Decimal;
3use std::fmt;
4
5use crate::{BinaryOperator, UnaryOperator};
6
7/// An expression represents an entity which can be evaluated to a value.
8#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
9pub enum Expression {
10    /// Literal null.
11    Null,
12
13    /// Literal boolean.
14    Boolean(bool),
15
16    /// Literal string.
17    String(String),
18
19    /// Literal number.
20    Number(Decimal),
21
22    /// A named local variable.
23    Identifier(String),
24
25    /// Literal list.
26    List(Vec<SpannedExpression>),
27
28    /// Literal key-value object.
29    Object(Vec<(Spanned<String>, SpannedExpression)>),
30
31    /// Function
32    Function {
33        args: Vec<Spanned<String>>,
34        body: Box<SpannedExpression>,
35    },
36
37    /// An operation on a single [`Expression`] operand with an [`Operator`]
38    Unary {
39        right: Box<SpannedExpression>,
40        operator: UnaryOperator,
41    },
42
43    /// An operation on two [`Expression`] operands with a an [`Operator`].
44    Binary {
45        left: Box<SpannedExpression>,
46        right: Box<SpannedExpression>,
47        operator: BinaryOperator,
48    },
49
50    /// A function invocation with a list of [`Expression`] parameters.
51    Call {
52        function: Box<SpannedExpression>,
53        args: Vec<SpannedExpression>,
54    },
55
56    /// Get index operation (`a[x]`).
57    GetIndex {
58        container: Box<SpannedExpression>,
59        index: Box<SpannedExpression>,
60    },
61
62    /// Get key operation (`c.z`).
63    GetKey {
64        container: Box<SpannedExpression>,
65        key: Spanned<String>,
66    },
67
68    /// Slice operation (`b[x:y]`).
69    GetSlice {
70        container: Box<SpannedExpression>,
71        start: Option<Box<SpannedExpression>>,
72        end: Option<Box<SpannedExpression>>,
73    },
74
75    Error,
76}
77
78pub type SpannedExpression = Spanned<Expression>;
79
80impl fmt::Display for Expression {
81    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82        match self {
83            Expression::Null => write!(f, "null"),
84            Expression::Boolean(boolean) => write!(f, "{}", boolean),
85            Expression::String(string) => write!(f, "\"{}\"", string),
86            Expression::Number(number) => write!(f, "{}", number),
87            Expression::List(list) => {
88                let keys = list
89                    .iter()
90                    .map(ToString::to_string)
91                    .collect::<Vec<String>>()
92                    .join(", ");
93                write!(f, "[{}]", keys)
94            }
95            Expression::Function { args, body } => {
96                let args = args
97                    .iter()
98                    .map(ToString::to_string)
99                    .collect::<Vec<String>>()
100                    .join(", ");
101                write!(f, "({}) => {}", args, body)
102            }
103            Expression::Object(object) => {
104                let entries = object
105                    .iter()
106                    .map(|(key, value)| format!("\"{}\": {}", key, value))
107                    .collect::<Vec<String>>()
108                    .join(", ");
109                write!(f, "{{{}}}", entries)
110            }
111            Expression::Identifier(identifier) => write!(f, "{}", identifier),
112            Expression::Unary { right, operator } => write!(f, "{}{}", operator, right),
113            Expression::Binary {
114                left,
115                operator,
116                right,
117            } => write!(f, "{} {} {}", left, operator, right),
118            Expression::Call { function, args } => {
119                let args = args
120                    .iter()
121                    .map(ToString::to_string)
122                    .collect::<Vec<String>>()
123                    .join(", ");
124                write!(f, "{}({})", function, args)
125            }
126            Expression::GetIndex { container, index } => write!(f, "{}[{}]", container, index),
127            Expression::GetKey { container, key } => write!(f, "{}.{}", container, key),
128            Expression::GetSlice {
129                container,
130                start,
131                end,
132            } => write!(
133                f,
134                "{}[{}:{}]",
135                container,
136                start.as_ref().map(|s| s.to_string()).unwrap_or("".into()),
137                end.as_ref().map(|e| e.to_string()).unwrap_or("".into()),
138            ),
139            Expression::Error => write!(f, "error"),
140        }
141    }
142}