コード例 #1
0
def build_arbitrary_blocks(block_links, code=None, block_type=None):
    # build all block and assume it's in module scope
    block_list = BlockList()
    as_tree_string = ""
    current_line_number = 1
    for i in range(len(block_links)):
        block_name = chr(65 + i)
        if block_type:
            type_instance = block_type.get(block_name)
            if type_instance is not None:
                if type_instance.__name__ == "ParentScopeBlock":
                    basic_block = type_instance(current_line_number,
                                                current_line_number,
                                                None,
                                                scope_name=block_name)
                else:
                    basic_block = type_instance(current_line_number,
                                                current_line_number, None)
            else:
                basic_block = RawBasicBlock(current_line_number,
                                            current_line_number, None)
        else:
            basic_block = RawBasicBlock(current_line_number,
                                        current_line_number, None)
        current_line_number += 1
        basic_block.name = block_name
        block_list.append(basic_block)

        if code is not None:
            ast_stmts = code.get(basic_block.name)  # type: str
            as_tree_string += ast_stmts

    as_tree = AstBuilder().string_build(as_tree_string)
    for i in range(len(block_links)):
        basic_block = block_list[i]
        if code is not None:
            ast_stmts = code.get(basic_block.name)  # type: str
            ast = AstBuilder().string_build(ast_stmts)
            for b in ast.body:
                b.parent = as_tree
            basic_block.ssa_code.code_list = ast.body
            basic_block.end_line += ast_stmts.count("\n") - 1

    for key, value in block_links.items():
        key_block = block_list.get_block_by_name(key)
        for value_block_str in value:
            Cfg.connect_2_blocks(key_block,
                                 block_list.get_block_by_name(value_block_str))

    if code is None:
        return block_list
    else:
        return block_list, as_tree
コード例 #2
0
 def test_var_replace(self):
     tree = AstBuilder().string_build("""\
         x = 3
         x = 2
         y = x
     """)
     tree.body[0].targets[0].version = 0
     tree.body[1].targets[0].version = 1
     tree.body[2].value.version = 1
     tree.locals["x_1"] = tree.body[1]
     link_stmts_to_def(tree.body[2])
     assert tree.body[2].value.links == tree.body[1]
コード例 #3
0
 def test_function_def_global(self):
     tree = AstBuilder().string_build("""\
         def foo():
             global x, y, z
             global f
     """)
     assert tree.body[0].global_var.keys() == {"x", "y", "z", "f"}
コード例 #4
0
 def test_get_dunder_binop(self):
     as_tree = AstBuilder().string_build("""\
         a = 1
         a - 2
         class F:
             def __add__(self, other):
                 pass
         f = F()
     """)
     cfg_real = Cfg(as_tree)
     cfg_real.convert_to_ssa()
     with self.assertRaises(exceptions.OperationIncompatible) as e:
         list(
             protocols.get_custom_dunder_method(as_tree.body[1].value.left,
                                                "-"))
     assert e.exception.msg == "the node: 1 is not of type ClassInstance"
     meth = list(
         protocols.get_custom_dunder_method(as_tree.body[-1].targets[0],
                                            "+"))[0]
     assert str(
         meth
     ) == 'Proxy to the object: Function __add__ in scope Class "F" in scope Module'
     with self.assertRaises(exceptions.DunderUnimplemented) as e:
         list(
             protocols.get_custom_dunder_method(as_tree.body[-1].targets[0],
                                                "<"))
     assert e.exception.method_name == "__lt__"
コード例 #5
0
 def test_bootstrap(self):
     tree = AstBuilder().string_build("""\
         x = 1 + 3
     """)
     s = tree.body[0].value.left.locals["__add__"]
     assert str(
         s) == 'Function __add__ in scope Class "int" in scope Module'
コード例 #6
0
 def test_repr_variable(self):
     tree = AstBuilder().string_build("""\
         a.b.c = s
     """)
     tree.body[0].targets[0].version = 2
     assert repr(tree.body[0].targets[0]) == "a.b.c_2"
     assert tree.body[0].targets[0].get_var_repr() == "c_2"
コード例 #7
0
    def test_cfg_given_if_elif_no_else(self):
        as_tree = AstBuilder().string_build(
            dedent("""\
            a = 3          #--- 1st
            if a > 3:      #---  |
                a = 4      #--- 2nd
            elif a < 1:    #--- 3rd
                a = 5      #--- 4th
            c = 5          #--- 5th
            """))
        cfg_real = Cfg(as_tree)

        self.assertCfgWithBasicBlocks(
            cfg_real,
            [1, 2, "If", "L1"],
            [3, 3, "", "L3"],
            [4, 4, "If", "L4"],
            [5, 5, "", "L5"],
            [6, 6, "", "L6"],
            [None, None, "Module", "Module"],
            [-1, -1, "", "PhiStub"],
            block_links={
                "0": [1, 2],
                "1": [4],
                "2": [3, 4],
                "3": [4],
                "4": [6],
                "5": [0],
                "6": []
            },
        )
コード例 #8
0
    def test_1_function_def(self):
        as_tree = AstBuilder().string_build(
            dedent("""\
             def foo(x):
                if x < 2:
                    x = 2
                else:
                    x = 1
                z = 1

             f = 5
             z = 5
            """))
        cfg_real = Cfg(as_tree)
        cfg_real.fill_df()
        expected_idom = {
            "foo": ["L2"],
            "L2": ["L3", "L5", "L6"],
            "L3": [],
            "L5": [],
            "L6": ["PhiStub"],
            "PhiStub": []
        }
        self.assert_idom_equal(cfg_real, expected_idom)
        assert cfg_real.block_list[4].df == [cfg_real.block_list[6]]
コード例 #9
0
 def test_renaming_nameconstant(self):
     as_tree = AstBuilder().string_build(
         dedent("""\
                     if True:
                         x = True
                     else:
                         x = None
                     if False:
                         pass
                     """))
     cfg_real = Cfg(as_tree)
     cfg_real.convert_to_ssa()
     self.assertBlockSsaList(
         cfg_real.block_list,
         {
             "L1":
             dedent("""\
                                 True
                                 """),
             "L4":
             "Assign: (x_1,) = None",
             "L5":
             dedent("""\
                                 Assign: (x_2,) = Phi(x_0, x_1)
                                 False
                                 """),
         },
     )
コード例 #10
0
 def test_cfg_given_simple_class(self):
     as_tree = AstBuilder().string_build(
         dedent("""\
             class SomeClass:
                 def __init__(self):
                     pass
         """))
     cfg_real = Cfg(as_tree)
     self.assertCfgWithBasicBlocks(
         cfg_real,
         [1, 1, "ClassDef", "SomeClass"],
         [2, 2, "FunctionDef", "__init__"],
         [3, 3, "", "L3"],
         [None, None, "Module", "Module"],
         [1, 1, TEMP_ASSIGN, TEMP_ASSIGN],
         [2, 2, TEMP_ASSIGN, TEMP_ASSIGN],
         [-1, -1, "", "PhiStub"],
         [-1, -1, "", "PhiStub"],
         [-1, -1, "", "PhiStub"],
         block_links={
             "0": [5],
             "1": [2],
             "2": [6],
             "3": [4],
             "4": [7],
             "5": [6],
             "6": [],
             "7": [],
             "8": []
         },
     )
コード例 #11
0
    def test_renaming_multiple_scope(self):
        as_tree = AstBuilder().string_build(
            dedent("""\
                        def foo(x):
                            a = 3
                            return x

                        a = 2
                        foo(a)
                        """))
        cfg_real = Cfg(as_tree)
        cfg_real.convert_to_ssa()
        self.assertBlockSsaList(
            cfg_real.block_list,
            {
                "L2":
                dedent("""\
                                            Assign: (ret_val_0,) = x_0
                                            Assign: (a_0,) = 3
                                    """),
                "L5":
                dedent("""\
                                            Assign: (a_0,) = 2
                                            Call: foo_0((a_0,))
                                            """),
            },
        )
コード例 #12
0
    def test_initial_info_given_3_simple_stmt_given_if(self):
        as_tree = AstBuilder().string_build(
            dedent(
                """\
            a = 3
            if c < 3:
                y = a + b
                x = a
                y = b
                a.b = c
            """
            )
        )

        cfg_real = Cfg(as_tree)
        cfg_real.gather_initial_info()

        expected_ue_var = (set(), {"c"}, {"a", "b", "c"}, set())
        expected_var_kill = (set(), {"a"}, {"y", "x", "a.b"}, set())
        self.assert_uevar_varkill(cfg_real.block_list, expected_ue_var, expected_var_kill)

        expected_globals_var = {"b", "a", "c"}
        assert cfg_real.globals_var == expected_globals_var

        real_block_set = {str(k): v for k, v in cfg_real.block_set.items()}
        expected_block_set = {
            "x": cfg_real.block_list[2],
            "a": cfg_real.block_list[1],
            "y": cfg_real.block_list[2],
            "a.b": cfg_real.block_list[2],
        }
        assert real_block_set == expected_block_set
コード例 #13
0
    def test_cfg_given_while_body_if(self):
        as_tree = AstBuilder().string_build(
            dedent("""\
            z = 2           # 0th block
            while a < 3:    # 1st block
                if a < 2:   # 2nd block
                     z = 2  # 3rd block
                b = 2       # 4th block
            c = 3           # 5th block
            """))

        cfg_real = Cfg(as_tree)

        self.assertCfgWithBasicBlocks(
            cfg_real,
            [1, 1, "", "L1"],
            [2, 2, "While", "L2"],
            [3, 3, "If", "L3"],
            [4, 4, "", "L4"],
            [5, 5, "", "L5"],
            [6, 6, "", "L6"],
            block_links={
                "0": [1],
                "1": [2, 5],
                "2": [3, 4],
                "3": [4],
                "4": [1],
                "5": []
            },
        )
コード例 #14
0
    def test_ssa_generation_2_stmt(self):
        as_tree = AstBuilder().string_build(
            dedent(
                """\
            a = 1
            y = 2
            b = 3
            c = 4
            z = a + y
            x = b + c"""
            )
        )

        cfg = Cfg(as_tree)
        cfg.root.nxt_block_list[0].enumerate()
        expected_ssa_dict = {
            "z": deque([0]),
            "a": deque([0]),
            "y": deque([0]),
            "x": deque([0]),
            "b": deque([0]),
            "c": deque([0]),
        }
        real_ssa_dict = as_tree.ssa_record.var_version_list
        assert real_ssa_dict == expected_ssa_dict
コード例 #15
0
    def test_initial_info_given_3_simple_stmt_expect_ue_a_vk_a_y_x(self):
        as_tree = AstBuilder().string_build(
            dedent(
                """\
            a = 3
            y = a + b
            x = a
            y = b
            """
            )
        )
        cfg_real = Cfg(as_tree)
        cfg_real.gather_initial_info()

        expected_ue_var = {"b"}
        expected_var_kill = {"a", "y", "x"}

        assert cfg_real.block_list[1].ue_var == expected_ue_var
        assert cfg_real.block_list[1].var_kill == expected_var_kill

        expected_globals_var = {"b"}
        assert cfg_real.globals_var == expected_globals_var

        real_block_set = {str(k): v for k, v in cfg_real.block_set.items()}
        expected_block_set = {"x": cfg_real.block_list[1], "a": cfg_real.block_list[1], "y": cfg_real.block_list[1]}
        assert real_block_set == expected_block_set
コード例 #16
0
    def test_cfg_given_for(self):
        as_tree = AstBuilder().string_build(
            dedent("""\
            for a in z:     # 0st block
                if a < 2:   # 1nd block
                     z = 2  # 2rd block
                b = 2       # 3th block
            z = 4
            """))

        cfg_real = Cfg(as_tree)

        self.assertCfgWithBasicBlocks(
            cfg_real,
            [1, 1, "For", "L1"],
            [2, 2, "If", "L2"],
            [3, 3, "", "L3"],
            [4, 4, "", "L4"],
            [5, 5, "", "L5"],
            block_links={
                "0": [1, 4],
                "1": [2, 3],
                "2": [3],
                "3": [0],
                "4": []
            },
        )
コード例 #17
0
    def test_cfg_given_for_with_else(self):
        as_tree = AstBuilder().string_build(
            dedent("""\
            z = 2           # 0th block
            for a in z:     # 1st block
                if a < 2:   # 2nd block
                     z = 2  # 3rd block
                b = 2       # 4th block
            else:
                c = 3       # 5th block
            z = 4
            """))

        cfg_real = Cfg(as_tree)

        self.assertCfgWithBasicBlocks(
            cfg_real,
            [1, 1, "", "L1"],
            [2, 2, "For", "L2"],
            [3, 3, "If", "L3"],
            [4, 4, "", "L4"],
            [5, 5, "", "L5"],
            [7, 7, "", "L7"],
            [8, 8, "", "L8"],
            block_links={
                "0": [1],
                "1": [2, 5, 6],
                "2": [3, 4],
                "3": [4],
                "4": [1],
                "5": [6],
                "6": []
            },
        )
コード例 #18
0
 def test_cfg_given_simple_class_stmt_between(self):
     as_tree = AstBuilder().string_build(
         dedent("""\
             class SomeClass:
                 if True:
                     x = 1
                 else:
                     x = 3
                 def __init__(self):
                     pass
         """))
     cfg_real = Cfg(as_tree)
     self.assertCfgWithBasicBlocks(
         cfg_real,
         [1, 1, "ClassDef", "SomeClass"],
         [2, 2, "If", "L2"],
         [3, 3, "", "L3"],
         [5, 5, "", "L5"],
         [6, 6, TEMP_ASSIGN, TEMP_ASSIGN],
         block_links={
             "0": [1],
             "1": [2, 3],
             "2": [4],
             "3": [4],
             "4": []
         },
     )
コード例 #19
0
    def test_cfg_given_while(self):
        as_tree = AstBuilder().string_build(
            dedent("""\
            while 3 < 4:
                x = 3
                if x < 2:
                    y = 5
            """))
        cfg_real = Cfg(as_tree)

        self.assertCfgWithBasicBlocks(
            cfg_real,
            [1, 1, "While", "L1"],
            [2, 3, "If", "L2"],
            [4, 4, "", "L4"],
            [None, None, "Module", "Module"],
            [-1, -1, "", "PhiStub"],
            block_links={
                "0": [1, 4],
                "1": [2, 0],
                "2": [0],
                "3": [0],
                "4": []
            },
        )
コード例 #20
0
 def test_renaming_given_3_scopes(self):
     as_tree = AstBuilder().string_build(
         dedent("""\
                     class Foo():
                         x = 1
                         def __init__(self):
                             x = 2
                     x = 3
                     f = Foo(2)
                     """))
     cfg_real = Cfg(as_tree)
     cfg_real.convert_to_ssa()
     self.assertBlockSsaList(
         cfg_real.block_list,
         {
             "L2":
             dedent("""\
                 Assign: (x_0,) = 1
                 Assign: (__init___0,) = Proxy to the object: Function __init__ in scope Class "Foo" in scope Module
                 """),
             "L4":
             "Assign: (x_0,) = 2",
             "L5":
             dedent("""\
                 Assign: (x_0,) = 3
                 Assign: (f_0,) = Call: Foo_0((2,))
                 """),
         },
     )
コード例 #21
0
    def bootstrap_builtins(self):
        """Construct builtin class type (e.g. int, float) in ast form
        This will need to only parse builtins.pyi for the class definition,
        and construct the class with appropriate locals method with the return type.
        """
        self.logger.info(
            "INITIALIZE",
            "constructing builtins ast classes for type inference purposes")

        def builtins_proxy(c):
            return self.builtins_ast_cls[type(c.value)]

        builtins_file = pathlib.PurePath(__file__).parent / self.BUILTINS_FILE
        self.builtins_tree = AstBuilder(
            tree_rewriter=StubTreeRewriter).file_build(
                builtins_file, py2_version_check=self.config.py_version == 2)
        for field in dir(builtins):
            loc = self.builtins_tree.locals.get(field)
            if loc:
                self.builtins_ast_cls[getattr(builtins, field)] = loc
        self.builtins_ast_cls[type(None)] = None
        nodes.Const.obj = property(builtins_proxy)
        nodes.List.obj = self.builtins_ast_cls[list]
        nodes.Dict.obj = self.builtins_ast_cls[dict]
        nodes.Tuple.obj = self.builtins_ast_cls[tuple]
        nodes.Set.obj = self.builtins_ast_cls[set]
コード例 #22
0
    def test_cfg_given_if_else_with_link_tail(self):
        as_tree = AstBuilder().string_build(
            dedent("""\
            a = 3           # 1st
            if a > 3:       #  |
                a = 4       # 2nd
            else:           # 3rd
                z = 5       #  |
            y = 5           # 4th
            """))
        cfg_real = Cfg(as_tree)

        self.assertCfgWithBasicBlocks(
            cfg_real,
            [1, 2, "If", "L1"],
            [3, 3, "", "L3"],
            [5, 5, "", "L5"],
            [6, 6, "", "L6"],
            [None, None, "Module", "Module"],
            [-1, -1, "", "PhiStub"],
            block_links={
                "0": [1, 2],
                "1": [3],
                "2": [3],
                "3": [5],
                "4": [0],
                "5": []
            },
        )
コード例 #23
0
    def test_renaming_args_attribute(self):
        as_tree = AstBuilder().string_build(
            dedent("""\
                        class Temp:
                            def __init__(self):
                                pass

                        def foo(x):
                            return x + 1

                        y = Temp()
                        y.z = 3
                        foo(y.z)
                        """))
        cfg_real = Cfg(as_tree)
        cfg_real.convert_to_ssa()
        self.assertBlockSsaList(
            cfg_real.block_list,
            {
                "L9":
                dedent("""\
                                    Assign: (y_0.z_0,) = 3
                                    Call: foo_0((y_0.z_0,))
                                    """)
            },
        )
コード例 #24
0
 def test_lhs_multiple_assignment(self):
     tree = AstBuilder().string_build("""\
             a, b = c, d = 3, 4
         """)
     s = tree.body[0].get_lhs_value(tree.body[0].value.elts[0])
     assert s == [
         tree.body[0].targets[0].elts[0], tree.body[0].targets[1].elts[0]
     ]
コード例 #25
0
 def test_var_not_exist(self):
     tree = AstBuilder().string_build("""\
         y = x
     """)
     tree.body[0].value.version = 0
     tree.body[0].targets[0].version = 0
     link_stmts_to_def(tree.body[0])
     assert tree.body[0].value.links is None
コード例 #26
0
 def test_nested_tuple(self):
     tree = AstBuilder().string_build("""\
             (a, b, *c, d), e, f = (1, 2, 3, 4, 5, 6), 7, 8
         """)
     s = tree.body[0].get_rhs_value(tree.body[0].targets[0].elts[0].elts[2])
     assert str(s) == "(3, 4, 5)"
     s = tree.body[0].get_rhs_value(tree.body[0].targets[0].elts[1])
     assert str(s) == "7"
コード例 #27
0
 def test_renaming_str_format(self):
     as_tree = AstBuilder().string_build(
         dedent("""\
                 v = 1
                 s = "some{}".format(v)
                 """))
     cfg_real = Cfg(as_tree)
     cfg_real.convert_to_ssa()
コード例 #28
0
 def test_async(self):
     as_tree = AstBuilder().string_build("""\
         async def f():
             async with something():
                 async for i in range(3):
                     await g()
         """)
     s = as_tree.body[0].body[0].body[0].body[0].value.scope()
     assert s == as_tree.body[0]
コード例 #29
0
 def test_nested_tuple_variable(self):
     tree = AstBuilder().string_build("""\
             (a, b, *c, d), e, f = z
             (a, b, *c, d), e, f = z, 1, 3
         """)
     s = tree.body[0].get_rhs_value(tree.body[0].targets[0].elts[0].elts[2])
     assert str(s) == "z[0][2:-1:]"
     s = tree.body[1].get_rhs_value(tree.body[1].targets[0].elts[0].elts[2])
     assert str(s) == "z[2:-1:]"
コード例 #30
0
 def test_starred_last(self):
     tree = AstBuilder().string_build("""\
             a, *b = (1, 2, 3, 4)
             a, *b = a
         """)
     s = tree.body[0].get_rhs_value(tree.body[0].targets[0].elts[1])
     assert str(s) == "(2, 3, 4)"
     s = tree.body[1].get_rhs_value(tree.body[1].targets[0].elts[1])
     assert str(s) == "a[1::]"