Skip to main content

mist_codegen/
expr.rs

1use mist_parser::ast::*;
2
3use crate::Context;
4
5use crate::{GenRust, GetRust, RustCodegen};
6
7impl GetRust for ExprPath {
8    fn get_rust(&self) -> String {
9        self.0
10            .iter()
11            .map(ExprPathSegment::get_rust)
12            .collect::<Vec<_>>()
13            .join("::")
14    }
15
16    fn get_rust_ctx(&self, cx: &mut Context) -> String {
17        let mut a = self.clone();
18
19        if let Some(path) = &cx.expr_super {
20            if self.0[0].ident.0 == "super" && self.0.len() == 1 {
21                a.0[0].ident.0 = String::from("self._super");
22            } else if self.0[0].ident.0 == "Super" {
23                a.0[0] = path.0[0].clone();
24            }
25        }
26
27        a.get_rust()
28    }
29}
30
31impl GetRust for ExprPathSegment {
32    fn get_rust(&self) -> String {
33        format!(
34            "{}{}",
35            self.ident.get_rust(),
36            self.generics
37                .as_ref()
38                .map(|v| format!("::{}", v.get_rust()))
39                .unwrap_or_default()
40        )
41    }
42}
43
44impl GenRust for Literal {
45    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
46        match self {
47            Self::Int(n) => cg.add(&n.to_string()),
48            Self::Float(n) => cg.add(&format!("{n:?}")),
49            Self::Bool(b) => cg.add(&b.to_string()),
50            Self::String(s) => cg.add(&format!("\"{s}\"")),
51
52            Self::Tuple(values) => {
53                cg.add("(");
54
55                for (i, val) in values.iter().enumerate() {
56                    if i > 0 {
57                        cg.add(", ");
58                    }
59
60                    val.gen_rust(ctx, cg);
61                }
62
63                cg.add(")");
64            }
65        }
66    }
67}
68
69impl GenRust for Expression {
70    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
71        let ensure_semicolon = if ctx.expr_ensure_semicolon {
72            ctx.expr_ensure_semicolon = false;
73
74            true
75        } else {
76            false
77        };
78
79        match self {
80            Expression::Path(path) => cg.add(&path.get_rust_ctx(ctx)),
81            Expression::Literal(literal) => literal.gen_rust(ctx, cg),
82            Expression::Statement(stmt) => stmt.gen_rust(ctx, cg),
83            Expression::Array(values) => {
84                cg.add("[");
85
86                for (i, val) in values.iter().enumerate() {
87                    if i > 0 {
88                        cg.add(", ");
89                    }
90
91                    val.gen_rust(ctx, cg);
92                }
93
94                cg.add("]");
95            }
96            Expression::ArrayRepeat(value, repeat) => {
97                cg.add("[");
98                value.gen_rust(ctx, cg);
99                cg.add("; ");
100                repeat.gen_rust(ctx, cg);
101                cg.add("]");
102            }
103            Expression::Fix {
104                initial,
105                prefixes,
106                postfixes,
107            } => {
108                prefixes.gen_rust(ctx, cg);
109                initial.gen_rust(ctx, cg);
110                for postfix in postfixes {
111                    postfix.gen_rust(ctx, cg);
112                }
113            }
114
115            Expression::Binary { lhs, op, rhs } => {
116                if op == "->" {
117                    cg.add("unsafe { std::ptr::write(&mut ");
118                    lhs.gen_rust(ctx, cg);
119                    cg.add(", ");
120                    rhs.gen_rust(ctx, cg);
121                    cg.add(") }");
122                } else {
123                    lhs.gen_rust(ctx, cg);
124                    cg.add(op);
125                    rhs.gen_rust(ctx, cg);
126                }
127            }
128
129            Expression::Closure {
130                return_type,
131                params,
132                body,
133            } => {
134                cg.add("|");
135                for (i, arg) in params.iter().enumerate() {
136                    if i > 0 {
137                        cg.add(", ");
138                    }
139
140                    arg.gen_rust(ctx, cg);
141                }
142                cg.add("| ");
143
144                if let Some(ty) = return_type {
145                    cg.add("-> ");
146                    cg.add(&ty.get_rust());
147                    cg.add(" ");
148
149                    cg.ensure_brackets_expr(ctx, body);
150                } else {
151                    body.gen_rust(ctx, cg);
152                }
153            }
154        }
155
156        if ensure_semicolon {
157            ctx.expr_ensure_semicolon = true;
158
159            if !self.is_block() {
160                cg.add(";");
161            }
162        }
163    }
164}
165
166impl GenRust for Prefix {
167    fn gen_rust(&self, _ctx: &mut Context, cg: &mut RustCodegen) {
168        match self {
169            Self::Deref => cg.add("*"),
170            Self::Ref => cg.add("&"),
171            Self::RefMut => cg.add("&mut "),
172            Self::Not => cg.add("!"),
173            Self::Neg => cg.add("-"),
174        }
175    }
176}
177
178impl GenRust for Vec<Prefix> {
179    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
180        for prefix in self {
181            prefix.gen_rust(ctx, cg);
182        }
183    }
184}
185
186impl GenRust for Postfix {
187    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
188        match self {
189            Postfix::TupleFieldAccess(field, generics) => cg.add(&format!(
190                ".{}{}",
191                field,
192                generics
193                    .iter()
194                    .map(|v| format!("::{}", v.get_rust()))
195                    .collect::<String>()
196            )),
197            Postfix::FieldAccess(field, generics) => cg.add(&format!(
198                ".{}{}",
199                field.get_rust(),
200                generics
201                    .iter()
202                    .map(|v| format!("::{}", v.get_rust()))
203                    .collect::<String>()
204            )),
205
206            Postfix::Call(args) => {
207                cg.add("(");
208
209                for (i, arg) in args.iter().enumerate() {
210                    if i > 0 {
211                        cg.add(", ");
212                    }
213
214                    arg.gen_rust(ctx, cg);
215                }
216
217                cg.add(")");
218            }
219
220            Postfix::MacroCall { inner, delimiter } => {
221                let (open, close) = match delimiter {
222                    MacroDelimiter::Paren => ("!(", ")"),
223                    MacroDelimiter::Bracket => ("![", "]"),
224                    MacroDelimiter::Brace => ("!{", "}"),
225                };
226                cg.add(open);
227                cg.add(inner);
228                cg.add(close);
229            }
230
231            Postfix::StructCall(fields) => {
232                cg.add("{");
233
234                for (name, expr) in fields {
235                    cg.add(&name.get_rust());
236                    if let Some(expr) = expr {
237                        cg.add(": ");
238                        expr.gen_rust(ctx, cg);
239                    }
240                    cg.add(",");
241                }
242
243                cg.add("}");
244            }
245
246            Postfix::Index(idx) => {
247                cg.add("[");
248                idx.gen_rust(ctx, cg);
249                cg.add("]");
250            }
251
252            Postfix::As(ty) => {
253                cg.add(" as ");
254                cg.add(&ty.get_rust());
255            }
256
257            Postfix::Try => cg.add("?"),
258
259            Postfix::Assign(cmp, expr) => {
260                cg.add(" ");
261                cg.add(cmp);
262                expr.gen_rust(ctx, cg);
263            }
264            Postfix::Increment => cg.add("+=1"),
265            Postfix::Decrement => cg.add("-=1"),
266        }
267    }
268}
269
270impl GetRust for Generics {
271    fn get_rust(&self) -> String {
272        if self.0.len() == 0 {
273            String::new()
274        } else {
275            format!(
276                "<{}>",
277                self.0
278                    .iter()
279                    .map(Generic::get_rust)
280                    .collect::<Vec<_>>()
281                    .join(", ")
282            )
283        }
284    }
285}
286
287impl GetRust for Generic {
288    fn get_rust(&self) -> String {
289        match self {
290            Self::Lifetime(name) => format!("'{}", name.get_rust()),
291            Self::Type(ty) => ty.get_rust(),
292        }
293    }
294}