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                ctx.expr_ensure_semicolon = false;
94                initial.condition.gen_rust(ctx, cg);
95                cg.add(" ");
96                cg.ensure_brackets_body(ctx, &initial.body);
97
98                for else_if_branch in else_if {
99                    cg.add(" else if ");
100                    ctx.expr_ensure_semicolon = false;
101                    else_if_branch.condition.gen_rust(ctx, cg);
102                    cg.add(" ");
103                    cg.ensure_brackets_body(ctx, &else_if_branch.body);
104                }
105
106                if let Some(else_br) = else_branch {
107                    cg.add(" else ");
108                    cg.ensure_brackets_body(ctx, else_br);
109                }
110            }
111
112            Statement::While(StatementBranch { condition, body }) => {
113                cg.add("while ");
114                condition.gen_rust(ctx, cg);
115                cg.add(" ");
116                cg.ensure_brackets_body(ctx, body);
117            }
118
119            Statement::Loop(body) => {
120                cg.add("loop ");
121                cg.ensure_brackets_body(ctx, body);
122            }
123
124            Statement::CStyleFor {
125                init,
126                condition,
127                update,
128                body,
129            } => {
130                cg.addln("{");
131                cg.indent += 1;
132
133                ctx.expr_ensure_semicolon = true;
134
135                cg.add_indented("");
136
137                init.gen_rust(ctx, cg);
138
139                cg.addln("");
140
141                cg.add_indented("while ");
142
143                ctx.expr_ensure_semicolon = false;
144                condition.gen_rust(ctx, cg);
145
146                cg.add(" ");
147
148                cg.add("{");
149                cg.indent += 1;
150
151                ctx.expr_ensure_semicolon = true;
152
153                body.gen_rust(ctx, cg);
154
155                update.gen_rust(ctx, cg);
156
157                cg.addln("");
158
159                cg.indent -= 1;
160                cg.add_indentedln("}");
161
162                cg.indent -= 1;
163                cg.add_indented("}");
164            }
165
166            Statement::For {
167                pattern,
168                iterator,
169                body,
170            } => {
171                cg.add("for ");
172                pattern.gen_rust(ctx, cg);
173                cg.add(" in ");
174                iterator.gen_rust(ctx, cg);
175                cg.ensure_brackets_body(ctx, body);
176            }
177
178            Statement::Return(expr) => {
179                cg.add("return ");
180                if let Some(expr) = expr {
181                    expr.gen_rust(ctx, cg);
182                }
183            }
184
185            Statement::Break => cg.add_indentedln("break"),
186            Statement::Continue => cg.add_indentedln("continue"),
187        }
188    }
189}
190
191impl GenRust for VarDecl {
192    fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) {
193        self.name.gen_rust(ctx, cg);
194
195        cg.add(
196            &self
197                .type_
198                .as_ref()
199                .map(|t| format!(": {}", t.get_rust()))
200                .unwrap_or_default(),
201        );
202    }
203}