darklua_core/nodes/expressions/
mod.rs

1mod binary;
2mod field;
3mod function;
4mod if_expression;
5mod index;
6mod interpolated_string;
7mod number;
8mod parenthese;
9mod prefix;
10mod string;
11pub(crate) mod string_utils;
12mod table;
13mod type_cast;
14mod unary;
15
16pub use binary::*;
17pub use field::*;
18pub use function::*;
19pub use if_expression::*;
20pub use index::*;
21pub use interpolated_string::*;
22pub use number::*;
23pub use parenthese::*;
24pub use prefix::*;
25pub use string::*;
26pub use string_utils::StringError;
27pub use table::*;
28pub use type_cast::*;
29pub use unary::*;
30
31use crate::nodes::{FunctionCall, Identifier, Token, Variable};
32
33use super::impl_token_fns;
34
35use std::num::FpCategory;
36
37#[derive(Clone, Debug, PartialEq, Eq)]
38pub enum Expression {
39    Binary(Box<BinaryExpression>),
40    Call(Box<FunctionCall>),
41    False(Option<Token>),
42    Field(Box<FieldExpression>),
43    Function(FunctionExpression),
44    Identifier(Identifier),
45    If(Box<IfExpression>),
46    Index(Box<IndexExpression>),
47    Nil(Option<Token>),
48    Number(NumberExpression),
49    Parenthese(Box<ParentheseExpression>),
50    String(StringExpression),
51    InterpolatedString(InterpolatedStringExpression),
52    Table(TableExpression),
53    True(Option<Token>),
54    Unary(Box<UnaryExpression>),
55    VariableArguments(Option<Token>),
56    TypeCast(TypeCastExpression),
57}
58
59impl Expression {
60    #[inline]
61    pub fn nil() -> Self {
62        Self::Nil(None)
63    }
64
65    #[inline]
66    pub fn variable_arguments() -> Self {
67        Self::VariableArguments(None)
68    }
69
70    pub fn identifier<S: Into<Identifier>>(identifier: S) -> Self {
71        Self::Identifier(identifier.into())
72    }
73
74    pub fn in_parentheses(self) -> Self {
75        Self::Parenthese(ParentheseExpression::new(self).into())
76    }
77}
78
79impl From<bool> for Expression {
80    fn from(boolean: bool) -> Expression {
81        if boolean {
82            Expression::True(None)
83        } else {
84            Expression::False(None)
85        }
86    }
87}
88
89impl From<f64> for Expression {
90    fn from(value: f64) -> Expression {
91        match value.classify() {
92            FpCategory::Nan => BinaryExpression::new(
93                BinaryOperator::Slash,
94                DecimalNumber::new(0.0),
95                DecimalNumber::new(0.0),
96            )
97            .into(),
98            FpCategory::Infinite => BinaryExpression::new(
99                BinaryOperator::Slash,
100                Expression::from(if value.is_sign_positive() { 1.0 } else { -1.0 }),
101                DecimalNumber::new(0.0),
102            )
103            .into(),
104            FpCategory::Zero => {
105                DecimalNumber::new(if value.is_sign_positive() { 0.0 } else { -0.0 }).into()
106            }
107            FpCategory::Subnormal | FpCategory::Normal => {
108                if value < 0.0 {
109                    UnaryExpression::new(UnaryOperator::Minus, Expression::from(value.abs())).into()
110                } else if value < 0.1 {
111                    let exponent = value.log10().floor();
112                    let new_value = value / 10_f64.powf(exponent);
113
114                    DecimalNumber::new(new_value)
115                        .with_exponent(exponent as i64, true)
116                        .into()
117                } else if value > 999.0 && (value / 100.0).fract() == 0.0 {
118                    let mut exponent = value.log10().floor();
119                    let mut power = 10_f64.powf(exponent);
120
121                    while exponent > 2.0 && (value / power).fract() != 0.0 {
122                        exponent -= 1.0;
123                        power /= 10.0;
124                    }
125
126                    DecimalNumber::new(value / power)
127                        .with_exponent(exponent as i64, true)
128                        .into()
129                } else {
130                    DecimalNumber::new(value).into()
131                }
132            }
133        }
134    }
135}
136
137impl From<f32> for Expression {
138    fn from(value: f32) -> Self {
139        (value as f64).into()
140    }
141}
142
143impl From<usize> for Expression {
144    fn from(value: usize) -> Self {
145        (value as f64).into()
146    }
147}
148
149impl From<u64> for Expression {
150    fn from(value: u64) -> Self {
151        (value as f64).into()
152    }
153}
154
155impl From<u32> for Expression {
156    fn from(value: u32) -> Self {
157        (value as f64).into()
158    }
159}
160
161impl From<u16> for Expression {
162    fn from(value: u16) -> Self {
163        (value as f64).into()
164    }
165}
166
167impl From<u8> for Expression {
168    fn from(value: u8) -> Self {
169        (value as f64).into()
170    }
171}
172
173impl From<i64> for Expression {
174    fn from(value: i64) -> Self {
175        (value as f64).into()
176    }
177}
178
179impl From<i32> for Expression {
180    fn from(value: i32) -> Self {
181        (value as f64).into()
182    }
183}
184
185impl From<i16> for Expression {
186    fn from(value: i16) -> Self {
187        (value as f64).into()
188    }
189}
190
191impl From<i8> for Expression {
192    fn from(value: i8) -> Self {
193        (value as f64).into()
194    }
195}
196
197impl From<BinaryExpression> for Expression {
198    fn from(binary: BinaryExpression) -> Expression {
199        Expression::Binary(Box::new(binary))
200    }
201}
202
203impl From<FunctionCall> for Expression {
204    fn from(call: FunctionCall) -> Expression {
205        Expression::Call(Box::new(call))
206    }
207}
208
209impl From<FieldExpression> for Expression {
210    fn from(field: FieldExpression) -> Expression {
211        Expression::Field(Box::new(field))
212    }
213}
214
215impl From<FunctionExpression> for Expression {
216    fn from(function: FunctionExpression) -> Self {
217        Expression::Function(function)
218    }
219}
220
221impl From<Identifier> for Expression {
222    fn from(identifier: Identifier) -> Self {
223        Expression::Identifier(identifier)
224    }
225}
226
227impl From<IfExpression> for Expression {
228    fn from(if_expression: IfExpression) -> Expression {
229        Expression::If(Box::new(if_expression))
230    }
231}
232
233impl From<IndexExpression> for Expression {
234    fn from(index: IndexExpression) -> Self {
235        Self::Index(Box::new(index))
236    }
237}
238
239impl From<NumberExpression> for Expression {
240    fn from(number: NumberExpression) -> Self {
241        Self::Number(number)
242    }
243}
244
245impl From<DecimalNumber> for Expression {
246    fn from(number: DecimalNumber) -> Self {
247        Self::Number(NumberExpression::Decimal(number))
248    }
249}
250
251impl From<HexNumber> for Expression {
252    fn from(number: HexNumber) -> Self {
253        Self::Number(NumberExpression::Hex(number))
254    }
255}
256
257impl From<BinaryNumber> for Expression {
258    fn from(number: BinaryNumber) -> Self {
259        Self::Number(NumberExpression::Binary(number))
260    }
261}
262
263impl From<Prefix> for Expression {
264    fn from(prefix: Prefix) -> Self {
265        match prefix {
266            Prefix::Call(call) => Self::Call(Box::new(call)),
267            Prefix::Field(field) => Self::Field(field),
268            Prefix::Identifier(name) => Self::Identifier(name),
269            Prefix::Index(index) => Self::Index(index),
270            Prefix::Parenthese(expression) => expression.into(),
271        }
272    }
273}
274
275impl From<ParentheseExpression> for Expression {
276    fn from(expression: ParentheseExpression) -> Self {
277        Self::Parenthese(expression.into())
278    }
279}
280
281impl From<StringExpression> for Expression {
282    fn from(string: StringExpression) -> Self {
283        Self::String(string)
284    }
285}
286
287impl From<InterpolatedStringExpression> for Expression {
288    fn from(interpolated_string: InterpolatedStringExpression) -> Self {
289        Self::InterpolatedString(interpolated_string)
290    }
291}
292
293impl From<TableExpression> for Expression {
294    fn from(table: TableExpression) -> Self {
295        Self::Table(table)
296    }
297}
298
299impl From<UnaryExpression> for Expression {
300    fn from(unary: UnaryExpression) -> Self {
301        Self::Unary(Box::new(unary))
302    }
303}
304
305impl From<TypeCastExpression> for Expression {
306    fn from(type_cast: TypeCastExpression) -> Self {
307        Self::TypeCast(type_cast)
308    }
309}
310
311impl From<Variable> for Expression {
312    fn from(variable: Variable) -> Self {
313        match variable {
314            Variable::Identifier(identifier) => Self::Identifier(identifier),
315            Variable::Field(field) => Self::Field(field),
316            Variable::Index(index) => Self::Index(index),
317        }
318    }
319}
320
321impl<T: Into<Expression>> From<Option<T>> for Expression {
322    fn from(value: Option<T>) -> Self {
323        match value {
324            None => Self::nil(),
325            Some(value) => value.into(),
326        }
327    }
328}
329
330#[cfg(test)]
331mod test {
332    macro_rules! snapshot_from_expression {
333        ($($name:ident => $input:expr),+ $(,)?) => {
334            $(
335                #[test]
336                fn $name() {
337                    let result = crate::nodes::Expression::from($input);
338
339                    insta::assert_debug_snapshot!(stringify!($name), result);
340                }
341            )+
342        };
343    }
344
345    mod expression_from_floats {
346        snapshot_from_expression!(
347            f64_0 => 0_f64,
348            f64_1e42 => 1e42_f64,
349            f64_infinity => f64::INFINITY,
350            i64_minus_one => -1_i64,
351            f64_minus_zero => -0.0,
352        );
353    }
354}