1use alloc::{collections::{BTreeMap, BTreeSet}, vec::Vec};
2use alloc::vec;
3use cfg_traits::{Block, Func, Target, Term};
4
5pub fn calculate_postorder<
6 F: Func<Block: Ord + Clone>,
7 SuccFn: FnMut(F::Block) -> Vec<F::Block>,
8>(
9 entry: F::Block,
10 mut succ_blocks: SuccFn,
11) -> Vec<F::Block> {
12 let mut ret = vec![];
13
14 let mut visited: BTreeSet<F::Block> = BTreeSet::new();
16
17 #[derive(Debug)]
18 struct State<F: Func> {
19 block: F::Block,
20 succs: Vec<F::Block>,
21 next_succ: usize,
22 }
23 let mut stack: Vec<State<F>> = vec![];
24
25 visited.insert(entry.clone());
26 stack.push(State {
27 block: entry.clone(),
28 succs: succ_blocks(entry.clone()),
29 next_succ: 0,
30 });
31
32 while let Some(ref mut state) = stack.last_mut() {
33 if state.next_succ < state.succs.len() {
36 let succ = state.succs[state.next_succ].clone();
37 state.next_succ += 1;
39 if !visited.contains(&succ) {
40 visited.insert(succ.clone());
42 stack.push(State {
43 block: succ.clone(),
44 succs: succ_blocks(succ.clone()),
45 next_succ: 0,
46 });
47 }
48 } else {
49 ret.push(state.block.clone());
51 stack.pop();
52 }
53 }
54
55 ret
56}
57pub fn postorder<F: Func<Block: Ord + Clone>>(f: &F) -> Vec<F::Block> {
58 return calculate_postorder::<F, _>(f.entry(), |a| {
59 f.blocks()[a].term().targets().map(|a| a.block()).collect()
60 });
61}