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