rocks_lang/
stmt.rs

1use crate::expr::Expr;
2use crate::token::Token;
3
4/// Represents an [`expression`](Stmt::Expression) statement's data in the language.
5#[derive(Debug, PartialEq, Clone)]
6pub struct ExpressionData {
7    pub expr: Expr,
8}
9
10/// Represents a [`function`](Stmt::Function) statement's data in the language.
11#[derive(Debug, PartialEq, Clone)]
12pub struct FunctionData {
13    /// The function's name.
14    pub name: Token,
15    /// The function's parameters.
16    pub params: Vec<Token>,
17    /// The function's body.
18    pub body: Vec<Stmt>,
19}
20
21/// Represents an [`if`](Stmt::If) statement's data in the language.
22#[derive(Debug, PartialEq, Clone)]
23pub struct IfData {
24    /// The condition to check.
25    pub condition: Expr,
26    /// The statement to execute if the condition is true.
27    pub then_branch: Box<Stmt>,
28    /// The statement to execute if the condition is false (optional).
29    pub else_branch: Option<Box<Stmt>>,
30}
31
32/// Represents a [`print`](Stmt::Print) statement's data in the language.
33#[derive(Debug, PartialEq, Clone)]
34pub struct PrintData {
35    /// The expression to print.
36    pub expr: Expr,
37}
38
39/// Represents a [`return`](Stmt::Return) statement's data in the language.
40#[derive(Debug, PartialEq, Clone)]
41pub struct ReturnData {
42    /// The 'return' keyword.
43    pub keyword: Token,
44    /// The value to return (optional).
45    pub value: Option<Expr>,
46}
47
48/// Represents a [`break`](Stmt::Break) statement's data in the language.
49#[derive(Debug, PartialEq, Clone)]
50pub struct BreakData {
51    pub keyword: Token,
52}
53
54/// Represents a [`var`](Stmt::Var) statement's data in the language.
55#[derive(Debug, PartialEq, Clone)]
56pub struct VarData {
57    /// The variable's name.
58    pub name: Token,
59    /// The variable's initializer (optional).
60    /// If the initializer is `None`, the variable is initialized to `null`.
61    pub initializer: Option<Expr>,
62}
63
64/// Represents a [`while`](Stmt::While) statement's data in the language.
65#[derive(Debug, PartialEq, Clone)]
66pub struct WhileData {
67    /// The condition to check.
68    pub condition: Expr,
69    /// The statement to execute while the condition is true.
70    pub body: Box<Stmt>,
71}
72
73/// Represents a [`block`](Stmt::Block) statement's data in the language.
74#[derive(Debug, PartialEq, Clone)]
75pub struct BlockData {
76    /// The statements in the block.
77    pub statements: Vec<Stmt>,
78}
79
80/// Represents a [`class`](Stmt::Class) statement's data in the language.
81#[derive(Debug, PartialEq, Clone)]
82pub struct ClassData {
83    /// The class's name.
84    pub name: Token,
85    /// The class's superclass (optional).
86    pub superclass: Option<Expr>,
87    /// The class's methods.
88    pub methods: Vec<Stmt>,
89}
90
91/// Represents a statement in the language.
92#[derive(Debug, PartialEq, Clone)]
93pub enum Stmt {
94    /// An [`expression`](crate::expr::Expr) statement.
95    /// This is the only statement that evaluates to a value.
96    Expression(ExpressionData),
97
98    /// A function statement.
99    /// This is used to construct a [`function`](crate::function::Function)
100    /// (or a [`method`](crate::class::Class)) value.
101    Function(FunctionData),
102
103    /// An if statement.
104    /// This is used to conditionally execute a statement.
105    If(IfData),
106
107    /// A print statement.
108    /// This is used to print a value to the standard output.
109    Print(PrintData),
110
111    /// A return statement.
112    /// This is used to return from a function (optionally with a value).
113    Return(ReturnData),
114
115    /// A break statement.
116    /// This is used to break out of a loop.
117    Break(BreakData),
118
119    /// A var statement.
120    /// This is used to declare a variable.
121    Var(VarData),
122
123    /// A while statement.
124    /// This is used to conditionally execute a statement repeatedly.
125    While(WhileData),
126
127    /// A block statement.
128    /// This is used to group statements together like a function body.
129    Block(BlockData),
130
131    /// A class statement.
132    /// This is used to declare a class.
133    Class(ClassData),
134}
135
136impl Stmt {
137    /// Accepts a visitor and returns the result of the visit.
138    /// This is used to implement the visitor pattern.
139    pub fn accept<T>(&self, visitor: &mut dyn StmtVisitor<T>) -> T {
140        use Stmt::*;
141
142        match self {
143            Expression(_) => visitor.visit_expression_stmt(self),
144            Function(_) => visitor.visit_function_stmt(self),
145            If(_) => visitor.visit_if_stmt(self),
146            Print(_) => visitor.visit_print_stmt(self),
147            Return(_) => visitor.visit_return_stmt(self),
148            Break(_) => visitor.visit_break_stmt(self),
149            Var(_) => visitor.visit_var_stmt(self),
150            While(_) => visitor.visit_while_stmt(self),
151            Block(_) => visitor.visit_block_stmt(self),
152            Class(_) => visitor.visit_class_stmt(self),
153        }
154    }
155}
156
157/// A visitor for statements.
158pub trait StmtVisitor<T> {
159    fn visit_expression_stmt(&mut self, stmt: &Stmt) -> T;
160    fn visit_function_stmt(&mut self, stmt: &Stmt) -> T;
161    fn visit_if_stmt(&mut self, stmt: &Stmt) -> T;
162    fn visit_print_stmt(&mut self, stmt: &Stmt) -> T;
163    fn visit_return_stmt(&mut self, stmt: &Stmt) -> T;
164    fn visit_break_stmt(&mut self, stmt: &Stmt) -> T;
165    fn visit_var_stmt(&mut self, stmt: &Stmt) -> T;
166    fn visit_while_stmt(&mut self, stmt: &Stmt) -> T;
167    fn visit_block_stmt(&mut self, stmt: &Stmt) -> T;
168    fn visit_class_stmt(&mut self, stmt: &Stmt) -> T;
169}