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