1#[derive(Debug, Clone, PartialEq)]
8pub enum BinOp {
9 Add, Subtract, Multiply, Divide, Modulo, Equal, NotEqual, Less, LessEqual, Greater, GreaterEqual, And, Or, }
28
29#[derive(Debug, Clone, PartialEq)]
31pub enum UnaryOp {
32 Minus, Not, }
35
36#[derive(Debug, Clone, PartialEq)]
38pub enum Expr {
39 Number(f64),
41 BigInteger(String), String(String),
43 Boolean(bool),
44 Null,
45
46 Identifier(String),
48
49 Binary {
51 left: Box<Expr>,
52 op: BinOp,
53 right: Box<Expr>,
54 },
55
56 Unary {
58 op: UnaryOp,
59 expr: Box<Expr>,
60 },
61
62 Call {
64 func: Box<Expr>,
65 args: Vec<Expr>,
66 },
67
68 Array(Vec<Expr>),
70
71 Dict(Vec<(String, Expr)>),
73
74 Index {
76 object: Box<Expr>,
77 index: Box<Expr>,
78 },
79
80 If {
82 condition: Box<Expr>,
83 then_branch: Vec<Stmt>,
84 elif_branches: Vec<(Expr, Vec<Stmt>)>, else_branch: Option<Vec<Stmt>>,
86 },
87
88 Lambda {
90 params: Vec<String>,
91 body: Vec<Stmt>,
92 },
93}
94
95#[derive(Debug, Clone, PartialEq)]
97pub enum Stmt {
98 Set {
100 name: String,
101 value: Expr,
102 },
103
104 SetIndex {
106 object: Box<Expr>,
107 index: Box<Expr>,
108 value: Expr,
109 },
110
111 FuncDef {
113 name: String,
114 params: Vec<String>,
115 body: Vec<Stmt>,
116 },
117
118 GeneratorDef {
120 name: String,
121 params: Vec<String>,
122 body: Vec<Stmt>,
123 },
124
125 LazyDef {
127 name: String,
128 expr: Expr,
129 },
130
131 Return(Expr),
133
134 Yield(Expr),
136
137 Break,
139
140 Continue,
142
143 While {
145 condition: Expr,
146 body: Vec<Stmt>,
147 },
148
149 For {
151 var: String,
152 iterable: Expr,
153 body: Vec<Stmt>,
154 },
155
156 ForIndexed {
158 index_var: String,
159 value_var: String,
160 iterable: Expr,
161 body: Vec<Stmt>,
162 },
163
164 Switch {
166 expr: Expr,
167 cases: Vec<(Expr, Vec<Stmt>)>,
168 default: Option<Vec<Stmt>>,
169 },
170
171 Import {
173 names: Vec<String>,
174 path: String,
175 aliases: Vec<Option<String>>, },
177
178 Export(String),
180
181 Throw(Expr),
183
184 Expression(Expr),
186}
187
188pub type Program = Vec<Stmt>;
190
191impl Expr {
192 pub fn binary(left: Expr, op: BinOp, right: Expr) -> Self {
194 Expr::Binary {
195 left: Box::new(left),
196 op,
197 right: Box::new(right),
198 }
199 }
200
201 pub fn unary(op: UnaryOp, expr: Expr) -> Self {
203 Expr::Unary {
204 op,
205 expr: Box::new(expr),
206 }
207 }
208
209 pub fn call(func: Expr, args: Vec<Expr>) -> Self {
211 Expr::Call {
212 func: Box::new(func),
213 args,
214 }
215 }
216
217 pub fn index(object: Expr, index: Expr) -> Self {
219 Expr::Index {
220 object: Box::new(object),
221 index: Box::new(index),
222 }
223 }
224}
225
226impl std::fmt::Display for BinOp {
227 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
228 match self {
229 BinOp::Add => write!(f, "+"),
230 BinOp::Subtract => write!(f, "-"),
231 BinOp::Multiply => write!(f, "*"),
232 BinOp::Divide => write!(f, "/"),
233 BinOp::Modulo => write!(f, "%"),
234 BinOp::Equal => write!(f, "=="),
235 BinOp::NotEqual => write!(f, "!="),
236 BinOp::Less => write!(f, "<"),
237 BinOp::LessEqual => write!(f, "<="),
238 BinOp::Greater => write!(f, ">"),
239 BinOp::GreaterEqual => write!(f, ">="),
240 BinOp::And => write!(f, "&&"),
241 BinOp::Or => write!(f, "||"),
242 }
243 }
244}
245
246impl std::fmt::Display for UnaryOp {
247 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
248 match self {
249 UnaryOp::Minus => write!(f, "-"),
250 UnaryOp::Not => write!(f, "!"),
251 }
252 }
253}
254
255#[cfg(test)]
256mod tests {
257 use super::*;
258
259 #[test]
260 fn test_expr_helpers() {
261 let expr = Expr::binary(Expr::Number(1.0), BinOp::Add, Expr::Number(2.0));
263 match expr {
264 Expr::Binary { left, op, right } => {
265 assert_eq!(*left, Expr::Number(1.0));
266 assert_eq!(op, BinOp::Add);
267 assert_eq!(*right, Expr::Number(2.0));
268 }
269 _ => panic!("Expected Binary expression"),
270 }
271
272 let expr = Expr::unary(UnaryOp::Minus, Expr::Number(5.0));
274 match expr {
275 Expr::Unary { op, expr } => {
276 assert_eq!(op, UnaryOp::Minus);
277 assert_eq!(*expr, Expr::Number(5.0));
278 }
279 _ => panic!("Expected Unary expression"),
280 }
281
282 let expr = Expr::call(
284 Expr::Identifier("ADD".to_string()),
285 vec![Expr::Number(1.0), Expr::Number(2.0)],
286 );
287 match expr {
288 Expr::Call { func, args } => {
289 assert_eq!(*func, Expr::Identifier("ADD".to_string()));
290 assert_eq!(args.len(), 2);
291 }
292 _ => panic!("Expected Call expression"),
293 }
294 }
295
296 #[test]
297 fn test_binop_display() {
298 assert_eq!(format!("{}", BinOp::Add), "+");
299 assert_eq!(format!("{}", BinOp::Equal), "==");
300 assert_eq!(format!("{}", BinOp::And), "&&");
301 }
302
303 #[test]
304 fn test_unaryop_display() {
305 assert_eq!(format!("{}", UnaryOp::Minus), "-");
306 assert_eq!(format!("{}", UnaryOp::Not), "!");
307 }
308}