1use super::expr::*;
2use super::*;
3use serde::{Deserialize, Serialize};
4
5#[derive(Clone, Debug, Serialize, Deserialize)]
6#[serde(tag = "type")]
7pub enum IfBranch {
8 If { condition: Value, content: Block },
9 Elif { condition: Value, content: Block },
10 Else { content: Block },
11}
12
13#[derive(Clone, Debug, Serialize, Deserialize)]
14#[serde(tag = "type")]
15pub struct SetStmt {
16 name: Ident,
17 value: Value,
18}
19
20#[derive(Clone, Debug, Serialize, Deserialize)]
21#[serde(tag = "type")]
22pub struct ImportStmt {
23 mod_name: Value,
24}
25
26#[derive(Clone, Debug, Serialize, Deserialize)]
27#[serde(tag = "type")]
28pub struct ImportAsStmt {
29 mod_name: Value,
30 import_as: Ident,
31}
32
33#[derive(Clone, Debug, Serialize, Deserialize)]
34#[serde(tag = "type")]
35pub struct FromImportStmt {
36 mod_name: Value,
37 import_from: Value,
38}
39
40#[derive(Clone, Debug, Serialize, Deserialize)]
41#[serde(tag = "type")]
42pub struct CallStmt {
43 base: Value,
44 args: Box<[Value]>,
45 kw_args: Box<[Kwarg]>,
46}
47
48#[derive(Clone, Debug, Serialize, Deserialize)]
49#[serde(tag = "type")]
50pub struct ReturnStmt {
51 value: Value,
52}
53
54#[derive(Clone, Debug, Serialize, Deserialize)]
55#[serde(tag = "type")]
56pub struct YieldStmt {
57 value: Value,
58}
59
60#[derive(Clone, Debug, Serialize, Deserialize)]
61#[serde(tag = "type")]
62pub struct PropertyStmt {
63 base: Value,
64 props: Box<[Ident]>,
65}
66
67#[derive(Clone, Debug, Serialize, Deserialize)]
68#[serde(tag = "type")]
69pub struct IfStmt {
70 branches: Box<[IfBranch]>,
71 block_indents: Option<usize>,
72}
73
74#[derive(Clone, Debug, Serialize, Deserialize)]
75#[serde(tag = "type")]
76pub struct ForStmt {
77 iter_subj: Value,
78 iter_vals: Box<[Ident]>,
79 content: Block,
80 block_indents: Option<usize>,
81}
82
83#[derive(Clone, Debug, Serialize, Deserialize)]
84#[serde(tag = "type")]
85pub struct WhileStmt {
86 cond: Value,
87 content: Block,
88 block_indents: Option<usize>,
89}
90
91#[derive(Clone, Debug, Serialize, Deserialize)]
92#[serde(tag = "type")]
93pub struct DefStmt {
94 name: Ident,
95 args: Box<[Ident]>,
96 kw_args: Box<[Kwarg]>,
97 content: Block,
98 decorator: Option<Value>,
99 block_indents: Option<usize>,
100}
101
102#[derive(Clone, Debug, Serialize, Deserialize)]
103#[serde(tag = "type")]
104pub struct ClassStmt {
105 name: Ident,
106 parents: Box<[Value]>,
107 methods: Box<[DefStmt]>,
108 block_indents: Option<usize>,
109}
110
111#[typetag::serde]
112impl Codegen for SetStmt {
113 fn code_gen(&self) -> String {
114 format!("{} = {}", self.name.code_gen(), self.value.code_gen())
115 }
116}
117
118#[typetag::serde]
119impl Codegen for CallStmt {
120 fn code_gen(&self) -> String {
121 let mut args = self
122 .args
123 .iter()
124 .map(|expr| expr.code_gen())
125 .collect::<Vec<String>>()
126 .join(", ");
127
128 let kwargs_vec = self
129 .kw_args
130 .iter()
131 .map(|kwarg| kwarg.code_gen())
132 .collect::<Vec<String>>();
133
134 let kwargs = if !kwargs_vec.is_empty() {
135 if !self.args.is_empty() {
136 args += ", "
137 }
138 kwargs_vec.join(", ")
139 } else {
140 "".to_owned()
141 };
142
143 format!("{}({}{})", self.base.code_gen(), args, kwargs)
144 }
145}
146
147#[typetag::serde]
148impl Codegen for ReturnStmt {
149 fn code_gen(&self) -> String {
150 format!("return {}", self.value.code_gen())
151 }
152}
153
154#[typetag::serde]
155impl Codegen for YieldStmt {
156 fn code_gen(&self) -> String {
157 format!("yield {}", self.value.code_gen())
158 }
159}
160
161#[typetag::serde]
162impl Codegen for PropertyStmt {
163 fn code_gen(&self) -> String {
164 let mut prop_items = self
165 .props
166 .iter()
167 .map(|ident| ident.code_gen())
168 .collect::<Vec<String>>();
169
170 let mut res = Vec::new();
171 res.push(self.base.code_gen());
172 res.append(&mut prop_items);
173
174 res.join(".")
175 }
176}
177
178#[typetag::serde]
179impl Codegen for ImportStmt {
180 fn code_gen(&self) -> String {
181 format!("import {}", self.mod_name.code_gen())
182 }
183}
184
185#[typetag::serde]
186impl Codegen for ImportAsStmt {
187 fn code_gen(&self) -> String {
188 format!(
189 "import {} as {}",
190 self.mod_name.code_gen(),
191 self.import_as.code_gen()
192 )
193 }
194}
195
196#[typetag::serde]
197impl Codegen for FromImportStmt {
198 fn code_gen(&self) -> String {
199 format!(
200 "from {} import {}",
201 self.import_from.code_gen(),
202 self.mod_name.code_gen()
203 )
204 }
205}
206
207#[typetag::serde]
208impl Codegen for IfStmt {
209 fn code_gen(&self) -> String {
210 let gen_branch = |branch: &IfBranch| {
211 use IfBranch::*;
212
213 match branch {
214 If { condition, content } => {
215 format!("if {}{}", condition.code_gen(), content.code_gen())
216 }
217 Elif { condition, content } => {
218 format!("elif {}{}", condition.code_gen(), content.code_gen())
219 }
220 Else { content } => format!("else{}", content.code_gen()),
221 }
222 };
223
224 self.branches
225 .iter()
226 .map(gen_branch)
227 .collect::<Vec<String>>()
228 .join("")
229 }
230
231 fn get_indents(&self) -> Option<usize> {
232 Some(self.block_indents.unwrap_or(1))
233 }
234
235 fn set_indents(&mut self, n: usize) {
236 self.block_indents = Some(n);
237
238 self.branches = self
239 .branches
240 .iter()
241 .map(|branch| match branch {
242 IfBranch::If { condition, content } => {
243 let mut content = content.clone();
244 content.set_indents(n);
245 IfBranch::If {
246 condition: condition.clone(),
247 content,
248 }
249 }
250 IfBranch::Elif { condition, content } => {
251 let mut content = content.clone();
252 content.set_indents(n);
253 IfBranch::Elif {
254 condition: condition.clone(),
255 content,
256 }
257 }
258 IfBranch::Else { content } => {
259 let mut content = content.clone();
260 content.set_indents(n);
261 IfBranch::Else { content }
262 }
263 })
264 .collect::<Vec<IfBranch>>()
265 .into_boxed_slice();
266 }
267}
268
269#[typetag::serde]
270impl Codegen for ForStmt {
271 fn code_gen(&self) -> String {
272 let iter_vals = {
273 let res = self
274 .iter_vals
275 .iter()
276 .map(|ident| ident.code_gen())
277 .collect::<Vec<String>>()
278 .join(",");
279 format!("{}", res)
280 };
281
282 format!(
283 "for {} in {}{}",
284 iter_vals,
285 self.iter_subj.code_gen(),
286 self.content.code_gen()
287 )
288 }
289
290 fn get_indents(&self) -> Option<usize> {
291 Some(self.block_indents.unwrap_or(1))
292 }
293
294 fn set_indents(&mut self, n: usize) {
295 (self.block_indents, self.content.indents) = (Some(n), Some(n));
296 }
297}
298
299#[typetag::serde]
300impl Codegen for WhileStmt {
301 fn code_gen(&self) -> String {
302 format!("while {}{}", self.cond.code_gen(), self.content.code_gen())
303 }
304
305 fn get_indents(&self) -> Option<usize> {
306 Some(self.block_indents.unwrap_or(1))
307 }
308
309 fn set_indents(&mut self, n: usize) {
310 (self.block_indents, self.content.indents) = (Some(n), Some(n));
311 }
312}
313
314#[typetag::serde]
315impl Codegen for DefStmt {
316 fn code_gen(&self) -> String {
317 let indents_stmt = " ".repeat(self.get_indents().unwrap() - 1);
318 let args = self
319 .args
320 .iter()
321 .map(|expr| expr.code_gen())
322 .collect::<Vec<String>>()
323 .join(", ");
324
325 let mut kwargs = self
326 .kw_args
327 .iter()
328 .map(|expr| expr.code_gen())
329 .collect::<Vec<String>>()
330 .join(", ");
331
332 if self.kw_args.is_empty() {
333 kwargs = "".to_owned()
334 }
335
336 let decorator = if let Some(deco) = &self.decorator {
337 format!("@{}\n{}", deco.code_gen(), indents_stmt)
338 } else {
339 "".to_owned()
340 };
341
342 format!(
343 "{}def {}({}{}){}",
344 decorator,
345 self.name.code_gen(),
346 args,
347 kwargs,
348 self.content.code_gen()
349 )
350 }
351
352 fn get_indents(&self) -> Option<usize> {
353 Some(self.block_indents.unwrap_or(1))
354 }
355
356 fn set_indents(&mut self, n: usize) {
357 (self.block_indents, self.content.indents) = (Some(n), Some(n));
358 }
359}
360
361#[typetag::serde]
362impl Codegen for ClassStmt {
363 fn code_gen(&self) -> String {
364 let indents = " ".repeat(self.get_indents().unwrap());
365
366 let methods = self
367 .methods
368 .iter()
369 .map(|blk| {
370 let mut res = blk.clone();
371 res.set_indents(self.get_indents().unwrap() + 1);
372 format!("{}{}", indents, res.code_gen())
373 })
374 .collect::<Vec<String>>();
375
376 let methods_string = methods.join("\n");
377 let mut methods = String::from(":\n");
378 methods += methods_string.as_str();
379
380 let parents = self
381 .parents
382 .iter()
383 .map(|expr| expr.code_gen())
384 .collect::<Vec<String>>()
385 .join(", ");
386
387 format!("class {}({}){}", self.name.code_gen(), parents, methods)
388 }
389
390 fn get_indents(&self) -> Option<usize> {
391 Some(self.block_indents.unwrap_or(1))
392 }
393
394 fn set_indents(&mut self, n: usize) {
395 self.block_indents = Some(n);
396 self.methods = self
397 .methods
398 .iter()
399 .map(|stmt| {
400 let mut s = stmt.clone();
401 s.set_indents(n);
402 s
403 })
404 .collect::<Vec<DefStmt>>()
405 .into_boxed_slice();
406 }
407}