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                cg.add(&prefixes.get_rust());
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 GetRust for Prefix {
114    fn get_rust(&self) -> String {
115        match self {
116            Self::Deref => "*",
117            Self::Ref => "&",
118            Self::RefMut => "&mut ",
119            Self::Not => "!",
120            Self::New(_) => "",
121            Self::Neg => "-",
122        }
123        .to_string()
124    }
125}
126
127impl GetRust for Vec<Prefix> {
128    fn get_rust(&self) -> String {
129        self.into_iter().map(Prefix::get_rust).collect()
130    }
131}
132
133impl GetRust for Option<&Vec<Prefix>> {
134    fn get_rust(&self) -> String {
135        if let Some(prefixes) = self {
136            prefixes
137                .into_iter()
138                .last()
139                .map(|p| match p {
140                    Prefix::New(generics) => format!(
141                        "::new{}",
142                        generics
143                            .clone()
144                            .map(|v| format!("::{}", v.get_rust()))
145                            .unwrap_or_default(),
146                    ),
147                    _ => String::new(),
148                })
149                .unwrap_or_default()
150                .to_string()
151        } else {
152            String::new()
153        }
154    }
155}
156
157impl GenRust for Postfix {
158    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
159        match self {
160            Postfix::FieldAccess(field, generics) => cg.add(&format!(
161                ".{}{}",
162                field.get_rust(),
163                generics
164                    .iter()
165                    .map(|v| format!("::{}", v.get_rust()))
166                    .collect::<String>()
167            )),
168
169            Postfix::Call(args) => {
170                cg.add("(");
171
172                for (i, arg) in args.iter().enumerate() {
173                    if i > 0 {
174                        cg.add(", ");
175                    }
176
177                    arg.gen_rust(ctx, cg);
178                }
179
180                cg.add(")");
181            }
182
183            Postfix::MacroCall(inner) => {
184                cg.add("!(");
185                cg.add(inner);
186                cg.add(")");
187            }
188
189            Postfix::StructCall(fields) => {
190                cg.add("{");
191
192                for (name, expr) in fields {
193                    cg.add(&name.get_rust());
194                    cg.add(": ");
195                    expr.gen_rust(ctx, cg);
196                    cg.add(",");
197                }
198
199                cg.add("}");
200            }
201
202            Postfix::Index(idx) => {
203                cg.add("[");
204                idx.gen_rust(ctx, cg);
205                cg.add("]");
206            }
207
208            Postfix::As(ty) => {
209                cg.add(" as ");
210                cg.add(&ty.get_rust());
211            }
212
213            Postfix::Try => cg.add("?"),
214
215            Postfix::Assign(cmp, expr) => {
216                cg.add(" ");
217                cg.add(cmp);
218                expr.gen_rust(ctx, cg);
219            }
220            Postfix::Increment => cg.add("+=1"),
221            Postfix::Decrement => cg.add("-=1"),
222        }
223    }
224}
225
226impl GetRust for Generics {
227    fn get_rust(&self) -> String {
228        if self.0.len() == 0 {
229            String::new()
230        } else {
231            format!(
232                "<{}>",
233                self.0
234                    .iter()
235                    .map(Generic::get_rust)
236                    .collect::<Vec<_>>()
237                    .join(", ")
238            )
239        }
240    }
241}
242
243impl GetRust for Generic {
244    fn get_rust(&self) -> String {
245        match self {
246            Self::Lifetime(name) => format!("'{}", name.get_rust()),
247            Self::Type(ty) => ty.get_rust(),
248        }
249    }
250}