1use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
11pub enum PyLiteral {
12 Int(i64),
14 Float(f64),
16 String(String),
18 Bool(bool),
20 None,
22 Bytes(Vec<u8>),
24}
25
26#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
28pub enum PyExpr {
29 Literal(PyLiteral),
31 Name(String),
33 BinOp {
35 left: Box<PyExpr>,
36 op: BinOp,
37 right: Box<PyExpr>,
38 },
39 UnaryOp {
41 op: UnaryOp,
42 operand: Box<PyExpr>,
43 },
44 Call {
46 func: Box<PyExpr>,
47 args: Vec<PyExpr>,
48 kwargs: HashMap<String, PyExpr>,
49 },
50 Attribute {
52 value: Box<PyExpr>,
53 attr: String,
54 },
55 Subscript {
57 value: Box<PyExpr>,
58 index: Box<PyExpr>,
59 },
60 Slice {
62 value: Box<PyExpr>,
63 lower: Option<Box<PyExpr>>,
64 upper: Option<Box<PyExpr>>,
65 step: Option<Box<PyExpr>>,
66 },
67 List(Vec<PyExpr>),
69 Tuple(Vec<PyExpr>),
71 Dict {
73 keys: Vec<PyExpr>,
74 values: Vec<PyExpr>,
75 },
76 Set(Vec<PyExpr>),
78 ListComp {
80 element: Box<PyExpr>,
81 generators: Vec<Comprehension>,
82 },
83 IfExp {
85 test: Box<PyExpr>,
86 body: Box<PyExpr>,
87 orelse: Box<PyExpr>,
88 },
89 Lambda {
91 args: Vec<String>,
92 body: Box<PyExpr>,
93 },
94 Compare {
96 left: Box<PyExpr>,
97 op: CmpOp,
98 right: Box<PyExpr>,
99 },
100 BoolOp {
102 op: BoolOp,
103 left: Box<PyExpr>,
104 right: Box<PyExpr>,
105 },
106 Await(Box<PyExpr>),
108 Yield(Option<Box<PyExpr>>),
110}
111
112#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
114pub enum BinOp {
115 Add, Sub, Mult, Div, FloorDiv, Mod, Pow, LShift, RShift, BitOr, BitXor, BitAnd, MatMult, }
129
130#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
132pub enum UnaryOp {
133 Invert, Not, UAdd, USub, }
138
139#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
141pub enum CmpOp {
142 Eq, NotEq, Lt, LtE, Gt, GtE, Is, IsNot, In, NotIn, }
153
154#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
156pub enum BoolOp {
157 And, Or, }
160
161#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
163pub struct Comprehension {
164 pub target: PyExpr,
165 pub iter: PyExpr,
166 pub ifs: Vec<PyExpr>,
167}
168
169#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
171pub struct FunctionParam {
172 pub name: String,
173 pub type_annotation: Option<TypeAnnotation>,
174 pub default_value: Option<PyExpr>,
175}
176
177#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
179pub enum TypeAnnotation {
180 Name(String),
182 Generic {
184 base: Box<TypeAnnotation>,
185 args: Vec<TypeAnnotation>,
186 },
187}
188
189#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
191pub enum PyStmt {
192 Expr(PyExpr),
194 Assign {
196 target: PyExpr,
197 value: PyExpr,
198 },
199 AugAssign {
201 target: PyExpr,
202 op: BinOp,
203 value: PyExpr,
204 },
205 AnnAssign {
207 target: PyExpr,
208 annotation: TypeAnnotation,
209 value: Option<PyExpr>,
210 },
211 FunctionDef {
213 name: String,
214 params: Vec<FunctionParam>,
215 body: Vec<PyStmt>,
216 return_type: Option<TypeAnnotation>,
217 decorators: Vec<PyExpr>,
218 is_async: bool,
219 },
220 Return {
222 value: Option<PyExpr>,
223 },
224 If {
226 test: PyExpr,
227 body: Vec<PyStmt>,
228 orelse: Vec<PyStmt>,
229 },
230 While {
232 test: PyExpr,
233 body: Vec<PyStmt>,
234 orelse: Vec<PyStmt>,
235 },
236 For {
238 target: PyExpr,
239 iter: PyExpr,
240 body: Vec<PyStmt>,
241 orelse: Vec<PyStmt>,
242 },
243 Pass,
245 Break,
247 Continue,
249 ClassDef {
251 name: String,
252 bases: Vec<PyExpr>,
253 body: Vec<PyStmt>,
254 decorators: Vec<PyExpr>,
255 },
256 Import {
258 modules: Vec<(String, Option<String>)>,
259 },
260 ImportFrom {
262 module: Option<String>,
263 names: Vec<(String, Option<String>)>,
264 level: usize,
265 },
266 Assert {
268 test: PyExpr,
269 msg: Option<PyExpr>,
270 },
271 Try {
273 body: Vec<PyStmt>,
274 handlers: Vec<ExceptHandler>,
275 orelse: Vec<PyStmt>,
276 finalbody: Vec<PyStmt>,
277 },
278 Raise {
280 exception: Option<PyExpr>,
281 },
282 With {
284 items: Vec<WithItem>,
285 body: Vec<PyStmt>,
286 },
287 Delete {
289 targets: Vec<PyExpr>,
290 },
291 Global {
293 names: Vec<String>,
294 },
295 Nonlocal {
297 names: Vec<String>,
298 },
299}
300
301#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
303pub struct WithItem {
304 pub context_expr: PyExpr,
305 pub optional_vars: Option<PyExpr>,
306}
307
308#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
310pub struct ExceptHandler {
311 pub exception_type: Option<PyExpr>,
312 pub name: Option<String>,
313 pub body: Vec<PyStmt>,
314}
315
316#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
318pub struct Arg {
319 pub name: String,
320 pub type_hint: Option<String>,
321 pub default: Option<PyExpr>,
322}
323
324#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
326pub struct PyModule {
327 pub statements: Vec<PyStmt>,
328}
329
330impl PyModule {
331 pub fn new() -> Self {
332 Self {
333 statements: vec![],
334 }
335 }
336
337 pub fn add_stmt(&mut self, stmt: PyStmt) {
338 self.statements.push(stmt);
339 }
340
341 pub fn body(&self) -> &[PyStmt] {
343 &self.statements
344 }
345}
346
347impl Default for PyModule {
348 fn default() -> Self {
349 Self::new()
350 }
351}
352
353#[cfg(test)]
354mod tests {
355 use super::*;
356
357 #[test]
358 fn test_literal_creation() {
359 let int_lit = PyLiteral::Int(42);
360 assert_eq!(int_lit, PyLiteral::Int(42));
361
362 let str_lit = PyLiteral::String("hello".to_string());
363 assert_eq!(str_lit, PyLiteral::String("hello".to_string()));
364
365 let bool_lit = PyLiteral::Bool(true);
366 assert_eq!(bool_lit, PyLiteral::Bool(true));
367 }
368
369 #[test]
370 fn test_simple_assignment() {
371 let module = PyModule {
372 statements: vec![PyStmt::Assign {
373 target: PyExpr::Name("x".to_string()),
374 value: PyExpr::Literal(PyLiteral::Int(42)),
375 }],
376 };
377
378 assert_eq!(module.statements.len(), 1);
379 }
380
381 #[test]
382 fn test_binary_operation() {
383 let expr = PyExpr::BinOp {
384 left: Box::new(PyExpr::Literal(PyLiteral::Int(2))),
385 op: BinOp::Add,
386 right: Box::new(PyExpr::Literal(PyLiteral::Int(3))),
387 };
388
389 match expr {
390 PyExpr::BinOp { left, op, right } => {
391 assert_eq!(*left, PyExpr::Literal(PyLiteral::Int(2)));
392 assert_eq!(op, BinOp::Add);
393 assert_eq!(*right, PyExpr::Literal(PyLiteral::Int(3)));
394 }
395 _ => panic!("Expected BinOp"),
396 }
397 }
398
399 #[test]
400 fn test_function_definition() {
401 let func = PyStmt::FunctionDef {
402 name: "add".to_string(),
403 params: vec![
404 FunctionParam {
405 name: "a".to_string(),
406 type_annotation: Some(TypeAnnotation::Name("int".to_string())),
407 default_value: None,
408 },
409 FunctionParam {
410 name: "b".to_string(),
411 type_annotation: Some(TypeAnnotation::Name("int".to_string())),
412 default_value: None,
413 },
414 ],
415 body: vec![PyStmt::Return {
416 value: Some(PyExpr::BinOp {
417 left: Box::new(PyExpr::Name("a".to_string())),
418 op: BinOp::Add,
419 right: Box::new(PyExpr::Name("b".to_string())),
420 }),
421 }],
422 return_type: Some(TypeAnnotation::Name("int".to_string())),
423 decorators: vec![],
424 is_async: false,
425 };
426
427 match func {
428 PyStmt::FunctionDef { name, params, .. } => {
429 assert_eq!(name, "add");
430 assert_eq!(params.len(), 2);
431 }
432 _ => panic!("Expected FunctionDef"),
433 }
434 }
435}