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