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