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