1use aleph_syntax_tree::syntax::AlephTree as at;
2use rustpython_parser::ast::{
3 Expr, Stmt, BoolOp, CmpOp, Operator, UnaryOp, Arguments, ExprName, StmtReturn,
4 ExprBoolOp, ExprBinOp, ExprUnaryOp, ExprLambda, ExprIfExp, ExprCompare, ExprCall,
5 StmtFunctionDef, StmtAsyncFunctionDef, StmtClassDef, StmtFor, StmtAsyncFor, StmtWhile,
6 StmtIf, StmtAssert, StmtImport, StmtExpr
7};
8use rustpython_parser::Parse;
9
10fn extract_constant(value: rustpython_parser::ast::Constant) -> at {
12 match value {
13 rustpython_parser::ast::Constant::None => at::Unit,
14 rustpython_parser::ast::Constant::Bool(b) => at::Bool { value: b.to_string() },
15 rustpython_parser::ast::Constant::Str(s) => at::String { value: format!("\"{}\"", s) },
16 rustpython_parser::ast::Constant::Bytes(b) => at::Bytes { elems: b },
17 rustpython_parser::ast::Constant::Int(i) => at::Int { value: i.to_string() },
18 rustpython_parser::ast::Constant::Tuple(v) => at::Tuple {
19 elems: v.into_iter().map(|c| Box::new(extract_constant(c))).collect(),
20 },
21 rustpython_parser::ast::Constant::Float(f) => at::Float { value: f.to_string() },
22 rustpython_parser::ast::Constant::Complex { real, imag } => at::Complex {
23 real: real.to_string(),
24 imag: imag.to_string(),
25 },
26 rustpython_parser::ast::Constant::Ellipsis => at::Ellipsis,
27 }
28}
29
30fn extract_name(expr: &Expr) -> String {
32 match expr {
33 Expr::Name(ExprName { id, .. }) => id.to_string(),
34 _ => {
35 println!("Not implemented: extract_name for {:?}", expr);
36 String::new()
37 }
38 }
39}
40
41fn translate_arguments_vec(_args: &Arguments) -> Vec<Box<at>> {
44 Vec::new()
45}
46
47fn translate_expr(expr: &Expr) -> at {
49 match expr {
50 Expr::BoolOp(ExprBoolOp { op, values, .. }) => {
51 let mut res = at::Unit;
52 for value in values {
53 res = match op {
54 BoolOp::And => match res {
55 at::Unit => translate_expr(value),
56 _ => at::And {
57 bool_expr1: Box::new(res),
58 bool_expr2: Box::new(translate_expr(value)),
59 },
60 },
61 BoolOp::Or => match res {
62 at::Unit => translate_expr(value),
63 _ => at::Or {
64 bool_expr1: Box::new(res),
65 bool_expr2: Box::new(translate_expr(value)),
66 },
67 },
68 }
69 }
70 res
71 }
72 Expr::BinOp(ExprBinOp { left, op, right, .. }) => match op {
73 Operator::Add => at::Add {
74 number_expr1: Box::new(translate_expr(left)),
75 number_expr2: Box::new(translate_expr(right)),
76 },
77 Operator::Sub => at::Sub {
78 number_expr1: Box::new(translate_expr(left)),
79 number_expr2: Box::new(translate_expr(right)),
80 },
81 Operator::Mult => at::Mul {
82 number_expr1: Box::new(translate_expr(left)),
83 number_expr2: Box::new(translate_expr(right)),
84 },
85 Operator::Div => at::Div {
86 number_expr1: Box::new(translate_expr(left)),
87 number_expr2: Box::new(translate_expr(right)),
88 },
89 _ => {
90 println!("Not implemented: BinOp {:?} {:?} {:?}", left, op, right);
91 at::Unit
92 }
93 },
94 Expr::UnaryOp(ExprUnaryOp { op, operand, .. }) => match op {
95 UnaryOp::Not => at::Not {
96 bool_expr: Box::new(translate_expr(operand)),
97 },
98 UnaryOp::USub => at::Neg {
99 expr: Box::new(translate_expr(operand)),
100 },
101 _ => {
102 println!("Not implemented: UnaryOp {:?} {:?}", op, operand);
103 at::Unit
104 }
105 },
106 Expr::Lambda(ExprLambda { args, body, .. }) => at::LetRec {
107 name: "lambda".to_string(),
108 args: translate_arguments_vec(args),
109 body: Box::new(translate_expr(body)),
110 },
111 Expr::IfExp(ExprIfExp { test, body, orelse, .. }) => at::If {
112 condition: Box::new(translate_expr(test)),
113 then: Box::new(translate_expr(body)),
114 els: Box::new(translate_expr(orelse)),
115 },
116 Expr::Compare(ExprCompare { left, ops, comparators, .. }) => {
117 let mut res = translate_expr(left);
118 for (op, right) in ops.iter().zip(comparators.iter()) {
119 let right_expr = translate_expr(right);
120 res = match op {
121 CmpOp::Eq => at::Eq {
122 expr1: Box::new(res),
123 expr2: Box::new(right_expr),
124 },
125 CmpOp::NotEq => at::Not {
126 bool_expr: Box::new(at::Eq {
127 expr1: Box::new(res),
128 expr2: Box::new(right_expr),
129 }),
130 },
131 CmpOp::Lt => at::And {
132 bool_expr1: Box::new(at::LE {
133 expr1: Box::new(res.clone()),
134 expr2: Box::new(right_expr.clone()),
135 }),
136 bool_expr2: Box::new(at::Not {
137 bool_expr: Box::new(at::Eq {
138 expr1: Box::new(res.clone()),
139 expr2: Box::new(right_expr.clone()),
140 }),
141 }),
142 },
143 CmpOp::LtE => at::LE {
144 expr1: Box::new(res),
145 expr2: Box::new(right_expr),
146 },
147 CmpOp::Gt => at::Not {
148 bool_expr: Box::new(at::LE {
149 expr1: Box::new(res),
150 expr2: Box::new(right_expr.clone()),
151 }),
152 },
153 CmpOp::GtE => at::Or {
154 bool_expr1: Box::new(at::LE {
155 expr1: Box::new(res.clone()),
156 expr2: Box::new(right_expr.clone()),
157 }),
158 bool_expr2: Box::new(at::Eq {
159 expr1: Box::new(res.clone()),
160 expr2: Box::new(right_expr.clone()),
161 }),
162 },
163 CmpOp::Is => at::Eq {
164 expr1: Box::new(res),
165 expr2: Box::new(right_expr),
166 },
167 CmpOp::IsNot => at::Not {
168 bool_expr: Box::new(at::Eq {
169 expr1: Box::new(res),
170 expr2: Box::new(right_expr),
171 }),
172 },
173 CmpOp::In => at::In {
174 expr1: Box::new(res),
175 expr2: Box::new(right_expr),
176 },
177 CmpOp::NotIn => at::Not {
178 bool_expr: Box::new(at::In {
179 expr1: Box::new(res),
180 expr2: Box::new(right_expr),
181 }),
182 },
183 }
184 }
185 res
186 }
187 Expr::Call(ExprCall { func, args, .. }) => {
188 let name = extract_name(func);
189 let param_list = args.iter().map(|arg| Box::new(translate_expr(arg))).collect();
190 at::App {
191 object_name: "".to_string(),
192 fun: Box::new(at::String { value: name }),
193 param_list,
194 }
195 }
196 Expr::Constant(expr_constant) => extract_constant(expr_constant.value.clone()),
197 Expr::Name(ExprName { id, .. }) => at::Ident { value: id.to_string() },
198 _ => {
199 println!("Not implemented expression {:?}", expr);
200 at::Unit
201 }
202 }
203}
204
205fn translate_stmt(stmt: &Stmt) -> at {
207 match stmt {
208 Stmt::FunctionDef(StmtFunctionDef { name, args, body, .. }) |
209 Stmt::AsyncFunctionDef(StmtAsyncFunctionDef { name, args, body, .. }) => at::LetRec {
210 name: name.to_string(),
211 args: translate_arguments_vec(args),
212 body: Box::new(translate_stmt_list(body)),
213 },
214 Stmt::ClassDef(StmtClassDef { name, body, .. }) => at::Clss {
215 name: name.to_string(),
216 attribute_list: Vec::new(),
217 extends: None,
218 implements: Vec::new(),
219 body: Box::new(translate_stmt_list(body)),
220 },
221 Stmt::Return(StmtReturn { value, .. }) => match value {
222 None => at::Unit,
223 Some(expr) => at::Return {
224 value: Box::new(translate_expr(expr)),
225 },
226 },
227 Stmt::For(StmtFor { target, iter, body, orelse, .. }) |
228 Stmt::AsyncFor(StmtAsyncFor { target, iter, body, orelse, .. }) => at::While {
229 init_expr: Box::new(translate_expr(target)),
230 condition: Box::new(translate_expr(iter)),
231 loop_expr: Box::new(translate_stmt_list(body)),
232 post_expr: Box::new(translate_stmt_list(orelse)),
233 },
234 Stmt::While(StmtWhile { test, body, orelse, .. }) => at::While {
235 init_expr: Box::new(at::Unit),
236 condition: Box::new(translate_expr(test)),
237 loop_expr: Box::new(translate_stmt_list(body)),
238 post_expr: Box::new(translate_stmt_list(orelse)),
239 },
240 Stmt::If(StmtIf { test, body, orelse, .. }) => at::If {
241 condition: Box::new(translate_expr(test)),
242 then: Box::new(translate_stmt_list(body)),
243 els: Box::new(translate_stmt_list(orelse)),
244 },
245 Stmt::Assert(StmtAssert { test, msg, .. }) => at::Assert {
246 condition: Box::new(translate_expr(test)),
247 message: msg
248 .as_ref()
249 .map_or_else(|| Box::new(at::Unit), |m| Box::new(translate_expr(m))),
250 },
251 Stmt::Import(StmtImport { names, .. }) => {
252 let items = names.iter().map(|alias| alias.name.to_string()).collect();
253 at::Iprt {
254 name: "".to_string(),
255 items,
256 }
257 }
258 Stmt::Expr(StmtExpr { value, .. }) => translate_expr(value),
259 Stmt::Pass(_) => at::Unit,
260 Stmt::Break(_) => at::Break,
261 Stmt::Continue(_) => at::Continue,
262 _ => {
263 println!("Not implemented statement {:?}", stmt);
264 at::Unit
265 }
266 }
267}
268
269fn translate_stmt_list(stmts: &[Stmt]) -> at {
271 let mut res = at::Unit;
272 for stmt in stmts {
273 let current = translate_stmt(stmt);
274 res = match res {
275 at::Unit => current,
276 _ => at::Stmts {
277 expr1: Box::new(res),
278 expr2: Box::new(current),
279 },
280 };
281 }
282 res
283}
284
285pub fn python_parse(source: String) -> at {
287 let ast = rustpython_parser::ast::Suite::parse(&source, "<embedded>")
288 .expect("Failed to parse Python source.");
289 translate_stmt_list(&ast)
290}
291