Skip to main content

mist_codegen/
statement.rs

1use mist_parser::ast::*;
2
3use crate::{Context, get_mutable};
4
5use crate::{GenRust, GetRust, RustCodegen};
6
7impl GenRust for Block {
8    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
9        cg.addln("{");
10        cg.indent += 1;
11
12        for stmt in &self.0 {
13            ctx.expr_ensure_semicolon = true;
14            stmt.gen_rust(ctx, cg);
15            cg.addln("");
16        }
17
18        if let Some(soft_return) = &self.1 {
19            ctx.expr_ensure_semicolon = false;
20            soft_return.gen_rust(ctx, cg);
21            cg.addln("");
22        }
23
24        cg.indent -= 1;
25        cg.add_indented("}");
26    }
27}
28
29impl GenRust for StatementBody {
30    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
31        match self {
32            Self::Expression(expr) => expr.gen_rust(ctx, cg),
33            Self::Statement(stmt) => {
34                ctx.expr_ensure_semicolon = true;
35                stmt.gen_rust(ctx, cg);
36            }
37        }
38    }
39}
40
41impl GenRust for Statement {
42    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
43        match self {
44            Statement::Block(block) => block.gen_rust(ctx, cg),
45
46            Statement::VarDecl(VarDeclStmt { decl, init }) => {
47                cg.add("let ");
48                decl.gen_rust(ctx, cg);
49
50                if let Some(init) = init {
51                    cg.add(" = ");
52                    init.gen_rust(ctx, cg);
53                }
54            }
55
56            Statement::Match(expr, match_items) => {
57                cg.add("match ");
58                expr.gen_rust(ctx, cg);
59                cg.add(" {");
60                cg.indent += 1;
61
62                for (pat, body) in match_items {
63                    for (i, p) in pat.iter().enumerate() {
64                        cg.addln("");
65                        cg.add_indented("");
66                        if i > 0 {
67                            cg.add(" | ");
68                        }
69
70                        p.gen_rust(ctx, cg);
71                    }
72
73                    cg.add(" => ");
74
75                    cg.ensure_brackets_expr(ctx, body);
76                }
77
78                cg.indent -= 1;
79                cg.addln("");
80                cg.add_indented("}");
81            }
82
83            Statement::If {
84                initial,
85                else_if,
86                else_branch,
87            } => {
88                cg.add("if ");
89                initial.condition.gen_rust(ctx, cg);
90                cg.add(" ");
91                cg.ensure_brackets_body(ctx, &initial.body);
92
93                for else_if_branch in else_if {
94                    cg.add("else if");
95                    else_if_branch.condition.gen_rust(ctx, cg);
96                    cg.add(" ");
97                    cg.ensure_brackets_body(ctx, &else_if_branch.body);
98                }
99
100                if let Some(else_br) = else_branch {
101                    cg.add(" else ");
102                    cg.ensure_brackets_body(ctx, else_br);
103                }
104            }
105
106            Statement::While(StatementBranch { condition, body }) => {
107                cg.add("while ");
108                condition.gen_rust(ctx, cg);
109                cg.add(" ");
110                cg.ensure_brackets_body(ctx, body);
111            }
112
113            Statement::Loop(body) => {
114                cg.add("loop ");
115                cg.ensure_brackets_body(ctx, body);
116            }
117
118            Statement::CStyleFor {
119                init,
120                condition,
121                update,
122                body,
123            } => {
124                cg.addln("{");
125                cg.indent += 1;
126
127                ctx.expr_ensure_semicolon = true;
128
129                cg.add_indented("");
130
131                init.gen_rust(ctx, cg);
132
133                cg.addln("");
134
135                cg.add_indented("while ");
136
137                ctx.expr_ensure_semicolon = false;
138                condition.gen_rust(ctx, cg);
139
140                cg.add(" ");
141
142                cg.add("{");
143                cg.indent += 1;
144
145                ctx.expr_ensure_semicolon = true;
146
147                body.gen_rust(ctx, cg);
148
149                update.gen_rust(ctx, cg);
150
151                cg.addln("");
152
153                cg.indent -= 1;
154                cg.add_indentedln("}");
155
156                cg.indent -= 1;
157                cg.add_indented("}");
158            }
159
160            Statement::For {
161                mutable,
162                pattern,
163                iterator,
164                body,
165            } => {
166                cg.add("for ");
167                cg.add(&get_mutable(*mutable));
168                pattern.gen_rust(ctx, cg);
169                cg.add(" in ");
170                iterator.gen_rust(ctx, cg);
171                cg.ensure_brackets_body(ctx, body);
172            }
173
174            Statement::Return(expr) => {
175                cg.add("return ");
176                if let Some(expr) = expr {
177                    expr.gen_rust(ctx, cg);
178                }
179            }
180
181            Statement::Break => cg.add_indentedln("break"),
182            Statement::Continue => cg.add_indentedln("continue"),
183        }
184    }
185}
186
187impl GenRust for VarDecl {
188    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
189        cg.add(&get_mutable(self.mutable));
190
191        self.name.gen_rust(ctx, cg);
192
193        cg.add(
194            &self
195                .type_
196                .as_ref()
197                .map(|t| format!(": {}", t.get_rust()))
198                .unwrap_or_default(),
199        );
200    }
201}