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}