Skip to main content

qanglang_core/frontend/
nodes.rs

1use crate::{
2    StringHandle, Token,
3    frontend::{ast_node_arena::NodeId, node_array_arena::NodeArrayId},
4};
5use std::convert::TryFrom;
6
7#[derive(Debug, Clone, PartialEq, Default, Copy)]
8pub struct SourceSpan {
9    pub start: usize,
10    pub end: usize,
11}
12
13impl SourceSpan {
14    pub fn new(start: usize, end: usize) -> Self {
15        Self { start, end }
16    }
17
18    pub fn from_token(token: &Token) -> Self {
19        Self {
20            start: token.start,
21            end: token.end,
22        }
23    }
24
25    pub fn combine(start: SourceSpan, end: SourceSpan) -> Self {
26        Self {
27            start: start.start,
28            end: end.end,
29        }
30    }
31}
32
33/// Assignment operators
34#[derive(Debug, Clone, PartialEq, Copy)]
35pub enum AssignmentOperator {
36    Assign,         // =
37    AddAssign,      // +=
38    SubtractAssign, // -=
39    MultiplyAssign, // *=
40    DivideAssign,   // /=
41    ModuloAssign,   // %=
42}
43
44#[derive(Debug, Clone, PartialEq, Copy)]
45pub enum ComparisonOperator {
46    Greater,      // >
47    GreaterEqual, // >=
48    Less,         // <
49    LessEqual,    // <=
50}
51
52#[derive(Debug, Clone, PartialEq, Copy)]
53pub enum EqualityOperator {
54    Equal,    // ==
55    NotEqual, // !=
56    Is,       // is
57}
58
59#[derive(Debug, Clone, PartialEq, Copy)]
60pub enum FactorOperator {
61    Divide,   // /
62    Multiply, // *
63    Modulo,   // %
64}
65
66#[derive(Debug, Clone, PartialEq, Copy)]
67pub enum TermOperator {
68    Add,      // +
69    Subtract, // -
70}
71
72#[derive(Debug, Clone, PartialEq, Copy)]
73pub enum UnaryOperator {
74    Minus, // -
75    Not,   // !
76}
77
78#[derive(Debug, Clone, PartialEq, Copy)]
79pub enum AstNode {
80    Module(Module),
81    Class(ClassDeclNode),
82    Function(FunctionDeclNode),
83    Identifier(IdentifierNode),
84    FieldDecl(FieldDeclNode),
85    FunctionDecl(FunctionDeclNode),
86    FunctionExpr(FunctionExprNode),
87    NumberLiteral(NumberLiteralNode),
88    StringLiteral(StringLiteralNode),
89    BooleanLiteral(BooleanLiteralNode),
90    NilLiteral(NilLiteralNode),
91    ThisExpr(ThisExprNode),
92    SuperExpr(SuperExprNode),
93    AssignmentExpr(AssignmentExprNode),
94    PipeExpr(PipeExprNode),
95    TernaryExpr(TernaryExprNode),
96    LogicalOrExpr(LogicalOrExprNode),
97    LogicalAndExpr(LogicalAndExprNode),
98    EqualityExpr(EqualityExprNode),
99    ComparisonExpr(ComparisonExprNode),
100    TermExpr(TermExprNode),
101    FactorExpr(FactorExprNode),
102    UnaryExpr(UnaryExprNode),
103    CallExpr(CallExprNode),
104    CallOperation(CallNode),
105    PropertyAccess(PropertyNode),
106    PropertyAssignment(PropertyAssignmentNode),
107    OptionalPropertyAccess(OptionalPropertyNode),
108    IndexAccess(IndexNode),
109    IndexAssignment(IndexAssignmentNode),
110    ArrayLiteralExpr(ArrayLiteralExprNode),
111    ObjectLiteralExpr(ObjectLiteralExprNode),
112    ObjectEntry(ObjectEntryNode),
113    MapExpr(MapExprNode),
114    OptionalMapExpr(OptionalMapExprNode),
115    WhenExpr(WhenExprNode),
116    WhenBranch(WhenBranchNode),
117    ExprStmt(ExprStmtNode),
118    GroupingExpr(GroupingExprNode),
119    LambdaDecl(LambdaDeclNode),
120    LambdaExpr(LambdaExprNode),
121    ReturnStmt(ReturnStmtNode),
122    BreakStmt(BreakStmtNode),
123    ContinueStmt(ContinueStmtNode),
124    BlockStmt(BlockStmtNode),
125    IfStmt(IfStmtNode),
126    WhileStmt(WhileStmtNode),
127    ForStmt(ForStmtNode),
128    VariableDecl(VariableDeclNode),
129    ImportModuleDecl(ImportModuleDeclNode),
130}
131
132impl AstNode {
133    pub fn span(&self) -> SourceSpan {
134        match self {
135            AstNode::Module(node) => node.span,
136            AstNode::Class(node) => node.span,
137            AstNode::Function(node) => node.span,
138            AstNode::Identifier(node) => node.span,
139            AstNode::FieldDecl(node) => node.span,
140            AstNode::FunctionDecl(node) => node.span,
141            AstNode::FunctionExpr(node) => node.span,
142            AstNode::NumberLiteral(node) => node.span,
143            AstNode::StringLiteral(node) => node.span,
144            AstNode::BooleanLiteral(node) => node.span,
145            AstNode::NilLiteral(node) => node.span,
146            AstNode::ThisExpr(node) => node.span,
147            AstNode::SuperExpr(node) => node.span,
148            AstNode::AssignmentExpr(node) => node.span,
149            AstNode::PipeExpr(node) => node.span,
150            AstNode::TernaryExpr(node) => node.span,
151            AstNode::LogicalOrExpr(node) => node.span,
152            AstNode::LogicalAndExpr(node) => node.span,
153            AstNode::EqualityExpr(node) => node.span,
154            AstNode::ComparisonExpr(node) => node.span,
155            AstNode::TermExpr(node) => node.span,
156            AstNode::FactorExpr(node) => node.span,
157            AstNode::UnaryExpr(node) => node.span,
158            AstNode::CallExpr(node) => node.span,
159            AstNode::CallOperation(node) => node.span,
160            AstNode::PropertyAccess(node) => node.span,
161            AstNode::PropertyAssignment(node) => node.span,
162            AstNode::OptionalPropertyAccess(node) => node.span,
163            AstNode::IndexAccess(node) => node.span,
164            AstNode::IndexAssignment(node) => node.span,
165            AstNode::ArrayLiteralExpr(node) => node.span,
166            AstNode::ObjectLiteralExpr(node) => node.span,
167            AstNode::ObjectEntry(node) => node.span,
168            AstNode::MapExpr(node) => node.span,
169            AstNode::OptionalMapExpr(node) => node.span,
170            AstNode::WhenExpr(node) => node.span,
171            AstNode::WhenBranch(node) => node.span,
172            AstNode::ExprStmt(node) => node.span,
173            AstNode::GroupingExpr(node) => node.span,
174            AstNode::LambdaDecl(node) => node.span,
175            AstNode::LambdaExpr(node) => node.span,
176            AstNode::ReturnStmt(node) => node.span,
177            AstNode::BreakStmt(node) => node.span,
178            AstNode::ContinueStmt(node) => node.span,
179            AstNode::BlockStmt(node) => node.span,
180            AstNode::IfStmt(node) => node.span,
181            AstNode::WhileStmt(node) => node.span,
182            AstNode::ForStmt(node) => node.span,
183            AstNode::VariableDecl(node) => node.span,
184            AstNode::ImportModuleDecl(node) => node.span,
185        }
186    }
187}
188
189/// Root AST node representing a complete program
190#[derive(Debug, Clone, PartialEq, Copy)]
191pub struct Module {
192    pub decls: NodeArrayId, // [DeclNode]
193    pub span: SourceSpan,
194}
195
196#[derive(Debug, Clone, PartialEq, Copy)]
197pub struct IdentifierNode {
198    pub name: StringHandle,
199    pub span: SourceSpan,
200}
201
202/// Number literal
203#[derive(Debug, Clone, PartialEq, Copy)]
204pub struct NumberLiteralNode {
205    pub value: f64,
206    pub span: SourceSpan,
207}
208
209/// String literal
210#[derive(Debug, Clone, PartialEq, Copy)]
211pub struct StringLiteralNode {
212    pub value: StringHandle,
213    pub span: SourceSpan,
214}
215
216/// Boolean literal
217#[derive(Debug, Clone, PartialEq, Copy)]
218pub struct BooleanLiteralNode {
219    pub value: bool,
220    pub span: SourceSpan,
221}
222
223/// Nil literal
224#[derive(Debug, Clone, PartialEq, Copy)]
225pub struct NilLiteralNode {
226    pub span: SourceSpan,
227}
228
229/// This expression
230#[derive(Debug, Clone, PartialEq, Copy)]
231pub struct ThisExprNode {
232    pub span: SourceSpan,
233}
234
235/// Super method access: "super.method"
236#[derive(Debug, Clone, PartialEq, Copy)]
237pub struct SuperExprNode {
238    pub method: NodeId, // IdentifierNode
239    pub span: SourceSpan,
240}
241
242/// Grouping expression: ( expression )
243#[derive(Debug, Clone, PartialEq, Copy)]
244pub struct GroupingExprNode {
245    pub expr: NodeId, // ExprNode
246    pub span: SourceSpan,
247}
248
249/// Array literal: [ ( expression ( , expression )* )? ]
250#[derive(Debug, Clone, PartialEq, Copy)]
251pub struct ArrayLiteralExprNode {
252    pub elements: NodeArrayId, // [ExprNode]
253    pub span: SourceSpan,
254}
255
256#[derive(Debug, Clone, PartialEq, Copy)]
257pub struct ObjectLiteralExprNode {
258    pub entries: NodeArrayId, // [ObjectEntryNode]
259    pub span: SourceSpan,
260}
261
262#[derive(Debug, Clone, PartialEq, Copy)]
263pub struct ObjectEntryNode {
264    pub key: NodeId,   // IdentifierNode
265    pub value: NodeId, // ExprNode
266    pub span: SourceSpan,
267}
268
269#[derive(Debug, Clone, PartialEq, Copy)]
270pub struct ImportModuleDeclNode {
271    pub path: StringHandle,
272    pub name: NodeId,                  // IdentifierNode
273    pub path_literal_span: SourceSpan, // Span of the string literal of the path
274    pub span: SourceSpan,
275}
276
277/// Class declaration: class IDENTIFIER ( : IDENTIFIER )? { classMember* }
278#[derive(Debug, Clone, PartialEq, Copy)]
279pub struct ClassDeclNode {
280    pub name: NodeId,               // IdentifierNode
281    pub superclass: Option<NodeId>, // IdentifierNode
282    pub members: NodeArrayId,       // [FunctionExprNode | FieldDeclNode]
283    pub span: SourceSpan,
284}
285
286/// Field declaration: IDENTIFIER ( = expression )? ;
287#[derive(Debug, Clone, PartialEq, Copy)]
288pub struct FieldDeclNode {
289    pub name: NodeId,                // IdentifierNode
290    pub initializer: Option<NodeId>, // ExprNode
291    pub span: SourceSpan,
292}
293
294/// Function declaration: fn function
295#[derive(Debug, Clone, PartialEq, Copy)]
296pub struct FunctionDeclNode {
297    pub function: NodeId, // FunctionExprNode
298    pub span: SourceSpan,
299}
300
301/// Function expression: IDENTIFIER ( parameters? ) block
302#[derive(Debug, Clone, PartialEq, Copy)]
303pub struct FunctionExprNode {
304    pub name: NodeId,            // IdentifierNode,
305    pub parameters: NodeArrayId, // [IdentifierNode]
306    pub body: NodeId,            // BlockStmtNode
307    pub span: SourceSpan,
308}
309
310/// Assignment expression: ( call . IDENTIFIER | IDENTIFIER ) ( = | += | -= | *= | /= | %= ) assignment | pipe
311#[derive(Debug, Clone, PartialEq, Copy)]
312pub struct AssignmentExprNode {
313    pub target: NodeId, // AssignmentTargetNode
314    pub operator: AssignmentOperator,
315    pub value: NodeId, // ExprNode
316    pub span: SourceSpan,
317}
318
319/// Property access for assignment: call . IDENTIFIER
320#[derive(Debug, Clone, PartialEq, Copy)]
321pub struct PropertyAssignmentNode {
322    pub property: NodeId, // IdentifierNode
323    pub object: NodeId,   // ExprNode
324    pub span: SourceSpan,
325}
326
327/// Index access for assignment: call [ expression ]
328#[derive(Debug, Clone, PartialEq, Copy)]
329pub struct IndexAssignmentNode {
330    pub object: NodeId, // ExprNode
331    pub index: NodeId,  // ExprNode
332    pub span: SourceSpan,
333}
334
335/// Pipe expression: ternary ( |> pipe )?
336#[derive(Debug, Clone, PartialEq, Copy)]
337pub struct PipeExprNode {
338    pub left: NodeId,  // ExprNode
339    pub right: NodeId, //ExprNode
340    pub span: SourceSpan,
341}
342
343/// Ternary expression: logicOr ( ? expression : ternary )?
344#[derive(Debug, Clone, PartialEq, Copy)]
345pub struct TernaryExprNode {
346    pub condition: NodeId, // ExprNode
347    pub then_expr: NodeId, // ExprNode
348    pub else_expr: NodeId, //ExprNode
349    pub span: SourceSpan,
350}
351
352/// Logical OR expression: logicAnd ( or logicAnd )*
353#[derive(Debug, Clone, PartialEq, Copy)]
354pub struct LogicalOrExprNode {
355    pub left: NodeId,  // ExprNode
356    pub right: NodeId, // ExprNode
357    pub span: SourceSpan,
358}
359
360/// Logical AND expression: equality ( and equality )*
361#[derive(Debug, Clone, PartialEq, Copy)]
362pub struct LogicalAndExprNode {
363    pub left: NodeId,  // ExprNode
364    pub right: NodeId, // ExprNode
365    pub span: SourceSpan,
366}
367
368/// Equality expression: comparison ( ( != | == ) comparison )*
369#[derive(Debug, Clone, PartialEq, Copy)]
370pub struct EqualityExprNode {
371    pub left: NodeId, // ExprNode
372    pub operator: EqualityOperator,
373    pub right: NodeId, // ExprNode
374    pub span: SourceSpan,
375}
376
377/// Comparison expression: term ( ( > | >= | < | <= ) term )*
378#[derive(Debug, Clone, PartialEq, Copy)]
379pub struct ComparisonExprNode {
380    pub left: NodeId, // ExprNode
381    pub operator: ComparisonOperator,
382    pub right: NodeId, // ExprNode
383    pub span: SourceSpan,
384}
385
386#[derive(Debug, Clone, PartialEq, Copy)]
387pub struct TermExprNode {
388    pub left: NodeId, // ExprNode
389    pub operator: TermOperator,
390    pub right: NodeId, // ExprNode
391    pub span: SourceSpan,
392}
393
394#[derive(Debug, Clone, PartialEq, Copy)]
395pub struct FactorExprNode {
396    pub left: NodeId, // ExprNode
397    pub operator: FactorOperator,
398    pub right: NodeId, // ExprNode
399    pub span: SourceSpan,
400}
401
402#[derive(Debug, Clone, PartialEq, Copy)]
403pub struct UnaryExprNode {
404    pub operator: UnaryOperator,
405    pub operand: NodeId, //ExprNode
406    pub span: SourceSpan,
407}
408
409/// Call expression: primary ( ( arguments? ) | . IDENTIFIER | .? IDENTIFIER | [ expression ] )*
410#[derive(Debug, Clone, PartialEq, Copy)]
411pub struct CallExprNode {
412    pub callee: NodeId,    // ExprNode
413    pub operation: NodeId, // CallOperationNode
414    pub span: SourceSpan,
415}
416
417#[derive(Debug, Clone, PartialEq, Copy)]
418pub struct CallNode {
419    pub args: NodeArrayId, // [ExprNode]
420    pub span: SourceSpan,
421}
422
423#[derive(Debug, Clone, PartialEq, Copy)]
424pub struct PropertyNode {
425    pub identifier: NodeId, // IdentifierNode
426    pub span: SourceSpan,
427}
428
429#[derive(Debug, Clone, PartialEq, Copy)]
430pub struct OptionalPropertyNode {
431    pub identifier: NodeId, // IdentifierNode
432    pub span: SourceSpan,
433}
434
435#[derive(Debug, Clone, PartialEq, Copy)]
436pub struct IndexNode {
437    pub index: NodeId, // ExprNode
438    pub span: SourceSpan,
439}
440
441/// Map call expression: target||parameter -> expression|
442#[derive(Debug, Clone, PartialEq, Copy)]
443pub struct MapExprNode {
444    pub parameter: NodeId, // IdentifierNode
445    pub body: NodeId,      // ExprNode
446    pub span: SourceSpan,
447}
448
449/// Optional map call expression: target?|parameter -> expression|
450#[derive(Debug, Clone, PartialEq, Copy)]
451pub struct OptionalMapExprNode {
452    pub parameter: NodeId, // IdentifierNode
453    pub body: NodeId,      //ExprNode
454    pub span: SourceSpan,
455}
456
457/// When expression: when ( value )? { branch* ( else => expression )? }
458#[derive(Debug, Clone, PartialEq, Copy)]
459pub struct WhenExprNode {
460    pub value: Option<NodeId>,       // Optional value being matched
461    pub branches: NodeArrayId,       // [WhenBranchNode]
462    pub else_branch: Option<NodeId>, // Optional else expression
463    pub span: SourceSpan,
464}
465
466/// When branch: condition => expression
467#[derive(Debug, Clone, PartialEq, Copy)]
468pub struct WhenBranchNode {
469    pub condition: NodeId,   // ExprNode - the left side (expression or pattern)
470    pub is_type_check: bool, // whether this uses the `is` operator
471    pub body: NodeId,        // ExprNode - the right side expression
472    pub span: SourceSpan,
473}
474
475/// Lambda declaration: var IDENTIFIER = lambda
476#[derive(Debug, Clone, PartialEq, Copy)]
477pub struct LambdaDeclNode {
478    pub name: NodeId,   // IdentifierNode
479    pub lambda: NodeId, // LambdaExprNode
480    pub span: SourceSpan,
481}
482
483/// Lambda expression: ( parameters? ) -> ( block | expression )
484#[derive(Debug, Clone, PartialEq, Copy)]
485pub struct LambdaExprNode {
486    pub parameters: NodeArrayId, // [IdentifierNode]
487    pub body: NodeId,            // BlockStmtNode | ExprNode
488    pub span: SourceSpan,
489}
490
491/// Variable declaration: var ( IDENTIFIER | destructurePattern ) ( = expression )? ;
492#[derive(Debug, Clone, PartialEq, Copy)]
493pub struct VariableDeclNode {
494    pub target: NodeId,              // IdentifierNode
495    pub initializer: Option<NodeId>, // ExprNode
496    pub span: SourceSpan,
497}
498
499/// Expression statement: expression ;
500#[derive(Debug, Clone, PartialEq, Copy)]
501pub struct ExprStmtNode {
502    pub expr: NodeId, // ExprNode
503    pub span: SourceSpan,
504}
505
506/// Block statement: { declaration* }
507#[derive(Debug, Clone, PartialEq, Copy)]
508pub struct BlockStmtNode {
509    pub decls: NodeArrayId, // [DeclNode]
510    pub span: SourceSpan,
511}
512
513/// If statement: if ( expression ) statement ( else statement )?
514#[derive(Debug, Clone, PartialEq, Copy)]
515pub struct IfStmtNode {
516    pub condition: NodeId,           // ExprNode
517    pub then_branch: NodeId,         // StmtNode
518    pub else_branch: Option<NodeId>, // StmtNode
519    pub span: SourceSpan,
520}
521
522/// While statement: while ( expression ) statement
523#[derive(Debug, Clone, PartialEq, Copy)]
524pub struct WhileStmtNode {
525    pub condition: NodeId, // ExprNode
526    pub body: NodeId,      // StmtNode
527    pub span: SourceSpan,
528}
529
530/// For statement: for ( ( varDecl | exprStmt | ; ) expression? ; expression? ) statement
531#[derive(Debug, Clone, PartialEq, Copy)]
532pub struct ForStmtNode {
533    pub initializer: Option<NodeId>,  // VariableDeclNode | ExprNode
534    pub condition: Option<NodeId>,    // ExprNode
535    pub afterthought: Option<NodeId>, // ExprNode
536    pub body: NodeId,                 // StmtNode
537    pub span: SourceSpan,
538}
539
540/// Break statement: break ;
541#[derive(Debug, Clone, PartialEq, Copy)]
542pub struct BreakStmtNode {
543    pub span: SourceSpan,
544}
545
546/// Continue statement: continue ;
547#[derive(Debug, Clone, PartialEq, Copy)]
548pub struct ContinueStmtNode {
549    pub span: SourceSpan,
550}
551
552/// Return statement: return expression? ;
553#[derive(Debug, Clone, PartialEq, Copy)]
554pub struct ReturnStmtNode {
555    pub value: Option<NodeId>, // ExprNode
556    pub span: SourceSpan,
557}
558
559#[derive(Debug, Clone, PartialEq)]
560pub struct NodeConversionError(String);
561
562#[derive(Debug, Clone, PartialEq, Copy)]
563
564pub enum DeclNode {
565    Class(ClassDeclNode),
566    Function(FunctionDeclNode),
567    Lambda(LambdaDeclNode),
568    Variable(VariableDeclNode),
569    Stmt(StmtNode),
570    Module(ImportModuleDeclNode),
571}
572
573impl DeclNode {
574    pub fn span(&self) -> SourceSpan {
575        match self {
576            Self::Class(class_decl) => class_decl.span,
577            Self::Function(func_decl) => func_decl.span,
578            Self::Lambda(lambda_decl) => lambda_decl.span,
579            Self::Variable(variable_decl) => variable_decl.span,
580            Self::Stmt(stmt) => stmt.span(),
581            Self::Module(import_decl) => import_decl.span,
582        }
583    }
584}
585
586impl TryFrom<AstNode> for DeclNode {
587    type Error = NodeConversionError;
588
589    fn try_from(value: AstNode) -> Result<Self, Self::Error> {
590        match value {
591            AstNode::Class(class_decl) => Ok(DeclNode::Class(class_decl)),
592            AstNode::FunctionDecl(func_decl) => Ok(DeclNode::Function(func_decl)),
593            AstNode::LambdaDecl(lambda_decl) => Ok(DeclNode::Lambda(lambda_decl)),
594            AstNode::VariableDecl(var_decl) => Ok(DeclNode::Variable(var_decl)),
595            AstNode::ImportModuleDecl(imprt_decl) => Ok(DeclNode::Module(imprt_decl)),
596            _ => Ok(DeclNode::Stmt(StmtNode::try_from(value)?)),
597        }
598    }
599}
600
601#[derive(Debug, Clone, PartialEq, Copy)]
602
603pub enum StmtNode {
604    Expr(ExprStmtNode),
605    Block(BlockStmtNode),
606    If(IfStmtNode),
607    While(WhileStmtNode),
608    For(ForStmtNode),
609    Break(BreakStmtNode),
610    Continue(ContinueStmtNode),
611    Return(ReturnStmtNode),
612}
613
614impl StmtNode {
615    pub fn span(&self) -> SourceSpan {
616        match self {
617            Self::Expr(expr_stmt) => expr_stmt.span,
618            Self::Block(block_stmt) => block_stmt.span,
619            Self::If(if_stmt) => if_stmt.span,
620            Self::While(while_stmt) => while_stmt.span,
621            Self::For(for_stmt) => for_stmt.span,
622            Self::Break(break_stmt) => break_stmt.span,
623            Self::Continue(continue_stmt) => continue_stmt.span,
624            Self::Return(return_stmt) => return_stmt.span,
625        }
626    }
627}
628
629impl TryFrom<AstNode> for StmtNode {
630    type Error = NodeConversionError;
631
632    fn try_from(value: AstNode) -> Result<Self, Self::Error> {
633        match value {
634            AstNode::ExprStmt(expr_stmt) => Ok(StmtNode::Expr(expr_stmt)),
635            AstNode::BlockStmt(block_stmt) => Ok(StmtNode::Block(block_stmt)),
636            AstNode::IfStmt(if_stmt) => Ok(StmtNode::If(if_stmt)),
637            AstNode::WhileStmt(while_stmt) => Ok(StmtNode::While(while_stmt)),
638            AstNode::ForStmt(for_stmt) => Ok(StmtNode::For(for_stmt)),
639            AstNode::BreakStmt(break_stmt) => Ok(StmtNode::Break(break_stmt)),
640            AstNode::ContinueStmt(continue_stmt) => Ok(StmtNode::Continue(continue_stmt)),
641            AstNode::ReturnStmt(return_stmt) => Ok(StmtNode::Return(return_stmt)),
642            _ => Err(NodeConversionError(format!(
643                "Cannot convert {:?} to StmtNode",
644                value
645            ))),
646        }
647    }
648}
649
650#[derive(Debug, Clone, PartialEq, Copy)]
651pub enum ExprNode {
652    Assignment(AssignmentExprNode),
653    Pipe(PipeExprNode),
654    Ternary(TernaryExprNode),
655    LogicalOr(LogicalOrExprNode),
656    LogicalAnd(LogicalAndExprNode),
657    Equality(EqualityExprNode),
658    Comparison(ComparisonExprNode),
659    Term(TermExprNode),
660    Factor(FactorExprNode),
661    Unary(UnaryExprNode),
662    Call(CallExprNode),
663    Primary(PrimaryNode),
664}
665
666impl ExprNode {
667    pub fn span(&self) -> SourceSpan {
668        match self {
669            Self::Assignment(assignment_expr) => assignment_expr.span,
670            Self::Pipe(pipe_expr) => pipe_expr.span,
671            Self::Ternary(ternary_expr) => ternary_expr.span,
672            Self::LogicalOr(logical_or_expr) => logical_or_expr.span,
673            Self::LogicalAnd(logical_and_expr) => logical_and_expr.span,
674            Self::Equality(equality_expr) => equality_expr.span,
675            Self::Comparison(comparison_expr) => comparison_expr.span,
676            Self::Term(term_expr) => term_expr.span,
677            Self::Factor(factor_expr) => factor_expr.span,
678            Self::Unary(unary_expr) => unary_expr.span,
679            Self::Call(call_expr) => call_expr.span,
680            Self::Primary(primary) => primary.span(),
681        }
682    }
683}
684
685impl TryFrom<AstNode> for ExprNode {
686    type Error = NodeConversionError;
687
688    fn try_from(value: AstNode) -> Result<Self, Self::Error> {
689        match value {
690            AstNode::AssignmentExpr(assignment_expr) => Ok(ExprNode::Assignment(assignment_expr)),
691            AstNode::PipeExpr(pipe_expr) => Ok(ExprNode::Pipe(pipe_expr)),
692            AstNode::TernaryExpr(ternary_expr) => Ok(ExprNode::Ternary(ternary_expr)),
693            AstNode::LogicalOrExpr(logical_or_expr) => Ok(ExprNode::LogicalOr(logical_or_expr)),
694            AstNode::LogicalAndExpr(logical_and_expr) => Ok(ExprNode::LogicalAnd(logical_and_expr)),
695            AstNode::EqualityExpr(equality_expr) => Ok(ExprNode::Equality(equality_expr)),
696            AstNode::ComparisonExpr(comparison_expr) => Ok(ExprNode::Comparison(comparison_expr)),
697            AstNode::TermExpr(term_expr) => Ok(ExprNode::Term(term_expr)),
698            AstNode::FactorExpr(factor_expr) => Ok(ExprNode::Factor(factor_expr)),
699            AstNode::UnaryExpr(unary_expr) => Ok(ExprNode::Unary(unary_expr)),
700            AstNode::CallExpr(call_expr) => Ok(ExprNode::Call(call_expr)),
701            _ => Ok(ExprNode::Primary(PrimaryNode::try_from(value)?)),
702        }
703    }
704}
705
706#[derive(Debug, Clone, PartialEq, Copy)]
707pub enum CallOperationNode {
708    Call(CallNode),
709    Property(PropertyNode),
710    OptionalProperty(OptionalPropertyNode),
711    Index(IndexNode),
712    Map(MapExprNode),
713    OptionalMap(OptionalMapExprNode),
714}
715
716impl CallOperationNode {
717    pub fn span(&self) -> SourceSpan {
718        match self {
719            Self::Call(call) => call.span,
720            Self::Property(property) => property.span,
721            Self::OptionalProperty(optional_property) => optional_property.span,
722            Self::Index(index) => index.span,
723            Self::Map(map_expr) => map_expr.span,
724            Self::OptionalMap(optional_map_expr) => optional_map_expr.span,
725        }
726    }
727}
728
729impl TryFrom<AstNode> for CallOperationNode {
730    type Error = NodeConversionError;
731
732    fn try_from(value: AstNode) -> Result<Self, Self::Error> {
733        match value {
734            AstNode::CallOperation(call) => Ok(CallOperationNode::Call(call)),
735            AstNode::PropertyAccess(property) => Ok(CallOperationNode::Property(property)),
736            AstNode::OptionalPropertyAccess(optional_property) => {
737                Ok(CallOperationNode::OptionalProperty(optional_property))
738            }
739            AstNode::IndexAccess(index_access) => Ok(CallOperationNode::Index(index_access)),
740            AstNode::MapExpr(map_expr) => Ok(CallOperationNode::Map(map_expr)),
741            AstNode::OptionalMapExpr(optional_map_expr) => {
742                Ok(CallOperationNode::OptionalMap(optional_map_expr))
743            }
744            _ => Err(NodeConversionError(format!(
745                "Cannot convert {:?} to CallOperationNode",
746                value
747            ))),
748        }
749    }
750}
751
752#[derive(Debug, Clone, PartialEq, Copy)]
753pub enum AssignmentTargetNode {
754    Identifier(IdentifierNode),
755    Property(PropertyAssignmentNode),
756    Index(IndexAssignmentNode),
757}
758
759impl AssignmentTargetNode {
760    pub fn span(&self) -> SourceSpan {
761        match self {
762            Self::Identifier(identifier) => identifier.span,
763            Self::Property(property) => property.span,
764            Self::Index(index) => index.span,
765        }
766    }
767}
768
769impl TryFrom<AstNode> for AssignmentTargetNode {
770    type Error = NodeConversionError;
771
772    fn try_from(value: AstNode) -> Result<Self, Self::Error> {
773        match value {
774            AstNode::PropertyAssignment(property) => Ok(AssignmentTargetNode::Property(property)),
775            AstNode::IndexAssignment(index) => Ok(AssignmentTargetNode::Index(index)),
776            AstNode::Identifier(identifier) => Ok(AssignmentTargetNode::Identifier(identifier)),
777            _ => Err(NodeConversionError(format!(
778                "Cannot convert {:?} to AssignmentTargetNode",
779                value
780            ))),
781        }
782    }
783}
784
785#[derive(Debug, Clone, PartialEq, Copy)]
786pub enum PrimaryNode {
787    Number(NumberLiteralNode),
788    String(StringLiteralNode),
789    Boolean(BooleanLiteralNode),
790    Nil(NilLiteralNode),
791    Identifier(IdentifierNode),
792    This(ThisExprNode),
793    Super(SuperExprNode),
794    Grouping(GroupingExprNode),
795    Lambda(LambdaExprNode),
796    Array(ArrayLiteralExprNode),
797    Object(ObjectLiteralExprNode),
798    When(WhenExprNode),
799}
800
801impl PrimaryNode {
802    pub fn span(&self) -> SourceSpan {
803        match self {
804            Self::Array(array_literal) => array_literal.span,
805            Self::Boolean(boolean_literal) => boolean_literal.span,
806            Self::Grouping(grouping_expr) => grouping_expr.span,
807            Self::Identifier(identifier) => identifier.span,
808            Self::Lambda(lambda_expr) => lambda_expr.span,
809            Self::Nil(nil_literal) => nil_literal.span,
810            Self::Number(number_literal) => number_literal.span,
811            Self::Object(object_literal) => object_literal.span,
812            Self::String(string_literal) => string_literal.span,
813            Self::Super(super_expr) => super_expr.span,
814            Self::This(this_expr) => this_expr.span,
815            Self::When(when_expr) => when_expr.span,
816        }
817    }
818}
819
820impl TryFrom<AstNode> for PrimaryNode {
821    type Error = NodeConversionError;
822
823    fn try_from(value: AstNode) -> Result<Self, Self::Error> {
824        match value {
825            AstNode::NumberLiteral(number_literal) => Ok(PrimaryNode::Number(number_literal)),
826            AstNode::StringLiteral(string_literal) => Ok(PrimaryNode::String(string_literal)),
827            AstNode::BooleanLiteral(boolean_literal) => Ok(PrimaryNode::Boolean(boolean_literal)),
828            AstNode::NilLiteral(nil_literal) => Ok(PrimaryNode::Nil(nil_literal)),
829            AstNode::Identifier(identifier_literal) => {
830                Ok(PrimaryNode::Identifier(identifier_literal))
831            }
832            AstNode::ThisExpr(this_expr) => Ok(PrimaryNode::This(this_expr)),
833            AstNode::SuperExpr(super_expr) => Ok(PrimaryNode::Super(super_expr)),
834            AstNode::GroupingExpr(grouping_expr) => Ok(PrimaryNode::Grouping(grouping_expr)),
835            AstNode::LambdaExpr(lambda_expr) => Ok(PrimaryNode::Lambda(lambda_expr)),
836            AstNode::ArrayLiteralExpr(array_expr) => Ok(PrimaryNode::Array(array_expr)),
837            AstNode::ObjectLiteralExpr(object_expr) => Ok(PrimaryNode::Object(object_expr)),
838            AstNode::WhenExpr(when_expr) => Ok(PrimaryNode::When(when_expr)),
839            _ => Err(NodeConversionError(format!(
840                "Cannot convert {:?} to PrimaryNode",
841                value
842            ))),
843        }
844    }
845}
846
847#[derive(Debug, Clone, PartialEq, Copy)]
848pub enum ClassMemberNode {
849    Method(FunctionExprNode),
850    Field(FieldDeclNode),
851}
852
853impl ClassMemberNode {
854    pub fn span(&self) -> SourceSpan {
855        match self {
856            Self::Method(method) => method.span,
857            Self::Field(field) => field.span,
858        }
859    }
860}
861
862impl TryFrom<AstNode> for ClassMemberNode {
863    type Error = NodeConversionError;
864
865    fn try_from(value: AstNode) -> Result<Self, Self::Error> {
866        match value {
867            AstNode::FieldDecl(field) => Ok(ClassMemberNode::Field(field)),
868            AstNode::FunctionExpr(method) => Ok(ClassMemberNode::Method(method)),
869            _ => Err(NodeConversionError(format!(
870                "Cannot convert {:?} to ClassMember",
871                value
872            ))),
873        }
874    }
875}
876
877#[derive(Debug, Clone, PartialEq, Copy)]
878pub enum LambdaBodyNode {
879    Block(BlockStmtNode),
880    Expr(ExprNode),
881}
882
883impl LambdaBodyNode {
884    pub fn span(&self) -> SourceSpan {
885        match self {
886            Self::Block(block) => block.span,
887            Self::Expr(expr) => expr.span(),
888        }
889    }
890}
891
892impl TryFrom<AstNode> for LambdaBodyNode {
893    type Error = NodeConversionError;
894
895    fn try_from(value: AstNode) -> Result<Self, Self::Error> {
896        match value {
897            AstNode::BlockStmt(block) => Ok(LambdaBodyNode::Block(block)),
898            _ => Ok(LambdaBodyNode::Expr(value.try_into()?)),
899        }
900    }
901}
902
903#[derive(Debug, Clone, PartialEq, Copy)]
904pub enum ForInitializerNode {
905    VarDecl(VariableDeclNode),
906    Expr(ExprNode),
907}
908
909impl ForInitializerNode {
910    pub fn span(&self) -> SourceSpan {
911        match self {
912            Self::VarDecl(var_decl) => var_decl.span,
913            Self::Expr(expr) => expr.span(),
914        }
915    }
916}
917
918impl TryFrom<AstNode> for ForInitializerNode {
919    type Error = NodeConversionError;
920
921    fn try_from(value: AstNode) -> Result<Self, Self::Error> {
922        match value {
923            AstNode::VariableDecl(var_decl) => Ok(ForInitializerNode::VarDecl(var_decl)),
924            _ => Ok(ForInitializerNode::Expr(value.try_into()?)),
925        }
926    }
927}