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, generics) => {
212 if let Some(generics) = generics {
213 format!("{}{}", get_static_type_path(path), generics.get_rust())
214 } else {
215 get_static_type_path(path)
216 }
217 }
218 TypeExprKind::Lifetime(name) => format!("'{}", name.get_rust()),
219 TypeExprKind::Tuple(types) => format!(
220 "({})",
221 types
222 .into_iter()
223 .map(|t| t.get_rust())
224 .collect::<Vec<_>>()
225 .join(", ")
226 ),
227 }
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}