Skip to main content

mist_codegen/
statement.rs

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