Skip to main content

mist_codegen/
top_level.rs

1use mist_parser::ast::*;
2
3use crate::Context;
4
5use crate::{GenRust, GetRust, RustCodegen};
6
7impl GetRust for GenericsDecl {
8    fn get_rust(&self) -> String {
9        if self.0.len() == 0 {
10            String::new()
11        } else {
12            format!(
13                "<{}>",
14                self.0
15                    .iter()
16                    .map(|v| v.get_rust())
17                    .collect::<Vec<_>>()
18                    .join(", ")
19            )
20        }
21    }
22}
23
24impl GetRust for GenericDecl {
25    fn get_rust(&self) -> String {
26        match self {
27            GenericDecl::Lifetime(name) => format!("'{}", name.get_rust()),
28            GenericDecl::Type(name, requirements) => {
29                name.get_rust()
30                    + &(if requirements.len() != 0 {
31                        format!(
32                            ": {}",
33                            requirements
34                                .into_iter()
35                                .map(TypeExpr::get_rust)
36                                .collect::<Vec<_>>()
37                                .join("+")
38                        )
39                    } else {
40                        String::new()
41                    })
42            }
43        }
44    }
45}
46
47impl GenRust for ImplDecl {
48    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
49        if let Some(trait_) = &self.trait_ {
50            cg.add_indentedln(&format!(
51                "impl{} {} for {} {{",
52                self.generics.get_rust(),
53                trait_.get_rust(),
54                self.target.get_rust()
55            ));
56        } else {
57            cg.add_indentedln(&format!(
58                "impl{} {} {{",
59                self.generics.get_rust(),
60                self.target.get_rust()
61            ));
62        }
63        cg.indent += 1;
64
65        for method in &self.methods {
66            method.gen_rust(ctx, cg);
67        }
68
69        cg.indent -= 1;
70        cg.add_indentedln("}");
71    }
72}
73
74impl GenRust for FunctionDecl {
75    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
76        cg.add(&format!(
77            "{}fn {}{}(",
78            self.visibility.get_rust(),
79            self.name.get_rust(),
80            self.generics.get_rust(),
81        ));
82
83        for (i, param) in self.params.0.iter().enumerate() {
84            if i > 0 {
85                cg.add(", ");
86            }
87
88            param.gen_rust(ctx, cg);
89        }
90
91        cg.add(") ");
92        if let Some(return_type) = &self.return_type {
93            cg.add("-> ");
94            cg.add(&return_type.get_rust());
95        }
96
97        if let Some(body) = &self.body {
98            cg.add(" ");
99            body.gen_rust(ctx, cg);
100        } else {
101            cg.add(";");
102        }
103    }
104}
105
106impl GetRust for FieldDecl {
107    fn get_rust(&self) -> String {
108        format!(
109            "{}{}: {},",
110            self.visibility.get_rust(),
111            self.name.get_rust(),
112            self.type_.get_rust()
113        )
114    }
115}
116
117impl GetRust for EnumItem {
118    fn get_rust(&self) -> String {
119        match self {
120            Self::Named(id) => id.get_rust(),
121            Self::Struct(id, s) => format!(
122                "{} {{{}}}",
123                id.get_rust(),
124                s.into_iter()
125                    .map(|field| format!("{}: {}", field.name.get_rust(), field.type_.get_rust()))
126                    .collect::<Vec<_>>()
127                    .join(", ")
128            ),
129            Self::Tuple(id, t) => format!(
130                "{} ({})",
131                id.get_rust(),
132                t.into_iter()
133                    .map(TypeExpr::get_rust)
134                    .collect::<Vec<_>>()
135                    .join(", ")
136            ),
137        }
138    }
139}
140
141impl GenRust for ParamList {
142    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
143        for (i, param) in self.0.iter().enumerate() {
144            if i > 0 {
145                cg.add(", ");
146            }
147
148            param.gen_rust(ctx, cg);
149        }
150    }
151}
152
153impl GenRust for TopLevel {
154    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
155        if let TopLevelKind::ModAttribute = self.0.item {
156            for attr in &self.1 {
157                cg.add("#![");
158                attr.gen_rust(ctx, cg);
159                cg.addln("]");
160            }
161        } else {
162            for attr in &self.1 {
163                cg.add("#[");
164                attr.gen_rust(ctx, cg);
165                cg.addln("]");
166            }
167        }
168
169        self.0.gen_rust(ctx, cg);
170    }
171}
172
173impl GenRust for (&Vec<Spanned<FieldDeclStmt>>, &Spanned<ClassConstructor>) {
174    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
175        cg.add_indented(&format!(
176            "{}fn new{}(",
177            self.1.item.visibility.get_rust(),
178            self.1.item.generics.get_rust()
179        ));
180
181        let params = self
182            .1
183            .item
184            .params
185            .0
186            .clone()
187            .into_iter()
188            .enumerate()
189            .map(|(idx, mut v)| {
190                v.name = construct_pattern(&v.name, idx);
191                (idx, v)
192            })
193            .collect::<Vec<_>>();
194
195        for (i, param) in &params {
196            if *i > 0 {
197                cg.add(", ");
198            }
199
200            param.gen_rust(ctx, cg);
201        }
202
203        cg.addln(") -> Self {");
204        cg.indent += 1;
205
206        cg.add_indentedln("let mut this: Self = unsafe { std::mem::MaybeUninit::<Self>::zeroed().assume_init() };");
207
208        for field in self.0 {
209            let comment = field.get_comment();
210
211            if let Some(init) = &field.item.init {
212                cg.add_indentedln(&comment);
213
214                cg.add_indentedln(&format!("this.{} = ", field.item.decl.name.get_rust()));
215
216                init.gen_rust(ctx, cg);
217            }
218        }
219
220        cg.add_indented(&format!("this.constructor("));
221
222        for (i, param) in params {
223            if i > 0 {
224                cg.add(", ");
225            }
226
227            ctx.expr_ensure_semicolon = false;
228            param.name.gen_rust(ctx, cg);
229        }
230
231        cg.addln(");");
232
233        cg.add_indentedln("this");
234
235        cg.indent -= 1;
236        cg.add_indentedln("}\n");
237
238        let mut constructor_params = vec![VarDecl {
239            name: Pattern::Path(false, Path(vec![Identifier(String::from("self"))])),
240            type_: Some(TypeExpr::Ref {
241                lifetime: None,
242                mutable: true,
243                ty: Box::new(TypeExpr::Path(
244                    Path(vec![Identifier(String::from("Self"))]),
245                    None,
246                )),
247            }),
248        }];
249
250        constructor_params.append(&mut self.1.item.params.0.clone());
251
252        Spanned {
253            line: self.1.line,
254            column: self.1.column,
255            item: FunctionDecl {
256                visibility: self.1.item.visibility.clone(),
257                name: Identifier(String::from("constructor")),
258                generics: self.1.item.generics.clone(),
259                params: ParamList(constructor_params),
260                return_type: Some(TypeExpr::Tuple(Vec::new())),
261                body: Some(self.1.item.body.clone()),
262            },
263        }
264        .gen_rust(ctx, cg);
265    }
266}
267
268fn construct_pattern(pat: &Pattern, idx: usize) -> Pattern {
269    match pat {
270        Pattern::Literal(v) => Pattern::Literal(v.clone()),
271        Pattern::Path(is_mut, v) => Pattern::Path(*is_mut, v.clone().into()),
272        _ => Pattern::Path(false, Path(vec![Identifier(format!("_{idx}"))])),
273    }
274}
275
276impl GenRust for TopLevelKind {
277    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
278        match self {
279            Self::ModAttribute => {}
280            Self::Import(vis, path) => {
281                cg.addln(&format!("{}use {};", vis.get_rust(), path.get_rust()))
282            }
283            Self::Mod(vis, id) => cg.addln(&format!("{}mod {};", vis.get_rust(), id.get_rust())),
284            Self::FunctionDecl(decl) => decl.gen_rust(ctx, cg),
285            Self::ImplDecl(impl_) => impl_.gen_rust(ctx, cg),
286            Self::StructDecl {
287                visibility,
288                name,
289                generics,
290                fields,
291            } => {
292                cg.addln(&format!(
293                    "{}struct {}{} {{",
294                    visibility.get_rust(),
295                    name.get_rust(),
296                    generics.get_rust()
297                ));
298                cg.indent += 1;
299
300                for field in fields {
301                    cg.add_indentedln(&field.get_rust());
302                }
303
304                cg.indent -= 1;
305                cg.addln("}\n");
306            }
307            Self::EnumDecl {
308                visibility,
309                name,
310                generics,
311                fields,
312            } => {
313                cg.addln(&format!(
314                    "{}enum {}{} {{",
315                    visibility.get_rust(),
316                    name.get_rust(),
317                    generics.get_rust()
318                ));
319                cg.indent += 1;
320
321                for field in fields {
322                    cg.add_indentedln(&(field.get_rust() + ","));
323                }
324
325                cg.indent -= 1;
326                cg.addln("}\n");
327            }
328            Self::TraitDecl {
329                visibility,
330                name,
331                generics,
332                requirements,
333                items,
334            } => {
335                cg.addln(&format!(
336                    "{}trait {}{}{} {{",
337                    visibility.get_rust(),
338                    name.get_rust(),
339                    generics.get_rust(),
340                    if requirements.len() != 0 {
341                        String::from(": ")
342                            + &requirements
343                                .into_iter()
344                                .map(TypeExpr::get_rust)
345                                .collect::<Vec<_>>()
346                                .join("+")
347                    } else {
348                        String::new()
349                    },
350                ));
351                cg.indent += 1;
352
353                for item in items {
354                    item.gen_rust(ctx, cg);
355                }
356
357                cg.indent -= 1;
358                cg.addln("}\n");
359            }
360            Self::ClassDecl {
361                visibility,
362                name,
363                generics,
364                inherits,
365                fields,
366                constructor,
367                items,
368            } => {
369                // Struct decl
370                cg.addln(&format!(
371                    "{}struct {}{} {{",
372                    visibility.get_rust(),
373                    name.clone().get_rust(),
374                    generics.clone().get_rust()
375                ));
376                cg.indent += 1;
377
378                if let Some(inherits) = inherits {
379                    cg.add_indented("pub _super: ");
380                    cg.add(&inherits.get_rust());
381                    cg.addln(",");
382                }
383
384                for field in fields.clone() {
385                    cg.add_indentedln(&field.get_comment());
386                    cg.add_indentedln(&field.item.decl.get_rust());
387                }
388
389                cg.indent -= 1;
390                cg.addln("}\n");
391
392                // Constructor
393                cg.addln(&format!(
394                    "impl{} {}{} {{",
395                    generics.clone().get_rust(),
396                    name.clone().get_rust(),
397                    format!(
398                        "<{}>",
399                        generics
400                            .clone()
401                            .0
402                            .into_iter()
403                            .map(|v| Generic::from(v).get_rust())
404                            .collect::<Vec<_>>()
405                            .join(", ")
406                    )
407                ));
408                cg.indent += 1;
409
410                let constructor_comment = constructor.get_comment();
411
412                cg.add_indentedln("#[allow(invalid_value)]");
413                cg.add_indentedln(&constructor_comment);
414
415                (fields, constructor).gen_rust(ctx, cg);
416
417                for item in items.clone() {
418                    match item {
419                        ClassItem::ImplDecl(_) => {}
420                        ClassItem::Method(method) => method.gen_rust(ctx, cg),
421                    }
422                }
423
424                cg.indent -= 1;
425                cg.addln("}\n");
426
427                for item in items {
428                    match item {
429                        ClassItem::ImplDecl(impl_) => {
430                            let mut impl_ = impl_.clone();
431
432                            impl_.item.trait_ = Some(impl_.item.target);
433                            impl_.item.target = TypeExpr::Path(Path(vec![name.clone()]), None);
434
435                            impl_.gen_rust(ctx, cg);
436                        }
437                        ClassItem::Method(_) => {}
438                    }
439                }
440
441                if let Some(inherits) = inherits {
442                    cg.add("impl std::ops::Deref for ");
443                    cg.add(&name.get_rust());
444
445                    cg.addln(" {");
446                    cg.indent += 1;
447
448                    cg.add_indented("type Target = ");
449                    cg.add(&inherits.get_rust());
450                    cg.addln(";");
451
452                    cg.add_indentedln("fn deref(&self) -> &Self::Target {&self._super}");
453
454                    cg.indent -= 1;
455                    cg.addln("}");
456
457                    // Mut
458
459                    cg.add("impl std::ops::DerefMut for ");
460                    cg.add(&name.get_rust());
461
462                    cg.addln(" {");
463                    cg.indent += 1;
464
465                    cg.add_indentedln(
466                        "fn deref_mut(&mut self) -> &mut Self::Target {&mut self._super}",
467                    );
468
469                    cg.indent -= 1;
470                    cg.addln("}");
471                }
472            }
473        }
474    }
475}