charon_lib/ast/
ullbc_ast_utils.rs1use crate::meta::Span;
3use crate::ullbc_ast::*;
4use std::mem;
5
6impl SwitchTargets {
7 pub fn get_targets(&self) -> Vec<BlockId> {
8 match self {
9 SwitchTargets::If(then_tgt, else_tgt) => {
10 vec![*then_tgt, *else_tgt]
11 }
12 SwitchTargets::SwitchInt(_, targets, otherwise) => {
13 let mut all_targets = vec![];
14 for (_, target) in targets {
15 all_targets.push(*target);
16 }
17 all_targets.push(*otherwise);
18 all_targets
19 }
20 }
21 }
22}
23
24impl Statement {
25 pub fn new(span: Span, content: RawStatement) -> Self {
26 Statement {
27 span,
28 content,
29 comments_before: vec![],
30 }
31 }
32}
33
34impl Terminator {
35 pub fn new(span: Span, content: RawTerminator) -> Self {
36 Terminator {
37 span,
38 content,
39 comments_before: vec![],
40 }
41 }
42 pub fn goto(span: Span, target: BlockId) -> Self {
43 Self::new(span, RawTerminator::Goto { target })
44 }
45
46 pub fn into_block(self) -> BlockData {
47 BlockData {
48 statements: vec![],
49 terminator: self,
50 }
51 }
52}
53
54impl BlockData {
55 pub fn new_goto(span: Span, target: BlockId) -> Self {
57 BlockData {
58 statements: vec![],
59 terminator: Terminator::goto(span, target),
60 }
61 }
62
63 pub fn targets(&self) -> Vec<BlockId> {
64 match &self.terminator.content {
65 RawTerminator::Goto { target } => {
66 vec![*target]
67 }
68 RawTerminator::Switch { targets, .. } => targets.get_targets(),
69 RawTerminator::Call {
70 call: _,
71 target,
72 on_unwind,
73 } => vec![*target, *on_unwind],
74 RawTerminator::Abort(..) | RawTerminator::Return | RawTerminator::UnwindResume => {
75 vec![]
76 }
77 }
78 }
79
80 pub fn transform_operands<F: FnMut(&Span, &mut Vec<Statement>, &mut Operand)>(
82 &mut self,
83 mut f: F,
84 ) {
85 for mut st in mem::take(&mut self.statements) {
87 st.content
88 .dyn_visit_in_body_mut(|op: &mut Operand| f(&st.span, &mut self.statements, op));
89 self.statements.push(st)
91 }
92
93 self.terminator
95 .content
96 .dyn_visit_in_body_mut(|op: &mut Operand| {
97 f(&self.terminator.span, &mut self.statements, op)
98 });
99 }
100
101 pub fn transform<F: FnMut(&mut Statement) -> Vec<Statement>>(&mut self, mut f: F) {
107 self.transform_sequences_bwd(|slice| {
108 let new_statements = f(&mut slice[0]);
109 if new_statements.is_empty() {
110 vec![]
111 } else {
112 vec![(0, new_statements)]
113 }
114 });
115 }
116
117 fn transform_sequences<F>(&mut self, mut f: F, forward: bool)
119 where
120 F: FnMut(&mut [Statement]) -> Vec<(usize, Vec<Statement>)>,
121 {
122 let mut to_insert = vec![];
123 let mut final_len = self.statements.len();
124 if forward {
125 for i in 0..self.statements.len() {
126 let new_to_insert = f(&mut self.statements[i..]);
127 to_insert.extend(new_to_insert.into_iter().map(|(j, stmts)| {
128 final_len += stmts.len();
129 (i + j, stmts)
130 }));
131 }
132 } else {
133 for i in (0..self.statements.len()).rev() {
134 let new_to_insert = f(&mut self.statements[i..]);
135 to_insert.extend(new_to_insert.into_iter().map(|(j, stmts)| {
136 final_len += stmts.len();
137 (i + j, stmts)
138 }));
139 }
140 }
141 if !to_insert.is_empty() {
142 to_insert.sort_by_key(|(i, _)| *i);
143 to_insert.reverse();
145 let old_statements = mem::replace(&mut self.statements, Vec::with_capacity(final_len));
147 for (i, stmt) in old_statements.into_iter().enumerate() {
148 while let Some((j, _)) = to_insert.last()
149 && *j == i
150 {
151 let (_, mut stmts) = to_insert.pop().unwrap();
152 self.statements.append(&mut stmts);
153 }
154 self.statements.push(stmt);
155 }
156 }
157 }
158
159 pub fn transform_sequences_fwd<F>(&mut self, f: F)
165 where
166 F: FnMut(&mut [Statement]) -> Vec<(usize, Vec<Statement>)>,
167 {
168 self.transform_sequences(f, true);
169 }
170
171 pub fn transform_sequences_bwd<F>(&mut self, f: F)
177 where
178 F: FnMut(&mut [Statement]) -> Vec<(usize, Vec<Statement>)>,
179 {
180 self.transform_sequences(f, false);
181 }
182}
183
184impl ExprBody {
185 pub fn transform_sequences_fwd<F>(&mut self, mut f: F)
186 where
187 F: FnMut(&mut Locals, &mut [Statement]) -> Vec<(usize, Vec<Statement>)>,
188 {
189 for block in &mut self.body {
190 block.transform_sequences_fwd(|seq| f(&mut self.locals, seq));
191 }
192 }
193
194 pub fn transform_sequences_bwd<F>(&mut self, mut f: F)
195 where
196 F: FnMut(&mut Locals, &mut [Statement]) -> Vec<(usize, Vec<Statement>)>,
197 {
198 for block in &mut self.body {
199 block.transform_sequences_bwd(|seq| f(&mut self.locals, seq));
200 }
201 }
202
203 pub fn visit_statements<F: FnMut(&mut Statement)>(&mut self, mut f: F) {
205 for block in self.body.iter_mut().rev() {
206 for st in block.statements.iter_mut().rev() {
207 f(st);
208 }
209 }
210 }
211}