Skip to main content

zuzu_rust/
ast.rs

1#[derive(Debug, Clone, PartialEq, Eq)]
2pub struct Program {
3    pub line: usize,
4    pub source_file: Option<String>,
5    pub statements: Vec<Statement>,
6}
7
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub enum Statement {
10    Block(BlockStatement),
11    VariableDeclaration(VariableDeclaration),
12    VariableUnpackDeclaration(VariableUnpackDeclaration),
13    FunctionDeclaration(FunctionDeclaration),
14    ClassDeclaration(ClassDeclaration),
15    TraitDeclaration(TraitDeclaration),
16    ImportDeclaration(ImportDeclaration),
17    IfStatement(IfStatement),
18    WhileStatement(WhileStatement),
19    ForStatement(ForStatement),
20    SwitchStatement(SwitchStatement),
21    TryStatement(TryStatement),
22    ReturnStatement(ReturnStatement),
23    LoopControlStatement(LoopControlStatement),
24    ThrowStatement(ThrowStatement),
25    DieStatement(DieStatement),
26    PostfixConditionalStatement(PostfixConditionalStatement),
27    KeywordStatement(KeywordStatement),
28    ExpressionStatement(ExpressionStatement),
29}
30
31#[derive(Debug, Clone, PartialEq, Eq)]
32pub struct BlockStatement {
33    pub line: usize,
34    pub source_file: Option<String>,
35    pub statements: Vec<Statement>,
36    pub needs_lexical_scope: bool,
37}
38
39#[derive(Debug, Clone, PartialEq, Eq)]
40pub struct VariableDeclaration {
41    pub line: usize,
42    pub source_file: Option<String>,
43    pub kind: String,
44    pub declared_type: Option<String>,
45    pub name: String,
46    pub init: Option<Expression>,
47    pub is_weak_storage: bool,
48    pub runtime_typecheck_required: Option<bool>,
49}
50
51#[derive(Debug, Clone, PartialEq, Eq)]
52pub struct VariableUnpackDeclaration {
53    pub line: usize,
54    pub source_file: Option<String>,
55    pub kind: String,
56    pub pattern: DeclarationBindingPattern,
57    pub init: Expression,
58}
59
60#[derive(Debug, Clone, PartialEq, Eq)]
61pub enum DeclarationBindingPattern {
62    Keyed {
63        line: usize,
64        source_file: Option<String>,
65        entries: Vec<DeclarationBindingEntry>,
66    },
67}
68
69#[derive(Debug, Clone, PartialEq, Eq)]
70pub struct DeclarationBindingEntry {
71    pub line: usize,
72    pub source_file: Option<String>,
73    pub key: DictKey,
74    pub declared_type: Option<String>,
75    pub name: String,
76    pub default_value: Option<Expression>,
77    pub is_weak_storage: bool,
78    pub runtime_typecheck_required: Option<bool>,
79}
80
81#[derive(Debug, Clone, PartialEq, Eq)]
82pub struct FunctionDeclaration {
83    pub line: usize,
84    pub source_file: Option<String>,
85    pub name: String,
86    pub params: Vec<Parameter>,
87    pub return_type: Option<String>,
88    pub body: BlockStatement,
89    pub is_async: bool,
90    pub is_predeclared: bool,
91}
92
93#[derive(Debug, Clone, PartialEq, Eq)]
94pub struct ClassDeclaration {
95    pub line: usize,
96    pub source_file: Option<String>,
97    pub name: String,
98    pub base: Option<String>,
99    pub traits: Vec<String>,
100    pub body: Vec<ClassMember>,
101    pub shorthand: bool,
102}
103
104#[derive(Debug, Clone, PartialEq, Eq)]
105pub struct TraitDeclaration {
106    pub line: usize,
107    pub source_file: Option<String>,
108    pub name: String,
109    pub body: Vec<ClassMember>,
110    pub shorthand: bool,
111}
112
113#[derive(Debug, Clone, PartialEq, Eq)]
114pub enum ClassMember {
115    Field(FieldDeclaration),
116    Method(MethodDeclaration),
117    Class(ClassDeclaration),
118    Trait(TraitDeclaration),
119}
120
121#[derive(Debug, Clone, PartialEq, Eq)]
122pub struct FieldDeclaration {
123    pub line: usize,
124    pub source_file: Option<String>,
125    pub kind: String,
126    pub declared_type: Option<String>,
127    pub name: String,
128    pub accessors: Vec<String>,
129    pub default_value: Option<Expression>,
130    pub is_weak_storage: bool,
131    pub runtime_typecheck_required: Option<bool>,
132}
133
134#[derive(Debug, Clone, PartialEq, Eq)]
135pub struct MethodDeclaration {
136    pub line: usize,
137    pub source_file: Option<String>,
138    pub name: String,
139    pub params: Vec<Parameter>,
140    pub return_type: Option<String>,
141    pub body: BlockStatement,
142    pub is_static: bool,
143    pub is_async: bool,
144    pub is_predeclared: bool,
145}
146
147#[derive(Debug, Clone, PartialEq, Eq)]
148pub struct Parameter {
149    pub line: usize,
150    pub source_file: Option<String>,
151    pub declared_type: Option<String>,
152    pub name: String,
153    pub optional: bool,
154    pub variadic: bool,
155    pub default_value: Option<Expression>,
156}
157
158#[derive(Debug, Clone, PartialEq, Eq)]
159pub struct ImportDeclaration {
160    pub line: usize,
161    pub source_file: Option<String>,
162    pub source: String,
163    pub try_mode: bool,
164    pub import_all: bool,
165    pub specifiers: Vec<ImportSpecifier>,
166    pub condition: Option<PostfixCondition>,
167}
168
169#[derive(Debug, Clone, PartialEq, Eq)]
170pub struct ImportSpecifier {
171    pub line: usize,
172    pub source_file: Option<String>,
173    pub imported: String,
174    pub local: String,
175}
176
177#[derive(Debug, Clone, PartialEq, Eq)]
178pub struct PostfixCondition {
179    pub line: usize,
180    pub source_file: Option<String>,
181    pub keyword: String,
182    pub test: Expression,
183}
184
185#[derive(Debug, Clone, PartialEq, Eq)]
186pub struct IfStatement {
187    pub line: usize,
188    pub source_file: Option<String>,
189    pub test: Expression,
190    pub consequent: BlockStatement,
191    pub alternate: Option<Box<Statement>>,
192}
193
194#[derive(Debug, Clone, PartialEq, Eq)]
195pub struct WhileStatement {
196    pub line: usize,
197    pub source_file: Option<String>,
198    pub test: Expression,
199    pub body: BlockStatement,
200}
201
202#[derive(Debug, Clone, PartialEq, Eq)]
203pub struct ForStatement {
204    pub line: usize,
205    pub source_file: Option<String>,
206    pub binding_kind: Option<String>,
207    pub variable: String,
208    pub iterable: Expression,
209    pub body: BlockStatement,
210    pub else_block: Option<BlockStatement>,
211}
212
213#[derive(Debug, Clone, PartialEq, Eq)]
214pub struct SwitchStatement {
215    pub line: usize,
216    pub source_file: Option<String>,
217    pub discriminant: Expression,
218    pub comparator: Option<String>,
219    pub cases: Vec<SwitchCase>,
220    pub default: Option<Vec<Statement>>,
221    pub index: Option<Vec<SwitchIndexEntry>>,
222}
223
224#[derive(Debug, Clone, PartialEq, Eq)]
225pub struct SwitchIndexEntry {
226    pub key: String,
227    pub case_index: usize,
228}
229
230#[derive(Debug, Clone, PartialEq, Eq)]
231pub struct SwitchCase {
232    pub line: usize,
233    pub source_file: Option<String>,
234    pub values: Vec<Expression>,
235    pub operators: Vec<Option<String>>,
236    pub consequent: Vec<Statement>,
237}
238
239#[derive(Debug, Clone, PartialEq, Eq)]
240pub struct TryStatement {
241    pub line: usize,
242    pub source_file: Option<String>,
243    pub body: BlockStatement,
244    pub handlers: Vec<CatchClause>,
245}
246
247#[derive(Debug, Clone, PartialEq, Eq)]
248pub struct CatchClause {
249    pub line: usize,
250    pub source_file: Option<String>,
251    pub binding: Option<CatchBinding>,
252    pub body: BlockStatement,
253}
254
255#[derive(Debug, Clone, PartialEq, Eq)]
256pub struct CatchBinding {
257    pub line: usize,
258    pub source_file: Option<String>,
259    pub declared_type: Option<String>,
260    pub name: Option<String>,
261}
262
263#[derive(Debug, Clone, PartialEq, Eq)]
264pub struct ReturnStatement {
265    pub line: usize,
266    pub source_file: Option<String>,
267    pub argument: Option<Expression>,
268    pub runtime_typecheck_required: Option<bool>,
269}
270
271#[derive(Debug, Clone, PartialEq, Eq)]
272pub struct LoopControlStatement {
273    pub line: usize,
274    pub source_file: Option<String>,
275    pub keyword: String,
276}
277
278#[derive(Debug, Clone, PartialEq, Eq)]
279pub struct ThrowStatement {
280    pub line: usize,
281    pub source_file: Option<String>,
282    pub argument: Expression,
283}
284
285#[derive(Debug, Clone, PartialEq, Eq)]
286pub struct DieStatement {
287    pub line: usize,
288    pub source_file: Option<String>,
289    pub argument: Expression,
290}
291
292#[derive(Debug, Clone, PartialEq, Eq)]
293pub struct PostfixConditionalStatement {
294    pub line: usize,
295    pub source_file: Option<String>,
296    pub statement: Box<Statement>,
297    pub keyword: String,
298    pub test: Expression,
299}
300
301#[derive(Debug, Clone, PartialEq, Eq)]
302pub struct KeywordStatement {
303    pub line: usize,
304    pub source_file: Option<String>,
305    pub keyword: String,
306    pub arguments: Vec<Expression>,
307}
308
309#[derive(Debug, Clone, PartialEq, Eq)]
310pub struct ExpressionStatement {
311    pub line: usize,
312    pub source_file: Option<String>,
313    pub expression: Expression,
314}
315
316#[derive(Debug, Clone, PartialEq, Eq)]
317pub enum Expression {
318    Identifier {
319        line: usize,
320        source_file: Option<String>,
321        name: String,
322        inferred_type: Option<String>,
323        binding_depth: Option<usize>,
324    },
325    NumberLiteral {
326        line: usize,
327        source_file: Option<String>,
328        value: String,
329        inferred_type: Option<String>,
330    },
331    StringLiteral {
332        line: usize,
333        source_file: Option<String>,
334        value: String,
335        inferred_type: Option<String>,
336    },
337    BinaryStringLiteral {
338        line: usize,
339        source_file: Option<String>,
340        bytes: Vec<u8>,
341        inferred_type: Option<String>,
342    },
343    RegexLiteral {
344        line: usize,
345        source_file: Option<String>,
346        pattern: String,
347        parts: Vec<TemplatePart>,
348        flags: String,
349        cache_key: Option<String>,
350        inferred_type: Option<String>,
351    },
352    BooleanLiteral {
353        line: usize,
354        source_file: Option<String>,
355        value: bool,
356        inferred_type: Option<String>,
357    },
358    NullLiteral {
359        line: usize,
360        source_file: Option<String>,
361        inferred_type: Option<String>,
362    },
363    ArrayLiteral {
364        line: usize,
365        source_file: Option<String>,
366        elements: Vec<Expression>,
367        capacity_hint: Option<usize>,
368        inferred_type: Option<String>,
369    },
370    SetLiteral {
371        line: usize,
372        source_file: Option<String>,
373        elements: Vec<Expression>,
374        capacity_hint: Option<usize>,
375        inferred_type: Option<String>,
376    },
377    BagLiteral {
378        line: usize,
379        source_file: Option<String>,
380        elements: Vec<Expression>,
381        capacity_hint: Option<usize>,
382        inferred_type: Option<String>,
383    },
384    DictLiteral {
385        line: usize,
386        source_file: Option<String>,
387        entries: Vec<DictEntry>,
388        capacity_hint: Option<usize>,
389        inferred_type: Option<String>,
390    },
391    PairListLiteral {
392        line: usize,
393        source_file: Option<String>,
394        entries: Vec<DictEntry>,
395        capacity_hint: Option<usize>,
396        inferred_type: Option<String>,
397    },
398    TemplateLiteral {
399        line: usize,
400        source_file: Option<String>,
401        parts: Vec<TemplatePart>,
402        inferred_type: Option<String>,
403    },
404    Unary {
405        line: usize,
406        source_file: Option<String>,
407        operator: String,
408        argument: Box<Expression>,
409        traits: Vec<String>,
410        inferred_type: Option<String>,
411    },
412    Binary {
413        line: usize,
414        source_file: Option<String>,
415        operator: String,
416        left: Box<Expression>,
417        right: Box<Expression>,
418        inferred_type: Option<String>,
419    },
420    Ternary {
421        line: usize,
422        source_file: Option<String>,
423        test: Box<Expression>,
424        consequent: Box<Expression>,
425        alternate: Box<Expression>,
426        inferred_type: Option<String>,
427    },
428    DefinedOr {
429        line: usize,
430        source_file: Option<String>,
431        left: Box<Expression>,
432        right: Box<Expression>,
433        inferred_type: Option<String>,
434    },
435    Assignment {
436        line: usize,
437        source_file: Option<String>,
438        operator: String,
439        left: Box<Expression>,
440        right: Box<Expression>,
441        is_weak_write: bool,
442        inferred_type: Option<String>,
443        runtime_typecheck_required: Option<bool>,
444    },
445    Call {
446        line: usize,
447        source_file: Option<String>,
448        callee: Box<Expression>,
449        arguments: Vec<CallArgument>,
450        inferred_type: Option<String>,
451    },
452    MemberAccess {
453        line: usize,
454        source_file: Option<String>,
455        object: Box<Expression>,
456        member: String,
457        inferred_type: Option<String>,
458    },
459    DynamicMemberCall {
460        line: usize,
461        source_file: Option<String>,
462        object: Box<Expression>,
463        member: Box<Expression>,
464        arguments: Vec<CallArgument>,
465        inferred_type: Option<String>,
466    },
467    Index {
468        line: usize,
469        source_file: Option<String>,
470        object: Box<Expression>,
471        index: Box<Expression>,
472        inferred_type: Option<String>,
473    },
474    Slice {
475        line: usize,
476        source_file: Option<String>,
477        object: Box<Expression>,
478        start: Option<Box<Expression>>,
479        end: Option<Box<Expression>>,
480        inferred_type: Option<String>,
481    },
482    DictAccess {
483        line: usize,
484        source_file: Option<String>,
485        object: Box<Expression>,
486        key: Box<DictKey>,
487        inferred_type: Option<String>,
488    },
489    PostfixUpdate {
490        line: usize,
491        source_file: Option<String>,
492        operator: String,
493        argument: Box<Expression>,
494        inferred_type: Option<String>,
495    },
496    Lambda {
497        line: usize,
498        source_file: Option<String>,
499        params: Vec<Parameter>,
500        body: Box<Expression>,
501        is_async: bool,
502        inferred_type: Option<String>,
503    },
504    FunctionExpression {
505        line: usize,
506        source_file: Option<String>,
507        params: Vec<Parameter>,
508        return_type: Option<String>,
509        body: BlockStatement,
510        is_async: bool,
511        inferred_type: Option<String>,
512    },
513    LetExpression {
514        line: usize,
515        source_file: Option<String>,
516        kind: String,
517        declared_type: Option<String>,
518        name: String,
519        init: Option<Box<Expression>>,
520        is_weak_storage: bool,
521        inferred_type: Option<String>,
522        runtime_typecheck_required: Option<bool>,
523    },
524    TryExpression {
525        line: usize,
526        source_file: Option<String>,
527        body: BlockStatement,
528        handlers: Vec<CatchClause>,
529        inferred_type: Option<String>,
530    },
531    DoExpression {
532        line: usize,
533        source_file: Option<String>,
534        body: BlockStatement,
535        inferred_type: Option<String>,
536    },
537    AwaitExpression {
538        line: usize,
539        source_file: Option<String>,
540        body: BlockStatement,
541        inferred_type: Option<String>,
542    },
543    SpawnExpression {
544        line: usize,
545        source_file: Option<String>,
546        body: BlockStatement,
547        inferred_type: Option<String>,
548    },
549    SuperCall {
550        line: usize,
551        source_file: Option<String>,
552        arguments: Vec<CallArgument>,
553        inferred_type: Option<String>,
554    },
555}
556
557#[derive(Debug, Clone, PartialEq, Eq)]
558pub enum TemplatePart {
559    Text {
560        line: usize,
561        source_file: Option<String>,
562        value: String,
563    },
564    Expression {
565        line: usize,
566        source_file: Option<String>,
567        expression: Box<Expression>,
568    },
569}
570
571#[derive(Debug, Clone, PartialEq, Eq)]
572pub struct DictEntry {
573    pub line: usize,
574    pub source_file: Option<String>,
575    pub key: DictKey,
576    pub value: Expression,
577}
578
579#[derive(Debug, Clone, PartialEq, Eq)]
580pub enum DictKey {
581    Identifier {
582        line: usize,
583        source_file: Option<String>,
584        name: String,
585    },
586    StringLiteral {
587        line: usize,
588        source_file: Option<String>,
589        value: String,
590    },
591    Expression {
592        line: usize,
593        source_file: Option<String>,
594        expression: Box<Expression>,
595    },
596}
597
598#[derive(Debug, Clone, PartialEq, Eq)]
599pub enum CallArgument {
600    Positional {
601        line: usize,
602        source_file: Option<String>,
603        value: Expression,
604    },
605    Spread {
606        line: usize,
607        source_file: Option<String>,
608        value: Expression,
609    },
610    Named {
611        line: usize,
612        source_file: Option<String>,
613        name: DictKey,
614        value: Expression,
615    },
616}
617
618impl Program {
619    pub fn to_json_pretty(&self) -> String {
620        let mut out = String::new();
621        self.write_json(&mut out, 0);
622        out
623    }
624
625    fn write_json(&self, out: &mut String, indent: usize) {
626        out.push_str("{\n");
627        write_string_field(out, indent + 1, "type", "Program", true);
628        write_number_field(out, indent + 1, "line", self.line, true);
629        write_field_name(out, indent + 1, "statements");
630        write_array(out, indent + 1, &self.statements, |out, indent, stmt| {
631            stmt.write_json(out, indent)
632        });
633        out.push('\n');
634        write_indent(out, indent);
635        out.push('}');
636    }
637}
638
639impl Statement {
640    pub fn line(&self) -> usize {
641        match self {
642            Statement::Block(node) => node.line,
643            Statement::VariableDeclaration(node) => node.line,
644            Statement::VariableUnpackDeclaration(node) => node.line,
645            Statement::FunctionDeclaration(node) => node.line,
646            Statement::ClassDeclaration(node) => node.line,
647            Statement::TraitDeclaration(node) => node.line,
648            Statement::ImportDeclaration(node) => node.line,
649            Statement::IfStatement(node) => node.line,
650            Statement::WhileStatement(node) => node.line,
651            Statement::ForStatement(node) => node.line,
652            Statement::SwitchStatement(node) => node.line,
653            Statement::TryStatement(node) => node.line,
654            Statement::ReturnStatement(node) => node.line,
655            Statement::LoopControlStatement(node) => node.line,
656            Statement::ThrowStatement(node) => node.line,
657            Statement::DieStatement(node) => node.line,
658            Statement::PostfixConditionalStatement(node) => node.line,
659            Statement::KeywordStatement(node) => node.line,
660            Statement::ExpressionStatement(node) => node.line,
661        }
662    }
663
664    pub fn source_file(&self) -> Option<&str> {
665        match self {
666            Statement::Block(node) => node.source_file.as_deref(),
667            Statement::VariableDeclaration(node) => node.source_file.as_deref(),
668            Statement::VariableUnpackDeclaration(node) => node.source_file.as_deref(),
669            Statement::FunctionDeclaration(node) => node.source_file.as_deref(),
670            Statement::ClassDeclaration(node) => node.source_file.as_deref(),
671            Statement::TraitDeclaration(node) => node.source_file.as_deref(),
672            Statement::ImportDeclaration(node) => node.source_file.as_deref(),
673            Statement::IfStatement(node) => node.source_file.as_deref(),
674            Statement::WhileStatement(node) => node.source_file.as_deref(),
675            Statement::ForStatement(node) => node.source_file.as_deref(),
676            Statement::SwitchStatement(node) => node.source_file.as_deref(),
677            Statement::TryStatement(node) => node.source_file.as_deref(),
678            Statement::ReturnStatement(node) => node.source_file.as_deref(),
679            Statement::LoopControlStatement(node) => node.source_file.as_deref(),
680            Statement::ThrowStatement(node) => node.source_file.as_deref(),
681            Statement::DieStatement(node) => node.source_file.as_deref(),
682            Statement::PostfixConditionalStatement(node) => node.source_file.as_deref(),
683            Statement::KeywordStatement(node) => node.source_file.as_deref(),
684            Statement::ExpressionStatement(node) => node.source_file.as_deref(),
685        }
686    }
687
688    fn write_json(&self, out: &mut String, indent: usize) {
689        match self {
690            Statement::Block(node) => node.write_json(out, indent),
691            Statement::VariableDeclaration(node) => node.write_json(out, indent),
692            Statement::VariableUnpackDeclaration(node) => node.write_json(out, indent),
693            Statement::FunctionDeclaration(node) => node.write_json(out, indent),
694            Statement::ClassDeclaration(node) => node.write_json(out, indent),
695            Statement::TraitDeclaration(node) => node.write_json(out, indent),
696            Statement::ImportDeclaration(node) => node.write_json(out, indent),
697            Statement::IfStatement(node) => node.write_json(out, indent),
698            Statement::WhileStatement(node) => node.write_json(out, indent),
699            Statement::ForStatement(node) => node.write_json(out, indent),
700            Statement::SwitchStatement(node) => node.write_json(out, indent),
701            Statement::TryStatement(node) => node.write_json(out, indent),
702            Statement::ReturnStatement(node) => node.write_json(out, indent),
703            Statement::LoopControlStatement(node) => node.write_json(out, indent),
704            Statement::ThrowStatement(node) => node.write_json(out, indent),
705            Statement::DieStatement(node) => node.write_json(out, indent),
706            Statement::PostfixConditionalStatement(node) => node.write_json(out, indent),
707            Statement::KeywordStatement(node) => node.write_json(out, indent),
708            Statement::ExpressionStatement(node) => node.write_json(out, indent),
709        }
710    }
711}
712
713impl BlockStatement {
714    fn write_json(&self, out: &mut String, indent: usize) {
715        write_object_start(out);
716        write_string_field(out, indent + 1, "type", "BlockStatement", true);
717        write_number_field(out, indent + 1, "line", self.line, true);
718        write_bool_field(
719            out,
720            indent + 1,
721            "needs_lexical_scope",
722            self.needs_lexical_scope,
723            true,
724        );
725        write_field_name(out, indent + 1, "statements");
726        write_array(out, indent + 1, &self.statements, |out, indent, stmt| {
727            stmt.write_json(out, indent)
728        });
729        out.push('\n');
730        write_object_end(out, indent);
731    }
732}
733
734impl VariableDeclaration {
735    fn write_json(&self, out: &mut String, indent: usize) {
736        write_object_start(out);
737        write_string_field(out, indent + 1, "type", "VariableDeclaration", true);
738        write_number_field(out, indent + 1, "line", self.line, true);
739        write_string_field(out, indent + 1, "kind", &self.kind, true);
740        write_optional_string_field(
741            out,
742            indent + 1,
743            "declared_type",
744            self.declared_type.as_deref(),
745            true,
746        );
747        write_string_field(out, indent + 1, "name", &self.name, true);
748        write_bool_field(
749            out,
750            indent + 1,
751            "is_weak_storage",
752            self.is_weak_storage,
753            true,
754        );
755        write_optional_bool_field(
756            out,
757            indent + 1,
758            "runtime_typecheck_required",
759            self.runtime_typecheck_required,
760            true,
761        );
762        write_optional_expr_field(out, indent + 1, "init", self.init.as_ref(), false);
763        write_object_end(out, indent);
764    }
765}
766
767impl VariableUnpackDeclaration {
768    fn write_json(&self, out: &mut String, indent: usize) {
769        write_object_start(out);
770        write_string_field(out, indent + 1, "type", "VariableUnpackDeclaration", true);
771        write_number_field(out, indent + 1, "line", self.line, true);
772        write_string_field(out, indent + 1, "kind", &self.kind, true);
773        write_field_name(out, indent + 1, "pattern");
774        self.pattern.write_json(out, indent + 1);
775        out.push_str(",\n");
776        write_field_name(out, indent + 1, "init");
777        self.init.write_json(out, indent + 1);
778        out.push('\n');
779        write_object_end(out, indent);
780    }
781}
782
783impl DeclarationBindingPattern {
784    pub fn entries(&self) -> &[DeclarationBindingEntry] {
785        match self {
786            DeclarationBindingPattern::Keyed { entries, .. } => entries,
787        }
788    }
789
790    pub fn entries_mut(&mut self) -> &mut [DeclarationBindingEntry] {
791        match self {
792            DeclarationBindingPattern::Keyed { entries, .. } => entries,
793        }
794    }
795
796    fn write_json(&self, out: &mut String, indent: usize) {
797        match self {
798            DeclarationBindingPattern::Keyed { line, entries, .. } => {
799                write_object_start(out);
800                write_string_field(out, indent + 1, "type", "KeyedBindingPattern", true);
801                write_number_field(out, indent + 1, "line", *line, true);
802                write_field_name(out, indent + 1, "entries");
803                write_array(out, indent + 1, entries, |out, indent, entry| {
804                    entry.write_json(out, indent)
805                });
806                out.push('\n');
807                write_object_end(out, indent);
808            }
809        }
810    }
811}
812
813impl DeclarationBindingEntry {
814    fn write_json(&self, out: &mut String, indent: usize) {
815        write_object_start(out);
816        write_string_field(out, indent + 1, "type", "BindingEntry", true);
817        write_number_field(out, indent + 1, "line", self.line, true);
818        write_field_name(out, indent + 1, "key");
819        self.key.write_json(out, indent + 1);
820        out.push_str(",\n");
821        write_optional_string_field(
822            out,
823            indent + 1,
824            "declared_type",
825            self.declared_type.as_deref(),
826            true,
827        );
828        write_string_field(out, indent + 1, "name", &self.name, true);
829        write_bool_field(
830            out,
831            indent + 1,
832            "is_weak_storage",
833            self.is_weak_storage,
834            true,
835        );
836        write_optional_bool_field(
837            out,
838            indent + 1,
839            "runtime_typecheck_required",
840            self.runtime_typecheck_required,
841            true,
842        );
843        write_optional_expr_field(
844            out,
845            indent + 1,
846            "default_value",
847            self.default_value.as_ref(),
848            false,
849        );
850        write_object_end(out, indent);
851    }
852}
853
854impl FunctionDeclaration {
855    fn write_json(&self, out: &mut String, indent: usize) {
856        write_object_start(out);
857        write_string_field(out, indent + 1, "type", "FunctionDeclaration", true);
858        write_number_field(out, indent + 1, "line", self.line, true);
859        write_string_field(out, indent + 1, "name", &self.name, true);
860        write_bool_field(out, indent + 1, "is_async", self.is_async, true);
861        write_bool_field(out, indent + 1, "is_predeclared", self.is_predeclared, true);
862        write_optional_string_field(
863            out,
864            indent + 1,
865            "return_type",
866            self.return_type.as_deref(),
867            true,
868        );
869        write_field_name(out, indent + 1, "params");
870        write_array(out, indent + 1, &self.params, |out, indent, param| {
871            param.write_json(out, indent)
872        });
873        out.push_str(",\n");
874        write_field_name(out, indent + 1, "body");
875        self.body.write_json(out, indent + 1);
876        out.push('\n');
877        write_object_end(out, indent);
878    }
879}
880
881impl ClassDeclaration {
882    fn write_json(&self, out: &mut String, indent: usize) {
883        write_object_start(out);
884        write_string_field(out, indent + 1, "type", "ClassDeclaration", true);
885        write_number_field(out, indent + 1, "line", self.line, true);
886        write_string_field(out, indent + 1, "name", &self.name, true);
887        write_optional_string_field(out, indent + 1, "base", self.base.as_deref(), true);
888        write_field_name(out, indent + 1, "traits");
889        write_string_array(out, indent + 1, &self.traits);
890        out.push_str(",\n");
891        write_bool_field(out, indent + 1, "shorthand", self.shorthand, true);
892        write_field_name(out, indent + 1, "body");
893        write_array(out, indent + 1, &self.body, |out, indent, member| {
894            member.write_json(out, indent)
895        });
896        out.push('\n');
897        write_object_end(out, indent);
898    }
899}
900
901impl TraitDeclaration {
902    fn write_json(&self, out: &mut String, indent: usize) {
903        write_object_start(out);
904        write_string_field(out, indent + 1, "type", "TraitDeclaration", true);
905        write_number_field(out, indent + 1, "line", self.line, true);
906        write_string_field(out, indent + 1, "name", &self.name, true);
907        write_bool_field(out, indent + 1, "shorthand", self.shorthand, true);
908        write_field_name(out, indent + 1, "body");
909        write_array(out, indent + 1, &self.body, |out, indent, member| {
910            member.write_json(out, indent)
911        });
912        out.push('\n');
913        write_object_end(out, indent);
914    }
915}
916
917impl ClassMember {
918    pub fn line(&self) -> usize {
919        match self {
920            ClassMember::Field(node) => node.line,
921            ClassMember::Method(node) => node.line,
922            ClassMember::Class(node) => node.line,
923            ClassMember::Trait(node) => node.line,
924        }
925    }
926
927    fn write_json(&self, out: &mut String, indent: usize) {
928        match self {
929            ClassMember::Field(node) => node.write_json(out, indent),
930            ClassMember::Method(node) => node.write_json(out, indent),
931            ClassMember::Class(node) => node.write_json(out, indent),
932            ClassMember::Trait(node) => node.write_json(out, indent),
933        }
934    }
935}
936
937impl FieldDeclaration {
938    fn write_json(&self, out: &mut String, indent: usize) {
939        write_object_start(out);
940        write_string_field(out, indent + 1, "type", "FieldDeclaration", true);
941        write_number_field(out, indent + 1, "line", self.line, true);
942        write_string_field(out, indent + 1, "kind", &self.kind, true);
943        write_optional_string_field(
944            out,
945            indent + 1,
946            "declared_type",
947            self.declared_type.as_deref(),
948            true,
949        );
950        write_string_field(out, indent + 1, "name", &self.name, true);
951        write_field_name(out, indent + 1, "accessors");
952        write_string_array(out, indent + 1, &self.accessors);
953        out.push_str(",\n");
954        write_bool_field(
955            out,
956            indent + 1,
957            "is_weak_storage",
958            self.is_weak_storage,
959            true,
960        );
961        write_optional_bool_field(
962            out,
963            indent + 1,
964            "runtime_typecheck_required",
965            self.runtime_typecheck_required,
966            true,
967        );
968        write_optional_expr_field(
969            out,
970            indent + 1,
971            "default_value",
972            self.default_value.as_ref(),
973            false,
974        );
975        write_object_end(out, indent);
976    }
977}
978
979impl MethodDeclaration {
980    fn write_json(&self, out: &mut String, indent: usize) {
981        write_object_start(out);
982        write_string_field(out, indent + 1, "type", "MethodDeclaration", true);
983        write_number_field(out, indent + 1, "line", self.line, true);
984        write_string_field(out, indent + 1, "name", &self.name, true);
985        write_bool_field(out, indent + 1, "is_static", self.is_static, true);
986        write_bool_field(out, indent + 1, "is_async", self.is_async, true);
987        write_bool_field(out, indent + 1, "is_predeclared", self.is_predeclared, true);
988        write_optional_string_field(
989            out,
990            indent + 1,
991            "return_type",
992            self.return_type.as_deref(),
993            true,
994        );
995        write_field_name(out, indent + 1, "params");
996        write_array(out, indent + 1, &self.params, |out, indent, param| {
997            param.write_json(out, indent)
998        });
999        out.push_str(",\n");
1000        write_field_name(out, indent + 1, "body");
1001        self.body.write_json(out, indent + 1);
1002        out.push('\n');
1003        write_object_end(out, indent);
1004    }
1005}
1006
1007impl Parameter {
1008    fn write_json(&self, out: &mut String, indent: usize) {
1009        write_object_start(out);
1010        write_string_field(out, indent + 1, "type", "Parameter", true);
1011        write_number_field(out, indent + 1, "line", self.line, true);
1012        write_optional_string_field(
1013            out,
1014            indent + 1,
1015            "declared_type",
1016            self.declared_type.as_deref(),
1017            true,
1018        );
1019        write_string_field(out, indent + 1, "name", &self.name, true);
1020        write_bool_field(out, indent + 1, "optional", self.optional, true);
1021        write_bool_field(out, indent + 1, "variadic", self.variadic, true);
1022        write_optional_expr_field(
1023            out,
1024            indent + 1,
1025            "default_value",
1026            self.default_value.as_ref(),
1027            false,
1028        );
1029        write_object_end(out, indent);
1030    }
1031}
1032
1033impl ImportDeclaration {
1034    fn write_json(&self, out: &mut String, indent: usize) {
1035        write_object_start(out);
1036        write_string_field(out, indent + 1, "type", "ImportDeclaration", true);
1037        write_number_field(out, indent + 1, "line", self.line, true);
1038        write_string_field(out, indent + 1, "source", &self.source, true);
1039        write_bool_field(out, indent + 1, "try_mode", self.try_mode, true);
1040        write_bool_field(out, indent + 1, "import_all", self.import_all, true);
1041        write_field_name(out, indent + 1, "specifiers");
1042        write_array(out, indent + 1, &self.specifiers, |out, indent, spec| {
1043            spec.write_json(out, indent)
1044        });
1045        out.push_str(",\n");
1046        match &self.condition {
1047            Some(condition) => {
1048                write_field_name(out, indent + 1, "condition");
1049                condition.write_json(out, indent + 1);
1050                out.push('\n');
1051            }
1052            None => {
1053                write_null_field(out, indent + 1, "condition", false);
1054            }
1055        }
1056        write_object_end(out, indent);
1057    }
1058}
1059
1060impl ImportSpecifier {
1061    fn write_json(&self, out: &mut String, indent: usize) {
1062        write_object_start(out);
1063        write_string_field(out, indent + 1, "type", "ImportSpecifier", true);
1064        write_number_field(out, indent + 1, "line", self.line, true);
1065        write_string_field(out, indent + 1, "imported", &self.imported, true);
1066        write_string_field(out, indent + 1, "local", &self.local, false);
1067        write_object_end(out, indent);
1068    }
1069}
1070
1071impl PostfixCondition {
1072    fn write_json(&self, out: &mut String, indent: usize) {
1073        write_object_start(out);
1074        write_number_field(out, indent + 1, "line", self.line, true);
1075        write_string_field(out, indent + 1, "keyword", &self.keyword, true);
1076        write_field_name(out, indent + 1, "test");
1077        self.test.write_json(out, indent + 1);
1078        out.push('\n');
1079        write_object_end(out, indent);
1080    }
1081}
1082
1083impl IfStatement {
1084    fn write_json(&self, out: &mut String, indent: usize) {
1085        write_object_start(out);
1086        write_string_field(out, indent + 1, "type", "IfStatement", true);
1087        write_number_field(out, indent + 1, "line", self.line, true);
1088        write_field_name(out, indent + 1, "test");
1089        self.test.write_json(out, indent + 1);
1090        out.push_str(",\n");
1091        write_field_name(out, indent + 1, "consequent");
1092        self.consequent.write_json(out, indent + 1);
1093        out.push_str(",\n");
1094        match &self.alternate {
1095            Some(alternate) => {
1096                write_field_name(out, indent + 1, "alternate");
1097                alternate.write_json(out, indent + 1);
1098                out.push('\n');
1099            }
1100            None => write_null_field(out, indent + 1, "alternate", false),
1101        }
1102        write_object_end(out, indent);
1103    }
1104}
1105
1106impl WhileStatement {
1107    fn write_json(&self, out: &mut String, indent: usize) {
1108        write_object_start(out);
1109        write_string_field(out, indent + 1, "type", "WhileStatement", true);
1110        write_number_field(out, indent + 1, "line", self.line, true);
1111        write_field_name(out, indent + 1, "test");
1112        self.test.write_json(out, indent + 1);
1113        out.push_str(",\n");
1114        write_field_name(out, indent + 1, "body");
1115        self.body.write_json(out, indent + 1);
1116        out.push('\n');
1117        write_object_end(out, indent);
1118    }
1119}
1120
1121impl ForStatement {
1122    fn write_json(&self, out: &mut String, indent: usize) {
1123        write_object_start(out);
1124        write_string_field(out, indent + 1, "type", "ForStatement", true);
1125        write_number_field(out, indent + 1, "line", self.line, true);
1126        write_optional_string_field(
1127            out,
1128            indent + 1,
1129            "binding_kind",
1130            self.binding_kind.as_deref(),
1131            true,
1132        );
1133        write_string_field(out, indent + 1, "variable", &self.variable, true);
1134        write_field_name(out, indent + 1, "iterable");
1135        self.iterable.write_json(out, indent + 1);
1136        out.push_str(",\n");
1137        write_field_name(out, indent + 1, "body");
1138        self.body.write_json(out, indent + 1);
1139        out.push_str(",\n");
1140        match &self.else_block {
1141            Some(body) => {
1142                write_field_name(out, indent + 1, "else_block");
1143                body.write_json(out, indent + 1);
1144                out.push('\n');
1145            }
1146            None => write_null_field(out, indent + 1, "else_block", false),
1147        }
1148        write_object_end(out, indent);
1149    }
1150}
1151
1152impl SwitchStatement {
1153    fn write_json(&self, out: &mut String, indent: usize) {
1154        write_object_start(out);
1155        write_string_field(out, indent + 1, "type", "SwitchStatement", true);
1156        write_number_field(out, indent + 1, "line", self.line, true);
1157        write_field_name(out, indent + 1, "discriminant");
1158        self.discriminant.write_json(out, indent + 1);
1159        out.push_str(",\n");
1160        write_optional_string_field(
1161            out,
1162            indent + 1,
1163            "comparator",
1164            self.comparator.as_deref(),
1165            true,
1166        );
1167        write_field_name(out, indent + 1, "cases");
1168        write_array(out, indent + 1, &self.cases, |out, indent, case| {
1169            case.write_json(out, indent)
1170        });
1171        out.push_str(",\n");
1172        match &self.index {
1173            Some(index) => {
1174                write_field_name(out, indent + 1, "index");
1175                write_array(out, indent + 1, index, |out, indent, entry| {
1176                    entry.write_json(out, indent)
1177                });
1178                out.push_str(",\n");
1179            }
1180            None => write_null_field(out, indent + 1, "index", true),
1181        }
1182        match &self.default {
1183            Some(default) => {
1184                write_field_name(out, indent + 1, "default");
1185                write_array(out, indent + 1, default, |out, indent, stmt| {
1186                    stmt.write_json(out, indent)
1187                });
1188                out.push('\n');
1189            }
1190            None => write_null_field(out, indent + 1, "default", false),
1191        }
1192        write_object_end(out, indent);
1193    }
1194}
1195
1196impl SwitchCase {
1197    fn write_json(&self, out: &mut String, indent: usize) {
1198        write_object_start(out);
1199        write_string_field(out, indent + 1, "type", "SwitchCase", true);
1200        write_number_field(out, indent + 1, "line", self.line, true);
1201        write_field_name(out, indent + 1, "values");
1202        write_array(out, indent + 1, &self.values, |out, indent, expr| {
1203            expr.write_json(out, indent)
1204        });
1205        out.push_str(",\n");
1206        write_field_name(out, indent + 1, "operators");
1207        write_array(out, indent + 1, &self.operators, |out, indent, operator| {
1208            write_indent(out, indent);
1209            match operator {
1210                Some(operator) => write_json_string(out, operator),
1211                None => out.push_str("null"),
1212            }
1213        });
1214        out.push_str(",\n");
1215        write_field_name(out, indent + 1, "consequent");
1216        write_array(out, indent + 1, &self.consequent, |out, indent, stmt| {
1217            stmt.write_json(out, indent)
1218        });
1219        out.push('\n');
1220        write_object_end(out, indent);
1221    }
1222}
1223
1224impl SwitchIndexEntry {
1225    fn write_json(&self, out: &mut String, indent: usize) {
1226        write_object_start(out);
1227        write_string_field(out, indent + 1, "key", &self.key, true);
1228        write_number_field(out, indent + 1, "case_index", self.case_index, false);
1229        write_object_end(out, indent);
1230    }
1231}
1232
1233impl TryStatement {
1234    fn write_json(&self, out: &mut String, indent: usize) {
1235        write_object_start(out);
1236        write_string_field(out, indent + 1, "type", "TryStatement", true);
1237        write_number_field(out, indent + 1, "line", self.line, true);
1238        write_field_name(out, indent + 1, "body");
1239        self.body.write_json(out, indent + 1);
1240        out.push_str(",\n");
1241        write_field_name(out, indent + 1, "handlers");
1242        write_array(out, indent + 1, &self.handlers, |out, indent, handler| {
1243            handler.write_json(out, indent)
1244        });
1245        out.push('\n');
1246        write_object_end(out, indent);
1247    }
1248}
1249
1250impl CatchClause {
1251    fn write_json(&self, out: &mut String, indent: usize) {
1252        write_object_start(out);
1253        write_string_field(out, indent + 1, "type", "CatchClause", true);
1254        write_number_field(out, indent + 1, "line", self.line, true);
1255        match &self.binding {
1256            Some(binding) => {
1257                write_field_name(out, indent + 1, "binding");
1258                binding.write_json(out, indent + 1);
1259                out.push_str(",\n");
1260            }
1261            None => write_null_field(out, indent + 1, "binding", true),
1262        }
1263        write_field_name(out, indent + 1, "body");
1264        self.body.write_json(out, indent + 1);
1265        out.push('\n');
1266        write_object_end(out, indent);
1267    }
1268}
1269
1270impl CatchBinding {
1271    fn write_json(&self, out: &mut String, indent: usize) {
1272        write_object_start(out);
1273        write_number_field(out, indent + 1, "line", self.line, true);
1274        write_optional_string_field(
1275            out,
1276            indent + 1,
1277            "declared_type",
1278            self.declared_type.as_deref(),
1279            true,
1280        );
1281        write_optional_string_field(out, indent + 1, "name", self.name.as_deref(), false);
1282        write_object_end(out, indent);
1283    }
1284}
1285
1286impl ReturnStatement {
1287    fn write_json(&self, out: &mut String, indent: usize) {
1288        write_object_start(out);
1289        write_string_field(out, indent + 1, "type", "ReturnStatement", true);
1290        write_number_field(out, indent + 1, "line", self.line, true);
1291        write_optional_bool_field(
1292            out,
1293            indent + 1,
1294            "runtime_typecheck_required",
1295            self.runtime_typecheck_required,
1296            true,
1297        );
1298        write_optional_expr_field(out, indent + 1, "argument", self.argument.as_ref(), false);
1299        write_object_end(out, indent);
1300    }
1301}
1302
1303impl LoopControlStatement {
1304    fn write_json(&self, out: &mut String, indent: usize) {
1305        write_object_start(out);
1306        write_string_field(out, indent + 1, "type", "LoopControlStatement", true);
1307        write_number_field(out, indent + 1, "line", self.line, true);
1308        write_string_field(out, indent + 1, "keyword", &self.keyword, false);
1309        write_object_end(out, indent);
1310    }
1311}
1312
1313impl ThrowStatement {
1314    fn write_json(&self, out: &mut String, indent: usize) {
1315        write_object_start(out);
1316        write_string_field(out, indent + 1, "type", "ThrowStatement", true);
1317        write_number_field(out, indent + 1, "line", self.line, true);
1318        write_field_name(out, indent + 1, "argument");
1319        self.argument.write_json(out, indent + 1);
1320        out.push('\n');
1321        write_object_end(out, indent);
1322    }
1323}
1324
1325impl DieStatement {
1326    fn write_json(&self, out: &mut String, indent: usize) {
1327        write_object_start(out);
1328        write_string_field(out, indent + 1, "type", "DieStatement", true);
1329        write_number_field(out, indent + 1, "line", self.line, true);
1330        write_field_name(out, indent + 1, "argument");
1331        self.argument.write_json(out, indent + 1);
1332        out.push('\n');
1333        write_object_end(out, indent);
1334    }
1335}
1336
1337impl PostfixConditionalStatement {
1338    fn write_json(&self, out: &mut String, indent: usize) {
1339        write_object_start(out);
1340        write_string_field(out, indent + 1, "type", "PostfixConditionalStatement", true);
1341        write_number_field(out, indent + 1, "line", self.line, true);
1342        write_string_field(out, indent + 1, "keyword", &self.keyword, true);
1343        write_field_name(out, indent + 1, "statement");
1344        self.statement.write_json(out, indent + 1);
1345        out.push_str(",\n");
1346        write_field_name(out, indent + 1, "test");
1347        self.test.write_json(out, indent + 1);
1348        out.push('\n');
1349        write_object_end(out, indent);
1350    }
1351}
1352
1353impl KeywordStatement {
1354    fn write_json(&self, out: &mut String, indent: usize) {
1355        write_object_start(out);
1356        write_string_field(out, indent + 1, "type", "KeywordStatement", true);
1357        write_number_field(out, indent + 1, "line", self.line, true);
1358        write_string_field(out, indent + 1, "keyword", &self.keyword, true);
1359        write_field_name(out, indent + 1, "arguments");
1360        write_array(out, indent + 1, &self.arguments, |out, indent, expr| {
1361            expr.write_json(out, indent)
1362        });
1363        out.push('\n');
1364        write_object_end(out, indent);
1365    }
1366}
1367
1368impl ExpressionStatement {
1369    fn write_json(&self, out: &mut String, indent: usize) {
1370        write_object_start(out);
1371        write_string_field(out, indent + 1, "type", "ExpressionStatement", true);
1372        write_number_field(out, indent + 1, "line", self.line, true);
1373        write_field_name(out, indent + 1, "expression");
1374        self.expression.write_json(out, indent + 1);
1375        out.push('\n');
1376        write_object_end(out, indent);
1377    }
1378}
1379
1380impl Expression {
1381    pub fn line(&self) -> usize {
1382        match self {
1383            Expression::Identifier { line, .. } => *line,
1384            Expression::NumberLiteral { line, .. } => *line,
1385            Expression::StringLiteral { line, .. } => *line,
1386            Expression::BinaryStringLiteral { line, .. } => *line,
1387            Expression::RegexLiteral { line, .. } => *line,
1388            Expression::BooleanLiteral { line, .. } => *line,
1389            Expression::NullLiteral { line, .. } => *line,
1390            Expression::ArrayLiteral { line, .. } => *line,
1391            Expression::SetLiteral { line, .. } => *line,
1392            Expression::BagLiteral { line, .. } => *line,
1393            Expression::DictLiteral { line, .. } => *line,
1394            Expression::PairListLiteral { line, .. } => *line,
1395            Expression::TemplateLiteral { line, .. } => *line,
1396            Expression::Unary { line, .. } => *line,
1397            Expression::Binary { line, .. } => *line,
1398            Expression::Ternary { line, .. } => *line,
1399            Expression::DefinedOr { line, .. } => *line,
1400            Expression::Assignment { line, .. } => *line,
1401            Expression::Call { line, .. } => *line,
1402            Expression::MemberAccess { line, .. } => *line,
1403            Expression::DynamicMemberCall { line, .. } => *line,
1404            Expression::Index { line, .. } => *line,
1405            Expression::Slice { line, .. } => *line,
1406            Expression::DictAccess { line, .. } => *line,
1407            Expression::PostfixUpdate { line, .. } => *line,
1408            Expression::Lambda { line, .. } => *line,
1409            Expression::FunctionExpression { line, .. } => *line,
1410            Expression::LetExpression { line, .. } => *line,
1411            Expression::TryExpression { line, .. } => *line,
1412            Expression::DoExpression { line, .. } => *line,
1413            Expression::AwaitExpression { line, .. } => *line,
1414            Expression::SpawnExpression { line, .. } => *line,
1415            Expression::SuperCall { line, .. } => *line,
1416        }
1417    }
1418
1419    pub fn source_file(&self) -> Option<&str> {
1420        match self {
1421            Expression::Identifier { source_file, .. }
1422            | Expression::NumberLiteral { source_file, .. }
1423            | Expression::StringLiteral { source_file, .. }
1424            | Expression::BinaryStringLiteral { source_file, .. }
1425            | Expression::RegexLiteral { source_file, .. }
1426            | Expression::BooleanLiteral { source_file, .. }
1427            | Expression::NullLiteral { source_file, .. }
1428            | Expression::ArrayLiteral { source_file, .. }
1429            | Expression::SetLiteral { source_file, .. }
1430            | Expression::BagLiteral { source_file, .. }
1431            | Expression::DictLiteral { source_file, .. }
1432            | Expression::PairListLiteral { source_file, .. }
1433            | Expression::TemplateLiteral { source_file, .. }
1434            | Expression::Unary { source_file, .. }
1435            | Expression::Binary { source_file, .. }
1436            | Expression::Ternary { source_file, .. }
1437            | Expression::DefinedOr { source_file, .. }
1438            | Expression::Assignment { source_file, .. }
1439            | Expression::Call { source_file, .. }
1440            | Expression::MemberAccess { source_file, .. }
1441            | Expression::DynamicMemberCall { source_file, .. }
1442            | Expression::Index { source_file, .. }
1443            | Expression::Slice { source_file, .. }
1444            | Expression::DictAccess { source_file, .. }
1445            | Expression::PostfixUpdate { source_file, .. }
1446            | Expression::Lambda { source_file, .. }
1447            | Expression::FunctionExpression { source_file, .. }
1448            | Expression::LetExpression { source_file, .. }
1449            | Expression::TryExpression { source_file, .. }
1450            | Expression::DoExpression { source_file, .. }
1451            | Expression::AwaitExpression { source_file, .. }
1452            | Expression::SpawnExpression { source_file, .. }
1453            | Expression::SuperCall { source_file, .. } => source_file.as_deref(),
1454        }
1455    }
1456
1457    pub fn inferred_type(&self) -> Option<&str> {
1458        match self {
1459            Expression::Identifier { inferred_type, .. }
1460            | Expression::NumberLiteral { inferred_type, .. }
1461            | Expression::StringLiteral { inferred_type, .. }
1462            | Expression::BinaryStringLiteral { inferred_type, .. }
1463            | Expression::RegexLiteral { inferred_type, .. }
1464            | Expression::BooleanLiteral { inferred_type, .. }
1465            | Expression::NullLiteral { inferred_type, .. }
1466            | Expression::ArrayLiteral { inferred_type, .. }
1467            | Expression::SetLiteral { inferred_type, .. }
1468            | Expression::BagLiteral { inferred_type, .. }
1469            | Expression::DictLiteral { inferred_type, .. }
1470            | Expression::PairListLiteral { inferred_type, .. }
1471            | Expression::TemplateLiteral { inferred_type, .. }
1472            | Expression::Unary { inferred_type, .. }
1473            | Expression::Binary { inferred_type, .. }
1474            | Expression::Ternary { inferred_type, .. }
1475            | Expression::DefinedOr { inferred_type, .. }
1476            | Expression::Assignment { inferred_type, .. }
1477            | Expression::Call { inferred_type, .. }
1478            | Expression::MemberAccess { inferred_type, .. }
1479            | Expression::DynamicMemberCall { inferred_type, .. }
1480            | Expression::Index { inferred_type, .. }
1481            | Expression::Slice { inferred_type, .. }
1482            | Expression::DictAccess { inferred_type, .. }
1483            | Expression::PostfixUpdate { inferred_type, .. }
1484            | Expression::Lambda { inferred_type, .. }
1485            | Expression::FunctionExpression { inferred_type, .. }
1486            | Expression::LetExpression { inferred_type, .. }
1487            | Expression::TryExpression { inferred_type, .. }
1488            | Expression::DoExpression { inferred_type, .. }
1489            | Expression::AwaitExpression { inferred_type, .. }
1490            | Expression::SpawnExpression { inferred_type, .. }
1491            | Expression::SuperCall { inferred_type, .. } => inferred_type.as_deref(),
1492        }
1493    }
1494
1495    pub fn set_inferred_type(&mut self, value: Option<String>) {
1496        match self {
1497            Expression::Identifier { inferred_type, .. }
1498            | Expression::NumberLiteral { inferred_type, .. }
1499            | Expression::StringLiteral { inferred_type, .. }
1500            | Expression::BinaryStringLiteral { inferred_type, .. }
1501            | Expression::RegexLiteral { inferred_type, .. }
1502            | Expression::BooleanLiteral { inferred_type, .. }
1503            | Expression::NullLiteral { inferred_type, .. }
1504            | Expression::ArrayLiteral { inferred_type, .. }
1505            | Expression::SetLiteral { inferred_type, .. }
1506            | Expression::BagLiteral { inferred_type, .. }
1507            | Expression::DictLiteral { inferred_type, .. }
1508            | Expression::PairListLiteral { inferred_type, .. }
1509            | Expression::TemplateLiteral { inferred_type, .. }
1510            | Expression::Unary { inferred_type, .. }
1511            | Expression::Binary { inferred_type, .. }
1512            | Expression::Ternary { inferred_type, .. }
1513            | Expression::DefinedOr { inferred_type, .. }
1514            | Expression::Assignment { inferred_type, .. }
1515            | Expression::Call { inferred_type, .. }
1516            | Expression::MemberAccess { inferred_type, .. }
1517            | Expression::DynamicMemberCall { inferred_type, .. }
1518            | Expression::Index { inferred_type, .. }
1519            | Expression::Slice { inferred_type, .. }
1520            | Expression::DictAccess { inferred_type, .. }
1521            | Expression::PostfixUpdate { inferred_type, .. }
1522            | Expression::Lambda { inferred_type, .. }
1523            | Expression::FunctionExpression { inferred_type, .. }
1524            | Expression::LetExpression { inferred_type, .. }
1525            | Expression::TryExpression { inferred_type, .. }
1526            | Expression::DoExpression { inferred_type, .. }
1527            | Expression::AwaitExpression { inferred_type, .. }
1528            | Expression::SpawnExpression { inferred_type, .. }
1529            | Expression::SuperCall { inferred_type, .. } => *inferred_type = value,
1530        }
1531    }
1532
1533    pub fn runtime_typecheck_required(&self) -> Option<bool> {
1534        match self {
1535            Expression::Assignment {
1536                runtime_typecheck_required,
1537                ..
1538            }
1539            | Expression::LetExpression {
1540                runtime_typecheck_required,
1541                ..
1542            } => *runtime_typecheck_required,
1543            _ => None,
1544        }
1545    }
1546
1547    pub fn set_runtime_typecheck_required(&mut self, value: Option<bool>) {
1548        match self {
1549            Expression::Assignment {
1550                runtime_typecheck_required,
1551                ..
1552            }
1553            | Expression::LetExpression {
1554                runtime_typecheck_required,
1555                ..
1556            } => *runtime_typecheck_required = value,
1557            _ => {}
1558        }
1559    }
1560
1561    pub fn is_weak_write(&self) -> bool {
1562        match self {
1563            Expression::Assignment { is_weak_write, .. } => *is_weak_write,
1564            _ => false,
1565        }
1566    }
1567
1568    pub fn is_weak_storage(&self) -> bool {
1569        match self {
1570            Expression::LetExpression {
1571                is_weak_storage, ..
1572            } => *is_weak_storage,
1573            _ => false,
1574        }
1575    }
1576
1577    fn write_json(&self, out: &mut String, indent: usize) {
1578        let inferred_type = self.inferred_type();
1579        match self {
1580            Expression::Identifier {
1581                line,
1582                name,
1583                binding_depth,
1584                ..
1585            } => {
1586                write_object_start(out);
1587                write_string_field(out, indent + 1, "type", "Identifier", true);
1588                write_number_field(out, indent + 1, "line", *line, true);
1589                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1590                write_optional_number_field(out, indent + 1, "binding_depth", *binding_depth, true);
1591                write_string_field(out, indent + 1, "name", name, false);
1592                write_object_end(out, indent);
1593            }
1594            Expression::NumberLiteral { line, value, .. } => {
1595                write_object_start(out);
1596                write_string_field(out, indent + 1, "type", "NumberLiteral", true);
1597                write_number_field(out, indent + 1, "line", *line, true);
1598                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1599                write_string_field(out, indent + 1, "value", value, false);
1600                write_object_end(out, indent);
1601            }
1602            Expression::StringLiteral { line, value, .. } => {
1603                write_object_start(out);
1604                write_string_field(out, indent + 1, "type", "StringLiteral", true);
1605                write_number_field(out, indent + 1, "line", *line, true);
1606                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1607                write_string_field(out, indent + 1, "value", value, false);
1608                write_object_end(out, indent);
1609            }
1610            Expression::BinaryStringLiteral { line, bytes, .. } => {
1611                write_object_start(out);
1612                write_string_field(out, indent + 1, "type", "BinaryStringLiteral", true);
1613                write_number_field(out, indent + 1, "line", *line, true);
1614                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1615                write_string_field(out, indent + 1, "bytes_hex", &bytes_to_hex(bytes), false);
1616                write_object_end(out, indent);
1617            }
1618            Expression::RegexLiteral {
1619                line,
1620                pattern,
1621                parts,
1622                flags,
1623                cache_key,
1624                ..
1625            } => {
1626                write_object_start(out);
1627                write_string_field(out, indent + 1, "type", "RegexLiteral", true);
1628                write_number_field(out, indent + 1, "line", *line, true);
1629                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1630                write_string_field(out, indent + 1, "pattern", pattern, true);
1631                write_string_field(out, indent + 1, "flags", flags, true);
1632                write_field_name(out, indent + 1, "parts");
1633                write_array(out, indent + 1, parts, |out, indent, part| {
1634                    part.write_json(out, indent)
1635                });
1636                out.push_str(",\n");
1637                write_optional_string_field(
1638                    out,
1639                    indent + 1,
1640                    "regex_cache_key",
1641                    cache_key.as_deref(),
1642                    false,
1643                );
1644                write_object_end(out, indent);
1645            }
1646            Expression::BooleanLiteral { line, value, .. } => {
1647                write_object_start(out);
1648                write_string_field(out, indent + 1, "type", "BooleanLiteral", true);
1649                write_number_field(out, indent + 1, "line", *line, true);
1650                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1651                write_field_name(out, indent + 1, "value");
1652                out.push_str(if *value { "true" } else { "false" });
1653                out.push('\n');
1654                write_object_end(out, indent);
1655            }
1656            Expression::NullLiteral { line, .. } => {
1657                write_object_start(out);
1658                write_string_field(out, indent + 1, "type", "NullLiteral", true);
1659                write_number_field(out, indent + 1, "line", *line, true);
1660                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, false);
1661                write_object_end(out, indent);
1662            }
1663            Expression::ArrayLiteral {
1664                line,
1665                elements,
1666                capacity_hint,
1667                ..
1668            } => {
1669                write_object_start(out);
1670                write_string_field(out, indent + 1, "type", "ArrayLiteral", true);
1671                write_number_field(out, indent + 1, "line", *line, true);
1672                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1673                write_optional_number_field(out, indent + 1, "capacity_hint", *capacity_hint, true);
1674                write_field_name(out, indent + 1, "elements");
1675                write_array(out, indent + 1, elements, |out, indent, expr| {
1676                    expr.write_json(out, indent)
1677                });
1678                out.push('\n');
1679                write_object_end(out, indent);
1680            }
1681            Expression::SetLiteral {
1682                line,
1683                elements,
1684                capacity_hint,
1685                ..
1686            } => {
1687                write_object_start(out);
1688                write_string_field(out, indent + 1, "type", "SetLiteral", true);
1689                write_number_field(out, indent + 1, "line", *line, true);
1690                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1691                write_optional_number_field(out, indent + 1, "capacity_hint", *capacity_hint, true);
1692                write_field_name(out, indent + 1, "elements");
1693                write_array(out, indent + 1, elements, |out, indent, expr| {
1694                    expr.write_json(out, indent)
1695                });
1696                out.push('\n');
1697                write_object_end(out, indent);
1698            }
1699            Expression::BagLiteral {
1700                line,
1701                elements,
1702                capacity_hint,
1703                ..
1704            } => {
1705                write_object_start(out);
1706                write_string_field(out, indent + 1, "type", "BagLiteral", true);
1707                write_number_field(out, indent + 1, "line", *line, true);
1708                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1709                write_optional_number_field(out, indent + 1, "capacity_hint", *capacity_hint, true);
1710                write_field_name(out, indent + 1, "elements");
1711                write_array(out, indent + 1, elements, |out, indent, expr| {
1712                    expr.write_json(out, indent)
1713                });
1714                out.push('\n');
1715                write_object_end(out, indent);
1716            }
1717            Expression::DictLiteral {
1718                line,
1719                entries,
1720                capacity_hint,
1721                ..
1722            } => {
1723                write_object_start(out);
1724                write_string_field(out, indent + 1, "type", "DictLiteral", true);
1725                write_number_field(out, indent + 1, "line", *line, true);
1726                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1727                write_optional_number_field(out, indent + 1, "capacity_hint", *capacity_hint, true);
1728                write_field_name(out, indent + 1, "entries");
1729                write_array(out, indent + 1, entries, |out, indent, entry| {
1730                    entry.write_json(out, indent)
1731                });
1732                out.push('\n');
1733                write_object_end(out, indent);
1734            }
1735            Expression::PairListLiteral {
1736                line,
1737                entries,
1738                capacity_hint,
1739                ..
1740            } => {
1741                write_object_start(out);
1742                write_string_field(out, indent + 1, "type", "PairListLiteral", true);
1743                write_number_field(out, indent + 1, "line", *line, true);
1744                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1745                write_optional_number_field(out, indent + 1, "capacity_hint", *capacity_hint, true);
1746                write_field_name(out, indent + 1, "entries");
1747                write_array(out, indent + 1, entries, |out, indent, entry| {
1748                    entry.write_json(out, indent)
1749                });
1750                out.push('\n');
1751                write_object_end(out, indent);
1752            }
1753            Expression::TemplateLiteral { line, parts, .. } => {
1754                write_object_start(out);
1755                write_string_field(out, indent + 1, "type", "TemplateLiteral", true);
1756                write_number_field(out, indent + 1, "line", *line, true);
1757                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1758                write_field_name(out, indent + 1, "parts");
1759                write_array(out, indent + 1, parts, |out, indent, part| {
1760                    part.write_json(out, indent)
1761                });
1762                out.push('\n');
1763                write_object_end(out, indent);
1764            }
1765            Expression::Unary {
1766                line,
1767                operator,
1768                argument,
1769                traits,
1770                ..
1771            } => {
1772                write_object_start(out);
1773                write_string_field(out, indent + 1, "type", "UnaryExpression", true);
1774                write_number_field(out, indent + 1, "line", *line, true);
1775                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1776                write_string_field(out, indent + 1, "operator", operator, true);
1777                write_string_field(
1778                    out,
1779                    indent + 1,
1780                    "operator_kind",
1781                    operator_kind(operator),
1782                    true,
1783                );
1784                if !traits.is_empty() {
1785                    write_field_name(out, indent + 1, "traits");
1786                    write_string_array(out, indent + 1, traits);
1787                    out.push_str(",\n");
1788                }
1789                write_field_name(out, indent + 1, "argument");
1790                argument.write_json(out, indent + 1);
1791                out.push('\n');
1792                write_object_end(out, indent);
1793            }
1794            Expression::Binary {
1795                line,
1796                operator,
1797                left,
1798                right,
1799                ..
1800            } => {
1801                write_object_start(out);
1802                write_string_field(out, indent + 1, "type", "BinaryExpression", true);
1803                write_number_field(out, indent + 1, "line", *line, true);
1804                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1805                write_string_field(out, indent + 1, "operator", operator, true);
1806                write_string_field(
1807                    out,
1808                    indent + 1,
1809                    "operator_kind",
1810                    operator_kind(operator),
1811                    true,
1812                );
1813                write_field_name(out, indent + 1, "left");
1814                left.write_json(out, indent + 1);
1815                out.push_str(",\n");
1816                write_field_name(out, indent + 1, "right");
1817                right.write_json(out, indent + 1);
1818                out.push('\n');
1819                write_object_end(out, indent);
1820            }
1821            Expression::Ternary {
1822                line,
1823                test,
1824                consequent,
1825                alternate,
1826                ..
1827            } => {
1828                write_object_start(out);
1829                write_string_field(out, indent + 1, "type", "TernaryExpression", true);
1830                write_number_field(out, indent + 1, "line", *line, true);
1831                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1832                write_field_name(out, indent + 1, "test");
1833                test.write_json(out, indent + 1);
1834                out.push_str(",\n");
1835                write_field_name(out, indent + 1, "consequent");
1836                consequent.write_json(out, indent + 1);
1837                out.push_str(",\n");
1838                write_field_name(out, indent + 1, "alternate");
1839                alternate.write_json(out, indent + 1);
1840                out.push('\n');
1841                write_object_end(out, indent);
1842            }
1843            Expression::DefinedOr {
1844                line, left, right, ..
1845            } => {
1846                write_object_start(out);
1847                write_string_field(out, indent + 1, "type", "DefinedOrExpression", true);
1848                write_number_field(out, indent + 1, "line", *line, true);
1849                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1850                write_field_name(out, indent + 1, "left");
1851                left.write_json(out, indent + 1);
1852                out.push_str(",\n");
1853                write_field_name(out, indent + 1, "right");
1854                right.write_json(out, indent + 1);
1855                out.push('\n');
1856                write_object_end(out, indent);
1857            }
1858            Expression::Assignment {
1859                line,
1860                operator,
1861                left,
1862                right,
1863                ..
1864            } => {
1865                write_object_start(out);
1866                write_string_field(out, indent + 1, "type", "AssignmentExpression", true);
1867                write_number_field(out, indent + 1, "line", *line, true);
1868                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1869                write_optional_bool_field(
1870                    out,
1871                    indent + 1,
1872                    "runtime_typecheck_required",
1873                    self.runtime_typecheck_required(),
1874                    true,
1875                );
1876                write_bool_field(out, indent + 1, "is_weak_write", self.is_weak_write(), true);
1877                write_string_field(out, indent + 1, "operator", operator, true);
1878                write_string_field(
1879                    out,
1880                    indent + 1,
1881                    "operator_kind",
1882                    operator_kind(operator),
1883                    true,
1884                );
1885                write_field_name(out, indent + 1, "left");
1886                left.write_json(out, indent + 1);
1887                out.push_str(",\n");
1888                write_field_name(out, indent + 1, "right");
1889                right.write_json(out, indent + 1);
1890                out.push('\n');
1891                write_object_end(out, indent);
1892            }
1893            Expression::Call {
1894                line,
1895                callee,
1896                arguments,
1897                ..
1898            } => {
1899                write_object_start(out);
1900                write_string_field(out, indent + 1, "type", "CallExpression", true);
1901                write_number_field(out, indent + 1, "line", *line, true);
1902                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1903                write_field_name(out, indent + 1, "callee");
1904                callee.write_json(out, indent + 1);
1905                out.push_str(",\n");
1906                write_field_name(out, indent + 1, "arguments");
1907                write_array(out, indent + 1, arguments, |out, indent, arg| {
1908                    arg.write_json(out, indent)
1909                });
1910                out.push('\n');
1911                write_object_end(out, indent);
1912            }
1913            Expression::MemberAccess {
1914                line,
1915                object,
1916                member,
1917                ..
1918            } => {
1919                write_object_start(out);
1920                write_string_field(out, indent + 1, "type", "MemberCallExpression", true);
1921                write_number_field(out, indent + 1, "line", *line, true);
1922                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1923                write_field_name(out, indent + 1, "object");
1924                object.write_json(out, indent + 1);
1925                out.push_str(",\n");
1926                write_string_field(out, indent + 1, "member", member, false);
1927                write_object_end(out, indent);
1928            }
1929            Expression::DynamicMemberCall {
1930                line,
1931                object,
1932                member,
1933                arguments,
1934                ..
1935            } => {
1936                write_object_start(out);
1937                write_string_field(out, indent + 1, "type", "DynamicMemberCall", true);
1938                write_number_field(out, indent + 1, "line", *line, true);
1939                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1940                write_field_name(out, indent + 1, "object");
1941                object.write_json(out, indent + 1);
1942                out.push_str(",\n");
1943                write_field_name(out, indent + 1, "member");
1944                member.write_json(out, indent + 1);
1945                out.push_str(",\n");
1946                write_field_name(out, indent + 1, "arguments");
1947                write_array(out, indent + 1, arguments, |out, indent, arg| {
1948                    arg.write_json(out, indent)
1949                });
1950                out.push('\n');
1951                write_object_end(out, indent);
1952            }
1953            Expression::Index {
1954                line,
1955                object,
1956                index,
1957                ..
1958            } => {
1959                write_object_start(out);
1960                write_string_field(out, indent + 1, "type", "IndexExpression", true);
1961                write_number_field(out, indent + 1, "line", *line, true);
1962                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1963                write_field_name(out, indent + 1, "object");
1964                object.write_json(out, indent + 1);
1965                out.push_str(",\n");
1966                write_field_name(out, indent + 1, "index");
1967                index.write_json(out, indent + 1);
1968                out.push('\n');
1969                write_object_end(out, indent);
1970            }
1971            Expression::Slice {
1972                line,
1973                object,
1974                start,
1975                end,
1976                ..
1977            } => {
1978                write_object_start(out);
1979                write_string_field(out, indent + 1, "type", "SliceExpression", true);
1980                write_number_field(out, indent + 1, "line", *line, true);
1981                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1982                write_field_name(out, indent + 1, "object");
1983                object.write_json(out, indent + 1);
1984                out.push_str(",\n");
1985                write_optional_boxed_expr_field(out, indent + 1, "start", start.as_ref(), true);
1986                write_optional_boxed_expr_field(out, indent + 1, "end", end.as_ref(), false);
1987                write_object_end(out, indent);
1988            }
1989            Expression::DictAccess {
1990                line, object, key, ..
1991            } => {
1992                write_object_start(out);
1993                write_string_field(out, indent + 1, "type", "DictAccessExpression", true);
1994                write_number_field(out, indent + 1, "line", *line, true);
1995                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
1996                write_field_name(out, indent + 1, "object");
1997                object.write_json(out, indent + 1);
1998                out.push_str(",\n");
1999                write_field_name(out, indent + 1, "key");
2000                key.write_json(out, indent + 1);
2001                out.push('\n');
2002                write_object_end(out, indent);
2003            }
2004            Expression::PostfixUpdate {
2005                line,
2006                operator,
2007                argument,
2008                ..
2009            } => {
2010                write_object_start(out);
2011                write_string_field(out, indent + 1, "type", "PostfixUpdateExpression", true);
2012                write_number_field(out, indent + 1, "line", *line, true);
2013                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
2014                write_string_field(out, indent + 1, "operator", operator, true);
2015                write_string_field(
2016                    out,
2017                    indent + 1,
2018                    "operator_kind",
2019                    operator_kind(operator),
2020                    true,
2021                );
2022                write_field_name(out, indent + 1, "argument");
2023                argument.write_json(out, indent + 1);
2024                out.push('\n');
2025                write_object_end(out, indent);
2026            }
2027            Expression::Lambda {
2028                line,
2029                params,
2030                body,
2031                is_async,
2032                ..
2033            } => {
2034                write_object_start(out);
2035                write_string_field(out, indent + 1, "type", "LambdaExpression", true);
2036                write_number_field(out, indent + 1, "line", *line, true);
2037                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
2038                write_bool_field(out, indent + 1, "is_async", *is_async, true);
2039                write_field_name(out, indent + 1, "params");
2040                write_array(out, indent + 1, params, |out, indent, param| {
2041                    param.write_json(out, indent)
2042                });
2043                out.push_str(",\n");
2044                write_field_name(out, indent + 1, "body");
2045                body.write_json(out, indent + 1);
2046                out.push('\n');
2047                write_object_end(out, indent);
2048            }
2049            Expression::FunctionExpression {
2050                line,
2051                params,
2052                return_type,
2053                body,
2054                is_async,
2055                ..
2056            } => {
2057                write_object_start(out);
2058                write_string_field(out, indent + 1, "type", "FunctionExpression", true);
2059                write_number_field(out, indent + 1, "line", *line, true);
2060                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
2061                write_bool_field(out, indent + 1, "is_async", *is_async, true);
2062                write_optional_string_field(
2063                    out,
2064                    indent + 1,
2065                    "return_type",
2066                    return_type.as_deref(),
2067                    true,
2068                );
2069                write_field_name(out, indent + 1, "params");
2070                write_array(out, indent + 1, params, |out, indent, param| {
2071                    param.write_json(out, indent)
2072                });
2073                out.push_str(",\n");
2074                write_field_name(out, indent + 1, "body");
2075                body.write_json(out, indent + 1);
2076                out.push('\n');
2077                write_object_end(out, indent);
2078            }
2079            Expression::LetExpression {
2080                line,
2081                kind,
2082                declared_type,
2083                name,
2084                init,
2085                ..
2086            } => {
2087                write_object_start(out);
2088                write_string_field(out, indent + 1, "type", "LetExpression", true);
2089                write_number_field(out, indent + 1, "line", *line, true);
2090                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
2091                write_string_field(out, indent + 1, "kind", kind, true);
2092                write_optional_string_field(
2093                    out,
2094                    indent + 1,
2095                    "declared_type",
2096                    declared_type.as_deref(),
2097                    true,
2098                );
2099                write_string_field(out, indent + 1, "name", name, true);
2100                write_bool_field(
2101                    out,
2102                    indent + 1,
2103                    "is_weak_storage",
2104                    self.is_weak_storage(),
2105                    true,
2106                );
2107                write_optional_bool_field(
2108                    out,
2109                    indent + 1,
2110                    "runtime_typecheck_required",
2111                    self.runtime_typecheck_required(),
2112                    true,
2113                );
2114                match init {
2115                    Some(init) => {
2116                        write_field_name(out, indent + 1, "init");
2117                        init.write_json(out, indent + 1);
2118                        out.push('\n');
2119                    }
2120                    None => write_null_field(out, indent + 1, "init", false),
2121                }
2122                write_object_end(out, indent);
2123            }
2124            Expression::TryExpression {
2125                line,
2126                body,
2127                handlers,
2128                ..
2129            } => {
2130                write_object_start(out);
2131                write_string_field(out, indent + 1, "type", "TryExpression", true);
2132                write_number_field(out, indent + 1, "line", *line, true);
2133                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
2134                write_field_name(out, indent + 1, "body");
2135                body.write_json(out, indent + 1);
2136                out.push_str(",\n");
2137                write_field_name(out, indent + 1, "handlers");
2138                write_array(out, indent + 1, handlers, |out, indent, clause| {
2139                    clause.write_json(out, indent)
2140                });
2141                out.push('\n');
2142                write_object_end(out, indent);
2143            }
2144            Expression::DoExpression { line, body, .. } => {
2145                write_object_start(out);
2146                write_string_field(out, indent + 1, "type", "DoExpression", true);
2147                write_number_field(out, indent + 1, "line", *line, true);
2148                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
2149                write_field_name(out, indent + 1, "body");
2150                body.write_json(out, indent + 1);
2151                out.push('\n');
2152                write_object_end(out, indent);
2153            }
2154            Expression::AwaitExpression { line, body, .. } => {
2155                write_object_start(out);
2156                write_string_field(out, indent + 1, "type", "AwaitExpression", true);
2157                write_number_field(out, indent + 1, "line", *line, true);
2158                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
2159                write_field_name(out, indent + 1, "body");
2160                body.write_json(out, indent + 1);
2161                out.push('\n');
2162                write_object_end(out, indent);
2163            }
2164            Expression::SpawnExpression { line, body, .. } => {
2165                write_object_start(out);
2166                write_string_field(out, indent + 1, "type", "SpawnExpression", true);
2167                write_number_field(out, indent + 1, "line", *line, true);
2168                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
2169                write_field_name(out, indent + 1, "body");
2170                body.write_json(out, indent + 1);
2171                out.push('\n');
2172                write_object_end(out, indent);
2173            }
2174            Expression::SuperCall {
2175                line, arguments, ..
2176            } => {
2177                write_object_start(out);
2178                write_string_field(out, indent + 1, "type", "SuperCallExpression", true);
2179                write_number_field(out, indent + 1, "line", *line, true);
2180                write_optional_string_field(out, indent + 1, "inferred_type", inferred_type, true);
2181                write_field_name(out, indent + 1, "arguments");
2182                write_array(out, indent + 1, arguments, |out, indent, arg| {
2183                    arg.write_json(out, indent)
2184                });
2185                out.push('\n');
2186                write_object_end(out, indent);
2187            }
2188        }
2189    }
2190}
2191
2192impl TemplatePart {
2193    fn write_json(&self, out: &mut String, indent: usize) {
2194        match self {
2195            TemplatePart::Text { line, value, .. } => {
2196                write_object_start(out);
2197                write_string_field(out, indent + 1, "type", "TemplateText", true);
2198                write_number_field(out, indent + 1, "line", *line, true);
2199                write_string_field(out, indent + 1, "value", value, false);
2200                write_object_end(out, indent);
2201            }
2202            TemplatePart::Expression {
2203                line, expression, ..
2204            } => {
2205                write_object_start(out);
2206                write_string_field(out, indent + 1, "type", "TemplateExpression", true);
2207                write_number_field(out, indent + 1, "line", *line, true);
2208                write_field_name(out, indent + 1, "expression");
2209                expression.write_json(out, indent + 1);
2210                out.push('\n');
2211                write_object_end(out, indent);
2212            }
2213        }
2214    }
2215}
2216
2217impl DictEntry {
2218    fn write_json(&self, out: &mut String, indent: usize) {
2219        write_object_start(out);
2220        write_number_field(out, indent + 1, "line", self.line, true);
2221        write_field_name(out, indent + 1, "key");
2222        self.key.write_json(out, indent + 1);
2223        out.push_str(",\n");
2224        write_field_name(out, indent + 1, "value");
2225        self.value.write_json(out, indent + 1);
2226        out.push('\n');
2227        write_object_end(out, indent);
2228    }
2229}
2230
2231impl DictKey {
2232    pub fn line(&self) -> usize {
2233        match self {
2234            DictKey::Identifier { line, .. } => *line,
2235            DictKey::StringLiteral { line, .. } => *line,
2236            DictKey::Expression { line, .. } => *line,
2237        }
2238    }
2239
2240    pub fn source_file(&self) -> Option<&str> {
2241        match self {
2242            DictKey::Identifier { source_file, .. }
2243            | DictKey::StringLiteral { source_file, .. }
2244            | DictKey::Expression { source_file, .. } => source_file.as_deref(),
2245        }
2246    }
2247
2248    fn write_json(&self, out: &mut String, indent: usize) {
2249        match self {
2250            DictKey::Identifier { line, name, .. } => {
2251                write_simple_object(out, indent, "IdentifierKey", *line, "name", name)
2252            }
2253            DictKey::StringLiteral { line, value, .. } => {
2254                write_simple_object(out, indent, "StringKey", *line, "value", value)
2255            }
2256            DictKey::Expression {
2257                line, expression, ..
2258            } => {
2259                write_object_start(out);
2260                write_string_field(out, indent + 1, "type", "ExpressionKey", true);
2261                write_number_field(out, indent + 1, "line", *line, true);
2262                write_field_name(out, indent + 1, "expression");
2263                expression.write_json(out, indent + 1);
2264                out.push('\n');
2265                write_object_end(out, indent);
2266            }
2267        }
2268    }
2269}
2270
2271impl CallArgument {
2272    pub fn line(&self) -> usize {
2273        match self {
2274            CallArgument::Positional { line, .. } => *line,
2275            CallArgument::Spread { line, .. } => *line,
2276            CallArgument::Named { line, .. } => *line,
2277        }
2278    }
2279
2280    fn write_json(&self, out: &mut String, indent: usize) {
2281        match self {
2282            CallArgument::Positional { line, value, .. } => {
2283                write_object_start(out);
2284                write_string_field(out, indent + 1, "type", "PositionalArgument", true);
2285                write_number_field(out, indent + 1, "line", *line, true);
2286                write_field_name(out, indent + 1, "value");
2287                value.write_json(out, indent + 1);
2288                out.push('\n');
2289                write_object_end(out, indent);
2290            }
2291            CallArgument::Spread { line, value, .. } => {
2292                write_object_start(out);
2293                write_string_field(out, indent + 1, "type", "SpreadArgument", true);
2294                write_number_field(out, indent + 1, "line", *line, true);
2295                write_field_name(out, indent + 1, "value");
2296                value.write_json(out, indent + 1);
2297                out.push('\n');
2298                write_object_end(out, indent);
2299            }
2300            CallArgument::Named {
2301                line, name, value, ..
2302            } => {
2303                write_object_start(out);
2304                write_string_field(out, indent + 1, "type", "NamedArgument", true);
2305                write_number_field(out, indent + 1, "line", *line, true);
2306                write_field_name(out, indent + 1, "name");
2307                name.write_json(out, indent + 1);
2308                out.push_str(",\n");
2309                write_field_name(out, indent + 1, "value");
2310                value.write_json(out, indent + 1);
2311                out.push('\n');
2312                write_object_end(out, indent);
2313            }
2314        }
2315    }
2316}
2317
2318fn write_array<T>(
2319    out: &mut String,
2320    indent: usize,
2321    items: &[T],
2322    mut write_item: impl FnMut(&mut String, usize, &T),
2323) {
2324    if items.is_empty() {
2325        out.push_str("[]");
2326        return;
2327    }
2328    out.push_str("[\n");
2329    for (index, item) in items.iter().enumerate() {
2330        write_indent(out, indent + 1);
2331        write_item(out, indent + 1, item);
2332        if index + 1 != items.len() {
2333            out.push(',');
2334        }
2335        out.push('\n');
2336    }
2337    write_indent(out, indent);
2338    out.push(']');
2339}
2340
2341fn write_string_array(out: &mut String, indent: usize, items: &[String]) {
2342    write_array(out, indent, items, |out, _indent, item| {
2343        write_json_string(out, item)
2344    });
2345}
2346
2347fn operator_kind(operator: &str) -> &str {
2348    match operator {
2349        "+" => "plus",
2350        "-" => "minus",
2351        "×" | "*" => "multiply",
2352        "÷" | "/" => "divide",
2353        "mod" => "modulo",
2354        "**" => "exponent",
2355        "=" => "numeric_equal",
2356        "≠" => "numeric_not_equal",
2357        "<" => "less_than",
2358        ">" => "greater_than",
2359        "≤" | "<=" => "less_equal",
2360        "≥" | ">=" => "greater_equal",
2361        "≶" | "<=>" | "≷" => "numeric_compare",
2362        "≡" | "==" => "strict_equal",
2363        "≢" | "!=" => "strict_not_equal",
2364        "default" => "default",
2365        "⋀" | "and" => "logical_and",
2366        "⋀?" | "and?" => "logical_and_value",
2367        "⋁" | "or" => "logical_or",
2368        "⋁?" | "or?" => "logical_or_value",
2369        "⊻" | "xor" => "logical_xor",
2370        "⊻?" | "xor?" => "logical_xor_value",
2371        "⊽" | "nor" => "logical_nor",
2372        "⊽?" | "nor?" => "logical_nor_value",
2373        "↔" | "xnor" => "logical_xnor",
2374        "↔?" | "xnor?" => "logical_xnor_value",
2375        "⊼" | "nand" => "logical_nand",
2376        "⊼?" | "nand?" => "logical_nand_value",
2377        "⊨" | "onlyif" => "logical_onlyif",
2378        "⊨?" | "onlyif?" => "logical_onlyif_value",
2379        "⊭" | "butnot" => "logical_butnot",
2380        "⊭?" | "butnot?" => "logical_butnot_value",
2381        "¬" | "not" | "!" => "logical_not",
2382        "√" | "sqrt" => "sqrt",
2383        "⋃" | "union" => "set_union",
2384        "⋂" | "intersection" => "set_intersection",
2385        "∖" | "\\" => "set_difference",
2386        "∈" | "in" => "membership",
2387        "∉" => "not_membership",
2388        "⊂" | "subsetof" => "subset",
2389        "⊃" | "supersetof" => "superset",
2390        "⊂⊃" | "equivalentof" => "set_equivalent",
2391        "@" => "path_first",
2392        "@@" => "path_all",
2393        "@?" => "path_exists",
2394        ":=" => "assign",
2395        "+=" => "add_assign",
2396        "-=" => "subtract_assign",
2397        "×=" | "*=" => "multiply_assign",
2398        "÷=" | "/=" => "divide_assign",
2399        "_=" => "concat_assign",
2400        "~=" => "regex_replace_assign",
2401        "**=" => "exponent_assign",
2402        "?:=" => "defined_assign",
2403        "++" => "increment",
2404        "--" => "decrement",
2405        other => other,
2406    }
2407}
2408
2409fn write_optional_expr_field(
2410    out: &mut String,
2411    indent: usize,
2412    key: &str,
2413    expr: Option<&Expression>,
2414    trailing_comma: bool,
2415) {
2416    match expr {
2417        Some(expr) => {
2418            write_field_name(out, indent, key);
2419            expr.write_json(out, indent);
2420            if trailing_comma {
2421                out.push_str(",\n");
2422            } else {
2423                out.push('\n');
2424            }
2425        }
2426        None => write_null_field(out, indent, key, trailing_comma),
2427    }
2428}
2429
2430fn write_optional_boxed_expr_field(
2431    out: &mut String,
2432    indent: usize,
2433    key: &str,
2434    expr: Option<&Box<Expression>>,
2435    trailing_comma: bool,
2436) {
2437    write_optional_expr_field(out, indent, key, expr.map(Box::as_ref), trailing_comma);
2438}
2439
2440fn write_string_field(
2441    out: &mut String,
2442    indent: usize,
2443    key: &str,
2444    value: &str,
2445    trailing_comma: bool,
2446) {
2447    write_field_name(out, indent, key);
2448    write_json_string(out, value);
2449    if trailing_comma {
2450        out.push_str(",\n");
2451    } else {
2452        out.push('\n');
2453    }
2454}
2455
2456fn write_number_field(
2457    out: &mut String,
2458    indent: usize,
2459    key: &str,
2460    value: usize,
2461    trailing_comma: bool,
2462) {
2463    write_field_name(out, indent, key);
2464    out.push_str(&value.to_string());
2465    if trailing_comma {
2466        out.push_str(",\n");
2467    } else {
2468        out.push('\n');
2469    }
2470}
2471
2472fn write_optional_string_field(
2473    out: &mut String,
2474    indent: usize,
2475    key: &str,
2476    value: Option<&str>,
2477    trailing_comma: bool,
2478) {
2479    match value {
2480        Some(value) => write_string_field(out, indent, key, value, trailing_comma),
2481        None => write_null_field(out, indent, key, trailing_comma),
2482    }
2483}
2484
2485fn write_optional_number_field(
2486    out: &mut String,
2487    indent: usize,
2488    key: &str,
2489    value: Option<usize>,
2490    trailing_comma: bool,
2491) {
2492    write_field_name(out, indent, key);
2493    match value {
2494        Some(value) => out.push_str(&value.to_string()),
2495        None => out.push_str("null"),
2496    }
2497    if trailing_comma {
2498        out.push_str(",\n");
2499    } else {
2500        out.push('\n');
2501    }
2502}
2503
2504fn write_bool_field(out: &mut String, indent: usize, key: &str, value: bool, trailing_comma: bool) {
2505    write_field_name(out, indent, key);
2506    out.push_str(if value { "true" } else { "false" });
2507    if trailing_comma {
2508        out.push_str(",\n");
2509    } else {
2510        out.push('\n');
2511    }
2512}
2513
2514fn write_optional_bool_field(
2515    out: &mut String,
2516    indent: usize,
2517    key: &str,
2518    value: Option<bool>,
2519    trailing_comma: bool,
2520) {
2521    write_field_name(out, indent, key);
2522    match value {
2523        Some(true) => out.push_str("true"),
2524        Some(false) => out.push_str("false"),
2525        None => out.push_str("null"),
2526    }
2527    if trailing_comma {
2528        out.push_str(",\n");
2529    } else {
2530        out.push('\n');
2531    }
2532}
2533
2534fn write_null_field(out: &mut String, indent: usize, key: &str, trailing_comma: bool) {
2535    write_field_name(out, indent, key);
2536    out.push_str("null");
2537    if trailing_comma {
2538        out.push_str(",\n");
2539    } else {
2540        out.push('\n');
2541    }
2542}
2543
2544fn write_field_name(out: &mut String, indent: usize, key: &str) {
2545    write_indent(out, indent);
2546    write_json_string(out, key);
2547    out.push_str(": ");
2548}
2549
2550fn write_indent(out: &mut String, indent: usize) {
2551    for _ in 0..indent {
2552        out.push_str("  ");
2553    }
2554}
2555
2556fn write_json_string(out: &mut String, value: &str) {
2557    out.push('"');
2558    for ch in value.chars() {
2559        match ch {
2560            '"' => out.push_str("\\\""),
2561            '\\' => out.push_str("\\\\"),
2562            '\n' => out.push_str("\\n"),
2563            '\r' => out.push_str("\\r"),
2564            '\t' => out.push_str("\\t"),
2565            _ => out.push(ch),
2566        }
2567    }
2568    out.push('"');
2569}
2570
2571fn bytes_to_hex(bytes: &[u8]) -> String {
2572    const HEX: &[u8; 16] = b"0123456789abcdef";
2573    let mut out = String::with_capacity(bytes.len() * 2);
2574    for byte in bytes {
2575        out.push(HEX[(byte >> 4) as usize] as char);
2576        out.push(HEX[(byte & 0x0f) as usize] as char);
2577    }
2578    out
2579}
2580
2581fn write_object_start(out: &mut String) {
2582    out.push_str("{\n");
2583}
2584
2585fn write_object_end(out: &mut String, indent: usize) {
2586    write_indent(out, indent);
2587    out.push('}');
2588}
2589
2590fn write_simple_object(
2591    out: &mut String,
2592    indent: usize,
2593    type_name: &str,
2594    line: usize,
2595    key: &str,
2596    value: &str,
2597) {
2598    write_object_start(out);
2599    write_string_field(out, indent + 1, "type", type_name, true);
2600    write_number_field(out, indent + 1, "line", line, true);
2601    write_string_field(out, indent + 1, key, value, false);
2602    write_object_end(out, indent);
2603}