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