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}