Skip to main content

darklua_core/generator/
dense.rs

1use crate::generator::{utils, LuaGenerator};
2use crate::nodes;
3
4/// This implementation of [LuaGenerator](trait.LuaGenerator.html) attempts to produce Lua code as
5/// small as possible. It is not meant to be read by humans.
6#[derive(Debug, Clone)]
7pub struct DenseLuaGenerator {
8    column_span: usize,
9    current_line_length: usize,
10    output: String,
11    last_push_length: usize,
12}
13
14impl DenseLuaGenerator {
15    /// Creates a generator that will wrap the code on a new line after the amount of
16    /// characters given by the `column_span` argument.
17    pub fn new(column_span: usize) -> Self {
18        Self {
19            column_span,
20            current_line_length: 0,
21            output: String::new(),
22            last_push_length: 0,
23        }
24    }
25
26    /// Appends a string to the current content of the DenseLuaGenerator. A space may be added
27    /// depending of the last character of the current content and the first character pushed.
28    fn push_str(&mut self, content: &str) {
29        if let Some(next_char) = content.chars().next() {
30            self.push_space_if_needed(next_char, content.len());
31            self.raw_push_str(content);
32        }
33    }
34
35    /// Same as the `push_str` function, but for a single character.
36    fn push_char(&mut self, character: char) {
37        self.push_space_if_needed(character, 1);
38
39        self.output.push(character);
40        self.current_line_length += 1;
41        self.last_push_length = 1;
42    }
43
44    /// This function pushes a character into the string, without appending a new line
45    /// or a space between the last pushed content.
46    fn merge_char(&mut self, character: char) {
47        if self.fits_on_current_line(1) {
48            self.raw_push_char(character);
49        } else {
50            let last_push_content = self.get_last_push_str().to_owned();
51            (0..self.last_push_length).for_each(|_| {
52                self.output.pop();
53            });
54
55            let mut last_char = self.output.pop();
56
57            while let Some(' ') = last_char {
58                last_char = self.output.pop();
59            }
60
61            if let Some(last_char) = last_char {
62                self.output.push(last_char);
63            }
64
65            self.output.push('\n');
66            self.output.push_str(&last_push_content);
67            self.output.push(character);
68            self.last_push_length += 1;
69            self.current_line_length = self.last_push_length;
70        }
71    }
72
73    fn push_new_line_if_needed(&mut self, pushed_length: usize) {
74        if self.current_line_length >= self.column_span {
75            self.push_new_line();
76        } else {
77            let total_length = self.current_line_length + pushed_length;
78
79            if total_length > self.column_span {
80                self.push_new_line();
81            }
82        }
83    }
84
85    fn push_space_if_needed(&mut self, next_character: char, pushed_length: usize) {
86        if self.current_line_length >= self.column_span {
87            self.push_new_line();
88        } else {
89            let total_length = self.current_line_length + pushed_length;
90
91            if self.needs_space(next_character) {
92                if total_length + 1 > self.column_span {
93                    self.push_new_line();
94                } else {
95                    self.output.push(' ');
96                    self.current_line_length += 1;
97                }
98            } else if total_length > self.column_span {
99                self.push_new_line();
100            }
101        }
102    }
103
104    #[inline]
105    fn push_new_line(&mut self) {
106        self.output.push('\n');
107        self.current_line_length = 0;
108    }
109
110    #[inline]
111    fn push_space(&mut self) {
112        self.output.push(' ');
113        self.current_line_length += 1;
114    }
115
116    #[inline]
117    fn fits_on_current_line(&self, length: usize) -> bool {
118        self.current_line_length + length <= self.column_span
119    }
120
121    #[inline]
122    fn needs_space(&self, next_character: char) -> bool {
123        if let Some(previous) = self.output.chars().last() {
124            utils::should_break_with_space(previous, next_character)
125        } else {
126            false
127        }
128    }
129
130    /// Consumes the LuaGenerator and produce a String object.
131    pub fn into_string(self) -> String {
132        self.output
133    }
134
135    #[inline]
136    fn raw_push_str(&mut self, content: &str) {
137        self.output.push_str(content);
138        self.last_push_length = content.len();
139        self.current_line_length += self.last_push_length;
140    }
141
142    #[inline]
143    fn raw_push_char(&mut self, character: char) {
144        self.output.push(character);
145        self.last_push_length = 1;
146        self.current_line_length += 1;
147    }
148
149    /// This function only insert a space or a new line if the given predicate returns true. In
150    /// the other case, the string is added to the current generator content.
151    fn push_str_and_break_if<F>(&mut self, content: &str, predicate: F)
152    where
153        F: Fn(&str) -> bool,
154    {
155        if predicate(self.get_last_push_str()) {
156            if self.fits_on_current_line(1 + content.len()) {
157                self.push_space();
158            } else {
159                self.push_new_line();
160            }
161        } else if !self.fits_on_current_line(content.len()) {
162            self.push_new_line();
163        }
164        self.raw_push_str(content);
165    }
166
167    /// Same as `push_str_and_break_if` but for a single character
168    fn push_char_and_break_if<F>(&mut self, content: char, predicate: F)
169    where
170        F: Fn(&str) -> bool,
171    {
172        if predicate(self.get_last_push_str()) {
173            if self.fits_on_current_line(2) {
174                self.push_space();
175            } else {
176                self.push_new_line();
177            }
178        } else if !self.fits_on_current_line(1) {
179            self.push_new_line();
180        }
181        self.raw_push_char(content);
182    }
183
184    fn get_last_push_str(&self) -> &str {
185        self.output
186            .get((self.output.len() - self.last_push_length)..)
187            .unwrap_or("")
188    }
189
190    fn write_function_parameters(
191        &mut self,
192        parameters: &[nodes::TypedIdentifier],
193        is_variadic: bool,
194        variadic_type: Option<&nodes::FunctionVariadicType>,
195    ) {
196        let last_index = parameters.len().saturating_sub(1);
197
198        parameters.iter().enumerate().for_each(|(index, variable)| {
199            self.write_typed_identifier(variable);
200
201            if index != last_index {
202                self.push_char(',');
203            }
204        });
205
206        if is_variadic {
207            if !parameters.is_empty() {
208                self.push_char(',');
209            };
210            self.push_str("...");
211
212            if let Some(variadic_type) = variadic_type {
213                self.push_char(':');
214                self.write_function_variadic_type(variadic_type);
215            }
216        };
217    }
218
219    fn write_attributes(&mut self, attributes: &nodes::Attributes) {
220        use nodes::Attribute;
221
222        for attribute in attributes.iter_attributes() {
223            match attribute {
224                Attribute::Name(named) => {
225                    let name = named.get_identifier().get_name();
226
227                    self.push_space_if_needed('@', 1 + name.len());
228                    self.raw_push_char('@');
229                    self.raw_push_str(name);
230                }
231                Attribute::Group(group) => {
232                    if !group.is_empty() {
233                        self.push_str("@[");
234
235                        let last_index = group.len().saturating_sub(1);
236
237                        for (index, attribute) in group.iter_attributes().enumerate() {
238                            self.push_str(attribute.name().get_name());
239
240                            if let Some(arguments) = attribute.get_arguments() {
241                                self.write_attribute_arguments(arguments);
242                            }
243
244                            if index != last_index {
245                                self.push_char(',');
246                            }
247                        }
248
249                        self.push_char(']');
250                    }
251                }
252            }
253        }
254    }
255
256    fn write_typed_identifier(&mut self, typed_identifier: &nodes::TypedIdentifier) {
257        self.push_str(typed_identifier.get_name());
258
259        if let Some(r#type) = typed_identifier.get_type() {
260            self.push_char(':');
261            self.write_type(r#type);
262        }
263    }
264
265    fn write_function_return_type(&mut self, return_type: &nodes::FunctionReturnType) {
266        match return_type {
267            nodes::FunctionReturnType::Type(r#type) => self.write_type(r#type),
268            nodes::FunctionReturnType::TypePack(type_pack) => self.write_type_pack(type_pack),
269            nodes::FunctionReturnType::VariadicTypePack(variadic_type_pack) => {
270                self.write_variadic_type_pack(variadic_type_pack);
271            }
272            nodes::FunctionReturnType::GenericTypePack(generic_type_pack) => {
273                self.write_generic_type_pack(generic_type_pack);
274            }
275        }
276    }
277
278    fn write_expression_in_parentheses(&mut self, expression: &nodes::Expression) {
279        self.push_char('(');
280        self.write_expression(expression);
281        self.push_char(')');
282    }
283
284    fn write_type_in_parentheses(&mut self, r#type: &nodes::Type) {
285        self.push_char('(');
286        self.write_type(r#type);
287        self.push_char(')');
288    }
289
290    fn write_function_generics(&mut self, generics: &nodes::GenericParameters) {
291        if generics.is_empty() {
292            return;
293        }
294        self.push_char('<');
295        let mut write_comma = false;
296        for type_variable in generics.iter_type_variable() {
297            if write_comma {
298                self.push_char(',');
299            } else {
300                write_comma = true;
301            }
302            self.write_identifier(type_variable);
303        }
304        for generic_pack in generics.iter_generic_type_pack() {
305            if write_comma {
306                self.push_char(',');
307            } else {
308                write_comma = true;
309            }
310            self.write_generic_type_pack(generic_pack);
311        }
312        self.push_char('>');
313    }
314}
315
316impl Default for DenseLuaGenerator {
317    fn default() -> Self {
318        Self::new(80)
319    }
320}
321
322impl LuaGenerator for DenseLuaGenerator {
323    /// Consumes the LuaGenerator and produce a String object.
324    fn into_string(self) -> String {
325        self.output
326    }
327
328    fn write_block(&mut self, block: &nodes::Block) {
329        let mut statements = block.iter_statements().peekable();
330
331        while let Some(statement) = statements.next() {
332            self.write_statement(statement);
333
334            if let Some(next_statement) = statements.peek() {
335                if utils::starts_with_parenthese(next_statement)
336                    && utils::ends_with_prefix(statement)
337                {
338                    self.push_char(';');
339                }
340            }
341        }
342
343        if let Some(last_statement) = block.get_last_statement() {
344            self.write_last_statement(last_statement);
345        }
346    }
347
348    fn write_assign_statement(&mut self, assign: &nodes::AssignStatement) {
349        let variables = assign.get_variables();
350        let last_variable_index = variables.len().saturating_sub(1);
351
352        variables.iter().enumerate().for_each(|(index, variable)| {
353            self.write_variable(variable);
354
355            if index != last_variable_index {
356                self.push_char(',');
357            }
358        });
359
360        self.push_char_and_break_if('=', utils::break_equal);
361
362        let last_value_index = assign.values_len().saturating_sub(1);
363
364        assign.iter_values().enumerate().for_each(|(index, value)| {
365            self.write_expression(value);
366
367            if index != last_value_index {
368                self.push_char(',');
369            }
370        });
371    }
372
373    fn write_do_statement(&mut self, do_statement: &nodes::DoStatement) {
374        self.push_str("do");
375        self.write_block(do_statement.get_block());
376        self.push_str("end");
377    }
378
379    fn write_generic_for(&mut self, generic_for: &nodes::GenericForStatement) {
380        self.push_str("for");
381
382        let identifiers = generic_for.get_identifiers();
383        let last_identifier_index = identifiers.len().saturating_sub(1);
384        identifiers
385            .iter()
386            .enumerate()
387            .for_each(|(index, identifier)| {
388                self.write_typed_identifier(identifier);
389
390                if index != last_identifier_index {
391                    self.push_char(',');
392                }
393            });
394        self.push_str("in");
395
396        let expressions = generic_for.get_expressions();
397        let last_expression_index = expressions.len().saturating_sub(1);
398        expressions
399            .iter()
400            .enumerate()
401            .for_each(|(index, expression)| {
402                self.write_expression(expression);
403
404                if index != last_expression_index {
405                    self.push_char(',');
406                }
407            });
408
409        self.push_str("do");
410        self.write_block(generic_for.get_block());
411        self.push_str("end");
412    }
413
414    fn write_if_statement(&mut self, if_statement: &nodes::IfStatement) {
415        let branches = if_statement.get_branches();
416
417        branches.iter().enumerate().for_each(|(index, branch)| {
418            if index == 0 {
419                self.push_str("if");
420            } else {
421                self.push_str("elseif");
422            }
423
424            self.write_expression(branch.get_condition());
425            self.push_str("then");
426            self.write_block(branch.get_block());
427        });
428
429        if let Some(else_block) = if_statement.get_else_block() {
430            self.push_str("else");
431            self.write_block(else_block)
432        }
433
434        self.push_str("end");
435    }
436
437    fn write_function_statement(&mut self, function: &nodes::FunctionStatement) {
438        self.write_attributes(function.attributes());
439        self.push_str("function");
440        let name = function.get_name();
441
442        self.push_str(name.get_name().get_name());
443        name.get_field_names().iter().for_each(|field| {
444            self.push_new_line_if_needed(1);
445            self.raw_push_char('.');
446            self.push_str(field.get_name());
447        });
448
449        if let Some(method) = name.get_method() {
450            self.push_char(':');
451            self.push_str(method.get_name());
452        }
453
454        if let Some(generics) = function.get_generic_parameters() {
455            self.write_function_generics(generics);
456        }
457
458        self.push_char('(');
459        self.write_function_parameters(
460            function.get_parameters(),
461            function.is_variadic(),
462            function.get_variadic_type(),
463        );
464        self.push_char(')');
465
466        if let Some(return_type) = function.get_return_type() {
467            self.push_char(':');
468            self.write_function_return_type(return_type);
469        }
470
471        let block = function.get_block();
472
473        if !block.is_empty() {
474            self.write_block(block);
475        }
476        self.push_str("end");
477    }
478
479    fn write_last_statement(&mut self, statement: &nodes::LastStatement) {
480        use nodes::LastStatement::*;
481
482        match statement {
483            Break(_) => self.push_str("break"),
484            Continue(_) => self.push_str("continue"),
485            Return(expressions) => {
486                self.push_str("return");
487                let last_index = expressions.len().saturating_sub(1);
488
489                expressions
490                    .iter_expressions()
491                    .enumerate()
492                    .for_each(|(index, expression)| {
493                        self.write_expression(expression);
494
495                        if index != last_index {
496                            self.push_char(',');
497                        }
498                    });
499            }
500        }
501    }
502
503    fn write_local_assign(&mut self, assign: &nodes::VariableAssignment) {
504        self.push_str(assign.get_assignment_kind().as_keyword());
505
506        let variables_length = assign.variables_len();
507        let last_variable_index = variables_length.saturating_sub(1);
508
509        for (index, variable) in assign.iter_variables().enumerate() {
510            self.write_typed_identifier(variable);
511
512            if index != last_variable_index {
513                self.push_char(',');
514            }
515        }
516
517        // const assignments must have at least one variable per value, so it may need
518        // additional variables
519        for i in 0..assign.required_new_variables() {
520            if i != 0 || variables_length > 0 {
521                self.push_char(',');
522            }
523            utils::THROWAWAY_IDENTIFIER.with(|identifier| {
524                self.write_typed_identifier(identifier);
525            });
526        }
527
528        // const assignments must have a value for each variable, so it may need additional
529        // nil values
530        let required_nil_values = assign.required_nil_values();
531
532        let has_values = assign.has_values();
533
534        if has_values || required_nil_values > 0 {
535            self.push_char_and_break_if('=', utils::break_equal);
536
537            let last_value_index = assign.values_len().saturating_sub(1);
538
539            for (index, value) in assign.iter_values().enumerate() {
540                self.write_expression(value);
541
542                if index != last_value_index {
543                    self.push_char(',');
544                }
545            }
546
547            for i in 0..required_nil_values {
548                if i != 0 || has_values {
549                    self.push_char(',');
550                }
551                utils::NIL_EXPRESSION.with(|nil| {
552                    self.write_expression(nil);
553                })
554            }
555        };
556    }
557
558    fn write_compound_assign(&mut self, assign: &nodes::CompoundAssignStatement) {
559        self.write_variable(assign.get_variable());
560
561        self.push_str(assign.get_operator().to_str());
562
563        self.write_expression(assign.get_value());
564    }
565
566    fn write_local_function(&mut self, function: &nodes::FunctionAssignment) {
567        self.write_attributes(function.attributes());
568        self.push_str(function.get_assignment_kind().as_keyword());
569        self.push_space();
570        self.push_str("function");
571        self.push_space();
572        self.push_str(function.get_name());
573
574        if let Some(generics) = function.get_generic_parameters() {
575            self.write_function_generics(generics);
576        }
577
578        self.push_char('(');
579
580        let parameters = function.get_parameters();
581        self.write_function_parameters(
582            parameters,
583            function.is_variadic(),
584            function.get_variadic_type(),
585        );
586        self.push_char(')');
587
588        if let Some(return_type) = function.get_return_type() {
589            self.push_char(':');
590            self.write_function_return_type(return_type);
591        }
592
593        let block = function.get_block();
594
595        if !block.is_empty() {
596            self.write_block(block);
597        }
598        self.push_str("end");
599    }
600
601    fn write_numeric_for(&mut self, numeric_for: &nodes::NumericForStatement) {
602        self.push_str("for");
603
604        self.write_typed_identifier(numeric_for.get_identifier());
605
606        self.push_char_and_break_if('=', utils::break_equal);
607
608        self.write_expression(numeric_for.get_start());
609        self.push_char(',');
610        self.write_expression(numeric_for.get_end());
611
612        if let Some(step) = numeric_for.get_step() {
613            self.push_char(',');
614            self.write_expression(step);
615        }
616
617        let block = numeric_for.get_block();
618
619        if block.is_empty() {
620            self.push_str("do end");
621        } else {
622            self.push_str("do");
623            self.write_block(block);
624            self.push_str("end");
625        }
626    }
627
628    fn write_repeat_statement(&mut self, repeat: &nodes::RepeatStatement) {
629        self.push_str("repeat");
630
631        let block = repeat.get_block();
632
633        if !block.is_empty() {
634            self.write_block(block);
635        }
636
637        self.push_str("until");
638        self.write_expression(repeat.get_condition());
639    }
640
641    fn write_while_statement(&mut self, while_statement: &nodes::WhileStatement) {
642        self.push_str("while");
643        self.write_expression(while_statement.get_condition());
644
645        let block = while_statement.get_block();
646
647        if block.is_empty() {
648            self.push_str("do end");
649        } else {
650            self.push_str("do");
651            self.write_block(block);
652            self.push_str("end");
653        }
654    }
655
656    fn write_type_declaration_statement(&mut self, statement: &nodes::TypeDeclarationStatement) {
657        if statement.is_exported() {
658            self.push_str("export");
659        }
660        self.push_str("type");
661
662        self.write_identifier(statement.get_name());
663
664        if let Some(generic_parameters) = statement
665            .get_generic_parameters()
666            .filter(|generic_parameters| !generic_parameters.is_empty())
667        {
668            self.push_char('<');
669            let last_index = generic_parameters.len().saturating_sub(1);
670            for (i, parameter) in generic_parameters.iter().enumerate() {
671                use nodes::GenericParameterRef;
672
673                match parameter {
674                    GenericParameterRef::TypeVariable(identifier) => {
675                        self.write_identifier(identifier);
676                    }
677                    GenericParameterRef::TypeVariableWithDefault(identifier_with_default) => {
678                        self.write_identifier(identifier_with_default.get_type_variable());
679                        self.push_char('=');
680                        self.write_type(identifier_with_default.get_default_type());
681                    }
682                    GenericParameterRef::GenericTypePack(generic_type_pack) => {
683                        self.write_generic_type_pack(generic_type_pack);
684                    }
685                    GenericParameterRef::GenericTypePackWithDefault(generic_pack_with_default) => {
686                        self.write_generic_type_pack(
687                            generic_pack_with_default.get_generic_type_pack(),
688                        );
689                        self.push_char('=');
690                        self.write_generic_type_pack_default(
691                            generic_pack_with_default.get_default_type(),
692                        );
693                    }
694                }
695
696                if i != last_index {
697                    self.push_char(',');
698                }
699            }
700
701            self.push_char('>');
702        }
703
704        self.push_char_and_break_if('=', utils::break_equal);
705        self.write_type(statement.get_type());
706    }
707
708    fn write_type_function_statement(&mut self, function: &nodes::TypeFunctionStatement) {
709        if function.is_exported() {
710            self.push_str("export");
711        }
712        self.push_str("type");
713        self.push_str("function");
714
715        self.write_identifier(function.get_identifier());
716
717        if let Some(generics) = function.get_generic_parameters() {
718            self.write_function_generics(generics);
719        }
720
721        self.push_char('(');
722
723        let parameters = function.get_parameters();
724        self.write_function_parameters(
725            parameters,
726            function.is_variadic(),
727            function.get_variadic_type(),
728        );
729        self.push_char(')');
730
731        if let Some(return_type) = function.get_return_type() {
732            self.push_char(':');
733            self.write_function_return_type(return_type);
734        }
735
736        let block = function.get_block();
737
738        if !block.is_empty() {
739            self.write_block(block);
740        }
741        self.push_str("end");
742    }
743
744    fn write_false_expression(&mut self, _token: &Option<nodes::Token>) {
745        self.push_str("false");
746    }
747
748    fn write_true_expression(&mut self, _token: &Option<nodes::Token>) {
749        self.push_str("true");
750    }
751
752    fn write_nil_expression(&mut self, _token: &Option<nodes::Token>) {
753        self.push_str("nil");
754    }
755
756    fn write_variable_arguments_expression(&mut self, _token: &Option<nodes::Token>) {
757        self.push_str_and_break_if("...", utils::break_variable_arguments);
758    }
759
760    fn write_binary_expression(&mut self, binary: &nodes::BinaryExpression) {
761        use nodes::BinaryOperator;
762
763        let operator = binary.operator();
764        let left = binary.left();
765        let right = binary.right();
766
767        if operator.left_needs_parentheses(left) {
768            self.write_expression_in_parentheses(left);
769        } else {
770            self.write_expression(left);
771        }
772
773        match operator {
774            BinaryOperator::Concat => self.push_str_and_break_if("..", utils::break_concat),
775            _ => self.push_str(operator.to_str()),
776        }
777
778        if operator.right_needs_parentheses(right) {
779            self.write_expression_in_parentheses(right);
780        } else {
781            self.write_expression(right);
782        }
783    }
784
785    fn write_unary_expression(&mut self, unary: &nodes::UnaryExpression) {
786        use nodes::{Expression, UnaryOperator::*};
787
788        match unary.operator() {
789            Length => self.push_char('#'),
790            Minus => self.push_char_and_break_if('-', utils::break_minus),
791            Not => self.push_str("not"),
792        }
793
794        let expression = unary.get_expression();
795
796        match expression {
797            Expression::Binary(binary) if !binary.operator().precedes_unary_expression() => {
798                self.write_expression_in_parentheses(expression);
799            }
800            _ => self.write_expression(expression),
801        }
802    }
803
804    fn write_function(&mut self, function: &nodes::FunctionExpression) {
805        self.write_attributes(function.attributes());
806        self.push_str("function");
807
808        if let Some(generics) = function.get_generic_parameters() {
809            self.write_function_generics(generics);
810        }
811
812        self.push_char('(');
813
814        let parameters = function.get_parameters();
815        self.write_function_parameters(
816            parameters,
817            function.is_variadic(),
818            function.get_variadic_type(),
819        );
820        self.push_char(')');
821
822        if let Some(return_type) = function.get_return_type() {
823            self.push_char(':');
824            self.write_function_return_type(return_type);
825        }
826
827        let block = function.get_block();
828
829        if !block.is_empty() {
830            self.write_block(block);
831        }
832        self.push_str("end");
833    }
834
835    fn write_function_call(&mut self, call: &nodes::FunctionCall) {
836        self.write_prefix(call.get_prefix());
837
838        if let Some(method) = &call.get_method() {
839            self.push_char(':');
840            self.push_str(method.get_name());
841        }
842
843        self.write_arguments(call.get_arguments());
844    }
845
846    fn write_field(&mut self, field: &nodes::FieldExpression) {
847        self.write_prefix(field.get_prefix());
848
849        self.push_new_line_if_needed(1);
850        self.raw_push_char('.');
851
852        self.push_str(field.get_field().get_name());
853    }
854
855    fn write_index(&mut self, index: &nodes::IndexExpression) {
856        self.write_prefix(index.get_prefix());
857
858        self.push_char('[');
859        self.write_expression(index.get_index());
860        self.push_char(']');
861    }
862
863    fn write_if_expression(&mut self, if_expression: &nodes::IfExpression) {
864        self.push_str("if");
865        self.write_expression(if_expression.get_condition());
866        self.push_str("then");
867        self.write_expression(if_expression.get_result());
868
869        for branch in if_expression.iter_branches() {
870            self.push_str("elseif");
871            self.write_expression(branch.get_condition());
872            self.push_str("then");
873            self.write_expression(branch.get_result());
874        }
875
876        self.push_str("else");
877        self.write_expression(if_expression.get_else_result());
878    }
879
880    fn write_table(&mut self, table: &nodes::TableExpression) {
881        self.push_char('{');
882
883        let entries = table.get_entries();
884        let last_index = entries.len().saturating_sub(1);
885
886        entries.iter().enumerate().for_each(|(index, entry)| {
887            self.write_table_entry(entry);
888
889            if index != last_index {
890                self.push_char(',');
891            }
892        });
893
894        self.push_char('}');
895    }
896
897    fn write_table_entry(&mut self, entry: &nodes::TableEntry) {
898        match entry {
899            nodes::TableEntry::Field(entry) => {
900                self.push_str(entry.get_field().get_name());
901                self.push_char('=');
902                self.write_expression(entry.get_value());
903            }
904            nodes::TableEntry::Index(entry) => {
905                self.push_char('[');
906                self.write_expression(entry.get_key());
907                self.push_char(']');
908                self.push_char('=');
909                self.write_expression(entry.get_value());
910            }
911            nodes::TableEntry::Value(expression) => self.write_expression(expression),
912        }
913    }
914
915    fn write_number(&mut self, number: &nodes::NumberExpression) {
916        use nodes::NumberExpression::*;
917
918        match number {
919            Decimal(decimal) => {
920                let float = decimal.get_raw_float();
921                if float.is_nan() {
922                    self.push_char('(');
923                    self.push_char('0');
924                    self.push_char('/');
925                    self.push_char('0');
926                    self.push_char(')');
927                } else if float.is_infinite() {
928                    self.push_char('(');
929                    if float.is_sign_negative() {
930                        self.push_char('-');
931                    }
932                    self.push_char('1');
933                    self.push_char('/');
934                    self.push_char('0');
935                    self.push_char(')');
936                } else {
937                    let result = utils::write_number(number);
938
939                    self.push_str(&result);
940                }
941            }
942            Hex(number) => {
943                let mut result = format!(
944                    "0{}{:x}",
945                    if number.is_x_uppercase() { 'X' } else { 'x' },
946                    number.get_raw_integer()
947                );
948
949                if let Some(exponent) = number.get_exponent() {
950                    let exponent_char = number
951                        .is_exponent_uppercase()
952                        .map(|is_uppercase| if is_uppercase { 'P' } else { 'p' })
953                        .unwrap_or('p');
954
955                    result.push(exponent_char);
956                    result.push_str(&format!("{}", exponent));
957                };
958
959                self.push_str(&result);
960            }
961            Binary(number) => {
962                self.push_str(&format!(
963                    "0{}{:b}",
964                    if number.is_b_uppercase() { 'B' } else { 'b' },
965                    number.get_raw_value()
966                ));
967            }
968        }
969    }
970
971    fn write_tuple_arguments(&mut self, arguments: &nodes::TupleArguments) {
972        self.merge_char('(');
973
974        let last_index = arguments.len().saturating_sub(1);
975        arguments
976            .iter_values()
977            .enumerate()
978            .for_each(|(index, expression)| {
979                self.write_expression(expression);
980
981                if index != last_index {
982                    self.push_char(',');
983                }
984            });
985
986        self.push_char(')');
987    }
988
989    fn write_string(&mut self, string: &nodes::StringExpression) {
990        let result = utils::write_string(string.get_value());
991        if result.starts_with('[') {
992            self.push_str_and_break_if(&result, utils::break_long_string);
993        } else {
994            self.push_str(&result);
995        }
996    }
997
998    fn write_interpolated_string(
999        &mut self,
1000        interpolated_string: &nodes::InterpolatedStringExpression,
1001    ) {
1002        self.push_char('`');
1003
1004        for segment in interpolated_string.iter_segments() {
1005            match segment {
1006                nodes::InterpolationSegment::String(string_segment) => {
1007                    self.raw_push_str(&utils::write_interpolated_string_segment(string_segment));
1008                }
1009                nodes::InterpolationSegment::Value(value) => {
1010                    self.raw_push_char('{');
1011                    // add space when value segment is a table
1012                    let expression = value.get_expression();
1013                    if utils::starts_with_table(expression).is_some() {
1014                        self.raw_push_char(' ');
1015                    }
1016                    self.write_expression(expression);
1017                    self.push_char('}');
1018                }
1019            }
1020        }
1021
1022        self.raw_push_char('`');
1023    }
1024
1025    fn write_attribute_tuple_arguments(&mut self, tuple: &nodes::AttributeTupleArguments) {
1026        self.push_char('(');
1027
1028        let last_index = tuple.len().saturating_sub(1);
1029        for (index, value) in tuple.iter_values().enumerate() {
1030            self.write_literal_expression(value);
1031            if index != last_index {
1032                self.push_char(',');
1033            }
1034        }
1035
1036        self.push_char(')');
1037    }
1038
1039    fn write_literal_table(&mut self, table: &nodes::LiteralTable) {
1040        self.push_char('{');
1041        let last_index = table.len().saturating_sub(1);
1042        for (index, entry) in table.iter_entries().enumerate() {
1043            self.write_literal_table_entry(entry);
1044            if index != last_index {
1045                self.push_char(',');
1046            }
1047        }
1048        self.push_char('}');
1049    }
1050
1051    fn write_literal_table_entry(&mut self, entry: &nodes::LiteralTableEntry) {
1052        use nodes::LiteralTableEntry::*;
1053        match entry {
1054            Field(field) => {
1055                self.write_identifier(field.get_field());
1056                self.push_char('=');
1057                self.write_literal_expression(field.get_value());
1058            }
1059            Value(value) => {
1060                self.write_literal_expression(value);
1061            }
1062        }
1063    }
1064
1065    fn write_identifier(&mut self, identifier: &nodes::Identifier) {
1066        self.push_str(identifier.get_name());
1067    }
1068
1069    fn write_parenthese(&mut self, parenthese: &nodes::ParentheseExpression) {
1070        self.write_expression_in_parentheses(parenthese.inner_expression());
1071    }
1072
1073    fn write_type_cast(&mut self, type_cast: &nodes::TypeCastExpression) {
1074        let inner_expression = type_cast.get_expression();
1075
1076        if nodes::TypeCastExpression::needs_parentheses(inner_expression) {
1077            self.write_expression_in_parentheses(inner_expression);
1078        } else {
1079            self.write_expression(inner_expression);
1080        }
1081
1082        self.push_str("::");
1083        self.write_type(type_cast.get_type());
1084    }
1085
1086    fn write_type_instantiation(
1087        &mut self,
1088        type_instantiation: &nodes::TypeInstantiationExpression,
1089    ) {
1090        self.write_prefix(type_instantiation.get_prefix());
1091
1092        self.push_new_line_if_needed(2);
1093        self.raw_push_char('<');
1094        self.raw_push_char('<');
1095
1096        let last_index = type_instantiation.types_len().saturating_sub(1);
1097        for (index, r#type) in type_instantiation.iter_types().enumerate() {
1098            self.write_type(r#type);
1099            if index != last_index {
1100                self.push_char(',');
1101            }
1102        }
1103
1104        self.push_new_line_if_needed(2);
1105        self.raw_push_char('>');
1106        self.raw_push_char('>');
1107    }
1108
1109    fn write_type_name(&mut self, type_name: &nodes::TypeName) {
1110        self.write_identifier(type_name.get_type_name());
1111        if let Some(parameters) = type_name.get_type_parameters() {
1112            self.push_char('<');
1113            let last_index = parameters.len().saturating_sub(1);
1114            for (index, parameter) in parameters.iter().enumerate() {
1115                self.write_type_parameter(parameter);
1116                if index != last_index {
1117                    self.push_char(',');
1118                }
1119            }
1120
1121            self.push_char('>');
1122        }
1123    }
1124
1125    fn write_type_field(&mut self, type_field: &nodes::TypeField) {
1126        self.write_identifier(type_field.get_namespace());
1127        self.push_new_line_if_needed(1);
1128        self.raw_push_char('.');
1129        self.write_type_name(type_field.get_type_name());
1130    }
1131
1132    fn write_true_type(&mut self, _: &Option<nodes::Token>) {
1133        self.push_str("true");
1134    }
1135
1136    fn write_false_type(&mut self, _: &Option<nodes::Token>) {
1137        self.push_str("false");
1138    }
1139
1140    fn write_nil_type(&mut self, _: &Option<nodes::Token>) {
1141        self.push_str("nil");
1142    }
1143
1144    fn write_string_type(&mut self, string_type: &nodes::StringType) {
1145        let result = utils::write_string(string_type.get_value());
1146        if result.starts_with('[') {
1147            self.push_str_and_break_if(&result, utils::break_long_string);
1148        } else {
1149            self.push_str(&result);
1150        }
1151    }
1152
1153    fn write_array_type(&mut self, array: &nodes::ArrayType) {
1154        self.push_char('{');
1155        self.write_type(array.get_element_type());
1156        self.push_char('}');
1157    }
1158
1159    fn write_table_type(&mut self, table_type: &nodes::TableType) {
1160        self.push_char('{');
1161
1162        let last_index = table_type.len().saturating_sub(1);
1163        for (index, property) in table_type.iter_entries().enumerate() {
1164            if let Some(modifier) = property.get_modifier() {
1165                match modifier {
1166                    nodes::TablePropertyModifier::Read => self.push_str("read"),
1167                    nodes::TablePropertyModifier::Write => self.push_str("write"),
1168                }
1169            }
1170
1171            match property {
1172                nodes::TableEntryType::Property(property) => {
1173                    self.write_identifier(property.get_identifier());
1174                    self.push_char(':');
1175                    self.write_type(property.get_type());
1176                }
1177                nodes::TableEntryType::Literal(property) => {
1178                    self.push_char('[');
1179                    self.write_string_type(property.get_string());
1180                    self.push_char(']');
1181                    self.push_char(':');
1182                    self.write_type(property.get_type());
1183                }
1184                nodes::TableEntryType::Indexer(indexer) => {
1185                    self.push_char('[');
1186
1187                    let key_type = indexer.get_key_type();
1188
1189                    let need_parentheses = matches!(
1190                        key_type,
1191                        nodes::Type::Optional(_)
1192                            | nodes::Type::Intersection(_)
1193                            | nodes::Type::Union(_)
1194                    );
1195
1196                    if need_parentheses {
1197                        self.push_char('(');
1198                        self.write_type(key_type);
1199                        self.push_char(')');
1200                    } else {
1201                        self.write_type(key_type);
1202                    }
1203
1204                    self.push_char(']');
1205                    self.push_char(':');
1206                    self.write_type(indexer.get_value_type());
1207                }
1208            }
1209            if index != last_index {
1210                self.push_char(',');
1211            }
1212        }
1213
1214        self.push_char('}');
1215    }
1216
1217    fn write_expression_type(&mut self, expression_type: &nodes::ExpressionType) {
1218        self.push_str("typeof(");
1219        self.write_expression(expression_type.get_expression());
1220        self.push_char(')');
1221    }
1222
1223    fn write_parenthese_type(&mut self, parenthese_type: &nodes::ParentheseType) {
1224        self.write_type_in_parentheses(parenthese_type.get_inner_type());
1225    }
1226
1227    fn write_function_type(&mut self, function_type: &nodes::FunctionType) {
1228        if let Some(generics) = function_type.get_generic_parameters() {
1229            self.write_function_generics(generics);
1230        }
1231
1232        self.push_char('(');
1233
1234        let last_index = function_type.argument_len().saturating_sub(1);
1235
1236        for (index, argument) in function_type.iter_arguments().enumerate() {
1237            if let Some(name) = argument.get_name() {
1238                self.write_identifier(name);
1239                self.push_char(':');
1240            }
1241            self.write_type(argument.get_type());
1242
1243            if index != last_index {
1244                self.push_char(',');
1245            }
1246        }
1247
1248        if let Some(variadic_argument_type) = function_type.get_variadic_argument_type() {
1249            if function_type.argument_len() > 0 {
1250                self.push_char(',');
1251            }
1252            self.write_variadic_argument_type(variadic_argument_type);
1253        }
1254
1255        self.push_str(")->");
1256        self.write_function_return_type(function_type.get_return_type());
1257    }
1258
1259    fn write_optional_type(&mut self, optional: &nodes::OptionalType) {
1260        let inner_type = optional.get_inner_type();
1261        if nodes::OptionalType::needs_parentheses(inner_type) {
1262            self.write_type_in_parentheses(inner_type);
1263        } else {
1264            self.write_type(inner_type);
1265        }
1266        self.push_char('?');
1267    }
1268
1269    fn write_intersection_type(&mut self, intersection: &nodes::IntersectionType) {
1270        let length = intersection.len();
1271        let last_index = length.saturating_sub(1);
1272        for (i, r#type) in intersection.iter_types().enumerate() {
1273            if i != 0 || intersection.has_leading_token() {
1274                self.push_char('&');
1275            }
1276
1277            let need_parentheses = if i == last_index {
1278                nodes::IntersectionType::last_needs_parentheses(r#type)
1279            } else {
1280                nodes::IntersectionType::intermediate_needs_parentheses(r#type)
1281            };
1282
1283            if need_parentheses {
1284                self.write_type_in_parentheses(r#type);
1285            } else {
1286                self.write_type(r#type);
1287            }
1288        }
1289    }
1290
1291    fn write_union_type(&mut self, union: &nodes::UnionType) {
1292        let length = union.len();
1293        let last_index = length.saturating_sub(1);
1294        for (i, r#type) in union.iter_types().enumerate() {
1295            if i != 0 || union.has_leading_token() {
1296                self.push_char('|');
1297            }
1298
1299            let need_parentheses = if i == last_index {
1300                nodes::UnionType::last_needs_parentheses(r#type)
1301            } else {
1302                nodes::UnionType::intermediate_needs_parentheses(r#type)
1303            };
1304
1305            if need_parentheses {
1306                self.write_type_in_parentheses(r#type);
1307            } else {
1308                self.write_type(r#type);
1309            }
1310        }
1311    }
1312
1313    fn write_type_pack(&mut self, type_pack: &nodes::TypePack) {
1314        self.push_char('(');
1315
1316        let last_index = type_pack.len().saturating_sub(1);
1317
1318        for (index, r#type) in type_pack.into_iter().enumerate() {
1319            self.write_type(r#type);
1320            if index != last_index {
1321                self.push_char(',');
1322            }
1323        }
1324
1325        if let Some(variadic_argument_type) = type_pack.get_variadic_type() {
1326            if !type_pack.is_empty() {
1327                self.push_char(',');
1328            }
1329            self.write_variadic_argument_type(variadic_argument_type);
1330        }
1331
1332        self.push_char(')');
1333    }
1334
1335    fn write_variadic_type_pack(&mut self, variadic_type_pack: &nodes::VariadicTypePack) {
1336        self.push_str("...");
1337        self.write_type(variadic_type_pack.get_type());
1338    }
1339
1340    fn write_generic_type_pack(&mut self, generic_type_pack: &nodes::GenericTypePack) {
1341        self.write_identifier(generic_type_pack.get_name());
1342        self.push_str("...");
1343    }
1344}