pub fn generate_cfg_in_dot_format<'env>(func_target: &'env FunctionTarget<'env>) -> String {
    let code = &func_target.data.code;
    let cfg = StacklessControlFlowGraph::new_forward(code);
    let label_offsets = Bytecode::label_offsets(code);
    let mut graph = Graph::new();

    // add nodes
    let mut node_map = Map::new();
    for (block_id, block) in &cfg.blocks {
        let dot_block = DotCFGBlock {
            block_id: *block_id,
            content: block.content,
            func_target,
            label_offsets: label_offsets.clone(),
        };
        let node_index = graph.add_node(dot_block);
        node_map.insert(block_id, node_index);
    }

    // add edges
    for (block_id, block) in &cfg.blocks {
        for successor in &block.successors {
            graph.add_edge(
                *node_map.get(block_id).unwrap(),
                *node_map.get(successor).unwrap(),
                DotCFGEdge {},
            );
        }
    }

    // generate dot string
    format!(
        "{}",
        Dot::with_attr_getters(&graph, &[], &|_, _| "".to_string(), &|_, _| {
            "shape=box".to_string()
        })
    )
}
/// Generate the dot representation of the CFG (which can be rendered by the Dot program)
Generate the dot representation of the CFG (which can be rendered by the Dot program)
Generate the dot representation of the CFG ( which can be rendered by the Dot program )
pub fn generate_cfg_in_dot_format<'env>(func_target: &'env FunctionTarget<'env>) -> String {
    let code = &func_target.data.code;
    let cfg = StacklessControlFlowGraph::new_forward(code);
    let label_offsets = Bytecode::label_offsets(code);
    let mut graph = Graph::new();
    // add nodes
    let mut node_map = Map::new();
    for (block_id, block) in &cfg.blocks {
        let dot_block = DotCFGBlock {
            block_id: *block_id,
            content: block.content,
            func_target,
            label_offsets: label_offsets.clone(),
        };
        let node_index = graph.add_node(dot_block);
        node_map.insert(block_id, node_index);
    }
    // add edges
    for (block_id, block) in &cfg.blocks {
        for successor in &block.successors {
            graph.add_edge(
                *node_map.get(block_id).unwrap(),
                *node_map.get(successor).unwrap(),
                DotCFGEdge {},
            );
        }
    }
    // generate dot string
    format!(
        "{}",
        Dot::with_attr_getters(&graph, &[], &|_, _| "".to_string(), &|_, _| {
            "shape=box".to_string()
        })
    )
}
pub fn generate_cfg_in_dot_format < ' env > ( func_target : & ' env FunctionTarget < ' env > ) -> String { let code = & func_target . data . code ; let cfg = StacklessControlFlowGraph :: new_forward ( code ) ; let label_offsets = Bytecode :: label_offsets ( code ) ; let mut graph = Graph :: new ( ) ; // add nodes let mut node_map = Map :: new ( ) ; for ( block_id , block ) in & cfg . blocks { let dot_block = DotCFGBlock { block_id : * block_id , content : block . content , func_target , label_offsets : label_offsets . clone ( ) , } ; let node_index = graph . add_node ( dot_block ) ; node_map . insert ( block_id , node_index ) ; } // add edges for ( block_id , block ) in & cfg . blocks { for successor in & block . successors { graph . add_edge ( * node_map . get ( block_id ) . unwrap ( ) , * node_map . get ( successor ) . unwrap ( ) , DotCFGEdge { } , ) ; } } // generate dot string format ! ( " " Dot with_attr_getters ( graph [ ] " " to_string ( ) { " " to_string ( ) } ) ) }
Generate the dot representation of the CFG (which can be rendered by the Dot program)
Generate the dot representation of the CFG ( which can be rendered by the Dot program )
func_target
&'env FunctionTarget<'env>