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::FieldAccess(field, generics) => cg.add(&format!(
157                ".{}{}",
158                field.get_rust(),
159                generics
160                    .iter()
161                    .map(|v| format!("::{}", v.get_rust()))
162                    .collect::<String>()
163            )),
164
165            Postfix::Call(args) => {
166                cg.add("(");
167
168                for (i, arg) in args.iter().enumerate() {
169                    if i > 0 {
170                        cg.add(", ");
171                    }
172
173                    arg.gen_rust(ctx, cg);
174                }
175
176                cg.add(")");
177            }
178
179            Postfix::MacroCall { inner, delimiter } => {
180                let (open, close) = match delimiter {
181                    MacroDelimiter::Paren => ("!(", ")"),
182                    MacroDelimiter::Bracket => ("![", "]"),
183                    MacroDelimiter::Brace => ("!{", "}"),
184                };
185                cg.add(open);
186                cg.add(inner);
187                cg.add(close);
188            }
189
190            Postfix::StructCall(fields) => {
191                cg.add("{");
192
193                for (name, expr) in fields {
194                    cg.add(&name.get_rust());
195                    cg.add(": ");
196                    expr.gen_rust(ctx, cg);
197                    cg.add(",");
198                }
199
200                cg.add("}");
201            }
202
203            Postfix::Index(idx) => {
204                cg.add("[");
205                idx.gen_rust(ctx, cg);
206                cg.add("]");
207            }
208
209            Postfix::As(ty) => {
210                cg.add(" as ");
211                cg.add(&ty.get_rust());
212            }
213
214            Postfix::Try => cg.add("?"),
215
216            Postfix::Assign(cmp, expr) => {
217                cg.add(" ");
218                cg.add(cmp);
219                expr.gen_rust(ctx, cg);
220            }
221            Postfix::Increment => cg.add("+=1"),
222            Postfix::Decrement => cg.add("-=1"),
223        }
224    }
225}
226
227impl GetRust for Generics {
228    fn get_rust(&self) -> String {
229        if self.0.len() == 0 {
230            String::new()
231        } else {
232            format!(
233                "<{}>",
234                self.0
235                    .iter()
236                    .map(Generic::get_rust)
237                    .collect::<Vec<_>>()
238                    .join(", ")
239            )
240        }
241    }
242}
243
244impl GetRust for Generic {
245    fn get_rust(&self) -> String {
246        match self {
247            Self::Lifetime(name) => format!("'{}", name.get_rust()),
248            Self::Type(ty) => ty.get_rust(),
249        }
250    }
251}