charon_lib/ast/
llbc_ast_utils.rs1use crate::llbc_ast::*;
4use crate::meta;
5use crate::meta::Span;
6use derive_generic_visitor::*;
7use std::mem;
8
9pub fn combine_switch_targets_span(targets: &Switch) -> Span {
11 match targets {
12 Switch::If(_, st1, st2) => meta::combine_span(&st1.span, &st2.span),
13 Switch::SwitchInt(_, _, branches, otherwise) => {
14 let branches = branches.iter().map(|b| &b.1.span);
15 let mbranches = meta::combine_span_iter(branches);
16 meta::combine_span(&mbranches, &otherwise.span)
17 }
18 Switch::Match(_, branches, otherwise) => {
19 let branches = branches.iter().map(|b| &b.1.span);
20 let mbranches = meta::combine_span_iter(branches);
21 if let Some(otherwise) = otherwise {
22 meta::combine_span(&mbranches, &otherwise.span)
23 } else {
24 mbranches
25 }
26 }
27 }
28}
29
30impl Switch {
31 pub fn iter_targets(&self) -> impl Iterator<Item = &Block> {
32 use itertools::Either;
33 match self {
34 Switch::If(_, exp1, exp2) => Either::Left([exp1, exp2].into_iter()),
35 Switch::SwitchInt(_, _, targets, otherwise) => Either::Right(Either::Left(
36 targets.iter().map(|(_, tgt)| tgt).chain([otherwise]),
37 )),
38 Switch::Match(_, targets, otherwise) => Either::Right(Either::Right(
39 targets.iter().map(|(_, tgt)| tgt).chain(otherwise.as_ref()),
40 )),
41 }
42 }
43
44 pub fn iter_targets_mut(&mut self) -> impl Iterator<Item = &mut Block> {
45 use itertools::Either;
46 match self {
47 Switch::If(_, exp1, exp2) => Either::Left([exp1, exp2].into_iter()),
48 Switch::SwitchInt(_, _, targets, otherwise) => Either::Right(Either::Left(
49 targets.iter_mut().map(|(_, tgt)| tgt).chain([otherwise]),
50 )),
51 Switch::Match(_, targets, otherwise) => Either::Right(Either::Right(
52 targets
53 .iter_mut()
54 .map(|(_, tgt)| tgt)
55 .chain(otherwise.as_mut()),
56 )),
57 }
58 }
59}
60
61impl StatementId {
62 pub fn fresh() -> StatementId {
63 use std::sync::atomic::AtomicUsize;
64 use std::sync::atomic::Ordering;
65 static COUNTER: AtomicUsize = AtomicUsize::new(0);
66 let id = COUNTER.fetch_add(1, Ordering::Relaxed);
67 StatementId::new(id)
68 }
69}
70
71impl Statement {
72 pub fn new(span: Span, content: RawStatement) -> Self {
73 Statement {
74 span,
75 id: StatementId::fresh(),
76 content,
77 comments_before: vec![],
78 }
79 }
80
81 pub fn into_box(self) -> Box<Self> {
82 Box::new(self)
83 }
84
85 pub fn into_block(self) -> Block {
86 Block {
87 span: self.span,
88 statements: vec![self],
89 }
90 }
91}
92
93impl Block {
94 pub fn from_seq(seq: Vec<Statement>) -> Option<Self> {
95 if seq.is_empty() {
96 None
97 } else {
98 let span = seq
99 .iter()
100 .map(|st| st.span)
101 .reduce(|a, b| meta::combine_span(&a, &b))
102 .unwrap();
103 Some(Block {
104 span,
105 statements: seq,
106 })
107 }
108 }
109
110 pub fn merge(mut self, mut other: Self) -> Self {
111 self.span = meta::combine_span(&self.span, &other.span);
112 self.statements.append(&mut other.statements);
113 self
114 }
115
116 pub fn then(mut self, r: Statement) -> Self {
117 self.span = meta::combine_span(&self.span, &r.span);
118 self.statements.push(r);
119 self
120 }
121
122 pub fn then_opt(self, other: Option<Statement>) -> Self {
123 if let Some(other) = other {
124 self.then(other)
125 } else {
126 self
127 }
128 }
129
130 pub fn visit_statements<F: FnMut(&mut Statement)>(&mut self, f: F) {
132 let _ = BlockVisitor::new(|_| {}, f).visit(self);
133 }
134
135 pub fn transform<F: FnMut(&mut Statement) -> Vec<Statement>>(&mut self, mut f: F) {
141 self.transform_sequences(|slice| f(&mut slice[0]));
142 }
143
144 pub fn transform_sequences<F: FnMut(&mut [Statement]) -> Vec<Statement>>(&mut self, mut f: F) {
153 self.visit_blocks_bwd(|blk: &mut Block| {
154 let mut final_len = blk.statements.len();
155 let mut to_insert = vec![];
156 for i in (0..blk.statements.len()).rev() {
157 let new_to_insert = f(&mut blk.statements[i..]);
158 final_len += new_to_insert.len();
159 to_insert.push((i, new_to_insert));
160 }
161 if !to_insert.is_empty() {
162 to_insert.sort_by_key(|(i, _)| *i);
163 to_insert.reverse();
165 let old_statements =
167 mem::replace(&mut blk.statements, Vec::with_capacity(final_len));
168 for (i, stmt) in old_statements.into_iter().enumerate() {
169 while let Some((j, _)) = to_insert.last()
170 && *j == i
171 {
172 let (_, mut stmts) = to_insert.pop().unwrap();
173 blk.statements.append(&mut stmts);
174 }
175 blk.statements.push(stmt);
176 }
177 }
178 })
179 }
180
181 pub fn visit_blocks_bwd<F: FnMut(&mut Block)>(&mut self, f: F) {
183 let _ = BlockVisitor::new(f, |_| {}).visit(self);
184 }
185}
186
187#[derive(Visitor)]
189pub struct BlockVisitor<F: FnMut(&mut Block), G: FnMut(&mut Statement)> {
190 exit_blk: F,
191 enter_stmt: G,
192}
193
194impl<F: FnMut(&mut Block), G: FnMut(&mut Statement)> BlockVisitor<F, G> {
195 pub fn new(exit_blk: F, enter_stmt: G) -> Self {
196 Self {
197 exit_blk,
198 enter_stmt,
199 }
200 }
201}
202
203impl<F: FnMut(&mut Block), G: FnMut(&mut Statement)> VisitBodyMut for BlockVisitor<F, G> {
204 fn exit_llbc_block(&mut self, x: &mut Block) {
205 (self.exit_blk)(x)
206 }
207 fn enter_llbc_statement(&mut self, x: &mut Statement) {
208 (self.enter_stmt)(x)
209 }
210}