darklua_core/generator/
mod.rs

1//! A module that contains the main [LuaGenerator](trait.LuaGenerator.html) trait
2//! and its implementations.
3
4mod dense;
5mod readable;
6mod token_based;
7mod utils;
8
9pub use dense::DenseLuaGenerator;
10pub use readable::ReadableLuaGenerator;
11pub use token_based::TokenBasedLuaGenerator;
12
13use crate::nodes;
14
15/// A trait to let its implementation define how the Lua code is generated. See
16/// [ReadableLuaGenerator](struct.ReadableLuaGenerator.html) and
17/// [DenseLuaGenerator](struct.DenseLuaGenerator.html) for implementations.
18pub trait LuaGenerator {
19    /// Consumes the LuaGenerator and produce a String object.
20    fn into_string(self) -> String;
21
22    fn write_block(&mut self, block: &nodes::Block);
23
24    fn write_statement(&mut self, statement: &nodes::Statement) {
25        use nodes::Statement::*;
26        match statement {
27            Assign(statement) => self.write_assign_statement(statement),
28            Do(statement) => self.write_do_statement(statement),
29            Call(statement) => self.write_function_call(statement),
30            CompoundAssign(statement) => self.write_compound_assign(statement),
31            Function(statement) => self.write_function_statement(statement),
32            GenericFor(statement) => self.write_generic_for(statement),
33            If(statement) => self.write_if_statement(statement),
34            LocalAssign(statement) => self.write_local_assign(statement),
35            LocalFunction(statement) => self.write_local_function(statement),
36            NumericFor(statement) => self.write_numeric_for(statement),
37            Repeat(statement) => self.write_repeat_statement(statement),
38            While(statement) => self.write_while_statement(statement),
39            TypeDeclaration(statement) => self.write_type_declaration_statement(statement),
40        }
41    }
42
43    fn write_assign_statement(&mut self, assign: &nodes::AssignStatement);
44    fn write_do_statement(&mut self, do_statement: &nodes::DoStatement);
45    fn write_compound_assign(&mut self, assign: &nodes::CompoundAssignStatement);
46    fn write_generic_for(&mut self, generic_for: &nodes::GenericForStatement);
47    fn write_if_statement(&mut self, if_statement: &nodes::IfStatement);
48    fn write_function_statement(&mut self, function: &nodes::FunctionStatement);
49    fn write_last_statement(&mut self, statement: &nodes::LastStatement);
50    fn write_local_assign(&mut self, assign: &nodes::LocalAssignStatement);
51    fn write_local_function(&mut self, function: &nodes::LocalFunctionStatement);
52    fn write_numeric_for(&mut self, numeric_for: &nodes::NumericForStatement);
53    fn write_repeat_statement(&mut self, repeat: &nodes::RepeatStatement);
54    fn write_while_statement(&mut self, while_statement: &nodes::WhileStatement);
55    fn write_type_declaration_statement(&mut self, statement: &nodes::TypeDeclarationStatement);
56
57    fn write_variable(&mut self, variable: &nodes::Variable) {
58        use nodes::Variable::*;
59        match variable {
60            Identifier(identifier) => self.write_identifier(identifier),
61            Field(field) => self.write_field(field),
62            Index(index) => self.write_index(index),
63        }
64    }
65
66    fn write_expression(&mut self, expression: &nodes::Expression) {
67        use nodes::Expression::*;
68        match expression {
69            Binary(binary) => self.write_binary_expression(binary),
70            Call(call) => self.write_function_call(call),
71            False(token) => self.write_false_expression(token),
72            Field(field) => self.write_field(field),
73            Function(function) => self.write_function(function),
74            Identifier(identifier) => self.write_identifier(identifier),
75            If(if_expression) => self.write_if_expression(if_expression),
76            Index(index) => self.write_index(index),
77            Nil(token) => self.write_nil_expression(token),
78            Number(number) => self.write_number(number),
79            Parenthese(parenthese) => self.write_parenthese(parenthese),
80            String(string) => self.write_string(string),
81            InterpolatedString(string) => self.write_interpolated_string(string),
82            Table(table) => self.write_table(table),
83            True(token) => self.write_true_expression(token),
84            Unary(unary) => self.write_unary_expression(unary),
85            VariableArguments(token) => self.write_variable_arguments_expression(token),
86            TypeCast(type_cast) => self.write_type_cast(type_cast),
87        }
88    }
89
90    fn write_identifier(&mut self, identifier: &nodes::Identifier);
91    fn write_binary_expression(&mut self, binary: &nodes::BinaryExpression);
92    fn write_if_expression(&mut self, if_expression: &nodes::IfExpression);
93    fn write_unary_expression(&mut self, unary: &nodes::UnaryExpression);
94    fn write_function(&mut self, function: &nodes::FunctionExpression);
95    fn write_function_call(&mut self, call: &nodes::FunctionCall);
96    fn write_field(&mut self, field: &nodes::FieldExpression);
97    fn write_index(&mut self, index: &nodes::IndexExpression);
98    fn write_parenthese(&mut self, parenthese: &nodes::ParentheseExpression);
99    fn write_type_cast(&mut self, type_cast: &nodes::TypeCastExpression);
100
101    fn write_false_expression(&mut self, token: &Option<nodes::Token>);
102    fn write_true_expression(&mut self, token: &Option<nodes::Token>);
103    fn write_nil_expression(&mut self, token: &Option<nodes::Token>);
104    fn write_variable_arguments_expression(&mut self, token: &Option<nodes::Token>);
105
106    fn write_prefix(&mut self, prefix: &nodes::Prefix) {
107        use nodes::Prefix::*;
108        match prefix {
109            Call(call) => self.write_function_call(call),
110            Field(field) => self.write_field(field),
111            Identifier(identifier) => self.write_identifier(identifier),
112            Index(index) => self.write_index(index),
113            Parenthese(parenthese) => self.write_parenthese(parenthese),
114        }
115    }
116
117    fn write_table(&mut self, table: &nodes::TableExpression);
118    fn write_table_entry(&mut self, entry: &nodes::TableEntry);
119    fn write_number(&mut self, number: &nodes::NumberExpression);
120
121    fn write_arguments(&mut self, arguments: &nodes::Arguments) {
122        use nodes::Arguments::*;
123        match arguments {
124            String(string) => self.write_string(string),
125            Table(table) => self.write_table(table),
126            Tuple(tuple) => self.write_tuple_arguments(tuple),
127        }
128    }
129
130    fn write_tuple_arguments(&mut self, arguments: &nodes::TupleArguments);
131
132    fn write_string(&mut self, string: &nodes::StringExpression);
133
134    fn write_interpolated_string(&mut self, string: &nodes::InterpolatedStringExpression);
135
136    fn write_type(&mut self, r#type: &nodes::Type) {
137        match r#type {
138            nodes::Type::Name(type_name) => self.write_type_name(type_name),
139            nodes::Type::Field(type_field) => self.write_type_field(type_field),
140            nodes::Type::True(token) => self.write_true_type(token),
141            nodes::Type::False(token) => self.write_false_type(token),
142            nodes::Type::Nil(token) => self.write_nil_type(token),
143            nodes::Type::String(string_type) => self.write_string_type(string_type),
144            nodes::Type::Array(array_type) => self.write_array_type(array_type),
145            nodes::Type::Table(table_type) => self.write_table_type(table_type),
146            nodes::Type::TypeOf(expression_type) => self.write_expression_type(expression_type),
147            nodes::Type::Parenthese(parenthese_type) => self.write_parenthese_type(parenthese_type),
148            nodes::Type::Function(function_type) => self.write_function_type(function_type),
149            nodes::Type::Optional(optional_type) => self.write_optional_type(optional_type),
150            nodes::Type::Intersection(intersection_type) => {
151                self.write_intersection_type(intersection_type)
152            }
153            nodes::Type::Union(union_type) => self.write_union_type(union_type),
154        }
155    }
156    fn write_type_name(&mut self, type_name: &nodes::TypeName);
157    fn write_type_field(&mut self, type_field: &nodes::TypeField);
158    fn write_true_type(&mut self, token: &Option<nodes::Token>);
159    fn write_false_type(&mut self, token: &Option<nodes::Token>);
160    fn write_nil_type(&mut self, token: &Option<nodes::Token>);
161    fn write_string_type(&mut self, string_type: &nodes::StringType);
162    fn write_array_type(&mut self, array_type: &nodes::ArrayType);
163    fn write_table_type(&mut self, table_type: &nodes::TableType);
164    fn write_expression_type(&mut self, expression_type: &nodes::ExpressionType);
165    fn write_parenthese_type(&mut self, parenthese_type: &nodes::ParentheseType);
166    fn write_function_type(&mut self, function_type: &nodes::FunctionType);
167    fn write_optional_type(&mut self, optional_type: &nodes::OptionalType);
168    fn write_intersection_type(&mut self, intersection_type: &nodes::IntersectionType);
169    fn write_union_type(&mut self, union_type: &nodes::UnionType);
170
171    fn write_type_pack(&mut self, type_pack: &nodes::TypePack);
172    fn write_variadic_type_pack(&mut self, variadic_type_pack: &nodes::VariadicTypePack);
173    fn write_generic_type_pack(&mut self, generic_type_pack: &nodes::GenericTypePack);
174
175    fn write_function_return_type(&mut self, return_type: &nodes::FunctionReturnType) {
176        match return_type {
177            nodes::FunctionReturnType::Type(r#type) => {
178                self.write_type(r#type);
179            }
180            nodes::FunctionReturnType::TypePack(type_pack) => {
181                self.write_type_pack(type_pack);
182            }
183            nodes::FunctionReturnType::VariadicTypePack(variadic_type_pack) => {
184                self.write_variadic_type_pack(variadic_type_pack);
185            }
186            nodes::FunctionReturnType::GenericTypePack(generic_type_pack) => {
187                self.write_generic_type_pack(generic_type_pack);
188            }
189        }
190    }
191
192    fn write_variadic_argument_type(
193        &mut self,
194        variadic_argument_type: &nodes::VariadicArgumentType,
195    ) {
196        match variadic_argument_type {
197            nodes::VariadicArgumentType::GenericTypePack(generic_type_pack) => {
198                self.write_generic_type_pack(generic_type_pack);
199            }
200            nodes::VariadicArgumentType::VariadicTypePack(variadic_type_pack) => {
201                self.write_variadic_type_pack(variadic_type_pack);
202            }
203        }
204    }
205
206    fn write_function_variadic_type(&mut self, variadic_type: &nodes::FunctionVariadicType) {
207        match variadic_type {
208            nodes::FunctionVariadicType::Type(r#type) => {
209                self.write_type(r#type);
210            }
211            nodes::FunctionVariadicType::GenericTypePack(generic_pack) => {
212                self.write_generic_type_pack(generic_pack);
213            }
214        }
215    }
216
217    fn write_type_parameter(&mut self, type_parameter: &nodes::TypeParameter) {
218        match type_parameter {
219            nodes::TypeParameter::Type(r#type) => self.write_type(r#type),
220            nodes::TypeParameter::TypePack(type_pack) => self.write_type_pack(type_pack),
221            nodes::TypeParameter::VariadicTypePack(variadic_type_pack) => {
222                self.write_variadic_type_pack(variadic_type_pack);
223            }
224            nodes::TypeParameter::GenericTypePack(generic_type_pack) => {
225                self.write_generic_type_pack(generic_type_pack);
226            }
227        }
228    }
229
230    fn write_generic_type_pack_default(
231        &mut self,
232        generic_type_pack_default: &nodes::GenericTypePackDefault,
233    ) {
234        match generic_type_pack_default {
235            nodes::GenericTypePackDefault::TypePack(type_pack) => self.write_type_pack(type_pack),
236            nodes::GenericTypePackDefault::VariadicTypePack(variadic_type_pack) => {
237                self.write_variadic_type_pack(variadic_type_pack);
238            }
239            nodes::GenericTypePackDefault::GenericTypePack(generic_type_pack) => {
240                self.write_generic_type_pack(generic_type_pack);
241            }
242        }
243    }
244}
245
246#[cfg(test)]
247mod test {
248    use super::*;
249    use crate::generator::{DenseLuaGenerator, ReadableLuaGenerator};
250
251    macro_rules! snapshot_node {
252        (
253            $generator_name:ident, $generator:expr, $node_name:ident, $write_name:ident => (
254                $($test_name:ident => $item:expr),+,
255            )
256        ) => {
257            mod $node_name {
258                use super::*;
259
260                $(
261                    #[test]
262                    fn $test_name() {
263                        let statement = $item;
264
265                        let mut generator = $generator;
266                        generator.$write_name(&statement.into());
267
268                        let snapshot_name = concat!(
269                            stringify!($generator_name),
270                            "_",
271                            stringify!($node_name),
272                            "_",
273                            stringify!($test_name),
274                        );
275
276                        insta::assert_snapshot!(
277                            snapshot_name,
278                            generator.into_string()
279                        );
280                    }
281                )*
282            }
283        }
284    }
285
286    macro_rules! test_numbers {
287        (
288            $generator:expr => (
289                $($name:ident => $value:expr),+,
290            )
291        ) => {
292            $(
293                #[test]
294                fn $name() {
295                    use std::str::FromStr;
296                    let number = $crate::nodes::NumberExpression::from_str($value).unwrap();
297
298                    let mut generator = $generator;
299                    generator.write_expression(&number.into());
300
301                    assert_eq!(generator.into_string(), $value);
302                }
303            )*
304        };
305    }
306
307    macro_rules! blocks_consistency {
308        (
309            $generator:expr => (
310                $($name:ident => $code:literal),+,
311            )
312        ) => {
313            $(
314                #[test]
315                fn $name() {
316                    let parser = $crate::Parser::default();
317
318                    let expected_block = parser.parse($code)
319                        .expect(&format!("unable to parse `{}`", $code));
320
321                    let mut generator = $generator;
322                    generator.write_block(&expected_block);
323                    let generated_code = generator.into_string();
324
325                    let generated_block = parser.parse(&generated_code)
326                        .expect(&format!("unable to parse generated code `{}`", &generated_code));
327
328                    assert_eq!(expected_block, generated_block);
329                }
330            )*
331        };
332    }
333
334    macro_rules! binary_precedence {
335        (
336            $generator:expr => (
337                $($name:ident($input:expr) => $expected:literal),+,
338            )
339        ) => {
340            $(
341                #[test]
342                fn $name() {
343                    let parser = $crate::Parser::default();
344
345                    let expected_block = parser.parse(&format!("return {}", $expected))
346                        .unwrap();
347                    let expected_return = expected_block.get_last_statement()
348                        .expect("it should have a return statement");
349
350                    let expected = match expected_return {
351                        LastStatement::Return(statement) => statement.iter_expressions()
352                            .next()
353                            .unwrap(),
354                        _ => panic!("return statement expected"),
355                    };
356
357                    let mut generator = $generator;
358                    generator.write_expression(&$input.into());
359
360                    let generated_code = format!("return {}", generator.into_string());
361                    let parsed_block = parser.parse(&generated_code)
362                        .expect(&format!("unable to parse generated code: `{}`", &generated_code));
363
364                    let parsed_return = parsed_block.get_last_statement()
365                        .expect("it should have a return statement");
366
367                    let parsed = match parsed_return {
368                        LastStatement::Return(statement) => {
369                            if statement.len() != 1 {
370                                panic!("return statement has more than one expression")
371                            }
372                            statement.iter_expressions().next().unwrap()
373                        },
374                        _ => panic!("return statement expected"),
375                    };
376
377                    pretty_assertions::assert_eq!(parsed, expected);
378                }
379            )*
380        };
381    }
382
383    macro_rules! snapshot_generator {
384        ($mod_name:ident, $generator:expr) => {
385
386mod $mod_name {
387    use super::*;
388    use $crate::nodes::*;
389
390    mod edge_cases {
391        use super::*;
392
393        blocks_consistency!($generator => (
394            index_with_bracket_string => "return ok[ [[field]]]",
395            call_with_bracket_string => "return ok[[ [field] ]]",
396            concat_numbers => "return 9 .. 3",
397            concat_float_numbers => "return 9. .. 3",
398            concat_number_with_variable_arguments => "return 9 .. ...",
399            concat_variable_arguments_with_number => "return ... ..1",
400            double_unary_minus => "return - -10",
401            binary_minus_with_unary_minus => "return 100- -10",
402        ));
403    }
404
405    mod numbers {
406        use super::*;
407
408        test_numbers!($generator => (
409            zero => "0",
410            one => "1",
411            integer => "123",
412            hex_number => "0x12",
413            hex_number_with_letter => "0x12a",
414            hex_with_exponent => "0x12p4",
415        ));
416    }
417
418    mod binary {
419        use super::*;
420
421        binary_precedence!($generator => (
422            left_associative_wraps_left_operand_if_has_lower_precedence(
423                BinaryExpression::new(
424                    BinaryOperator::Asterisk,
425                    DecimalNumber::new(2.0),
426                    BinaryExpression::new(
427                        BinaryOperator::Plus,
428                        DecimalNumber::new(1.0),
429                        DecimalNumber::new(3.0),
430                    )
431                )
432            ) => "2 * (1 + 3)",
433            left_associative_wraps_right_operand_if_has_lower_precedence(
434                BinaryExpression::new(
435                    BinaryOperator::And,
436                    false,
437                    BinaryExpression::new(
438                        BinaryOperator::Or,
439                        false,
440                        true,
441                    ),
442                )
443            ) => "false and (false or true)",
444            left_associative_wraps_right_operand_if_has_same_precedence(
445                BinaryExpression::new(
446                    BinaryOperator::Equal,
447                    true,
448                    BinaryExpression::new(
449                        BinaryOperator::LowerThan,
450                        DecimalNumber::new(1.0),
451                        DecimalNumber::new(2.0),
452                    ),
453                )
454            ) => "true == (1 < 2)",
455            right_associative_wrap_unary_left_operand_if_has_lower_precedence(
456                BinaryExpression::new(
457                    BinaryOperator::Caret,
458                    UnaryExpression::new(
459                        UnaryOperator::Minus,
460                        DecimalNumber::new(2.0),
461                    ),
462                    DecimalNumber::new(2.0),
463                )
464            ) => "(-2) ^ 2",
465            right_associative_wraps_left_operand_if_has_lower_precedence(
466                BinaryExpression::new(
467                    BinaryOperator::Caret,
468                    BinaryExpression::new(
469                        BinaryOperator::Plus,
470                        DecimalNumber::new(1.0),
471                        DecimalNumber::new(2.0),
472                    ),
473                    DecimalNumber::new(3.0),
474                )
475            ) => "(1 + 2) ^ 3",
476            right_associative_wraps_left_operand_if_has_same_precedence(
477                BinaryExpression::new(
478                    BinaryOperator::Caret,
479                    BinaryExpression::new(
480                        BinaryOperator::Caret,
481                        DecimalNumber::new(2.0),
482                        DecimalNumber::new(2.0),
483                    ),
484                    DecimalNumber::new(3.0),
485                )
486            ) => "(2 ^ 2) ^ 3",
487            right_associative_does_not_wrap_right_operand_if_unary(
488                BinaryExpression::new(
489                    BinaryOperator::Caret,
490                    DecimalNumber::new(2.0),
491                    UnaryExpression::new(
492                        UnaryOperator::Minus,
493                        DecimalNumber::new(2.0),
494                    ),
495                )
496            ) => "2 ^ -2",
497            right_associative_does_not_wrap_right_operand_if_has_same_precedence(
498                BinaryExpression::new(
499                    BinaryOperator::Caret,
500                    DecimalNumber::new(2.0),
501                    BinaryExpression::new(
502                        BinaryOperator::Caret,
503                        DecimalNumber::new(2.0),
504                        DecimalNumber::new(3.0),
505                    ),
506                )
507            ) => "2 ^ 2 ^ 3",
508            right_associative_does_not_wrap_right_operand_if_has_higher_precedence(
509                BinaryExpression::new(
510                    BinaryOperator::Concat,
511                    DecimalNumber::new(3.0),
512                    BinaryExpression::new(
513                        BinaryOperator::Plus,
514                        DecimalNumber::new(9.0),
515                        DecimalNumber::new(3.0),
516                    ),
517                )
518            ) => "3 .. 9 + 3",
519            if_does_not_wrap_else(
520                IfExpression::new(
521                    Expression::identifier("condition"),
522                    10.0,
523                    BinaryExpression::new(
524                        BinaryOperator::Percent,
525                        9.0,
526                        2.0,
527                    ),
528                )
529
530            ) => "if condition then 10 else 9 % 2",
531            binary_expression_wraps_if(
532                BinaryExpression::new(
533                    BinaryOperator::Percent,
534                    IfExpression::new(Expression::identifier("condition"), 10.0, 9.0),
535                    2.0,
536                )
537            ) => "(if condition then 10 else 9) % 2",
538            unary_does_not_wrap_if_with_binary_in_else_result(
539                UnaryExpression::new(
540                    UnaryOperator::Not,
541                    IfExpression::new(
542                        Expression::identifier("condition"),
543                        true,
544                        BinaryExpression::new(
545                            BinaryOperator::And,
546                            false,
547                            StringExpression::from_value("ok"),
548                        )
549                    ),
550                )
551            ) => "not if condition then true else false and 'ok'",
552            binary_wraps_unary_containing_an_if_expression(
553                BinaryExpression::new(
554                    BinaryOperator::And,
555                    UnaryExpression::new(
556                        UnaryOperator::Not,
557                        IfExpression::new(Expression::identifier("condition"), true, false),
558                    ),
559                    StringExpression::from_value("ok"),
560                )
561            ) => "(not if condition then true else false) and 'ok'",
562        ));
563    }
564
565    mod snapshots {
566        use super::*;
567
568        snapshot_node!($mod_name, $generator, block, write_block => (
569            ambiguous_function_call_from_assign => Block::default()
570                .with_statement(
571                    AssignStatement::from_variable(Variable::new("name"), Expression::identifier("variable"))
572                )
573                .with_statement(
574                    AssignStatement::from_variable(
575                        FieldExpression::new(ParentheseExpression::new(Expression::identifier("t")), "field"),
576                        false
577                    )
578                ),
579            ambiguous_function_call_from_compound_assign => Block::default()
580                .with_statement(
581                    CompoundAssignStatement::new(
582                        CompoundOperator::Plus,
583                        Variable::new("name"),
584                        BinaryExpression::new(
585                            BinaryOperator::Plus,
586                            Expression::identifier("variable"),
587                            Expression::identifier("value"),
588                        )
589                    )
590                )
591                .with_statement(
592                    AssignStatement::from_variable(
593                        IndexExpression::new(
594                            ParentheseExpression::new(Expression::identifier("t")),
595                            Expression::identifier("field"),
596                        ),
597                        false
598                    )
599                ),
600            ambiguous_function_call_from_local_assign => Block::default()
601                .with_statement(
602                    LocalAssignStatement::from_variable("name")
603                        .with_value(
604                            IfExpression::new(
605                                Expression::identifier("condition"),
606                                true,
607                                FunctionCall::from_name("fn")
608                            )
609                        )
610                )
611                .with_statement(
612                    FunctionCall::from_prefix(ParentheseExpression::new(Expression::identifier("fn")))
613                ),
614            ambiguous_function_call_from_function_call => Block::default()
615                .with_statement(
616                    FunctionCall::from_name("fn")
617                )
618                .with_statement(
619                    CompoundAssignStatement::new(
620                        CompoundOperator::Plus,
621                        IndexExpression::new(ParentheseExpression::new(
622                            Expression::identifier("t")),
623                            Expression::identifier("field"),
624                        ),
625                        1
626                    )
627                ),
628            ambiguous_function_call_from_repeat => Block::default()
629                .with_statement(
630                    RepeatStatement::new(
631                        Block::default(),
632                        UnaryExpression::new(UnaryOperator::Not, Expression::identifier("variable"))
633                    )
634                )
635                .with_statement(
636                    CompoundAssignStatement::new(
637                        CompoundOperator::Plus,
638                        FieldExpression::new(ParentheseExpression::new(Expression::identifier("t")), "field"),
639                        1
640                    )
641                ),
642        ));
643
644        snapshot_node!($mod_name, $generator, expression, write_expression => (
645            false_value => false,
646            true_value => true,
647            nil_value => Expression::nil(),
648            variable_arguments => Expression::variable_arguments(),
649            true_in_parenthese => Expression::from(true).in_parentheses(),
650        ));
651
652        snapshot_node!($mod_name, $generator, assign, write_statement => (
653            variable_with_one_value => AssignStatement::new(
654                vec![Variable::new("var")],
655                vec![Expression::from(false)],
656            ),
657            two_variables_with_one_value => AssignStatement::new(
658                vec![Variable::new("foo"), Variable::new("var")],
659                vec![Expression::from(false)],
660            ),
661            two_variables_with_two_values => AssignStatement::new(
662                vec![Variable::new("foo"), Variable::new("var")],
663                vec![Expression::nil(), Expression::from(false)],
664            ),
665        ));
666
667        snapshot_node!($mod_name, $generator, do_statement, write_statement => (
668            empty => DoStatement::default(),
669            nested_do => DoStatement::new(
670                Block::default().with_statement(DoStatement::default())
671            ),
672        ));
673
674        snapshot_node!($mod_name, $generator, compound_assign_statement, write_statement => (
675            increment_var_by_one => CompoundAssignStatement::new(
676                CompoundOperator::Plus,
677                Variable::new("var"),
678                1_f64,
679            ),
680        ));
681
682        snapshot_node!($mod_name, $generator, function_statement, write_statement => (
683            empty => FunctionStatement::from_name("foo", Block::default()),
684            empty_with_field =>  FunctionStatement::new(
685                FunctionName::from_name("foo").with_fields(vec!["bar".into()]),
686                Block::default(),
687                Vec::new(),
688                false
689            ),
690            empty_with_name_ending_with_number_with_field =>  FunctionStatement::new(
691                FunctionName::from_name("fn1").with_fields(vec!["bar".into()]),
692                Block::default(),
693                Vec::new(),
694                false
695            ),
696            empty_with_one_typed_parameter => FunctionStatement::from_name("fn", Block::default())
697                .with_parameter(Identifier::new("a").with_type(TypeName::new("string"))),
698            empty_with_two_typed_parameters => FunctionStatement::from_name("fn", Block::default())
699                .with_parameter(Identifier::new("a").with_type(TypeName::new("string")))
700                .with_parameter(Identifier::new("b").with_type(TypeName::new("bool"))),
701            empty_variadic_with_one_typed_parameter => FunctionStatement::from_name("fn", Block::default())
702                .variadic()
703                .with_parameter(Identifier::new("a").with_type(TypeName::new("string"))),
704            empty_variadic_typed_with_one_typed_parameter => FunctionStatement::from_name("fn", Block::default())
705                .with_variadic_type(TypeName::new("any"))
706                .with_parameter(Identifier::new("a").with_type(TypeName::new("string"))),
707            empty_with_string_return_type => FunctionStatement::from_name("fn", Block::default())
708                .with_return_type(TypeName::new("string")),
709            empty_with_void_return_type => FunctionStatement::from_name("fn", Block::default())
710                .with_return_type(TypePack::default()),
711            empty_with_generic_pack_return_type => FunctionStatement::from_name("fn", Block::default())
712                .with_return_type(GenericTypePack::new("T")),
713            empty_with_variadic_pack_return_type => FunctionStatement::from_name("fn", Block::default())
714                .with_return_type(
715                    VariadicTypePack::new(ParentheseType::new(
716                        UnionType::new(Type::from(true), Type::nil())
717                    ))
718                ),
719            empty_with_method => FunctionStatement::new(
720                FunctionName::from_name("foo").with_method("bar"),
721                Block::default(),
722                Vec::new(),
723                false
724            ),
725        ));
726
727        snapshot_node!($mod_name, $generator, generic_for, write_statement => (
728            empty => GenericForStatement::new(
729                vec!["var".into()],
730                vec![Expression::from(true)],
731                Block::default()
732            ),
733            empty_with_typed_var => GenericForStatement::new(
734                vec![Identifier::new("var").with_type(TypeName::new("string"))],
735                vec![Expression::from(true)],
736                Block::default()
737            ),
738            empty_with_two_typed_vars => GenericForStatement::new(
739                vec![
740                    Identifier::new("key").with_type(TypeName::new("string")),
741                    Identifier::new("value").with_type(TypeName::new("bool")),
742                ],
743                vec![Expression::from(true)],
744                Block::default()
745            ),
746        ));
747
748        snapshot_node!($mod_name, $generator, type_declaration, write_type_declaration_statement => (
749            string_alias => TypeDeclarationStatement::new("Str", TypeName::new("string")),
750            type_field => TypeDeclarationStatement::new("Object", TypeField::new("module", TypeName::new("Object"))),
751            type_field_with_name_ending_with_number
752                => TypeDeclarationStatement::new("Object", TypeField::new("module0", TypeName::new("Object"))),
753            exported_string_alias => TypeDeclarationStatement::new("Str", TypeName::new("string"))
754                .export(),
755            generic_array => TypeDeclarationStatement::new("Array", ArrayType::new(TypeName::new("T")))
756                .with_generic_parameters(
757                    GenericParametersWithDefaults::from_type_variable("T")
758                ),
759            generic_array_with_default
760                => TypeDeclarationStatement::new("Array", ArrayType::new(TypeName::new("T")))
761                    .with_generic_parameters(
762                        GenericParametersWithDefaults::from_type_variable_with_default(
763                            TypeVariableWithDefault::new("T", Type::nil())
764                        )
765                    ),
766            table_with_one_property => TypeDeclarationStatement::new(
767                "Obj",
768                TableType::default()
769                    .with_property(TablePropertyType::new("name", TypeName::new("string")))
770            ),
771            table_with_indexer_type => TypeDeclarationStatement::new(
772                "StringArray",
773                TableType::default()
774                    .with_indexer_type(TableIndexerType::new(TypeName::new("number"), TypeName::new("string")))
775            ),
776            table_with_one_property_and_indexer_type => TypeDeclarationStatement::new(
777                "PackedArray",
778                TableType::default()
779                    .with_property(TablePropertyType::new("n", TypeName::new("number")))
780                    .with_indexer_type(TableIndexerType::new(TypeName::new("number"), TypeName::new("string")))
781            ),
782            callback_with_variadic_type_is_string => TypeDeclarationStatement::new(
783                "Fn",
784                FunctionType::new(TypePack::default())
785                    .with_variadic_type(VariadicTypePack::new(TypeName::new("string")))
786            ),
787            callback_with_variadic_type_is_generic_pack => TypeDeclarationStatement::new(
788                "Fn",
789                FunctionType::new(TypePack::default())
790                    .with_variadic_type(GenericTypePack::new("T"))
791            ),
792            generic_fn_with_default_generic_pack
793                => TypeDeclarationStatement::new("Fn", FunctionType::new(GenericTypePack::new("R")))
794                    .with_generic_parameters(
795                        GenericParametersWithDefaults::from_generic_type_pack_with_default(
796                            GenericTypePackWithDefault::new(
797                                GenericTypePack::new("R"),
798                                GenericTypePack::new("T")
799                            )
800                        )
801                    ),
802            generic_fn_with_type_variable_and_default_generic_pack
803                => TypeDeclarationStatement::new(
804                    "Fn",
805                    FunctionType::new(GenericTypePack::new("R"))
806                        .with_argument(TypeName::new("T"))
807                )
808                    .with_generic_parameters(
809                        GenericParametersWithDefaults::from_type_variable("T")
810                        .with_generic_type_pack_with_default(
811                            GenericTypePackWithDefault::new(
812                                GenericTypePack::new("R"),
813                                VariadicTypePack::new(TypeName::new("string"))
814                            )
815                        )
816                    ),
817            generic_fn_with_type_variable_with_default_and_default_generic_pack
818                => TypeDeclarationStatement::new(
819                    "Fn",
820                    FunctionType::new(GenericTypePack::new("R"))
821                        .with_argument(TypeName::new("T"))
822                )
823                    .with_generic_parameters(
824                        GenericParametersWithDefaults::from_type_variable_with_default(
825                            TypeVariableWithDefault::new("T", TypeName::new("boolean"))
826                        )
827                        .with_generic_type_pack_with_default(
828                            GenericTypePackWithDefault::new(
829                                GenericTypePack::new("R"),
830                                VariadicTypePack::new(TypeName::new("string"))
831                            )
832                        )
833                    ),
834        ));
835
836        snapshot_node!($mod_name, $generator, if_statement, write_statement => (
837            empty => IfStatement::create(false, Block::default()),
838            empty_with_empty_else => IfStatement::create(false, Block::default())
839                .with_else_block(Block::default()),
840            empty_with_empty_multiple_branch => IfStatement::create(false, Block::default())
841                .with_new_branch(Expression::nil(), Block::default())
842                .with_new_branch(false, Block::default()),
843        ));
844
845        snapshot_node!($mod_name, $generator, intersection_type, write_intersection_type => (
846            single_type => IntersectionType::from(vec![Type::from(true)]),
847            two_types => IntersectionType::from(vec![Type::from(true), Type::from(false)]),
848            two_types_with_leading_token => IntersectionType::from(vec![Type::from(true), Type::from(false)])
849                .with_leading_token(),
850        ));
851
852        snapshot_node!($mod_name, $generator, union_type, write_union_type => (
853            single_type => UnionType::from(vec![Type::from(true)]),
854            two_types => UnionType::from(vec![Type::from(true), Type::from(false)]),
855            two_types_with_leading_token => UnionType::from(vec![Type::from(true), Type::from(false)])
856                .with_leading_token(),
857        ));
858
859        snapshot_node!($mod_name, $generator, local_assign, write_statement => (
860            foo_unassigned => LocalAssignStatement::from_variable("foo"),
861            foo_typed_unassigned => LocalAssignStatement::from_variable(
862                Identifier::new("foo").with_type(Type::from(true))
863            ),
864            foo_and_bar_unassigned => LocalAssignStatement::from_variable("foo")
865                .with_variable("bar"),
866            foo_and_bar_typed_unassigned => LocalAssignStatement::from_variable("foo")
867                .with_variable(Identifier::new("bar").with_type(Type::from(false))),
868            var_assign_to_false => LocalAssignStatement::from_variable("var")
869                .with_value(false),
870            typed_generic_var_break_equal_sign => LocalAssignStatement::from_variable(
871                Identifier::new("var").with_type(
872                    TypeName::new("List").with_type_parameter(TypeName::new("string"))
873                )
874            ).with_value(false),
875        ));
876
877        snapshot_node!($mod_name, $generator, local_function, write_statement => (
878            empty => LocalFunctionStatement::from_name("foo", Block::default()),
879            empty_variadic => LocalFunctionStatement::from_name("foo", Block::default())
880                .variadic(),
881            empty_with_one_parameter => LocalFunctionStatement::from_name("foo", Block::default())
882                .with_parameter("bar"),
883            empty_with_two_parameters => LocalFunctionStatement::from_name("foo", Block::default())
884                .with_parameter("bar")
885                .with_parameter("baz"),
886            empty_variadic_with_one_parameter => LocalFunctionStatement::from_name("foo", Block::default())
887                .with_parameter("bar")
888                .variadic(),
889            empty_with_generic_pack_return_type => LocalFunctionStatement::from_name("foo", Block::default())
890                .with_return_type(GenericTypePack::new("R")),
891        ));
892
893        snapshot_node!($mod_name, $generator, numeric_for, write_statement => (
894            empty_without_step => NumericForStatement::new(
895                "i",
896                Expression::identifier("start"),
897                Expression::identifier("max"),
898                None,
899                Block::default()
900            ),
901            empty_typed_without_step => NumericForStatement::new(
902                Identifier::new("i").with_type(TypeName::new("number")),
903                Expression::identifier("start"),
904                Expression::identifier("max"),
905                None,
906                Block::default()
907            ),
908            empty_with_step => NumericForStatement::new(
909                "i",
910                Expression::identifier("start"),
911                Expression::identifier("max"),
912                Some(Expression::identifier("step")),
913                Block::default()
914            ),
915            empty_typed_with_step => NumericForStatement::new(
916                Identifier::new("i").with_type(TypeName::new("number")),
917                Expression::identifier("start"),
918                Expression::identifier("max"),
919                Some(Expression::identifier("step")),
920                Block::default()
921            ),
922        ));
923
924        snapshot_node!($mod_name, $generator, repeat, write_statement => (
925            empty => RepeatStatement::new(
926                Block::default(),
927                false
928            ),
929        ));
930
931        snapshot_node!($mod_name, $generator, while_statement, write_statement => (
932            empty => WhileStatement::new(
933                Block::default(),
934                false
935            ),
936        ));
937
938        snapshot_node!($mod_name, $generator, last, write_last_statement => (
939            break_statement => LastStatement::new_break(),
940            continue_statement => LastStatement::new_continue(),
941            return_without_values => ReturnStatement::default(),
942            return_one_expression => ReturnStatement::one(Expression::from(true)),
943            return_two_expressions => ReturnStatement::one(Expression::from(true))
944                .with_expression(Expression::nil()),
945            return_parentheses => ReturnStatement::one(Expression::from(true).in_parentheses()),
946        ));
947
948        snapshot_node!($mod_name, $generator, binary, write_expression => (
949            true_and_false => BinaryExpression::new(
950                BinaryOperator::And,
951                Expression::from(true),
952                Expression::from(false)
953            ),
954            true_equal_false => BinaryExpression::new(
955                BinaryOperator::Equal,
956                Expression::from(true),
957                Expression::from(false)
958            ),
959            type_cast_break_type_parameters => BinaryExpression::new(
960                BinaryOperator::Equal,
961                TypeCastExpression::new(
962                    true,
963                    TypeName::new("Array").with_type_parameter(TypeName::new("string"))
964                ),
965                Expression::from(false)
966            ),
967            wrap_left_to_break_type_name_parameters => BinaryExpression::new(
968                BinaryOperator::LowerThan,
969                TypeCastExpression::new(true, TypeName::new("Array")),
970                Expression::from(false)
971            ),
972            wrap_left_to_break_type_field_parameters => BinaryExpression::new(
973                BinaryOperator::LowerThan,
974                TypeCastExpression::new(
975                    true,
976                    TypeField::new("Collections", TypeName::new("Array"))
977                ),
978                Expression::from(false)
979            ),
980        ));
981
982        snapshot_node!($mod_name, $generator, field, write_expression => (
983            identifier_prefix => FieldExpression::new(Prefix::from_name("foo"), "bar"),
984            identifier_ending_with_number_prefix => FieldExpression::new(Prefix::from_name("oof0"), "field"),
985        ));
986
987        snapshot_node!($mod_name, $generator, index, write_expression => (
988            identifier_prefix_with_identifier_value => IndexExpression::new(
989                Prefix::from_name("foo"),
990                Prefix::from_name("bar"),
991            ),
992        ));
993
994        snapshot_node!($mod_name, $generator, function_expr, write_expression => (
995            empty => FunctionExpression::default(),
996            empty_variadic => FunctionExpression::default().variadic(),
997            empty_variadic_with_one_parameter => FunctionExpression::default()
998                .with_parameter("a")
999                .variadic(),
1000            empty_variadic_with_two_parameter => FunctionExpression::default()
1001                .with_parameter("a")
1002                .with_parameter("b")
1003                .variadic(),
1004            empty_with_two_parameter => FunctionExpression::default()
1005                .with_parameter("a")
1006                .with_parameter("b"),
1007            empty_with_generic_pack_return_type => FunctionExpression::default()
1008                .with_return_type(GenericTypePack::new("R")),
1009        ));
1010
1011        snapshot_node!($mod_name, $generator, prefix, write_prefix => (
1012            identifier => Prefix::from_name("foo"),
1013            identifier_in_parenthese => Prefix::Parenthese(ParentheseExpression::new(Expression::identifier("foo"))),
1014        ));
1015
1016        snapshot_node!($mod_name, $generator, string, write_expression => (
1017            only_letters => StringExpression::from_value("hello"),
1018            with_single_quotes => StringExpression::from_value("I'm cool"),
1019            with_double_quotes => StringExpression::from_value(r#"Say: "Hi""#),
1020            with_single_and_double_quotes => StringExpression::from_value(r#"Say: "Don't""#),
1021        ));
1022
1023        snapshot_node!($mod_name, $generator, interpolated_string, write_expression => (
1024            only_letters => InterpolatedStringExpression::empty()
1025                .with_segment("hello"),
1026            with_single_quotes => InterpolatedStringExpression::empty()
1027                .with_segment("I'm cool"),
1028            with_double_quotes => InterpolatedStringExpression::empty()
1029                .with_segment(r#"Say: "Hi""#),
1030            with_backticks => InterpolatedStringExpression::empty()
1031                .with_segment("Say: `Hi`"),
1032            with_single_and_double_quotes => InterpolatedStringExpression::empty()
1033                .with_segment(r#"Say: "Don't""#),
1034            with_true_value => InterpolatedStringExpression::empty()
1035                .with_segment(true),
1036            with_empty_table => InterpolatedStringExpression::empty()
1037                .with_segment(TableExpression::default()),
1038            with_empty_table_in_type_cast => InterpolatedStringExpression::empty()
1039                .with_segment(TypeCastExpression::new(TableExpression::default(), TypeName::new("any"))),
1040        ));
1041
1042        snapshot_node!($mod_name, $generator, number, write_expression => (
1043            number_1 => 1.0,
1044            number_0_5 => 0.5,
1045            number_123 => 123.0,
1046            number_0_005 => 0.005,
1047            number_nan => DecimalNumber::new(f64::NAN),
1048            number_positive_infinity => DecimalNumber::new(f64::INFINITY),
1049            number_negative_infinity => DecimalNumber::new(f64::NEG_INFINITY),
1050            number_1_2345e_minus50 => 1.2345e-50,
1051            number_thousand => 1000.0,
1052            number_1_2345e50 => 1.2345e50,
1053            number_100_25 => 100.25,
1054            number_2000_05 => 2000.05,
1055            binary_0b10101 => BinaryNumber::new(0b10101, false),
1056        ));
1057
1058        snapshot_node!($mod_name, $generator, table, write_expression => (
1059            empty => TableExpression::default(),
1060            list_with_single_value => TableExpression::new(vec![
1061                TableEntry::Value(Expression::from(true)),
1062            ]),
1063            list_with_two_values => TableExpression::new(vec![
1064                TableEntry::Value(Expression::from(true)),
1065                TableEntry::Value(Expression::from(false)),
1066            ]),
1067            with_field_entry => TableExpression::new(vec![
1068                TableFieldEntry::new("field", true).into(),
1069            ]),
1070            with_index_entry => TableExpression::new(vec![
1071                TableIndexEntry::new(false, true).into(),
1072            ]),
1073            mixed_table => TableExpression::new(vec![
1074                TableEntry::Value(Expression::from(true)),
1075                TableFieldEntry::new("field", true).into(),
1076                TableIndexEntry::new(false, true).into(),
1077            ]),
1078        ));
1079
1080        snapshot_node!($mod_name, $generator, unary, write_expression => (
1081            not_true => UnaryExpression::new(
1082                UnaryOperator::Not,
1083                true,
1084            ),
1085            two_unary_minus_breaks_between_them => UnaryExpression::new(
1086                UnaryOperator::Minus,
1087                UnaryExpression::new(
1088                    UnaryOperator::Minus,
1089                    Expression::identifier("a"),
1090                ),
1091            ),
1092            wraps_in_parens_if_an_inner_binary_has_lower_precedence => UnaryExpression::new(
1093                UnaryOperator::Not,
1094                BinaryExpression::new(
1095                    BinaryOperator::Or,
1096                    false,
1097                    true,
1098                ),
1099            ),
1100            does_not_wrap_in_parens_if_an_inner_binary_has_higher_precedence => UnaryExpression::new(
1101                UnaryOperator::Minus,
1102                BinaryExpression::new(
1103                    BinaryOperator::Caret,
1104                    DecimalNumber::new(2.0),
1105                    DecimalNumber::new(2.0),
1106                ),
1107            ),
1108        ));
1109
1110        snapshot_node!($mod_name, $generator, arguments, write_arguments => (
1111            empty_tuple => TupleArguments::default(),
1112            tuple_with_one_value => TupleArguments::new(vec![true.into()]),
1113            tuple_with_two_values => TupleArguments::new(vec![true.into(), false.into()]),
1114        ));
1115    }
1116}
1117
1118        };
1119    }
1120
1121    snapshot_generator!(dense, DenseLuaGenerator::default());
1122    snapshot_generator!(readable, ReadableLuaGenerator::default());
1123    snapshot_generator!(token_based, TokenBasedLuaGenerator::new(""));
1124}