charon_lib/ast/
ullbc_ast_utils.rsuse crate::meta::Span;
use crate::ullbc_ast::*;
use std::mem;
impl SwitchTargets {
pub fn get_targets(&self) -> Vec<BlockId> {
match self {
SwitchTargets::If(then_tgt, else_tgt) => {
vec![*then_tgt, *else_tgt]
}
SwitchTargets::SwitchInt(_, targets, otherwise) => {
let mut all_targets = vec![];
for (_, target) in targets {
all_targets.push(*target);
}
all_targets.push(*otherwise);
all_targets
}
}
}
}
impl Statement {
pub fn new(span: Span, content: RawStatement) -> Self {
Statement {
span,
content,
comments_before: vec![],
}
}
}
impl Terminator {
pub fn new(span: Span, content: RawTerminator) -> Self {
Terminator {
span,
content,
comments_before: vec![],
}
}
}
impl BlockData {
pub fn targets(&self) -> Vec<BlockId> {
match &self.terminator.content {
RawTerminator::Goto { target } => {
vec![*target]
}
RawTerminator::Switch { targets, .. } => targets.get_targets(),
RawTerminator::Abort(..) | RawTerminator::Return => {
vec![]
}
}
}
pub fn transform_operands<F: FnMut(&Span, &mut Vec<Statement>, &mut Operand)>(
&mut self,
mut f: F,
) {
for mut st in mem::take(&mut self.statements) {
st.content
.dyn_visit_in_body_mut(|op: &mut Operand| f(&st.span, &mut self.statements, op));
self.statements.push(st)
}
self.terminator
.content
.dyn_visit_in_body_mut(|op: &mut Operand| {
f(&self.terminator.span, &mut self.statements, op)
});
}
pub fn transform<F: FnMut(&mut Statement) -> Vec<Statement>>(&mut self, mut f: F) {
self.transform_sequences(|slice| {
let new_statements = f(&mut slice[0]);
if new_statements.is_empty() {
vec![]
} else {
vec![(0, new_statements)]
}
});
}
pub fn transform_sequences<F>(&mut self, mut f: F)
where
F: FnMut(&mut [Statement]) -> Vec<(usize, Vec<Statement>)>,
{
let mut to_insert = vec![];
let mut final_len = self.statements.len();
for i in (0..self.statements.len()).rev() {
let new_to_insert = f(&mut self.statements[i..]);
to_insert.extend(new_to_insert.into_iter().map(|(j, stmts)| {
final_len += stmts.len();
(i + j, stmts)
}));
}
if !to_insert.is_empty() {
to_insert.sort_by_key(|(i, _)| *i);
to_insert.reverse();
let old_statements = mem::replace(&mut self.statements, Vec::with_capacity(final_len));
for (i, stmt) in old_statements.into_iter().enumerate() {
while let Some((j, _)) = to_insert.last()
&& *j == i
{
let (_, mut stmts) = to_insert.pop().unwrap();
self.statements.append(&mut stmts);
}
self.statements.push(stmt);
}
}
}
}
impl ExprBody {
pub fn transform_sequences<F>(&mut self, mut f: F)
where
F: FnMut(&mut Locals, &mut [Statement]) -> Vec<(usize, Vec<Statement>)>,
{
for block in &mut self.body {
block.transform_sequences(|seq| f(&mut self.locals, seq));
}
}
pub fn visit_statements<F: FnMut(&mut Statement)>(&mut self, mut f: F) {
for block in self.body.iter_mut().rev() {
for st in block.statements.iter_mut().rev() {
f(st);
}
}
}
}