neo_solidity/ir/statements/dispatch/
control_flow.rs1fn lower_block_statement(
2 statements: &[Statement],
3 ctx: &mut LoweringContext,
4 instructions: &mut Vec<Instruction>,
5) -> bool {
6 ctx.enter_scope();
7 let mut returned = false;
8 for stmt in statements {
9 if lower_statement(stmt, ctx, instructions) {
10 returned = true;
11 break;
12 }
13 }
14 ctx.exit_scope();
15 returned
16}
17
18fn lower_if_statement(
19 condition: &Expression,
20 then_stmt: &Statement,
21 else_stmt: Option<&Statement>,
22 ctx: &mut LoweringContext,
23 instructions: &mut Vec<Instruction>,
24) -> bool {
25 let else_label = ctx.next_label();
26 let end_label = if else_stmt.is_some() {
27 ctx.next_label()
28 } else {
29 else_label
30 };
31
32 lower_expression(condition, ctx, instructions);
33 instructions.push(Instruction::JumpIf { target: else_label });
34
35 let then_returns = lower_statement(then_stmt, ctx, instructions);
36
37 if let Some(else_stmt) = else_stmt {
38 instructions.push(Instruction::Jump { target: end_label });
39 instructions.push(Instruction::Label(else_label));
40 let else_returns = lower_statement(else_stmt, ctx, instructions);
41 instructions.push(Instruction::Label(end_label));
42 then_returns && else_returns
43 } else {
44 instructions.push(Instruction::Label(else_label));
45 false
46 }
47}
48
49fn lower_while_statement(
50 condition: &Expression,
51 body: &Statement,
52 ctx: &mut LoweringContext,
53 instructions: &mut Vec<Instruction>,
54) -> bool {
55 let start_label = ctx.next_label();
56 let end_label = ctx.next_label();
57
58 instructions.push(Instruction::Label(start_label));
59 lower_expression(condition, ctx, instructions);
60 instructions.push(Instruction::JumpIf { target: end_label });
61 ctx.push_loop(start_label, end_label);
62 lower_statement(body, ctx, instructions);
63 ctx.pop_loop();
64 instructions.push(Instruction::Jump {
65 target: start_label,
66 });
67 instructions.push(Instruction::Label(end_label));
68 false
69}
70
71fn lower_do_while_statement(
72 body: &Statement,
73 condition: &Expression,
74 ctx: &mut LoweringContext,
75 instructions: &mut Vec<Instruction>,
76) -> bool {
77 let start_label = ctx.next_label();
78 let condition_label = ctx.next_label();
79 let end_label = ctx.next_label();
80
81 instructions.push(Instruction::Label(start_label));
82 ctx.push_loop(condition_label, end_label);
83 lower_statement(body, ctx, instructions);
84 ctx.pop_loop();
85 instructions.push(Instruction::Label(condition_label));
86 lower_expression(condition, ctx, instructions);
87 instructions.push(Instruction::JumpIf { target: end_label });
88 instructions.push(Instruction::Jump {
89 target: start_label,
90 });
91 instructions.push(Instruction::Label(end_label));
92 false
93}
94
95fn lower_for_statement(
96 init: Option<&Statement>,
97 condition: Option<&Expression>,
98 post: Option<&Expression>,
99 body: Option<&Statement>,
100 ctx: &mut LoweringContext,
101 instructions: &mut Vec<Instruction>,
102) -> bool {
103 ctx.enter_scope();
104 if let Some(init_stmt) = init {
105 lower_statement(init_stmt, ctx, instructions);
106 }
107
108 let condition_label = ctx.next_label();
109 let post_label = ctx.next_label();
110 let end_label = ctx.next_label();
111
112 instructions.push(Instruction::Label(condition_label));
113
114 if let Some(cond_expr) = condition {
115 lower_expression(cond_expr, ctx, instructions);
116 instructions.push(Instruction::JumpIf { target: end_label });
117 }
118
119 if let Some(body_stmt) = body {
120 ctx.push_loop(post_label, end_label);
121 lower_statement(body_stmt, ctx, instructions);
122 ctx.pop_loop();
123 }
124
125 instructions.push(Instruction::Label(post_label));
126 if let Some(post_expr) = post {
127 if lower_expression(post_expr, ctx, instructions) {
128 instructions.push(Instruction::Drop(ValueType::Any));
129 }
130 }
131
132 instructions.push(Instruction::Jump {
133 target: condition_label,
134 });
135 instructions.push(Instruction::Label(end_label));
136 ctx.exit_scope();
137 false
138}
139
140fn lower_break_statement(ctx: &mut LoweringContext, instructions: &mut Vec<Instruction>) -> bool {
141 if let Some(label) = ctx.break_target() {
142 instructions.push(Instruction::Jump { target: label });
143 }
144 false
145}
146
147fn lower_continue_statement(ctx: &mut LoweringContext, instructions: &mut Vec<Instruction>) -> bool {
148 if let Some(label) = ctx.continue_target() {
149 instructions.push(Instruction::Jump { target: label });
150 }
151 false
152}