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        cg.add(&self.return_type.get_rust());
93
94        if let Some(body) = &self.body {
95            cg.add(" ");
96            body.gen_rust(ctx, cg);
97        } else {
98            cg.add(";");
99        }
100    }
101}
102
103impl GetRust for FieldDecl {
104    fn get_rust(&self) -> String {
105        format!(
106            "{}{}: {},",
107            self.visibility.get_rust(),
108            self.name.get_rust(),
109            self.type_.get_rust()
110        )
111    }
112}
113
114impl GetRust for EnumItem {
115    fn get_rust(&self) -> String {
116        match self {
117            Self::Named(id) => id.get_rust(),
118            Self::Struct(id, s) => format!(
119                "{} {{{}}}",
120                id.get_rust(),
121                s.into_iter()
122                    .map(|field| format!("{}: {}", field.name.get_rust(), field.type_.get_rust()))
123                    .collect::<Vec<_>>()
124                    .join(", ")
125            ),
126            Self::Tuple(id, t) => format!(
127                "{} ({})",
128                id.get_rust(),
129                t.into_iter()
130                    .map(TypeExpr::get_rust)
131                    .collect::<Vec<_>>()
132                    .join(", ")
133            ),
134        }
135    }
136}
137
138impl GenRust for ParamList {
139    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
140        for (i, param) in self.0.iter().enumerate() {
141            if i > 0 {
142                cg.add(", ");
143            }
144
145            param.gen_rust(ctx, cg);
146        }
147    }
148}
149
150impl GenRust for TopLevel {
151    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
152        if let TopLevelKind::ModAttribute = self.0.item {
153            for attr in &self.1 {
154                cg.add("#![");
155                attr.gen_rust(ctx, cg);
156                cg.addln("]");
157            }
158        } else {
159            for attr in &self.1 {
160                cg.add("#[");
161                attr.gen_rust(ctx, cg);
162                cg.addln("]");
163            }
164        }
165
166        self.0.gen_rust(ctx, cg);
167    }
168}
169
170impl GenRust for (&Vec<Spanned<FieldDeclStmt>>, &Spanned<ClassConstructor>) {
171    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
172        cg.add_indented(&format!(
173            "{}fn new{}(",
174            self.1.item.visibility.get_rust(),
175            self.1.item.generics.get_rust()
176        ));
177
178        self.1.item.params.gen_rust(ctx, cg);
179
180        cg.addln(") -> Self {");
181        cg.indent += 1;
182
183        cg.add_indentedln("let mut this: Self = unsafe { std::mem::MaybeUninit::<Self>::zeroed().assume_init() };");
184
185        for field in self.0 {
186            let comment = field.get_comment();
187
188            if let Some(init) = &field.item.init {
189                cg.add_indentedln(&comment);
190
191                cg.add_indentedln(&format!("this.{} = ", field.item.decl.name.get_rust()));
192
193                init.gen_rust(ctx, cg);
194            }
195        }
196
197        cg.add_indented(&format!("this.constructor("));
198
199        for (i, param) in self
200            .1
201            .item
202            .params
203            .0
204            .iter()
205            .map(|v| expr_pattern(&v.name))
206            .enumerate()
207        {
208            if i > 0 {
209                cg.add(", ");
210            }
211
212            ctx.expr_ensure_semicolon = false;
213            param.gen_rust(ctx, cg);
214        }
215
216        cg.addln(");");
217
218        cg.add_indentedln("this");
219
220        cg.indent -= 1;
221        cg.add_indentedln("}\n");
222
223        let mut constructor_params = vec![VarDecl {
224            name: Pattern::Path(false, Path(vec![Identifier(String::from("self"))])),
225            type_: Some(TypeExpr(
226                TypeExprKind::Path(Path(vec![Identifier(String::from("Self"))])),
227                vec![TypePostfix::RefMut],
228            )),
229        }];
230
231        constructor_params.append(&mut self.1.item.params.0.clone());
232
233        Spanned {
234            line: self.1.line,
235            column: self.1.column,
236            item: FunctionDecl {
237                visibility: self.1.item.visibility.clone(),
238                name: Identifier(String::from("constructor")),
239                generics: self.1.item.generics.clone(),
240                params: ParamList(constructor_params),
241                return_type: TypeExpr::no_px(TypeExprKind::Tuple(Vec::new())),
242                body: Some(self.1.item.body.clone()),
243            },
244        }
245        .gen_rust(ctx, cg);
246    }
247}
248
249pub fn expr_pattern(pat: &Pattern) -> Expression {
250    match pat {
251        Pattern::Literal(v) => Expression::Literal(v.clone()),
252        Pattern::Path(_, v) => Expression::Path(v.clone().into()),
253        Pattern::Tuple(items) => Expression::Literal(Literal::Tuple(
254            items.iter().map(|v| expr_pattern(&v)).collect(),
255        )),
256        Pattern::NamedTuple(path, items) => Expression::Fix {
257            initial: Box::new(Expression::Path(path.clone().into())),
258            prefixes: Vec::new(),
259            postfixes: vec![Postfix::Call(
260                items.iter().map(|v| expr_pattern(&v)).collect(),
261            )],
262        },
263        Pattern::Struct(_, _) => unimplemented!(),
264    }
265}
266
267impl GenRust for TopLevelKind {
268    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
269        match self {
270            Self::ModAttribute => {}
271            Self::Import(vis, path) => {
272                cg.addln(&format!("{}use {};", vis.get_rust(), path.get_rust()))
273            }
274            Self::Mod(vis, id) => cg.addln(&format!("{}mod {};", vis.get_rust(), id.get_rust())),
275            Self::FunctionDecl(decl) => decl.gen_rust(ctx, cg),
276            Self::ImplDecl(impl_) => impl_.gen_rust(ctx, cg),
277            Self::StructDecl {
278                visibility,
279                name,
280                generics,
281                fields,
282            } => {
283                cg.addln(&format!(
284                    "{}struct {}{} {{",
285                    visibility.get_rust(),
286                    name.get_rust(),
287                    generics.get_rust()
288                ));
289                cg.indent += 1;
290
291                for field in fields {
292                    cg.add_indentedln(&field.get_rust());
293                }
294
295                cg.indent -= 1;
296                cg.addln("}\n");
297            }
298            Self::EnumDecl {
299                visibility,
300                name,
301                generics,
302                fields,
303            } => {
304                cg.addln(&format!(
305                    "{}enum {}{} {{",
306                    visibility.get_rust(),
307                    name.get_rust(),
308                    generics.get_rust()
309                ));
310                cg.indent += 1;
311
312                for field in fields {
313                    cg.add_indentedln(&(field.get_rust() + ","));
314                }
315
316                cg.indent -= 1;
317                cg.addln("}\n");
318            }
319            Self::TraitDecl {
320                visibility,
321                name,
322                generics,
323                requirements,
324                items,
325            } => {
326                cg.addln(&format!(
327                    "{}trait {}{}{} {{",
328                    visibility.get_rust(),
329                    name.get_rust(),
330                    generics.get_rust(),
331                    if requirements.len() != 0 {
332                        String::from(": ")
333                            + &requirements
334                                .into_iter()
335                                .map(TypeExpr::get_rust)
336                                .collect::<Vec<_>>()
337                                .join("+")
338                    } else {
339                        String::new()
340                    },
341                ));
342                cg.indent += 1;
343
344                for item in items {
345                    item.gen_rust(ctx, cg);
346                }
347
348                cg.indent -= 1;
349                cg.addln("}\n");
350            }
351            Self::ClassDecl {
352                visibility,
353                name,
354                generics,
355                inherits,
356                fields,
357                constructor,
358                items,
359            } => {
360                // Struct decl
361                cg.addln(&format!(
362                    "{}struct {}{} {{",
363                    visibility.get_rust(),
364                    name.clone().get_rust(),
365                    generics.clone().get_rust()
366                ));
367                cg.indent += 1;
368
369                if let Some(inherits) = inherits {
370                    cg.add_indented("pub _super: ");
371                    cg.add(&inherits.get_rust());
372                    cg.addln(",");
373                }
374
375                for field in fields.clone() {
376                    cg.add_indentedln(&field.get_comment());
377                    cg.add_indentedln(&field.item.decl.get_rust());
378                }
379
380                cg.indent -= 1;
381                cg.addln("}\n");
382
383                // Constructor
384                cg.addln(&format!(
385                    "impl{} {}{} {{",
386                    generics.clone().get_rust(),
387                    name.clone().get_rust(),
388                    format!(
389                        "<{}>",
390                        generics
391                            .clone()
392                            .0
393                            .into_iter()
394                            .map(|v| Generic::from(v).get_rust())
395                            .collect::<Vec<_>>()
396                            .join(", ")
397                    )
398                ));
399                cg.indent += 1;
400
401                let constructor_comment = constructor.get_comment();
402
403                cg.add_indentedln("#[allow(invalid_value)]");
404                cg.add_indentedln(&constructor_comment);
405
406                (fields, constructor).gen_rust(ctx, cg);
407
408                for item in items.clone() {
409                    match item {
410                        ClassItem::ImplDecl(_) => {}
411                        ClassItem::Method(method) => method.gen_rust(ctx, cg),
412                    }
413                }
414
415                cg.indent -= 1;
416                cg.addln("}\n");
417
418                for item in items {
419                    match item {
420                        ClassItem::ImplDecl(impl_) => {
421                            let mut impl_ = impl_.clone();
422
423                            impl_.item.trait_ = Some(impl_.item.target);
424                            impl_.item.target =
425                                TypeExpr(TypeExprKind::Path(Path(vec![name.clone()])), Vec::new());
426
427                            impl_.gen_rust(ctx, cg);
428                        }
429                        ClassItem::Method(_) => {}
430                    }
431                }
432
433                if let Some(inherits) = inherits {
434                    cg.add("impl std::ops::Deref for ");
435                    cg.add(&name.get_rust());
436
437                    cg.addln(" {");
438                    cg.indent += 1;
439
440                    cg.add_indented("type Target = ");
441                    cg.add(&inherits.get_rust());
442                    cg.addln(";");
443
444                    cg.add_indentedln("fn deref(&self) -> &Self::Target {&self._super}");
445
446                    cg.indent -= 1;
447                    cg.addln("}");
448
449                    // Mut
450
451                    cg.add("impl std::ops::DerefMut for ");
452                    cg.add(&name.get_rust());
453
454                    cg.addln(" {");
455                    cg.indent += 1;
456
457                    cg.add_indentedln(
458                        "fn deref_mut(&mut self) -> &mut Self::Target {&mut self._super}",
459                    );
460
461                    cg.indent -= 1;
462                    cg.addln("}");
463                }
464            }
465        }
466    }
467}