1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use super::*;
fn check_finish(mut offending: Vec<(BbId, BbId)>) -> Result<(), OffendingIds> {
if offending.is_empty() {
Ok(())
} else {
offending.sort();
offending.dedup();
offending.shrink_to_fit();
Err(OffendingIds(offending))
}
}
impl<S, C> Arena<S, C>
where
ABB<S, C>: ForeachTarget<JumpTarget = BbId>,
{
fn check_intern(
&self,
bbid: BbId,
bb: &ABB<S, C>,
allow_new: bool,
offending: &mut Vec<(BbId, BbId)>,
) {
let endid = self.bbs.len() + if allow_new { 1 } else { 0 };
bb.foreach_target(|&t| {
if t >= endid {
offending.push((bbid, t));
}
});
}
fn check_bbs(&self) -> Vec<(BbId, BbId)> {
let mut errs = Vec::new();
for (n, i) in self.bbs.iter().enumerate() {
self.check_intern(n, i, false, &mut errs);
}
errs
}
pub fn check(&self) -> Result<(), OffendingIds> {
let mut errs = self.check_bbs();
errs.extend(self.labels.iter().filter_map(|(_, &i)| {
if i >= self.bbs.len() {
Some((i, i))
} else {
None
}
}));
for (n, i) in self.bbs.iter().enumerate() {
if i.inner.is_placeholder() && self.labels_of_bb(n).next().is_none() {
errs.push((n, n));
}
}
check_finish(errs)
}
pub fn push(&mut self, bb: ABB<S, C>) -> Result<usize, (ABB<S, C>, OffendingIds)> {
let ret = self.bbs.len();
let mut errs = Vec::new();
self.check_intern(ret, &bb, true, &mut errs);
match check_finish(errs) {
Ok(()) => {
self.bbs.push(bb);
Ok(ret)
}
Err(errs) => Err((bb, errs)),
}
}
pub fn pop(&mut self) -> Option<Result<(usize, ABB<S, C>, Vec<String>), OffendingIds>> {
let x = self.bbs.pop()?;
let offending = self.check_bbs();
Some(if offending.is_empty() {
let retid = self.bbs.len();
let (labelrt, rlabels) = take(&mut self.labels)
.into_iter()
.partition(|&(_, v)| v == retid);
self.labels = rlabels;
Ok((retid, x, labelrt.into_iter().map(|x| x.0).collect()))
} else {
self.bbs.push(x);
Err(OffendingIds(offending))
})
}
}