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