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 { call: _, target } => vec![*target],
70 RawTerminator::Abort(..) | RawTerminator::Return => {
71 vec![]
72 }
73 }
74 }
75
76 pub fn transform_operands<F: FnMut(&Span, &mut Vec<Statement>, &mut Operand)>(
78 &mut self,
79 mut f: F,
80 ) {
81 for mut st in mem::take(&mut self.statements) {
83 st.content
84 .dyn_visit_in_body_mut(|op: &mut Operand| f(&st.span, &mut self.statements, op));
85 self.statements.push(st)
87 }
88
89 self.terminator
91 .content
92 .dyn_visit_in_body_mut(|op: &mut Operand| {
93 f(&self.terminator.span, &mut self.statements, op)
94 });
95 }
96
97 pub fn transform<F: FnMut(&mut Statement) -> Vec<Statement>>(&mut self, mut f: F) {
103 self.transform_sequences_bwd(|slice| {
104 let new_statements = f(&mut slice[0]);
105 if new_statements.is_empty() {
106 vec![]
107 } else {
108 vec![(0, new_statements)]
109 }
110 });
111 }
112
113 fn transform_sequences<F>(&mut self, mut f: F, forward: bool)
115 where
116 F: FnMut(&mut [Statement]) -> Vec<(usize, Vec<Statement>)>,
117 {
118 let mut to_insert = vec![];
119 let mut final_len = self.statements.len();
120 if forward {
121 for i in 0..self.statements.len() {
122 let new_to_insert = f(&mut self.statements[i..]);
123 to_insert.extend(new_to_insert.into_iter().map(|(j, stmts)| {
124 final_len += stmts.len();
125 (i + j, stmts)
126 }));
127 }
128 } else {
129 for i in (0..self.statements.len()).rev() {
130 let new_to_insert = f(&mut self.statements[i..]);
131 to_insert.extend(new_to_insert.into_iter().map(|(j, stmts)| {
132 final_len += stmts.len();
133 (i + j, stmts)
134 }));
135 }
136 }
137 if !to_insert.is_empty() {
138 to_insert.sort_by_key(|(i, _)| *i);
139 to_insert.reverse();
141 let old_statements = mem::replace(&mut self.statements, Vec::with_capacity(final_len));
143 for (i, stmt) in old_statements.into_iter().enumerate() {
144 while let Some((j, _)) = to_insert.last()
145 && *j == i
146 {
147 let (_, mut stmts) = to_insert.pop().unwrap();
148 self.statements.append(&mut stmts);
149 }
150 self.statements.push(stmt);
151 }
152 }
153 }
154
155 pub fn transform_sequences_fwd<F>(&mut self, f: F)
161 where
162 F: FnMut(&mut [Statement]) -> Vec<(usize, Vec<Statement>)>,
163 {
164 self.transform_sequences(f, true);
165 }
166
167 pub fn transform_sequences_bwd<F>(&mut self, f: F)
173 where
174 F: FnMut(&mut [Statement]) -> Vec<(usize, Vec<Statement>)>,
175 {
176 self.transform_sequences(f, false);
177 }
178}
179
180impl ExprBody {
181 pub fn transform_sequences_fwd<F>(&mut self, mut f: F)
182 where
183 F: FnMut(&mut Locals, &mut [Statement]) -> Vec<(usize, Vec<Statement>)>,
184 {
185 for block in &mut self.body {
186 block.transform_sequences_fwd(|seq| f(&mut self.locals, seq));
187 }
188 }
189
190 pub fn transform_sequences_bwd<F>(&mut self, mut f: F)
191 where
192 F: FnMut(&mut Locals, &mut [Statement]) -> Vec<(usize, Vec<Statement>)>,
193 {
194 for block in &mut self.body {
195 block.transform_sequences_bwd(|seq| f(&mut self.locals, seq));
196 }
197 }
198
199 pub fn visit_statements<F: FnMut(&mut Statement)>(&mut self, mut f: F) {
201 for block in self.body.iter_mut().rev() {
202 for st in block.statements.iter_mut().rev() {
203 f(st);
204 }
205 }
206 }
207}