Skip to main content

mist_codegen/
lib.rs

1pub mod expr;
2pub mod statement;
3pub mod top_level;
4
5use mist_parser::ast::*;
6
7pub struct Context {
8    pub expr_ensure_semicolon: bool,
9}
10
11pub trait GenRust {
12    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen);
13}
14
15pub trait GetRust {
16    fn get_rust(&self) -> String;
17}
18
19#[derive(Default)]
20pub struct RustCodegen {
21    output: String,
22    indent: usize,
23}
24
25impl RustCodegen {
26    pub fn new() -> Self {
27        Self {
28            output: String::new(),
29            indent: 0,
30        }
31    }
32
33    fn indent_str(&self) -> String {
34        "    ".repeat(self.indent)
35    }
36
37    fn add(&mut self, s: &str) {
38        self.output.push_str(s);
39    }
40
41    fn addln(&mut self, s: &str) {
42        self.add(s);
43        self.add("\n");
44    }
45
46    fn add_indented(&mut self, s: &str) {
47        let line = format!("{}{}", self.indent_str(), s);
48        self.add(&line);
49    }
50
51    fn add_indentedln(&mut self, s: &str) {
52        let line = format!("{}{}\n", self.indent_str(), s);
53        self.add(&line);
54    }
55
56    pub fn generate(&mut self, toplevels: Vec<TopLevel>) -> String {
57        let mut ctx = Context {
58            expr_ensure_semicolon: true,
59        };
60
61        for tl in toplevels {
62            tl.gen_rust(&mut ctx, self);
63        }
64
65        self.output.clone()
66    }
67
68    pub fn ensure_brackets(&mut self, ctx: &mut Context, stmt: &Box<Statement>) {
69        match &**stmt {
70            Statement::Block(_) => stmt.gen_rust(ctx, self),
71            _ => {
72                self.add("{");
73                self.indent += 1;
74                stmt.gen_rust(ctx, self);
75                self.indent -= 1;
76                self.add("}");
77            }
78        }
79    }
80
81    pub fn ensure_brackets_expr(&mut self, ctx: &mut Context, expr: &Expression) {
82        match expr {
83            Expression::Statement(stmt) => self.ensure_brackets(ctx, stmt),
84            _ => {
85                self.add("{");
86                self.indent += 1;
87                expr.gen_rust(ctx, self);
88                self.indent -= 1;
89                self.add("}");
90            }
91        }
92    }
93
94    pub fn ensure_brackets_body(&mut self, ctx: &mut Context, body: &StatementBody) {
95        match body {
96            StatementBody::Expression(expr) => self.ensure_brackets_expr(ctx, expr),
97
98            StatementBody::Statement(expr) => {
99                ctx.expr_ensure_semicolon = true;
100                self.ensure_brackets_expr(ctx, expr);
101            }
102        }
103    }
104}
105
106impl GenRust for Attribute {
107    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
108        match self {
109            Self::Path(path) => cg.add(&path.get_rust()),
110            Self::NameValue { path, value } => {
111                cg.add(&format!("{} = ", path.get_rust()));
112                value.gen_rust(ctx, cg);
113            }
114            Self::List { path, items } => {
115                cg.add(&path.get_rust());
116                cg.add("(");
117                for (i, item) in items.iter().enumerate() {
118                    if i > 0 {
119                        cg.add(", ");
120                    }
121
122                    item.gen_rust(ctx, cg);
123                }
124                cg.add(")");
125            }
126        }
127    }
128}
129
130impl<T: GetRust> GetRust for Spanned<T> {
131    fn get_rust(&self) -> String {
132        format!(
133            "/* {}:{} */ {}",
134            self.line,
135            self.column,
136            self.item.get_rust()
137        )
138    }
139}
140
141impl<T: GenRust> GenRust for Spanned<T> {
142    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
143        cg.add_indentedln(&format!("/* {}:{} */", self.line, self.column));
144        cg.add_indented("");
145        self.item.gen_rust(ctx, cg);
146    }
147}
148
149impl GetRust for Path {
150    fn get_rust(&self) -> String {
151        self.0
152            .iter()
153            .map(Identifier::get_rust)
154            .collect::<Vec<String>>()
155            .join("::")
156    }
157}
158
159impl GetRust for TypePostfix {
160    fn get_rust(&self) -> String {
161        match self {
162            TypePostfix::Ref => format!("&"),
163            TypePostfix::RefMut => format!("&mut "),
164            TypePostfix::RefLifetime(lifetime) => format!("&'{} ", lifetime.get_rust()),
165            TypePostfix::RefMutLifetime(lifetime) => format!("&'{} mut ", lifetime.get_rust()),
166            TypePostfix::Dyn => format!("dyn "),
167        }
168    }
169}
170
171impl GetRust for Visibility {
172    fn get_rust(&self) -> String {
173        match self {
174            Visibility::Public => "pub ".to_string(),
175            Visibility::PublicTarget(path) => format!("pub({}) ", path.get_rust()),
176            Visibility::Private => "".to_string(),
177        }
178    }
179}
180
181impl GetRust for Identifier {
182    fn get_rust(&self) -> String {
183        self.0.clone()
184    }
185}
186
187impl GetRust for TypeExpr {
188    fn get_rust(&self) -> String {
189        self.1
190            .iter()
191            .map(TypePostfix::get_rust)
192            .rev()
193            .collect::<String>()
194            + &self.0.get_rust()
195    }
196}
197
198pub fn get_static_type_path(path: &Path) -> String {
199    let rust_path = path.get_rust();
200
201    if rust_path == "void" {
202        format!("()")
203    } else {
204        rust_path
205    }
206}
207
208impl GetRust for TypeExprKind {
209    fn get_rust(&self) -> String {
210        match self {
211            TypeExprKind::Path(path) => get_static_type_path(path),
212            TypeExprKind::Lifetime(name) => format!("'{}", name.get_rust()),
213            TypeExprKind::PathParams(path, params) => {
214                format!(
215                    "{}<{}>",
216                    get_static_type_path(path),
217                    params
218                        .into_iter()
219                        .map(|t| t.get_rust())
220                        .collect::<Vec<_>>()
221                        .join(", ")
222                )
223            }
224            TypeExprKind::Tuple(types) => format!(
225                "({})",
226                types
227                    .into_iter()
228                    .map(|t| t.get_rust())
229                    .collect::<Vec<_>>()
230                    .join(", ")
231            ),
232        }
233    }
234}
235
236impl GenRust for Pattern {
237    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
238        match self {
239            Self::Path(mutable, path) => {
240                if *mutable {
241                    cg.add("mut ");
242                };
243
244                cg.add(&path.get_rust())
245            }
246            Self::Literal(lit) => lit.gen_rust(ctx, cg),
247
248            Self::Struct(path, inner) => {
249                cg.add(&path.get_rust());
250                cg.add(" {");
251                for pat in inner {
252                    pat.gen_rust(ctx, cg);
253                    cg.add(",");
254                }
255                cg.add("}");
256            }
257
258            Self::NamedTuple(path, inner) => {
259                cg.add(&path.get_rust());
260                cg.add(" (");
261                for pat in inner {
262                    pat.gen_rust(ctx, cg);
263                    cg.add(",");
264                }
265                cg.add(")");
266            }
267
268            Self::Tuple(inner) => {
269                cg.add("(");
270                for pat in inner {
271                    pat.gen_rust(ctx, cg);
272                    cg.add(",");
273                }
274                cg.add(")");
275            }
276        }
277    }
278}