Skip to main content

mist_codegen/
top_level.rs

1use mist_parser::ast::*;
2
3use crate::{Context, class_decl};
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 TopLevelKind {
174    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
175        match self {
176            Self::ModAttribute => {}
177            Self::Import(vis, path) => {
178                cg.addln(&format!("{}use {};", vis.get_rust(), path.get_rust()))
179            }
180            Self::Mod(vis, id) => cg.addln(&format!("{}mod {};", vis.get_rust(), id.get_rust())),
181            Self::FunctionDecl(decl) => decl.gen_rust(ctx, cg),
182            Self::ImplDecl(impl_) => impl_.gen_rust(ctx, cg),
183            Self::StructDecl {
184                visibility,
185                name,
186                generics,
187                fields,
188            } => {
189                cg.addln(&format!(
190                    "{}struct {}{} {{",
191                    visibility.get_rust(),
192                    name.get_rust(),
193                    generics.get_rust()
194                ));
195                cg.indent += 1;
196
197                for field in fields {
198                    cg.add_indentedln(&field.get_rust());
199                }
200
201                cg.indent -= 1;
202                cg.addln("}\n");
203            }
204            Self::EnumDecl {
205                visibility,
206                name,
207                generics,
208                fields,
209            } => {
210                cg.addln(&format!(
211                    "{}enum {}{} {{",
212                    visibility.get_rust(),
213                    name.get_rust(),
214                    generics.get_rust()
215                ));
216                cg.indent += 1;
217
218                for field in fields {
219                    cg.add_indentedln(&(field.get_rust() + ","));
220                }
221
222                cg.indent -= 1;
223                cg.addln("}\n");
224            }
225            Self::TraitDecl {
226                visibility,
227                name,
228                generics,
229                requirements,
230                items,
231            } => {
232                cg.addln(&format!(
233                    "{}trait {}{}{} {{",
234                    visibility.get_rust(),
235                    name.get_rust(),
236                    generics.get_rust(),
237                    if requirements.len() != 0 {
238                        String::from(": ")
239                            + &requirements
240                                .into_iter()
241                                .map(TypeExpr::get_rust)
242                                .collect::<Vec<_>>()
243                                .join("+")
244                    } else {
245                        String::new()
246                    },
247                ));
248                cg.indent += 1;
249
250                for item in items {
251                    item.gen_rust(ctx, cg);
252                }
253
254                cg.indent -= 1;
255                cg.addln("}\n");
256            }
257            Self::ClassDecl {
258                visibility,
259                name,
260                generics,
261                inherits,
262                fields,
263                constructor,
264                items,
265            } => class_decl::class_decl(
266                ctx,
267                cg,
268                visibility,
269                name,
270                generics,
271                inherits,
272                fields,
273                constructor,
274                items,
275            ),
276        }
277    }
278}