コード例 #1
0
def gen_while(ast_while):
    """
    Generates CFG for a While Loop AST node
    """
    assert type(ast_while) == While

    guard = ast_while.get_guard()
    body = ast_while.get_body()

    dummy_node_num = gen_node_number()
    dummy_node = Node(dummy_node_num, [str(guard)])

    start_body, end_body, body_nodes, body_edges = gen_bodies(body)
    assert type(body_nodes) == list
    assert type(body_edges) == list

    exit_node_num = gen_node_number()
    exit_node = Node(exit_node_num, [])

    nodes = [dummy_node] + body_nodes + [exit_node]
    edges = [Edge(dummy_node, start_body, ["True"])] + \
        body_edges + \
        [Edge(end_body, dummy_node, []),
         Edge(dummy_node, exit_node, ["False"])]

    return dummy_node, exit_node, nodes, edges
コード例 #2
0
def gen_if(ast_if):
    """
    Generates CFG for an If Statement AST node
    """
    assert type(ast_if) == IfThenElse

    if_guard, if_body = ast_if.get_if_pair()
    elif_guards, elif_bodies = ast_if.get_elif_pair_list()
    else_body = ast_if.get_else()

    init = None
    _exit = None
    nodes = []
    edges = []

    dummy_node_num = gen_node_number()
    dummy_node = Node(dummy_node_num, [])

    start_body, end_body, body_nodes, body_edges = gen_bodies(if_body)
    assert type(body_nodes) == list
    assert type(body_edges) == list

    exit_node_num = gen_node_number()
    exit_node = Node(exit_node_num, [])

    init = dummy_node
    _exit = exit_node
    nodes += [dummy_node] + body_nodes
    edges += [Edge(dummy_node, start_body, [str(if_guard)])] + \
        body_edges + [Edge(end_body, exit_node, [])]

    if elif_guards != []:
        for guard, body in zip(elif_guards, elif_bodies):
            start_body, end_body, body_nodes, body_edges = gen_bodies(body)
            assert type(body_nodes) == list
            assert type(body_edges) == list

            nodes += body_nodes
            edges += [
                Edge(dummy_node, start_body, [f"Else: {str(guard)}"]),
                Edge(end_body, exit_node, [])
            ]

    if else_body != None:
        start_body, end_body, body_nodes, body_edges = gen_bodies(else_body)
        assert type(body_nodes) == list
        assert type(body_edges) == list

        nodes += body_nodes
        edges += [
            Edge(dummy_node, start_body, [f"Else: !{str(if_guard)}"]),
            Edge(end_body, exit_node, [])
        ]

    if elif_guards == [] and else_body == None:
        edges += [Edge(dummy_node, exit_node, [f"Else: !{str(if_guard)}"])]

    return init, _exit, nodes, edges
コード例 #3
0
def gen_return(ast_return):
    """
    Generates CFG for an returns Statement AST node
    """
    assert type(ast_return) == Return

    return_node_num = gen_node_number()
    return_node = Node(return_node_num, [str(ast_return)], final=True)
    # make exit node special number -1 as it should not connect to anything
    early_return_node = Node(EARLY_RETURN_NODE_NUMBER, [])
    return return_node, early_return_node, [return_node], []
コード例 #4
0
def gen_function(ast_function):
    """
    Generates a CFG from List of AST nodes corresponding to a function definition
    """
    assert type(ast_function) == Function
    bodies_list = ast_function.get_body()
    start, end, nodes, edges = gen_bodies(bodies_list)
    # set extra nodes for function
    extra_top = Node(FUNCTION_INDICATOR, [])
    extra_bottom = Node(FUNCTION_INDICATOR, [])
    # set last node to be a return out of function
    end.set_final(True)
    return extra_top, extra_bottom, nodes, edges
コード例 #5
0
def gen_basic(ast_node_list):
    """
    Generates a Basic Block CFG from List of AST nodes corresponding to basic block expressions
    """
    assert type(ast_node_list) == list

    single_node_num = gen_node_number()
    stmt = "\n".join(list(map(lambda n: str(n), ast_node_list)))
    single_node = Node(single_node_num, [stmt])
    return single_node, single_node, [single_node], []
コード例 #6
0
def gen_for(ast_for):
    """
    Generates Control Flow Graph for a For Loop AST node
    """
    assert type(ast_for) == For

    index_var = ast_for.get_index()
    from_int = ast_for.get_from()
    end_int = ast_for.get_end()
    by_int = ast_for.get_by()
    body = ast_for.get_body()

    set_idx = f"{index_var} = {from_int}"
    init_node_num = gen_node_number()
    init_node = Node(init_node_num, [set_idx])

    guard_node_num = gen_node_number()
    guard_node = Node(guard_node_num, [])

    start_body, end_body, body_nodes, body_edges = gen_bodies(body)
    assert type(body_nodes) == list
    assert type(body_edges) == list

    incr_node_num = gen_node_number()
    incr_idx = f"{index_var} += {by_int}"
    incr_node = Node(incr_node_num, [incr_idx])

    exit_node_num = gen_node_number()
    exit_node = Node(exit_node_num, [])

    nodes = [init_node, guard_node] + body_nodes + [incr_node, exit_node]
    edges = [Edge(init_node, guard_node, []),
             Edge(guard_node, start_body, [f"{index_var} <= {end_int}"])] + \
        body_edges + \
        [Edge(end_body, incr_node, []),
         Edge(incr_node, guard_node, []),
         Edge(guard_node, exit_node, [f"{index_var} > {end_int}"])]

    return init_node, exit_node, nodes, edges
コード例 #7
0
def gen_bodies(ast_node_list):
    """
    Generates a Body CFG from List of AST nodes corresponding to body expressions
    """
    assert type(ast_node_list) == list

    # pass in empty list of ast nodes
    if ast_node_list == []:
        empty_node_num = gen_node_number()
        empty_node = Node(empty_node_num, [])
        return empty_node, empty_node, [empty_node], []

    # formal base case: only 1 node
    if len(ast_node_list) == 1:
        node = ast_node_list[0]
        if is_basic(node):
            return gen_basic([node])
        return gen_cfg(node)

    # recursive case: multiple ast nodes
    # grab basic block(s) at front
    idx = 0
    while idx < len(ast_node_list) and is_basic(ast_node_list[idx]):
        idx += 1

    # handle basic block or first part
    first_init, first_exit, first_nodes, first_edges = None, None, None, None
    if idx == 0:
        first_init, first_exit, first_nodes, first_edges = gen_cfg(
            ast_node_list[idx])
    else:
        first_init, first_exit, first_nodes, first_edges = gen_basic(
            ast_node_list[:idx])

    # recurse on end
    final_init, final_exit, final_nodes, final_edges = gen_bodies(
        ast_node_list[idx + 1:])

    # combine parts
    init = first_init
    _exit = final_exit
    nodes = first_nodes + final_nodes
    edges = first_edges + [Edge(first_exit, final_init, [])] + final_edges

    return init, _exit, nodes, edges