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