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        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 match_item in match_items {
63                    cg.add_indentedln(&match_item.get_comment());
64
65                    let MatchItem(pat, body) = &match_item.item;
66
67                    for (i, p) in pat.iter().enumerate() {
68                        cg.addln("");
69                        cg.add_indented("");
70                        if i > 0 {
71                            cg.add(" | ");
72                        }
73
74                        p.gen_rust(ctx, cg);
75                    }
76
77                    cg.add(" => ");
78
79                    cg.ensure_brackets_expr(ctx, body);
80                }
81
82                cg.indent -= 1;
83                cg.addln("");
84                cg.add_indented("}");
85            }
86
87            Statement::If {
88                initial,
89                else_if,
90                else_branch,
91            } => {
92                cg.add("if ");
93                initial.condition.gen_rust(ctx, cg);
94                cg.add(" ");
95                cg.ensure_brackets_body(ctx, &initial.body);
96
97                for else_if_branch in else_if {
98                    cg.add("else if");
99                    else_if_branch.condition.gen_rust(ctx, cg);
100                    cg.add(" ");
101                    cg.ensure_brackets_body(ctx, &else_if_branch.body);
102                }
103
104                if let Some(else_br) = else_branch {
105                    cg.add(" else ");
106                    cg.ensure_brackets_body(ctx, else_br);
107                }
108            }
109
110            Statement::While(StatementBranch { condition, body }) => {
111                cg.add("while ");
112                condition.gen_rust(ctx, cg);
113                cg.add(" ");
114                cg.ensure_brackets_body(ctx, body);
115            }
116
117            Statement::Loop(body) => {
118                cg.add("loop ");
119                cg.ensure_brackets_body(ctx, body);
120            }
121
122            Statement::CStyleFor {
123                init,
124                condition,
125                update,
126                body,
127            } => {
128                cg.addln("{");
129                cg.indent += 1;
130
131                ctx.expr_ensure_semicolon = true;
132
133                cg.add_indented("");
134
135                init.gen_rust(ctx, cg);
136
137                cg.addln("");
138
139                cg.add_indented("while ");
140
141                ctx.expr_ensure_semicolon = false;
142                condition.gen_rust(ctx, cg);
143
144                cg.add(" ");
145
146                cg.add("{");
147                cg.indent += 1;
148
149                ctx.expr_ensure_semicolon = true;
150
151                body.gen_rust(ctx, cg);
152
153                update.gen_rust(ctx, cg);
154
155                cg.addln("");
156
157                cg.indent -= 1;
158                cg.add_indentedln("}");
159
160                cg.indent -= 1;
161                cg.add_indented("}");
162            }
163
164            Statement::For {
165                pattern,
166                iterator,
167                body,
168            } => {
169                cg.add("for ");
170                pattern.gen_rust(ctx, cg);
171                cg.add(" in ");
172                iterator.gen_rust(ctx, cg);
173                cg.ensure_brackets_body(ctx, body);
174            }
175
176            Statement::Return(expr) => {
177                cg.add("return ");
178                if let Some(expr) = expr {
179                    expr.gen_rust(ctx, cg);
180                }
181            }
182
183            Statement::Break => cg.add_indentedln("break"),
184            Statement::Continue => cg.add_indentedln("continue"),
185        }
186    }
187}
188
189impl GenRust for VarDecl {
190    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
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}