1use crate::ast::data::Data;
2use crate::ast::declaration::VariableDeclaration;
3use crate::ast::expr::{Expr, ExprNode};
4use crate::ast::NodeTrait;
5use crate::lexer::position::Position;
6use std::any::Any;
7use std::collections::HashMap;
8
9#[derive(Debug, Clone)]
10pub struct StmtNode {
11 stmt: Stmt,
12 pos: Position,
13}
14#[derive(Debug, Clone)]
15pub enum Stmt {
16 EvalExpr(Box<ExprNode>),
17 ValDecl(VariableDeclaration),
18 VarDecl(VariableDeclaration),
19 StaticDecl(VariableDeclaration),
20 Assign(Box<ExprNode>, Box<ExprNode>),
21 Return(Box<ExprNode>),
22 If(Box<IfStmt>),
23 While(Box<ExprNode>, Vec<StmtNode>),
24 ForIn(String, Box<ExprNode>, Vec<StmtNode>),
25 IndexAssign(Box<ExprNode>, Box<ExprNode>, Box<ExprNode>),
29 Break,
30 Continue,
31 Import(String),
32 Match(Box<ExprNode>, Vec<MatchBranch>),
34 IfLet(
36 Box<ExprNode>,
37 Box<ExprNode>,
38 Vec<StmtNode>,
39 Option<Vec<StmtNode>>,
40 ),
41 IfConst(
42 Box<ExprNode>,
43 Box<ExprNode>,
44 Vec<StmtNode>,
45 Option<Vec<StmtNode>>,
46 ),
47 Noop,
48}
49#[derive(Debug, Clone)]
50pub struct IfStmt {
51 branches: Vec<IfBranchStmt>,
52 else_body: Option<Vec<StmtNode>>,
53}
54
55impl IfStmt {
56 pub fn new(branches: Vec<IfBranchStmt>, else_body: Option<Vec<StmtNode>>) -> Self {
57 Self {
58 branches,
59 else_body,
60 }
61 }
62 pub fn set_else_body(&mut self, else_body: Option<Vec<StmtNode>>) {
63 self.else_body = else_body;
64 }
65 pub fn set_branches(&mut self, branches: Vec<IfBranchStmt>) {
66 self.branches = branches;
67 }
68 pub fn get_branches(&self) -> &Vec<IfBranchStmt> {
69 &self.branches
70 }
71 pub fn get_else_body(&self) -> Option<Vec<StmtNode>> {
72 self.else_body.clone()
73 }
74}
75#[derive(Debug, Clone)]
76pub struct IfBranchStmt {
77 condition: ExprNode,
78 body: Vec<StmtNode>,
79}
80
81impl IfBranchStmt {
82 pub fn new(condition: ExprNode, body: Vec<StmtNode>) -> Self {
83 Self { condition, body }
84 }
85
86 pub fn get_condition(&self) -> &ExprNode {
87 &self.condition
88 }
89 pub fn get_body(&self) -> &Vec<StmtNode> {
90 &self.body
91 }
92}
93
94#[derive(Debug, Clone)]
96pub struct MatchBranch {
97 pattern: ExprNode,
98 body: Vec<StmtNode>,
99}
100
101impl MatchBranch {
102 pub fn new(pattern: ExprNode, body: Vec<StmtNode>) -> Self {
103 Self { pattern, body }
104 }
105
106 pub fn get_pattern(&self) -> &ExprNode {
107 &self.pattern
108 }
109
110 pub fn get_body(&self) -> &Vec<StmtNode> {
111 &self.body
112 }
113}
114
115impl Stmt {
116 pub fn is_noop(&self) -> bool {
117 matches!(self, Stmt::Noop)
118 }
119 pub fn is_fn_call(&self) -> bool {
120 match self {
121 Stmt::EvalExpr(expr) => expr.is_fn_call(),
122 _ => false,
123 }
124 }
125 pub fn is_break(&self) -> bool {
126 matches!(self, Stmt::Break)
127 }
128 pub fn is_closure_decl(&self) -> bool {
129 match &self {
130 Stmt::ValDecl(v) => v.is_closure,
131 _ => false,
132 }
133 }
134}
135impl NodeTrait for StmtNode {
136 fn get_id(&self) -> &str {
137 match &self.stmt {
138 Stmt::EvalExpr(e) => e.get_id(),
139 Stmt::ValDecl(_) => "ValDecl",
140 Stmt::VarDecl(_) => "VarDecl",
141 Stmt::StaticDecl(_) => "StaticDecl",
142 Stmt::Assign(_, _) => "Assign",
143 Stmt::Return(_) => "Return",
144 Stmt::If(_) => "If",
145 Stmt::While(_, _) => "While",
146 Stmt::ForIn(_, _, _) => "ForIn",
147 Stmt::IndexAssign(_, _, _) => "IndexAssign",
148 Stmt::Break => "Break",
149 Stmt::Continue => "Continue",
150 Stmt::Import(_) => "Import",
151 Stmt::Noop => "Noop",
152 Stmt::Match(_, _) => "Match",
153 Stmt::IfLet(_, _, _, _) => "IfLet",
154 Stmt::IfConst(_, _, _, _) => "IfConst",
155 }
156 }
157
158 fn get_data(&self, key: &str) -> Option<Data> {
159 match &self.stmt {
160 Stmt::ValDecl(v) => v.get_data(key),
161 Stmt::EvalExpr(e) => e.get_data(key),
162 Stmt::VarDecl(v) => v.get_data(key),
163 Stmt::StaticDecl(v) => v.get_data(key),
164 _ => {
165 todo!()
166 }
167 }
168 }
169
170 fn set_data(&mut self, key: &str, value: Data) {
171 match &mut self.stmt {
172 Stmt::ValDecl(v) => {
173 if key == "name" {
174 v.set_name(value.as_str().unwrap());
175 }
176 }
177 Stmt::EvalExpr(e) => e.set_data(key, value),
178 Stmt::VarDecl(v) => {
179 if key == "name" {
180 v.set_name(value.as_str().unwrap());
181 }
182 }
183 Stmt::StaticDecl(v) => {
184 if key == "name" {
185 v.set_name(value.as_str().unwrap());
186 }
187 }
188 _ => {
189 todo!()
190 }
191 }
192 }
193
194 fn get_children(&self) -> Vec<&dyn NodeTrait> {
195 todo!()
196 }
197
198 fn get_mut_children(&mut self) -> Vec<&mut dyn NodeTrait> {
199 match &mut self.stmt {
200 Stmt::ValDecl(v) => {
201 let mut children = vec![];
202 let default = v.get_mut_default();
203 match default {
204 Some(default) => {
205 children.push(default as &mut dyn NodeTrait);
206 children
207 }
208 None => vec![],
209 }
210 }
211 Stmt::VarDecl(v) => {
212 let mut children = vec![];
213 let default = v.get_mut_default();
214 match default {
215 Some(default) => {
216 children.push(default as &mut dyn NodeTrait);
217 children
218 }
219 None => vec![],
220 }
221 }
222 Stmt::StaticDecl(v) => {
223 let mut children = vec![];
224 let default = v.get_mut_default();
225 match default {
226 Some(default) => {
227 children.push(default as &mut dyn NodeTrait);
228 children
229 }
230 None => vec![],
231 }
232 }
233 _ => vec![],
234 }
235 }
236
237 fn get_extra(&self) -> &HashMap<String, Box<dyn Any>> {
238 todo!()
239 }
240}
241impl StmtNode {
242 pub fn new(stmt: Stmt, pos: Position) -> Self {
243 Self { stmt, pos }
244 }
245
246 pub fn get_stmt(&self) -> &Stmt {
247 &self.stmt
248 }
249
250 pub fn position(&self) -> Position {
251 self.pos.clone()
252 }
253
254 pub fn is_noop(&self) -> bool {
255 self.stmt.is_noop()
256 }
257 pub fn is_fn_call(&self) -> bool {
258 self.stmt.is_fn_call()
259 }
260 pub fn get_fn_call_name(&self) -> Option<String> {
261 match &self.stmt {
262 Stmt::EvalExpr(expr) => match expr.get_expr() {
263 Expr::FnCall(fn_call) => Some(fn_call.name.clone()),
264 _ => None,
265 },
266 _ => None,
267 }
268 }
269 pub fn get_mut_stmt(&mut self) -> &mut Stmt {
270 &mut self.stmt
271 }
272 pub fn set_fn_call_name(&mut self, name: String) {
273 if let Stmt::EvalExpr(expr) = &mut self.stmt {
274 if let Expr::FnCall(ref mut fn_call) = expr.get_expr_mut() {
275 fn_call.name = name;
276 }
277 }
278 }
279 pub fn is_val_decl(&self) -> bool {
280 matches!(self.stmt, Stmt::ValDecl(_))
281 }
282 pub fn is_static_decl(&self) -> bool {
283 matches!(self.stmt, Stmt::StaticDecl(_))
284 }
285}