예제 #1
0
def evaluate_call(node: ast3.Call,
                  *,
                  scope: Scope,
                  module_path: catalog.Path) -> Node:
    if not is_named_tuple_definition(node,
                                     scope=scope,
                                     module_path=module_path):
        return node
    class_name_node, fields_node = node.args

    def field_to_parameter(field_node: ast3.expr) -> ast3.arg:
        name_node, annotation_node = field_node.elts
        return ast3.arg(ast3.literal_eval(name_node), annotation_node)

    initializer_node = ast3.FunctionDef(
            '__init__',
            ast3.arguments([ast3.arg('self', None)]
                           + list(map(field_to_parameter,
                                      fields_node.elts)),
                           None, [], [], None, []),
            [ast3.Pass()], [], None)
    function_path = evaluate_node(node.func,
                                  scope=scope,
                                  module_path=module_path)
    class_def = ast3.ClassDef(ast3.literal_eval(class_name_node),
                              [ast3.Name(str(function_path), ast3.Load())],
                              [], [initializer_node], [])
    return ast3.fix_missing_locations(ast3.copy_location(class_def, node))
예제 #2
0
 def visit_FuncDef(self, node) -> typed_ast3.FunctionDef:  # pylint: disable=invalid-name
     """Transform FuncDef."""
     assert node.decl is not None
     name, args, return_type = self.visit(node.decl)
     param_decls = self.visit(node.param_decls)
     if param_decls is not None:
         raise NotImplementedError(_node_debug(node.param_decls), str(param_decls))
     body = self.visit(node.body)
     assert isinstance(body, list) and body
     _ = self.visit(node.coord)
     funcdef = typed_ast3.FunctionDef(name=name, args=args, body=fix_stmts_in_body(body),
                                      decorator_list=[], returns=return_type)
     return funcdef
예제 #3
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
예제 #4
0
    def _Function(self, node: ET.Element):  # pylint: disable=invalid-name
        if not self.types.is_relevant(node):
            raise ContinueIteration()
        name = node.attrib['name']
        arguments = typed_ast3.arguments(
            args=self.transform_all_subnodes(node),
            vararg=None,
            kwonlyargs=[],
            kwarg=None,
            defaults=[],
            kw_defaults=[])

        body = [typed_ast3.Expr(value=typed_ast3.Ellipsis())]
        returns = self.types.resolved_types[node.attrib['returns']]
        return typed_ast3.FunctionDef(name=name,
                                      args=arguments,
                                      body=body,
                                      decorator_list=[],
                                      returns=returns)
예제 #5
0
    def test_inline_flash_subset_hydro(self):
        app_name = 'FLASH-SUBSET'
        if app_name not in _APPS_ROOT_PATHS and app_name in _APPS_OPTIONAL:
            self.skipTest('{} directory not found'.format(app_name))
        language = Language.find('Fortran')
        reader = CodeReader()
        parser = Parser.find(language)()
        ast_generalizer = AstGeneralizer.find(language)()
        f_unparser = Unparser.find(language)()
        py_unparser = Unparser.find(Language.find('Python'))()
        writer = CodeWriter()

        dir_name = app_name.lower()
        results_path = pathlib.Path(RESULTS_ROOT, 'transformations', 'inlining', dir_name)
        results_path.mkdir(parents=True, exist_ok=True)

        path_pairs = [
            (pathlib.Path('physics/Hydro/HydroMain/unsplit/hy_upwindTransverseFlux_loop.F90'),
             pathlib.Path('physics/Hydro/HydroMain/unsplit/hy_upwindTransverseFlux.F90'),
             (1, 1)),
            (pathlib.Path('physics/Eos/EosMain/Eos_getData_loop1.F90'),
             pathlib.Path('physics/Eos/EosMain/Eos_getData.F90'),
             (1, 2))]

        for inlined_path, target_path, (index, extra_lines) in path_pairs:
            inlined_path = pathlib.Path(_APPS_ROOT_PATHS[app_name], 'source', inlined_path)
            target_path = pathlib.Path(_APPS_ROOT_PATHS[app_name], 'source', target_path)

            output_inlined_path = results_path.joinpath(inlined_path.name)
            output_target_path = results_path.joinpath(target_path.name)
            output_path = results_path.joinpath(target_path.with_suffix('').name + '_inlined.F90')

            inlined_xml = parser.parse('', inlined_path)
            inlined_xml = inlined_xml.find('.//subroutine')
            writer.write_file(ET.tostring(inlined_xml, 'utf-8').decode(),
                              output_inlined_path.with_suffix('.xml'))

            inlined_syntax = ast_generalizer.generalize(inlined_xml)
            writer.write_file(typed_astunparse.dump(inlined_syntax),
                              output_inlined_path.with_suffix('.ast.py'))
            writer.write_file(py_unparser.unparse(inlined_syntax),
                              output_inlined_path.with_suffix('.py'))
            writer.write_file(f_unparser.unparse(inlined_syntax),
                              output_inlined_path.with_suffix('.f95'))

            target_code = reader.read_file(target_path)
            target_xml = parser.parse(target_code, target_path)
            # import ipdb; ipdb.set_trace()
            target_xml = target_xml.findall('.//call')[index]
            writer.write_file(ET.tostring(target_xml, 'utf-8').decode(),
                              output_target_path.with_suffix('.xml'))

            target_syntax = ast_generalizer.generalize(target_xml)
            writer.write_file(typed_astunparse.dump(target_syntax),
                              output_target_path.with_suffix('.ast.py'))
            writer.write_file(py_unparser.unparse(target_syntax),
                              output_target_path.with_suffix('.py'))
            writer.write_file(f_unparser.unparse(target_syntax),
                              output_target_path.with_suffix('.f95'))

            mock_function = typed_ast3.FunctionDef(
                'f', typed_ast3.arguments([], None, [], None, [], []),
                [typed_ast3.Expr(target_syntax)], [], None, None)
            output_syntax = inline_syntax(mock_function, inlined_syntax, globals_=globals())
            output_syntax = st.augment(typed_ast3.Module(output_syntax.body, []), eval_=False)
            writer.write_file(typed_astunparse.dump(output_syntax),
                              output_path.with_suffix('.ast.py'))
            writer.write_file(py_unparser.unparse(output_syntax),
                              output_path.with_suffix('.py'))
            output_code = f_unparser.unparse(output_syntax)
            writer.write_file(output_code, output_path.with_suffix('.f95'))

            _LOG.warning('[%s %s] <- %i', target_xml.attrib['line_begin'],
                         target_xml.attrib['line_end'], len(output_code))
            total_code = replace_scope(
                target_code, int(target_xml.attrib['line_begin']),
                int(target_xml.attrib['line_end']) + extra_lines, output_code)
            writer.write_file(total_code, output_path)
예제 #6
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
예제 #7
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