darklua_core/nodes/expressions/
mod.rs1mod 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
113 DecimalNumber::new(value)
114 .with_exponent(exponent as i64, true)
115 .into()
116 } else if value > 999.0 && (value / 100.0).fract() == 0.0 {
117 let mut exponent = value.log10().floor();
118 let mut power = 10_f64.powf(exponent);
119
120 while exponent > 2.0 && (value / power).fract() != 0.0 {
121 exponent -= 1.0;
122 power /= 10.0;
123 }
124
125 DecimalNumber::new(value)
126 .with_exponent(exponent as i64, true)
127 .into()
128 } else {
129 DecimalNumber::new(value).into()
130 }
131 }
132 }
133 }
134}
135
136impl From<f32> for Expression {
137 fn from(value: f32) -> Self {
138 (value as f64).into()
139 }
140}
141
142impl From<usize> for Expression {
143 fn from(value: usize) -> Self {
144 (value as f64).into()
145 }
146}
147
148impl From<u64> for Expression {
149 fn from(value: u64) -> Self {
150 (value as f64).into()
151 }
152}
153
154impl From<u32> for Expression {
155 fn from(value: u32) -> Self {
156 (value as f64).into()
157 }
158}
159
160impl From<u16> for Expression {
161 fn from(value: u16) -> Self {
162 (value as f64).into()
163 }
164}
165
166impl From<u8> for Expression {
167 fn from(value: u8) -> Self {
168 (value as f64).into()
169 }
170}
171
172impl From<i64> for Expression {
173 fn from(value: i64) -> Self {
174 (value as f64).into()
175 }
176}
177
178impl From<i32> for Expression {
179 fn from(value: i32) -> Self {
180 (value as f64).into()
181 }
182}
183
184impl From<i16> for Expression {
185 fn from(value: i16) -> Self {
186 (value as f64).into()
187 }
188}
189
190impl From<i8> for Expression {
191 fn from(value: i8) -> Self {
192 (value as f64).into()
193 }
194}
195
196impl From<BinaryExpression> for Expression {
197 fn from(binary: BinaryExpression) -> Expression {
198 Expression::Binary(Box::new(binary))
199 }
200}
201
202impl From<FunctionCall> for Expression {
203 fn from(call: FunctionCall) -> Expression {
204 Expression::Call(Box::new(call))
205 }
206}
207
208impl From<FieldExpression> for Expression {
209 fn from(field: FieldExpression) -> Expression {
210 Expression::Field(Box::new(field))
211 }
212}
213
214impl From<FunctionExpression> for Expression {
215 fn from(function: FunctionExpression) -> Self {
216 Expression::Function(function)
217 }
218}
219
220impl From<Identifier> for Expression {
221 fn from(identifier: Identifier) -> Self {
222 Expression::Identifier(identifier)
223 }
224}
225
226impl From<IfExpression> for Expression {
227 fn from(if_expression: IfExpression) -> Expression {
228 Expression::If(Box::new(if_expression))
229 }
230}
231
232impl From<IndexExpression> for Expression {
233 fn from(index: IndexExpression) -> Self {
234 Self::Index(Box::new(index))
235 }
236}
237
238impl From<NumberExpression> for Expression {
239 fn from(number: NumberExpression) -> Self {
240 Self::Number(number)
241 }
242}
243
244impl From<DecimalNumber> for Expression {
245 fn from(number: DecimalNumber) -> Self {
246 Self::Number(NumberExpression::Decimal(number))
247 }
248}
249
250impl From<HexNumber> for Expression {
251 fn from(number: HexNumber) -> Self {
252 Self::Number(NumberExpression::Hex(number))
253 }
254}
255
256impl From<BinaryNumber> for Expression {
257 fn from(number: BinaryNumber) -> Self {
258 Self::Number(NumberExpression::Binary(number))
259 }
260}
261
262impl From<Prefix> for Expression {
263 fn from(prefix: Prefix) -> Self {
264 match prefix {
265 Prefix::Call(call) => Self::Call(Box::new(call)),
266 Prefix::Field(field) => Self::Field(field),
267 Prefix::Identifier(name) => Self::Identifier(name),
268 Prefix::Index(index) => Self::Index(index),
269 Prefix::Parenthese(expression) => expression.into(),
270 }
271 }
272}
273
274impl From<ParentheseExpression> for Expression {
275 fn from(expression: ParentheseExpression) -> Self {
276 Self::Parenthese(expression.into())
277 }
278}
279
280impl From<StringExpression> for Expression {
281 fn from(string: StringExpression) -> Self {
282 Self::String(string)
283 }
284}
285
286impl From<InterpolatedStringExpression> for Expression {
287 fn from(interpolated_string: InterpolatedStringExpression) -> Self {
288 Self::InterpolatedString(interpolated_string)
289 }
290}
291
292impl From<TableExpression> for Expression {
293 fn from(table: TableExpression) -> Self {
294 Self::Table(table)
295 }
296}
297
298impl From<UnaryExpression> for Expression {
299 fn from(unary: UnaryExpression) -> Self {
300 Self::Unary(Box::new(unary))
301 }
302}
303
304impl From<TypeCastExpression> for Expression {
305 fn from(type_cast: TypeCastExpression) -> Self {
306 Self::TypeCast(type_cast)
307 }
308}
309
310impl From<Variable> for Expression {
311 fn from(variable: Variable) -> Self {
312 match variable {
313 Variable::Identifier(identifier) => Self::Identifier(identifier),
314 Variable::Field(field) => Self::Field(field),
315 Variable::Index(index) => Self::Index(index),
316 }
317 }
318}
319
320impl<T: Into<Expression>> From<Option<T>> for Expression {
321 fn from(value: Option<T>) -> Self {
322 match value {
323 None => Self::nil(),
324 Some(value) => value.into(),
325 }
326 }
327}
328
329#[cfg(test)]
330mod test {
331 macro_rules! snapshot_from_expression {
332 ($($name:ident => $input:expr),+ $(,)?) => {
333 $(
334 #[test]
335 fn $name() {
336 let result = crate::nodes::Expression::from($input);
337
338 insta::assert_debug_snapshot!(stringify!($name), result);
339 }
340 )+
341 };
342 }
343
344 mod expression_from_floats {
345 snapshot_from_expression!(
346 f64_0 => 0_f64,
347 f64_1e42 => 1e42_f64,
348 f64_1_2345e50 => 1.2345e50_f64,
349 f64_infinity => f64::INFINITY,
350 i64_minus_one => -1_i64,
351 f64_minus_zero => -0.0,
352 );
353 }
354}