示例#1
0
def pos_as_tuple(node: Union[ast3.expr, ast3.stmt]) -> Optional[ast3.Tuple]:
    if not hasattr(node, 'lineno'):
        return None

    return ast3.Tuple(elts=[
        ast3.Tuple(elts=[ast3.Num(node.lineno),
                         ast3.Num(node.col_offset)],
                   ctx=ast3.Load()),
        ast3.Name(id='fn', ctx=ast3.Load())
    ],
                      ctx=ast3.Load())
示例#2
0
    def visit_Attribute(self, node: ast3.Attribute) -> VisitorOutput:
        """Transforms accessing to an attribute to be handled as PythonValues do

        For example, it converts::

            expr.val

        into::

            expr.attr['val']

        or::

            expr.attr[('val', pos)]"""

        self.generic_visit(node)

        pos = pos_as_tuple(node)
        if pos is not None:
            varname = ast3.Tuple(elts=[ast3.Str(s=node.attr), pos],
                                 ctx=ast3.Load())  # type: ast3.expr
        else:
            varname = ast3.Str(s=node.attr)

        return ast3.Subscript(
            value=ast3.Attribute(
                value=node.value,
                attr='attr',
                ctx=ast3.Load(),
            ),
            slice=ast3.Index(value=varname, ),
            ctx=node.ctx,
        )
示例#3
0
def make_st_ndarray(data_type: typed_ast3.AST,
                    dimensions_or_sizes: t.Union[int, list]) -> typed_ast3.Subscript:
    """Create a typed_ast node equivalent to: st.ndarray[dimensions, data_type, sizes]."""
    if isinstance(dimensions_or_sizes, int):
        dimensions = dimensions_or_sizes
        sizes = None
    else:
        dimensions = len(dimensions_or_sizes)
        sizes = [make_expression_from_slice(size) for size in dimensions_or_sizes]
    return typed_ast3.Subscript(
        value=typed_ast3.Attribute(
            value=typed_ast3.Name(id='st', ctx=typed_ast3.Load()),
            attr='ndarray', ctx=typed_ast3.Load()),
        slice=typed_ast3.Index(value=typed_ast3.Tuple(
            elts=[typed_ast3.Num(n=dimensions), data_type] + [
                typed_ast3.Tuple(elts=sizes, ctx=typed_ast3.Load())] if sizes else [],
            ctx=typed_ast3.Load())),
        ctx=typed_ast3.Load())
示例#4
0
    def dispatch_var_type(self, tree):
        code = horast.unparse(tree)
        stripped_code = code.strip()
        if stripped_code in PYTHON_FORTRAN_TYPE_PAIRS:
            type_name, precision = PYTHON_FORTRAN_TYPE_PAIRS[stripped_code]
            self.write(type_name)
            if precision is not None:
                self.write('*')
                self.write(str(precision))
        elif _match_array(tree):
            sli = tree.slice
            assert isinstance(sli,
                              typed_ast3.Index), typed_astunparse.dump(tree)
            assert isinstance(sli.value, typed_ast3.Tuple)
            assert len(sli.value.elts) in (2, 3), sli.value.elts
            elts = sli.value.elts
            self.dispatch_var_type(elts[1])
            self.write(', ')
            self.write('dimension(')

            if len(sli.value.elts) == 2:
                self.write(':')
            else:
                if not self._context_input_args:
                    self.dispatch(elts[2])
                else:
                    assert isinstance(elts[2], typed_ast3.Tuple)
                    _LOG.warning('coercing indices of %i dims to 0-based',
                                 len(elts[2].elts))
                    # _LOG.warning('coercing indices of %s in %s to 0-based', arg.arg, t.name)
                    tup_elts = []
                    for elt in elts[2].elts:
                        if isinstance(elt, typed_ast3.Num):
                            assert isinstance(elt.n, int)
                            upper = typed_ast3.Num(n=elt.n - 1)
                        else:
                            assert isinstance(elt, typed_ast3.Name)
                            upper = typed_ast3.BinOp(left=elt,
                                                     op=typed_ast3.Sub(),
                                                     right=typed_ast3.Num(n=1))
                        tup_elts.append(
                            typed_ast3.Slice(lower=typed_ast3.Num(n=0),
                                             upper=upper,
                                             step=None))
                    tup = typed_ast3.Tuple(elts=tup_elts,
                                           ctx=typed_ast3.Load())
                    self.dispatch(tup)

            self.write(')')
        elif _match_io(tree):
            self.write('integer')
        elif isinstance(tree, typed_ast3.Call) and isinstance(tree.func, typed_ast3.Name) \
                and tree.func.id == 'type':
            self.dispatch(tree)
        else:
            raise NotImplementedError('not yet implemented: {}'.format(
                typed_astunparse.dump(tree)))
示例#5
0
def make_expression_from_slice(
        slice_: t.Union[typed_ast3.Index, typed_ast3.Slice, typed_ast3.ExtSlice]) -> typed_ast3.AST:
    """Transform code like '0:n:2' into a valid expression that is as simple as possible."""
    assert isinstance(slice_, (
        typed_ast3.Index, typed_ast3.Slice, typed_ast3.ExtSlice)), type(slice_)

    if isinstance(slice_, typed_ast3.Index):
        return slice_.value
    if isinstance(slice_, typed_ast3.Slice):
        lower, upper, step = slice_.lower, slice_.upper, slice_.step
        if lower is None and upper is not None and step is None:
            return upper
        return make_call_from_slice(slice_)
    assert isinstance(slice_, typed_ast3.ExtSlice)
    elts = [make_expression_from_slice(dim) for dim in slice_.dims]
    return typed_ast3.Tuple(elts=elts, ctx=typed_ast3.Load())
示例#6
0
    def visit_Name(self, node: ast3.Name) -> VisitorOutput:
        """Transforms a name lookup into a dictionary lookup.

        For example, it converts::

            var

        into::

            st[('var', ...)]
        """

        pos = pos_as_tuple(node)
        if pos is not None:
            varname = ast3.Tuple(elts=[ast3.Str(s=node.id), pos],
                                 ctx=ast3.Load())  # type: ast3.expr
        else:
            varname = ast3.Str(s=node.id)

        return ast3.Subscript(value=ast3.Name(id='st', ctx=ast3.Load()),
                              slice=ast3.Index(value=varname),
                              ctx=node.ctx)
示例#7
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
示例#8
0
    def visit_Call(self, node: ast3.Call) -> VisitorOutput:
        """Transforms a call to be handled by Pytropos

        For example, it converts::

            func(3, b, *c, d=2)

        into::

            func.call(st, Args((pt.int(3), st['b']), st['c'], {'d': pt.int(2)}), pos=...)"""

        self.generic_visit(node)

        args = []  # type: List[ast3.expr]
        starred = None  # type: Optional[ast3.expr]
        kwargs_keys = []  # type: List[ast3.expr]
        kwargs_values = []  # type: List[ast3.expr]

        for i, v in enumerate(node.args):
            if isinstance(v, ast3.Starred):
                starred = v.value
                break
            args.append(v)
        # In case a starred expresion was found
        else:
            # If there is something after the starred expr
            if len(node.args) > 0 and i < len(node.args) - 1:
                raise AstTransformerError(
                    f"{self.filename}:{v.lineno}:{v.col_offset}: Fatal Error: "
                    "Only one expression starred is allowed when calling a function"
                )

        for val in node.keywords:
            if val.arg is None:
                raise AstTransformerError(
                    f"{self.filename}:{v.lineno}:{v.col_offset}: Fatal Error: "
                    "No kargs parameters is allowed when calling a function")
            kwargs_keys.append(ast3.Str(s=val.arg))
            kwargs_values.append(val.value)

        new_call_args = [
            ast3.Tuple(
                elts=args,
                ctx=ast3.Load(),
            ),
        ]  # type: List[ast3.expr]

        if kwargs_keys:
            new_call_args.append(
                ast3.NameConstant(value=None) if starred is None else starred)
            new_call_args.append(
                ast3.Dict(keys=kwargs_keys, values=kwargs_values))
        elif starred is not None:
            new_call_args.append(starred)

        return ast3.Call(
            func=ast3.Attribute(
                value=node.func,
                attr='call',
                ctx=ast3.Load(),
            ),
            args=[
                ast3.Name(id='st', ctx=ast3.Load()),
                ast3.Call(
                    func=ast3.Attribute(
                        value=ast3.Name(id='pt', ctx=ast3.Load()),
                        attr='Args',
                        ctx=ast3.Load(),
                    ),
                    args=new_call_args,
                    keywords=[],
                )
            ],
            keywords=[
                ast3.keyword(arg='pos',
                             value=pos_as_tuple(node),
                             ctx=ast3.Load())
            ],
        )