コード例 #1
0
    def _emulate_yield_from(self, targets: Optional[List[ast.Name]],
                            node: ast.YieldFrom) -> Iterable[ast.AST]:
        generator = ast.Name(
            id='_py_backwards_generator_{}'.format(self._name_suffix))
        exception = ast.Name(
            id='_py_backwards_generator_exception_{}'.format(self._name_suffix))

        yield ast.Assign(targets=[generator],
                         value=ast.Call(func=ast.Name(id='iter'),
                                        args=[node.value],
                                        keywords=[]))

        assign_to_targets = [
            ast.If(test=ast.Call(func=ast.Name(id='hasattr'), args=[
                exception, ast.Str(s='value'),
            ], keywords=[]), body=[
                ast.Assign(targets=targets,
                           value=ast.Attribute(
                               value=exception, attr='value')),
            ], orelse=[]),
            ast.Break()] if targets else [ast.Break()]

        yield ast.While(test=ast.NameConstant(value=True), body=[
            ast.Try(body=[
                ast.Expr(value=ast.Yield(value=ast.Call(
                    func=ast.Name(id='next'),
                    args=[generator], keywords=[]))),
            ], handlers=[
                ast.ExceptHandler(
                    type=ast.Name(id='StopIteration'),
                    name=exception.id,
                    body=assign_to_targets),
            ], orelse=[], finalbody=[]),
        ], orelse=[])
        self._name_suffix += 1
コード例 #2
0
ファイル: ast_generalizer.py プロジェクト: yuanzy97/transpyle
 def visit_Cast(self, node):  # pylint: disable=invalid-name
     """Transform C cast into cast() function call."""
     to_type = self.visit(node.to_type)
     expr = self.visit(node.expr)
     _ = self.visit(node.coord)
     return typed_ast3.Call(func=typed_ast3.Name(id='cast', ctx=typed_ast3.Load()), args=[expr],
                            keywords=[typed_ast3.keyword(arg='type', value=to_type)])
コード例 #3
0
 def _set_arguments_to_super(self, call: ast.Call, first_argument: str):
     super_cls = ast.Name(
         id='cls') if first_argument == 'cls' else ast.Call(
             func=ast.Name(id='type'),
             args=[ast.Name(id=first_argument)],
             keywords=[])
     call.args = [super_cls, ast.Name(id=first_argument)]
コード例 #4
0
 def _merge_dicts(self, xs: Iterable[Union[ast.Call, ast.Dict]]) \
         -> ast.Call:
     """Creates call of function for merging dicts."""
     return ast.Call(
         func=ast.Name(id='_py_backwards_merge_dicts'),
         args=[ast.List(elts=list(xs))],
         keywords=[])
コード例 #5
0
ファイル: unparser.py プロジェクト: qshan/transpyle
 def _Attribute(self, t):
     if isinstance(t.value, typed_ast3.Name) and t.value.id == 'Fortran':
         raise NotImplementedError(
             'Fortran.{} can be handled only when subscripted.'.format(
                 t.attr))
     if isinstance(t.value, typed_ast3.Name) and t.attr == 'size':
         call = typed_ast3.Call(func=typed_ast3.Name(id='size',
                                                     ctx=typed_ast3.Load()),
                                args=[t.value],
                                keywords=[])
         self._Call(call)
         return
     if syntax_matches(
             t,
             typed_ast3.Attribute(value=typed_ast3.Attribute(
                 value=typed_ast3.Name(id='st', ctx=typed_ast3.Load()),
                 attr='generic',
                 ctx=typed_ast3.Load()),
                                  attr='GenericVar',
                                  ctx=typed_ast3.Load())):
         # t._fortran_metadata = {'is_generic_var': True}
         # self._generic_vars.append()
         return
     self._unsupported_syntax(t)
     '''
コード例 #6
0
    def visit_Compare(self, node: ast3.Compare) -> VisitorOutput:
        "Transforms a comparision into a function call. E.g. `ABC == MNO` into `ABC.eq(MNO)`"

        assert len(
            node.ops
        ) == 1, "Pytropos only supports comparisions of two values at the time"
        self.generic_visit(node)

        op_type = type(node.ops[0])
        if op_type not in compopt:
            raise AstTransformerError(
                f"Pytropos doesn't support the comparison {type(op_type)} yet, sorry :("
            )

        op_str = compopt[op_type]

        new_v = ast3.Call(func=ast3.Attribute(value=node.left,
                                              attr=op_str,
                                              ctx=ast3.Load()),
                          args=[node.comparators[0]],
                          keywords=[
                              ast3.keyword(arg='pos',
                                           value=pos_as_tuple(node),
                                           ctx=ast3.Load())
                          ])
        return new_v
コード例 #7
0
 def visit_FuncCall(self, node) -> typed_ast3.Call:  # pylint: disable=invalid-name
     """Return a call."""
     name = self.visit(node.name)
     assert isinstance(name, typed_ast3.Name)
     args = self.visit(node.args)
     _ = self.visit(node.coord)
     return typed_ast3.Call(func=name, args=args, keywords=[])
コード例 #8
0
 def assign_target(self, node, value):
     if isinstance(value.tp, EmptyList):
         func_node = ast.Expr(value=ast.Call(
             func=ast.Attribute(value=node, attr="clear"), args=[]))
         try:
             self.visit(func_node)
         except UnknownVariable:
             raise StaticTypeError(
                 "Must specify a list type when assigning an empty list")
         return
     if isinstance(node, ast.Name):
         left = self.context.assign_type(node.id, value.tp)
         self.start_line("{} = {};\n".format(left.code, value.as_value()))
     elif isinstance(node, ast.Subscript):
         container = self.get_expression_code(node.value)
         if isinstance(node.slice, ast.Index):
             index = self.get_expression_code(node.slice.value)
             setter = container.tp.get_method("set_item")
             code = setter.get_code(self.context, container, index, value)
             self.start_line(f"{code.code};\n")
         else:
             raise UnimplementedFeature("Slices not yet implemented")
     elif isinstance(node, ast.Attribute):
         owner = self.get_expression_code(node.value)
         owner.tp.set_attr(node.attr, value)
         left = self.get_expression_code(node)
         self.start_line(f"{left.code} = {value.code};\n")
コード例 #9
0
    def visit_JoinedStr(self, node: ast.JoinedStr) -> ast.Call:
        self._tree_changed = True

        join_call = ast.Call(func=ast.Attribute(value=ast.Str(s=''),
                                                attr='join'),
                             args=[ast.List(elts=node.values)],
                             keywords=[])
        return self.generic_visit(join_call)  # type: ignore
コード例 #10
0
def make_numpy_constructor(function: str, arg: typed_ast3.AST,
                           data_type: typed_ast3.AST) -> typed_ast3.Call:
    return typed_ast3.Call(
        func=typed_ast3.Attribute(
            value=typed_ast3.Name(id='np', ctx=typed_ast3.Load()),
            attr=function, ctx=typed_ast3.Load()),
        args=[arg],
        keywords=[typed_ast3.keyword(arg='dtype', value=data_type)])
コード例 #11
0
 def _prepare_lists(self, xs: List[Splitted]) -> Iterable[ListEntry]:
     """Wrap starred in list call and list elts to just List."""
     for x in xs:
         if isinstance(x, ast.Starred):
             yield ast.Call(func=ast.Name(id='list'),
                            args=[x.value],
                            keywords=[])
         elif x:
             yield ast.List(elts=x)
コード例 #12
0
 def _show_store_contents_expr(self) -> ast3.Expr:
     """Returns an ast3.Expr which prints the value of the store in the screen. Useful
     for debugging.
     """
     # print(st)
     return ast3.Expr(value=ast3.Call(
         func=ast3.Name(id='print', ctx=ast3.Load()),
         args=[ast3.Name(id='st', ctx=ast3.Load())],
         keywords=[],
     ), )
コード例 #13
0
 def _prepare_splitted(self, splitted: Splitted) \
         -> Iterable[Union[ast.Call, ast.Dict]]:
     """Wraps splitted in Call or Dict."""
     for group in splitted:
         if not isinstance(group, list):
             yield ast.Call(func=ast.Name(id='dict'),
                            args=[group],
                            keywords=[])
         elif group:
             yield ast.Dict(keys=[key for key, _ in group],
                            values=[value for _, value in group])
コード例 #14
0
    def visit_FormattedValue(self, node: ast.FormattedValue) -> ast.Call:
        if node.format_spec:
            template = ''.join(['{:', node.format_spec.s, '}'])  # type: ignore
        else:
            template = '{}'

        format_call = ast.Call(func=ast.Attribute(value=ast.Str(s=template),
                                                  attr='format'),
                               args=[node.value],
                               keywords=[])
        return self.generic_visit(format_call)  # type: ignore
コード例 #15
0
    def visit_Call(self, n):
        args = self.visit(n.args)
        if n.starargs is not None:
            args.append(ast3.Starred(self.visit(n.starargs), ast3.Load(), lineno=n.starargs.lineno, col_offset=n.starargs.col_offset))

        keywords = self.visit(n.keywords)
        if n.kwargs is not None:
            keywords.append(ast3.keyword(None, self.visit(n.kwargs)))

        return ast3.Call(self.visit(n.func),
                         args,
                         keywords)
コード例 #16
0
    def visit_Exec(self, n):
        new_globals = self.maybe_visit(n.globals)
        if new_globals is None:
            new_globals = ast3.Name("None", ast3.Load(), lineno=-1, col_offset=-1)
        new_locals = self.maybe_visit(n.locals)
        if new_locals is None:
            new_locals = ast3.Name("None", ast3.Load(), lineno=-1, col_offset=-1)

        return ast3.Expr(ast3.Call(ast3.Name("exec", ast3.Load(), lineno=n.lineno, col_offset=-1),
                                   [self.visit(n.body), new_globals, new_locals],
                                   [],
                                   lineno=n.lineno, col_offset=-1))
コード例 #17
0
    def visit_Print(self, n):
        keywords = []
        if n.dest is not None:
            keywords.append(ast3.keyword("file", self.visit(n.dest)))

        if not n.nl:
            keywords.append(ast3.keyword("end", ast3.Str(" ", lineno=n.lineno, col_offset=-1)))

        return ast3.Expr(ast3.Call(ast3.Name("print", ast3.Load(), lineno=n.lineno, col_offset=-1),
                                   self.visit(n.values),
                                   keywords,
                                   lineno=n.lineno, col_offset=-1))
コード例 #18
0
    def visit_ListComp(self, node):
        from parser.functions import FunctionImplementation

        # calculate result type
        if len(node.generators) > 1:
            raise InvalidOperation(
                "Only one for statement permitted in comprehensions")
        comp = node.generators[0]
        if len(comp.ifs) > 1:
            raise InvalidOperation(
                "Only one if statement allowed in List Comprehension")
        assign_node = ast.Assign(targets=[comp.target],
                                 value=ast.Subscript(value=comp.iter,
                                                     slice=ast.Index(
                                                         ast.Num(0))))
        return_node = ast.Return(value=node.elt)
        function_node = ast.FunctionDef(name="temp",
                                        args=ast.arguments(args=[],
                                                           vararg=None,
                                                           kwonlyargs=[],
                                                           kw_defaults=[],
                                                           kwarg=None,
                                                           defaults=[]),
                                        body=[assign_node, return_node])
        function_interpreter = FunctionImplementation(function_node, (),
                                                      self.context)
        result_type = TypeDB.get_list([function_interpreter.retval.tp])

        # create temp list to hold values
        result = self.context.get_temp_var(result_type)
        self.prepends.append(
            f"{result.code} = {result_type.as_literal([])};\n")
        # create for expression
        append_node = ast.Expr(
            ast.Call(func=ast.Attribute(value=ast.Name(id=result.code,
                                                       ctx=ast.Load()),
                                        attr="append",
                                        ctx=ast.Load()),
                     args=[node.elt],
                     keywords=[]))
        if comp.ifs:
            body = ast.If(test=comp.ifs[0], body=[append_node], orelse=[])
        else:
            body = append_node
        for_node = ast.For(target=comp.target,
                           iter=comp.iter,
                           body=[body],
                           orelse=[])
        self.prepends.append(for_node)
        return result
コード例 #19
0
 def _Attribute(self, t):
     if isinstance(t.value, typed_ast3.Name) and t.value.id == 'Fortran':
         raise NotImplementedError(
             'Fortran.{} can be handled only when subscripted.'.format(
                 t.attr))
     if isinstance(t.value, typed_ast3.Name) and t.attr == 'size':
         call = typed_ast3.Call(func=typed_ast3.Name(id='size',
                                                     ctx=typed_ast3.Load()),
                                args=[t.value],
                                keywords=[])
         self._Call(call)
         return
     self._unsupported_syntax(t)
     '''
コード例 #20
0
    def visit_Expr(self, node: ast3.Expr) -> VisitorOutput:
        """Only the internal parts of an Expr are modified, an Expr keeps being an Expr"""
        self.generic_visit(node)

        # In console mode ("single" for Python's compile) any expression statement should
        # print to console
        if self.console:
            return ast3.Expr(value=ast3.Call(
                func=ast3.Name(id='print_console', ctx=ast3.Load()),
                args=[node.value],
                keywords=[],
            ), )

        return node
コード例 #21
0
    def visit_NameConstant(self, node: ast3.NameConstant) -> VisitorOutput:
        """Transforms name constants (None, True, False) into Pytropos values.

        For example, it converts::

            True
            None

        into::

            pt.bool(True)
            pt.none()
        """
        if isinstance(node.value, bool):
            return ast3.Call(
                func=ast3.Attribute(
                    value=ast3.Name(id='pt', ctx=ast3.Load()),
                    attr='bool',
                    ctx=ast3.Load(),
                ),
                args=[ast3.NameConstant(value=node.value)],
                keywords=[],
            )
        elif node.value is None:
            return ast3.Call(
                func=ast3.Attribute(
                    value=ast3.Name(id='pt', ctx=ast3.Load()),
                    attr='none',
                    ctx=ast3.Load(),
                ),
                args=[],
                keywords=[],
            )
        else:
            raise AstTransformerError(
                f"Pytropos doesn't recognise {type(node.value)} as a constant. Sorry"
            )
コード例 #22
0
def make_range_call(begin: t.Optional[typed_ast3.AST] = None, end: typed_ast3.AST = None,
                    step: t.Optional[typed_ast3.AST] = None) -> typed_ast3.Call:
    """Create a typed_ast node equivalent to: range(begin, end, step)."""
    assert isinstance(end, typed_ast3.AST)
    if step is None:
        if begin is None:
            args = [end]
        else:
            args = [begin, end]
    else:
        assert isinstance(step, typed_ast3.AST)
        assert isinstance(begin, typed_ast3.AST)
        args = [begin, end, step]
    return typed_ast3.Call(func=typed_ast3.Name(id='range', ctx=typed_ast3.Load()),
                           args=args, keywords=[])
コード例 #23
0
    def visit_Raise(self, n):
        e = None
        if n.type is not None:
            e = self.visit(n.type)

            if n.inst is not None and not (isinstance(n.inst, ast27.Name) and n.inst.id == "None"):
                inst = self.visit(n.inst)
                if isinstance(inst, ast3.Tuple):
                    args = inst.elts
                else:
                    args = [inst]
                e = ast3.Call(e, args, [], lineno=e.lineno, col_offset=-1)

        ret = ast3.Raise(e, None)
        if n.tback is not None:
            ret.traceback = self.visit(n.tback)
        return ret
コード例 #24
0
    def visit_Num(self, node: ast3.Num) -> VisitorOutput:
        """Wraps a number into a Pytropos type.

        Example: given the number `3` returns `pt.int(3)`
        """
        if isinstance(node.n, (int, float)):
            attr = 'int' if isinstance(node.n, int) else 'float'
            new_v = ast3.Call(func=ast3.Attribute(value=ast3.Name(
                id='pt', ctx=ast3.Load()),
                                                  attr=attr,
                                                  ctx=ast3.Load()),
                              args=[ast3.Num(n=node.n)],
                              keywords=[])
            return new_v
        else:
            raise AstTransformerError(
                f"Number of type {type(node.n)} isn't supported by pytropos. Sorry :S"
            )
コード例 #25
0
def make_call_from_slice(slice_: typed_ast3.Slice) -> typed_ast3.Call:
    """Transform code like '0:n:2' into 'slice(0, n, 2)'."""
    assert isinstance(slice_, typed_ast3.Slice), type(slice_)
    lower, upper, step = slice_.lower, slice_.upper, slice_.step
    if lower is None and upper is None and step is None:
        args = [typed_ast3.NameConstant(None)]
    elif lower is not None and upper is None and step is None:
        args = [lower, typed_ast3.NameConstant(None)]
    elif lower is None and upper is not None and step is None:
        args = [typed_ast3.NameConstant(None), upper]
    elif lower is not None and upper is not None and step is None:
        args = [lower, upper]
    elif lower is not None and upper is None and step is not None:
        args = [lower, typed_ast3.NameConstant(None), step]
    elif lower is not None and upper is not None and step is not None:
        args = [lower, upper, step]
    else:
        raise NotImplementedError('unsupported slice form: "{}"'.format(typed_ast3.dump(slice_)))
    return typed_ast3.Call(typed_ast3.Name('slice', typed_ast3.Load()), args, [])
コード例 #26
0
    def _replace_return(self, parent: Any, return_: ast.Return) -> None:
        """Replace return with exception raising."""
        index = parent.body.index(return_)
        parent.body.pop(index)

        exception = ast.Name(id='_py_backwards_generator_return_{}'.format(
            self._name_suffix))

        raise_exception = ast.Raise(exc=exception, cause=None)
        parent.body.insert(index, raise_exception)

        set_value = ast.Assign(targets=[
            ast.Attribute(value=exception, attr='value'),
        ], value=return_.value)
        parent.body.insert(index, set_value)

        assign = ast.Assign(targets=[exception],
                            value=ast.Call(func=ast.Name(id='StopIteration'),
                                           args=[],
                                           keywords=[]))
        parent.body.insert(index, assign)
コード例 #27
0
    def visit_Tuple(self, node: ast3.Tuple) -> VisitorOutput:
        """Transforms a tuple into a Pytropos value.

        For example, it converts::

            (a, 5, 21)

        into::

            pt.tuple(st['a'], pt.int(5), pt.int(21))"""
        self.generic_visit(node)

        return ast3.Call(
            func=ast3.Attribute(
                value=ast3.Name(id='pt', ctx=ast3.Load()),
                attr='tuple',
                ctx=ast3.Load(),
            ),
            args=node.elts,
            keywords=[],
        )
コード例 #28
0
    def visit_List(self, node: ast3.List) -> VisitorOutput:
        """Transforms a list into a Pytropos value.

        For example, it converts::

            [a, 5, 21]

        into::

            pt.list([st['a'], pt.int(5), pt.int(21)])"""
        self.generic_visit(node)

        return ast3.Call(
            func=ast3.Attribute(
                value=ast3.Name(id='pt', ctx=ast3.Load()),
                attr='list',
                ctx=ast3.Load(),
            ),
            args=[node],
            keywords=[],
        )
コード例 #29
0
    def visit_BinOp(self, node: ast3.BinOp) -> VisitorOutput:
        "Transforms a binary operation into a function call. E.g. `ABC == MNO` into `ABC.eq(MNO)`"

        self.generic_visit(node)
        op_type = type(node.op)
        if op_type not in operations:
            raise AstTransformerError(
                f"Pytropos doesn't support the operation {type(op_type)} yet, sorry :("
            )

        op_str = operations[op_type]

        new_v = ast3.Call(func=ast3.Attribute(value=node.left,
                                              attr=op_str,
                                              ctx=ast3.Load()),
                          args=[node.right],
                          keywords=[
                              ast3.keyword(arg='pos',
                                           value=pos_as_tuple(node),
                                           ctx=ast3.Load())
                          ])
        return new_v
コード例 #30
0
    def visit_AnnAssign(self, node: ast3.AnnAssign) -> VisitorOutput:
        """Transforms an assignment with annotation into a pytropos type hint assignment.

        For example, it converts::

            var: ann = expr

        into::

            `var` = pt.type_hint(`ann`, `expr`)
        """
        if node.value is None:
            raise AstTransformerError(
                f"{self.filename}:{node.lineno}:{node.col_offset}: Fatal Error: "
                "Only annotated assignments are allowed (variables with initial values). "
                "I.e., no full support for PEP 526 yet. Sorry :(")

        pos = pos_as_tuple(node)

        # Deleting annotation :S
        self.generic_visit(node)
        # new_node = ast3.Assign(targets=[node.target], value=node.value)
        return ast3.Assign(
            targets=[node.target],
            value=ast3.Call(
                func=ast3.Attribute(
                    value=ast3.Name(id='pt', ctx=ast3.Load()),
                    attr='annotation',
                    ctx=ast3.Load(),
                ),
                args=[
                    node.annotation, node.value, pos if pos else ast3.Expr(
                        value=ast3.NameConstant(value=None))
                ],
                keywords=[],
            ),
        )