fn try_find_if_else_cascade(&mut self) {
        let cctx = self.cctx;

        // make a topological order of code nodes
        let mut order = Vec::new();
        for n in Topo::new(&self.graph).iter(&self.graph) {
            if self.graph[n].1.is_some() {
                order.push(n);
            }
        }
        let order = order;

        if order.len() < 2 {
            // can't make if-else with only one node
            return;
        }

        let trans_clos = graph_utils::dag_transitive_closure(&self.graph);

        let mut opt_cands = None;
        // for each prefix of `order` ...
        'n: for i in 0..order.len() {
            if self.graph[order[i]].0.is_true() {
                continue;
            }
            let init = &order[0..=i];
            // ... iterate backwards and try to add candidates
            let mut cands = NodeSet::new();
            let mut or_cand_conds = cctx.mk_false();
            for j in (0..init.len()).rev() {
                let n = init[j];
                let n_reaches = &trans_clos[&n];
                if cands.iter().all(|c| !n_reaches.contains(c)) {
                    // `n` is unreachable to/from `cands`
                    cands.insert(n);
                    or_cand_conds = cctx.mk_or(or_cand_conds, self.graph[n].0);
                    if or_cand_conds.is_true() {
                        opt_cands = Some(cands);
                        break 'n;
                    }
                }
            }
        }

        if let Some(cands) = opt_cands {
            graph_utils::contract_nodes_and_map(
                &mut self.graph,
                &cands,
                |_, n| n,
                |_, _| (),
                |mut casc_graph| {
                    debug_assert!(casc_graph.edge_count() == 0);
                    debug_assert!(casc_graph.node_count() >= 2);
                    debug_assert!(casc_graph.node_references().all(|(_, (_, x))| x.is_some()));

                    // remove all nodes
                    // `StableGraph` doesn't have `into_nodes_edges` :(
                    let mut nodes = Vec::new();
                    while let Some(n) = casc_graph.node_indices().next() {
                        let (cond, ast) = casc_graph.remove_node(n).unwrap();
                        nodes.push((cond, ast.unwrap()));
                    }

                    nodes.sort_unstable_by_key(|&(c, _)| c.complexity());

                    // build if-else cascade starting from last else block with
                    // the most complex reaching condition
                    let mut casc_ast = nodes.pop().unwrap().1;
                    for (cond, ast) in nodes.into_iter().rev() {
                        casc_ast = AstNodeC::Cond(cond, Box::new(ast), Some(Box::new(casc_ast)));
                    }

                    (cctx.mk_true(), Some(casc_ast))
                },
            );
        }
    }
/// Tries to find a set of code where exactly one of them will run.
Tries to find a set of code where exactly one of them will run.
Tries to find a set of code where exactly one of them will run .
fn try_find_if_else_cascade(&mut self) {
        let cctx = self.cctx;
        // make a topological order of code nodes
        let mut order = Vec::new();
        for n in Topo::new(&self.graph).iter(&self.graph) {
            if self.graph[n].1.is_some() {
                order.push(n);
            }
        }
        let order = order;
        if order.len() < 2 {
            // can't make if-else with only one node
            return;
        }
        let trans_clos = graph_utils::dag_transitive_closure(&self.graph);
        let mut opt_cands = None;
        // for each prefix of `order` ...
        'n: for i in 0..order.len() {
            if self.graph[order[i]].0.is_true() {
                continue;
            }
            let init = &order[0..=i];
            // ... iterate backwards and try to add candidates
            let mut cands = NodeSet::new();
            let mut or_cand_conds = cctx.mk_false();
            for j in (0..init.len()).rev() {
                let n = init[j];
                let n_reaches = &trans_clos[&n];
                if cands.iter().all(|c| !n_reaches.contains(c)) {
                    // `n` is unreachable to/from `cands`
                    cands.insert(n);
                    or_cand_conds = cctx.mk_or(or_cand_conds, self.graph[n].0);
                    if or_cand_conds.is_true() {
                        opt_cands = Some(cands);
                        break 'n;
                    }
                }
            }
        }
        if let Some(cands) = opt_cands {
            graph_utils::contract_nodes_and_map(
                &mut self.graph,
                &cands,
                |_, n| n,
                |_, _| (),
                |mut casc_graph| {
                    debug_assert!(casc_graph.edge_count() == 0);
                    debug_assert!(casc_graph.node_count() >= 2);
                    debug_assert!(casc_graph.node_references().all(|(_, (_, x))| x.is_some()));
                    // remove all nodes
                    // `StableGraph` doesn't have `into_nodes_edges` :(
                    let mut nodes = Vec::new();
                    while let Some(n) = casc_graph.node_indices().next() {
                        let (cond, ast) = casc_graph.remove_node(n).unwrap();
                        nodes.push((cond, ast.unwrap()));
                    }
                    nodes.sort_unstable_by_key(|&(c, _)| c.complexity());
                    // build if-else cascade starting from last else block with
                    // the most complex reaching condition
                    let mut casc_ast = nodes.pop().unwrap().1;
                    for (cond, ast) in nodes.into_iter().rev() {
                        casc_ast = AstNodeC::Cond(cond, Box::new(ast), Some(Box::new(casc_ast)));
                    }
                    (cctx.mk_true(), Some(casc_ast))
                },
            );
        }
    }
fn try_find_if_else_cascade ( & mut self ) { let cctx = self . cctx ; // make a topological order of code nodes let mut order = Vec :: new ( ) ; for n in Topo :: new ( & self . graph ) . iter ( & self . graph ) { if self . graph [ n ] . 1 . is_some ( ) { order . push ( n ) ; } } let order = order ; if order . len ( ) < 2 { // can't make if-else with only one node return ; } let trans_clos = graph_utils :: dag_transitive_closure ( & self . graph ) ; let mut opt_cands = None ; // for each prefix of `order` ... ' n : for i in 0 .. order . len ( ) { if self . graph [ order [ i ] ] . 0 . is_true ( ) { continue ; } let init = & order [ 0 ..= i ] ; // ... iterate backwards and try to add candidates let mut cands = NodeSet :: new ( ) ; let mut or_cand_conds = cctx . mk_false ( ) ; for j in ( 0 .. init . len ( ) ) . rev ( ) { let n = init [ j ] ; let n_reaches = & trans_clos [ & n ] ; if cands . iter ( ) . all ( | c | ! n_reaches . contains ( c ) ) { // `n` is unreachable to/from `cands` cands . insert ( n ) ; or_cand_conds = cctx . mk_or ( or_cand_conds , self . graph [ n ] . 0 ) ; if or_cand_conds . is_true ( ) { opt_cands = Some ( cands ) ; break ' n ; } } } } if let Some ( cands ) = opt_cands { graph_utils :: contract_nodes_and_map ( & mut self . graph , & cands , | _ , n | n , | _ , _ | ( ) , | mut casc_graph | { debug_assert ! ( casc_graph edge_count ( ) 0 ) ; debug_assert ! ( casc_graph node_count ( ) 2 ) ; debug_assert ! ( casc_graph node_references ( ) all ( ( ( x ) ) x is_some ( ) ) ) ; // remove all nodes // `StableGraph` doesn't have `into_nodes_edges` :( let mut nodes = Vec :: new ( ) ; while let Some ( n ) = casc_graph . node_indices ( ) . next ( ) { let ( cond , ast ) = casc_graph . remove_node ( n ) . unwrap ( ) ; nodes . push ( ( cond , ast . unwrap ( ) ) ) ; } nodes . sort_unstable_by_key ( | & ( c , _ ) | c . complexity ( ) ) ; // build if-else cascade starting from last else block with // the most complex reaching condition let mut casc_ast = nodes . pop ( ) . unwrap ( ) . 1 ; for ( cond , ast ) in nodes . into_iter ( ) . rev ( ) { casc_ast = AstNodeC :: Cond ( cond , Box :: new ( ast ) , Some ( Box :: new ( casc_ast ) ) ) ; } ( cctx . mk_true ( ) , Some ( casc_ast ) ) } , ) ; } }
Tries to find a set of code where exactly one of them will run.
Tries to find a set of code where exactly one of them will run .
&mut self
&mut self