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 Visibility {
160 fn get_rust(&self) -> String {
161 match self {
162 Visibility::Public => "pub ".to_string(),
163 Visibility::PublicTarget(path) => format!("pub({}) ", path.get_rust()),
164 Visibility::Private => "".to_string(),
165 }
166 }
167}
168
169impl GetRust for Identifier {
170 fn get_rust(&self) -> String {
171 self.0.clone()
172 }
173}
174
175impl GetRust for TypeExpr {
176 fn get_rust(&self) -> String {
177 match self {
178 Self::Path(path, generics) => {
184 if let Some(generics) = generics {
185 format!("{}{}", get_static_type_path(path), generics.get_rust())
186 } else {
187 get_static_type_path(path)
188 }
189 }
190 Self::Lifetime(name) => format!("'{}", name.get_rust()),
191 Self::Tuple(types) => format!(
192 "({})",
193 types
194 .into_iter()
195 .map(|t| t.get_rust())
196 .collect::<Vec<_>>()
197 .join(", ")
198 ),
199
200 Self::Ref {
201 lifetime,
202 mutable,
203 ty,
204 } => {
205 let mutable = if *mutable { "mut " } else { "" };
206
207 if let Some(lifetime) = lifetime {
208 format!("&'{} {mutable}{}", lifetime.get_rust(), ty.get_rust())
209 } else {
210 format!("&{mutable}{}", ty.get_rust())
211 }
212 }
213
214 Self::Dyn(ty) => {
215 format!("dyn {}", ty.get_rust())
216 }
217 }
218 }
219}
220
221pub fn get_static_type_path(path: &Path) -> String {
222 let rust_path = path.get_rust();
223
224 if rust_path == "void" {
225 format!("()")
226 } else {
227 rust_path
228 }
229}
230
231impl GenRust for Pattern {
232 fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
233 match self {
234 Self::Etc => cg.add(".."),
235 Self::Literal(lit) => lit.gen_rust(ctx, cg),
236 Self::Path(mutable, path) => {
237 if *mutable {
238 cg.add("mut ");
239 };
240
241 cg.add(&path.get_rust())
242 }
243 Self::Struct(path, inner) => {
244 cg.add(&path.get_rust());
245 cg.add(" {");
246
247 for (idx, i) in inner.iter().enumerate() {
248 if idx > 0 {
249 cg.add(", ");
250 }
251
252 if let Some((name, pat)) = i {
253 cg.add(&name.get_rust());
254 if let Some(pat) = pat {
255 cg.add(": ");
256 pat.gen_rust(ctx, cg);
257 }
258 } else {
259 cg.add("..");
260 }
261 }
262
263 cg.add("}");
264 }
265
266 Self::NamedTuple(path, inner) => {
267 cg.add(&path.get_rust());
268 cg.add(" (");
269 for pat in inner {
270 pat.gen_rust(ctx, cg);
271 cg.add(",");
272 }
273 cg.add(")");
274 }
275
276 Self::Tuple(inner) => {
277 cg.add("(");
278 for pat in inner {
279 pat.gen_rust(ctx, cg);
280 cg.add(",");
281 }
282 cg.add(")");
283 }
284 }
285 }
286}