Exemple #1
0
    def visit_For(self, node: ast.For) -> None:
        # create list to iterate over
        lst_name = self.context.get_temp_name()
        assign_node = ast.Assign(
            targets=[ast.Name(id=lst_name, ctx=ast.Store())], value=node.iter)
        self.visit(assign_node)

        lst = self.context[lst_name]
        index = self.context.get_temp_var(TypeDB.get_type_by_name("int"))
        length = lst.tp.get_method("len")
        length_code = length.get_code(self.context, lst).code

        # construct for statement
        self.start_line(
            f"for({index.code}=0; {index.code} < {length_code}; {index.code}++) {{\n"
        )
        self.indent += 4
        assign_node = ast.Assign(
            targets=[node.target],
            value=ast.Subscript(
                value=ast.Name(id=lst_name, ctx=ast.Load()),
                slice=ast.Index(value=ast.Name(id=index.code, ctx=ast.Load())),
                ctx=ast.Load()))
        self.visit(assign_node)
        for statement in node.body:
            self.visit(statement)
        self.indent -= 4
        self.start_line("}\n")
        self.all_paths_return = False
 def visit_Decl(self, node) -> t.Union[typed_ast3.AnnAssign,  # pylint: disable=invalid-name
                                       t.Tuple[str, typed_ast3.arguments, typed_ast3.AST]]:
     """Transform Decl."""
     name = node.name
     assert isinstance(name, str), type(name)
     quals = node.quals
     if quals:
         _LOG.warning('ignoring unsupported C grammar: %s', quals)
     storage = [self.visit(subnode) for subnode in node.storage]
     if storage:
         raise NotImplementedError(_node_debug(node.storage), str(storage))
     funcspec = [self.visit(subnode) for subnode in node.funcspec]
     if funcspec:
         raise NotImplementedError(_node_debug(node.funcspec), str(funcspec))
     type_data = self.visit(node.type)
     assert isinstance(type_data, tuple)
     assert len(type_data) == DECL_DATA_LENGTHS[type(node.type)], (type(node.type), type_data)
     init = self.visit(node.init)
     if init is not None:
         assert isinstance(node.type, INITIALIZABLE_DECLARATIONS)
         # assert isinstance(node.type, c_ast.TypeDecl), type(node.type)
         # raise NotImplementedError(_node_debug(node.init), str(init))
     bitsize = self.visit(node.bitsize)
     if bitsize is not None:
         raise NotImplementedError(_node_debug(node.bitsize), str(bitsize))
     _ = self.visit(node.coord)
     if init is not None or isinstance(node.type, INITIALIZABLE_DECLARATIONS):
         name_, type_ = type_data
         assert name_ == name
         return typed_ast3.AnnAssign(target=typed_ast3.Name(id=name_, ctx=typed_ast3.Store()),
                                     annotation=type_, value=init, simple=1)
     if isinstance(node.type, (c_ast.FuncDecl,)):
         return type_data
     return self.generic_visit(node)
 def test_non_str_type_comment(self):
     examples = {
         typed_ast3.Assign(targets=[
             typed_ast3.Name('x', typed_ast3.Store())
         ],
                           value=typed_ast3.Str('universe, life, and everything'),
                           type_comment=typed_ast3.Str('42')):
         logging.DEBUG,
         typed_ast3.Assign(targets=[
             typed_ast3.Name('x', typed_ast3.Store())
         ],
                           value=typed_ast3.Str('universe, life, and everything'),
                           type_comment=42):
         logging.WARNING
     }
     for example, expected_level in examples.items():
         resolver = TypeHintResolver[typed_ast3, typed_ast3](eval_=False)
         with self.subTest(example=example, expected_level=expected_level):
             with self.assertLogs(level=expected_level):
                 resolver.visit(example)
 def visit_Typedef(self, node):  # pylint: disable=invalid-name
     """Transform Typedef."""
     name = node.name
     assert isinstance(name, str), type(name)
     quals = node.quals
     if quals:
         _LOG.warning('ignoring unsupported C grammar: %s', quals)
     assert node.storage == ['typedef'], node.storage
     name_, type_ = self.visit(node.type)
     assert name == name_, (name, name_)
     _ = self.visit(node.coord)
     return typed_ast3.AnnAssign(target=typed_ast3.Name(name, typed_ast3.Store()), value=type_,
                                 annotation=typed_ast3.Name('type', typed_ast3.Load()), simple=1)
Exemple #5
0
    def visit_Attribute(self, node: ast3.Attribute):
        # If this Attribute isn't being used on the left-hand side of an assignment
        # statement, the visitor doesn't need to save it.
        if not self._is_store(node):
            return

        if self._in_class:
            # If in a class, only save "self.attr" expressions.
            if isinstance(node.value, ast3.Name) and node.value.id == "self":
                self._namespace[node.attr].append(
                    definitions.Variable(name=node.attr,
                                         source=self._source,
                                         lineno=node.lineno,
                                         col_offset=node.col_offset))
        else:
            # Outside of a class, an expression like "a.b.c" is stored as
            # Variable(name = "a"). When parsed, "a.b.c" becomes
            # Attribute(Attribute(Name("a"), "b"), "c"). Since only "a" needs to be
            # saved, proceed with the visit as normal so visit_Name handles "a".
            # However, "a" and "b" are considered Loads, not Stores, so we need to
            # update the node.
            node.value.ctx = ast3.Store()
            self.generic_visit(node)
Exemple #6
0
    def visit_ImportFrom(self, node: ast3.ImportFrom) -> VisitorOutput:
        """Defines how to import (from) modules (supported and nonsupported)

        For example, it converts::

            from numpy import array
            from numpy import *
            from somelib import var, othervar as var2
            from otherlib import *

        into::

            from pytropos.libs_checking import numpy_module
            st['array'] = numpy_module.attr['array', pos...]

            from pytropos.libs_checking import numpy_module
            st.importStar(numpy_module)

            st['var'] = pt.Top
            st['var2'] = pt.Top

            st.importStar()
            """

        libs: 'List[ast3.AST]' = []

        if node.module in self._supported_modules:
            module_name = self._supported_modules[node.module]
            # from pytropos.libs_checking import module_name
            libs.append(
                ast3.ImportFrom(
                    module='pytropos.libs_checking',
                    names=[ast3.alias(name=module_name, asname=None)],
                    level=0,
                ))
            if node.names[0].name == '*':
                # st.importStar(module_name)
                libs.append(
                    ast3.Expr(value=ast3.Call(
                        func=ast3.Attribute(
                            value=ast3.Name(id='st', ctx=ast3.Load()),
                            attr='importStar',
                            ctx=ast3.Load(),
                        ),
                        args=[ast3.Name(id=module_name, ctx=ast3.Load())],
                        keywords=[],
                    ), ))
            else:
                for alias in node.names:
                    # st['asname'] = modname.attr['name']

                    pos = pos_as_tuple(node)

                    if pos is not None:
                        attrname = ast3.Tuple(
                            elts=[ast3.Str(s=alias.name), pos],
                            ctx=ast3.Load())  # type: ast3.expr
                    else:
                        attrname = ast3.Str(s=alias.name)

                    libs.append(
                        ast3.Assign(
                            targets=[
                                ast3.Subscript(
                                    value=ast3.Name(id='st', ctx=ast3.Load()),
                                    slice=ast3.Index(value=ast3.Str(
                                        s=alias.asname if alias.
                                        asname else alias.name), ),
                                    ctx=ast3.Store(),
                                ),
                            ],
                            value=ast3.Subscript(
                                value=ast3.Attribute(
                                    value=ast3.Name(id=module_name,
                                                    ctx=ast3.Load()),
                                    attr='attr',
                                    ctx=ast3.Load(),
                                ),
                                slice=ast3.Index(value=attrname, ),
                                ctx=ast3.Load(),
                            ),
                        ))
        else:
            if node.names[0].name == '*':
                # st.importStar()
                libs.append(
                    ast3.Expr(value=ast3.Call(
                        func=ast3.Attribute(
                            value=ast3.Name(id='st', ctx=ast3.Load()),
                            attr='importStar',
                            ctx=ast3.Load(),
                        ),
                        args=[],
                        keywords=[],
                    ), ))
            else:
                libs.extend(
                    ast3.parse(  # type: ignore
                        '\n'.join([
                            "st['{asname}'] = pt.Top".format(
                                asname=alias.asname if alias.asname else alias.
                                name) for alias in node.names
                        ])).body)

        return libs
Exemple #7
0
    def visit_While(self, node: ast3.While) -> VisitorOutput:
        """Transforms an if statement into what Pytropos understands:

        For example, it converts::

            while question:
                body

        into::

            if_qstn = TRANSFORMED(question)
            def while_qst(st):
                return question
            def while_(st):
                body
                return st
            st = pt.runWhile(st, while_qstn, while_)
        """
        if node.orelse:
            raise AstTransformerError(
                f"Pytropos doesn't support else statement in while loop yet, sorry :("
            )

        self.generic_visit(node)
        new_body = node.body.copy()

        new_body.append(
            ast3.Return(value=ast3.Name(id='st', ctx=ast3.Load()), ))

        new_node = [
            ast3.FunctionDef(
                name='while_qst',
                args=ast3.arguments(args=[ast3.arg(arg='st', annotation=None)],
                                    vararg=None,
                                    kwonlyargs=[],
                                    kw_defaults=[],
                                    kwarg=None,
                                    defaults=[]),
                body=[ast3.Return(value=node.test)],
                decorator_list=[],
                returns=None,
            ),
            ast3.FunctionDef(
                name='while_',
                args=ast3.arguments(args=[ast3.arg(arg='st', annotation=None)],
                                    vararg=None,
                                    kwonlyargs=[],
                                    kw_defaults=[],
                                    kwarg=None,
                                    defaults=[]),
                body=new_body,
                decorator_list=[],
                returns=None,
            ),
            ast3.Assign(targets=[ast3.Name(id='st', ctx=ast3.Store())],
                        value=ast3.Call(
                            func=ast3.Attribute(
                                value=ast3.Name(id='pt', ctx=ast3.Load()),
                                attr='runWhile',
                                ctx=ast3.Load(),
                            ),
                            args=[
                                ast3.Name(id='st', ctx=ast3.Load()),
                                ast3.Name(id='while_qst', ctx=ast3.Load()),
                                ast3.Name(id='while_', ctx=ast3.Load())
                            ],
                            keywords=[],
                        ))
        ]
        return new_node  # type: ignore
Exemple #8
0
    def visit_If(self, node: ast3.If) -> VisitorOutput:
        """Transforms an if statement into what Pytropos understands:

        For example, it converts::

            if question:
                body1
            else:
                body2

        into::

            if_qstn = TRANSFORMED(question)
            def if_(st):
                body1
                return st
            def else_(st):
                body2
                return st
            st = pt.runIf(st, if_qstn, if_, else_)
        """
        self.generic_visit(node)
        new_body = node.body.copy()
        new_orelse = node.orelse.copy()
        orelse = bool(node.orelse)

        new_body.append(
            ast3.Return(value=ast3.Name(id='st', ctx=ast3.Load()), ))

        new_node = [
            ast3.Assign(targets=[ast3.Name(id='if_qstn', ctx=ast3.Store())],
                        value=node.test),
            ast3.FunctionDef(
                name='if_',
                args=ast3.arguments(args=[ast3.arg(arg='st', annotation=None)],
                                    vararg=None,
                                    kwonlyargs=[],
                                    kw_defaults=[],
                                    kwarg=None,
                                    defaults=[]),
                body=new_body,
                decorator_list=[],
                returns=None,
            ),
        ]
        if orelse:
            # adding "return st"
            new_orelse.append(
                ast3.Return(value=ast3.Name(id='st', ctx=ast3.Load()), ))
            new_node.append(
                ast3.FunctionDef(
                    name='else_',
                    args=ast3.arguments(
                        args=[ast3.arg(arg='st', annotation=None)],
                        vararg=None,
                        kwonlyargs=[],
                        kw_defaults=[],
                        kwarg=None,
                        defaults=[]),
                    body=new_orelse,
                    decorator_list=[],
                    returns=None,
                ))
        new_node.append(
            ast3.Assign(targets=[ast3.Name(id='st', ctx=ast3.Store())],
                        value=ast3.Call(
                            func=ast3.Attribute(
                                value=ast3.Name(id='pt', ctx=ast3.Load()),
                                attr='runIf',
                                ctx=ast3.Load(),
                            ),
                            args=[
                                ast3.Name(id='st', ctx=ast3.Load()),
                                ast3.Name(id='if_qstn', ctx=ast3.Load()),
                                ast3.Name(id='if_', ctx=ast3.Load()),
                                ast3.Name(id='else_', ctx=ast3.Load())
                            ] if orelse else [
                                ast3.Name(id='st', ctx=ast3.Load()),
                                ast3.Name(id='if_qstn', ctx=ast3.Load()),
                                ast3.Name(id='if_', ctx=ast3.Load())
                            ],
                            keywords=[],
                        )))
        return new_node  # type: ignore
Exemple #9
0
 def visit_Subscript(self, node: ast3.Subscript):
     # A Subscript expression may be on the left-hand side of an assignment, but
     # the value field (which should have a hint) is in a Load context.
     if self._is_store(node):
         node.value.ctx = ast3.Store()
         self.generic_visit(node)
Exemple #10
0
def expression_to_assignment(node: ast3.expr, *, name: str) -> ast3.Assign:
    name_node = ast3.copy_location(ast3.Name(name, ast3.Store()), node)
    result = ast3.Assign([name_node], node, None)
    return ast3.copy_location(result, node)