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)]
39pub enum Expression {
40 Binary(Box<BinaryExpression>),
42 Call(Box<FunctionCall>),
44 False(Option<Token>),
46 Field(Box<FieldExpression>),
48 Function(Box<FunctionExpression>),
50 Identifier(Identifier),
52 If(Box<IfExpression>),
54 Index(Box<IndexExpression>),
56 Nil(Option<Token>),
58 Number(NumberExpression),
60 Parenthese(Box<ParentheseExpression>),
62 String(StringExpression),
64 InterpolatedString(InterpolatedStringExpression),
66 Table(TableExpression),
68 True(Option<Token>),
70 Unary(Box<UnaryExpression>),
72 VariableArguments(Option<Token>),
74 TypeCast(TypeCastExpression),
76}
77
78impl Expression {
79 #[inline]
81 pub fn nil() -> Self {
82 Self::Nil(None)
83 }
84
85 #[inline]
87 pub fn variable_arguments() -> Self {
88 Self::VariableArguments(None)
89 }
90
91 pub fn identifier<S: Into<Identifier>>(identifier: S) -> Self {
93 Self::Identifier(identifier.into())
94 }
95
96 pub fn in_parentheses(self) -> Self {
98 Self::Parenthese(ParentheseExpression::new(self).into())
99 }
100
101 pub fn mutate_last_token(&mut self) -> &mut Token {
104 let mut current = self;
105 loop {
106 match current {
107 Self::Binary(binary) => {
108 current = binary.mutate_right();
109 }
110 Self::Call(call) => break call.mutate_last_token(),
111 Self::Field(field) => break field.mutate_last_token(),
112 Self::Function(function) => break function.mutate_last_token(),
113 Self::Identifier(identifier) => break identifier.mutate_or_insert_token(),
114 Self::If(if_expr) => {
115 current = if_expr.mutate_else_result();
116 }
117 Self::Index(index) => break index.mutate_last_token(),
118 Self::Number(number) => break number.mutate_or_insert_token(),
119 Self::String(string) => break string.mutate_or_insert_token(),
120 Self::InterpolatedString(interpolated) => break interpolated.mutate_last_token(),
121 Self::Table(table) => break table.mutate_last_token(),
122 Self::Parenthese(parenthese) => break parenthese.mutate_last_token(),
123 Self::TypeCast(type_cast) => break type_cast.mutate_last_token(),
124 Self::Unary(unary) => {
125 current = unary.mutate_expression();
126 }
127 Self::True(token) => {
128 if token.is_none() {
129 *token = Some(Token::from_content("true"));
130 }
131 break token.as_mut().unwrap();
132 }
133 Self::False(token) => {
134 if token.is_none() {
135 *token = Some(Token::from_content("false"));
136 }
137 break token.as_mut().unwrap();
138 }
139 Self::Nil(token) => {
140 if token.is_none() {
141 *token = Some(Token::from_content("nil"));
142 }
143 break token.as_mut().unwrap();
144 }
145 Self::VariableArguments(ref mut token) => {
146 if token.is_none() {
147 *token = Some(Token::from_content("..."));
148 }
149 break token.as_mut().unwrap();
150 }
151 }
152 }
153 }
154}
155
156impl From<bool> for Expression {
157 fn from(boolean: bool) -> Expression {
158 if boolean {
159 Expression::True(None)
160 } else {
161 Expression::False(None)
162 }
163 }
164}
165
166impl From<f64> for Expression {
167 fn from(value: f64) -> Expression {
168 match value.classify() {
169 FpCategory::Nan => BinaryExpression::new(
170 BinaryOperator::Slash,
171 DecimalNumber::new(0.0),
172 DecimalNumber::new(0.0),
173 )
174 .into(),
175 FpCategory::Infinite => BinaryExpression::new(
176 BinaryOperator::Slash,
177 Expression::from(if value.is_sign_positive() { 1.0 } else { -1.0 }),
178 DecimalNumber::new(0.0),
179 )
180 .into(),
181 FpCategory::Zero => {
182 DecimalNumber::new(if value.is_sign_positive() { 0.0 } else { -0.0 }).into()
183 }
184 FpCategory::Subnormal | FpCategory::Normal => {
185 if value < 0.0 {
186 UnaryExpression::new(UnaryOperator::Minus, Expression::from(value.abs())).into()
187 } else if value < 0.1 {
188 let exponent = value.log10().floor();
189
190 DecimalNumber::new(value)
191 .with_exponent(exponent as i64, true)
192 .into()
193 } else if value > 999.0 && (value / 100.0).fract() == 0.0 {
194 let mut exponent = value.log10().floor();
195 let mut power = 10_f64.powf(exponent);
196
197 while exponent > 2.0 && (value / power).fract() != 0.0 {
198 exponent -= 1.0;
199 power /= 10.0;
200 }
201
202 DecimalNumber::new(value)
203 .with_exponent(exponent as i64, true)
204 .into()
205 } else {
206 DecimalNumber::new(value).into()
207 }
208 }
209 }
210 }
211}
212
213impl From<f32> for Expression {
214 fn from(value: f32) -> Self {
215 (value as f64).into()
216 }
217}
218
219impl From<usize> for Expression {
220 fn from(value: usize) -> Self {
221 (value as f64).into()
222 }
223}
224
225impl From<u64> for Expression {
226 fn from(value: u64) -> Self {
227 (value as f64).into()
228 }
229}
230
231impl From<u32> for Expression {
232 fn from(value: u32) -> Self {
233 (value as f64).into()
234 }
235}
236
237impl From<u16> for Expression {
238 fn from(value: u16) -> Self {
239 (value as f64).into()
240 }
241}
242
243impl From<u8> for Expression {
244 fn from(value: u8) -> Self {
245 (value as f64).into()
246 }
247}
248
249impl From<i64> for Expression {
250 fn from(value: i64) -> Self {
251 (value as f64).into()
252 }
253}
254
255impl From<i32> for Expression {
256 fn from(value: i32) -> Self {
257 (value as f64).into()
258 }
259}
260
261impl From<i16> for Expression {
262 fn from(value: i16) -> Self {
263 (value as f64).into()
264 }
265}
266
267impl From<i8> for Expression {
268 fn from(value: i8) -> Self {
269 (value as f64).into()
270 }
271}
272
273impl From<BinaryExpression> for Expression {
274 fn from(binary: BinaryExpression) -> Expression {
275 Expression::Binary(Box::new(binary))
276 }
277}
278
279impl From<FunctionCall> for Expression {
280 fn from(call: FunctionCall) -> Expression {
281 Expression::Call(Box::new(call))
282 }
283}
284
285impl From<FieldExpression> for Expression {
286 fn from(field: FieldExpression) -> Expression {
287 Expression::Field(Box::new(field))
288 }
289}
290
291impl From<FunctionExpression> for Expression {
292 fn from(function: FunctionExpression) -> Self {
293 Expression::Function(Box::new(function))
294 }
295}
296
297impl From<Identifier> for Expression {
298 fn from(identifier: Identifier) -> Self {
299 Expression::Identifier(identifier)
300 }
301}
302
303impl From<IfExpression> for Expression {
304 fn from(if_expression: IfExpression) -> Expression {
305 Expression::If(Box::new(if_expression))
306 }
307}
308
309impl From<IndexExpression> for Expression {
310 fn from(index: IndexExpression) -> Self {
311 Self::Index(Box::new(index))
312 }
313}
314
315impl From<NumberExpression> for Expression {
316 fn from(number: NumberExpression) -> Self {
317 Self::Number(number)
318 }
319}
320
321impl From<DecimalNumber> for Expression {
322 fn from(number: DecimalNumber) -> Self {
323 Self::Number(NumberExpression::Decimal(number))
324 }
325}
326
327impl From<HexNumber> for Expression {
328 fn from(number: HexNumber) -> Self {
329 Self::Number(NumberExpression::Hex(number))
330 }
331}
332
333impl From<BinaryNumber> for Expression {
334 fn from(number: BinaryNumber) -> Self {
335 Self::Number(NumberExpression::Binary(number))
336 }
337}
338
339impl From<Prefix> for Expression {
340 fn from(prefix: Prefix) -> Self {
341 match prefix {
342 Prefix::Call(call) => Self::Call(call),
343 Prefix::Field(field) => Self::Field(field),
344 Prefix::Identifier(name) => Self::Identifier(name),
345 Prefix::Index(index) => Self::Index(index),
346 Prefix::Parenthese(expression) => (*expression).into(),
347 }
348 }
349}
350
351impl From<ParentheseExpression> for Expression {
352 fn from(expression: ParentheseExpression) -> Self {
353 Self::Parenthese(expression.into())
354 }
355}
356
357impl From<StringExpression> for Expression {
358 fn from(string: StringExpression) -> Self {
359 Self::String(string)
360 }
361}
362
363impl From<InterpolatedStringExpression> for Expression {
364 fn from(interpolated_string: InterpolatedStringExpression) -> Self {
365 Self::InterpolatedString(interpolated_string)
366 }
367}
368
369impl From<TableExpression> for Expression {
370 fn from(table: TableExpression) -> Self {
371 Self::Table(table)
372 }
373}
374
375impl From<UnaryExpression> for Expression {
376 fn from(unary: UnaryExpression) -> Self {
377 Self::Unary(Box::new(unary))
378 }
379}
380
381impl From<TypeCastExpression> for Expression {
382 fn from(type_cast: TypeCastExpression) -> Self {
383 Self::TypeCast(type_cast)
384 }
385}
386
387impl From<Variable> for Expression {
388 fn from(variable: Variable) -> Self {
389 match variable {
390 Variable::Identifier(identifier) => Self::Identifier(identifier),
391 Variable::Field(field) => Self::Field(field),
392 Variable::Index(index) => Self::Index(index),
393 }
394 }
395}
396
397impl<T: Into<Expression>> From<Option<T>> for Expression {
398 fn from(value: Option<T>) -> Self {
399 match value {
400 None => Self::nil(),
401 Some(value) => value.into(),
402 }
403 }
404}
405
406#[cfg(test)]
407mod test {
408 macro_rules! snapshot_from_expression {
409 ($($name:ident => $input:expr),+ $(,)?) => {
410 $(
411 #[test]
412 fn $name() {
413 let result = crate::nodes::Expression::from($input);
414
415 insta::assert_debug_snapshot!(stringify!($name), result);
416 }
417 )+
418 };
419 }
420
421 mod expression_from_floats {
422 snapshot_from_expression!(
423 f64_0 => 0_f64,
424 f64_1e42 => 1e42_f64,
425 f64_1_2345e50 => 1.2345e50_f64,
426 f64_infinity => f64::INFINITY,
427 i64_minus_one => -1_i64,
428 f64_minus_zero => -0.0,
429 f32_0_5 => 0.5_f32,
430 f32_infinity => f32::INFINITY,
431 f32_nan => f32::NAN,
432 f64_nan => f64::NAN,
433 );
434 }
435
436 mod expression_from_integers {
437 snapshot_from_expression!(
438 u8_max => u8::MAX,
439 u16_max => u16::MAX,
440 u32_max => u32::MAX,
441 u64_max => u64::MAX,
442 i8_max => i8::MIN,
443 i16_max => i16::MIN,
444 i32_max => i32::MIN,
445 i64_max => i64::MIN,
446 );
447 }
448}