Beispiel #1
0
def test_multiple_blank_lines():
    '''Test that multiple blank lines with or without white space are
    output as an empty Comment objects.

    '''
    input_text = ("   \n\n"
                  "program test\n"
                  "  \n\n"
                  "end program test\n"
                  "  \n\n")
    reader = FortranStringReader(input_text, ignore_comments=False)
    lines = list(reader)
    assert len(lines) == 8
    for index in [0, 1, 3, 4, 6, 7]:
        assert isinstance(lines[index], Comment)
        assert lines[index].span == (index + 1, index + 1)
        assert lines[index].line == ""
    assert isinstance(lines[2], Line)
    assert lines[2].span == (3, 3)
    assert lines[2].line == "program test"
    assert isinstance(lines[5], Line)
    assert lines[5].span == (6, 6)
    assert lines[5].line == "end program test"

    reader = FortranStringReader(input_text, ignore_comments=True)
    lines = list(reader)
    assert len(lines) == 2
    assert isinstance(lines[0], Line)
    assert lines[0].span == (3, 3)
    assert lines[0].line == "program test"
    assert isinstance(lines[1], Line)
    assert lines[1].span == (6, 6)
    assert lines[1].line == "end program test"
Beispiel #2
0
def test_base_fixed_continuation(log):
    '''
    Tests that FortranReaderBase.get_source_item() logs the correct messages
    when there are quote mismatches across a continuation in fixed format.
    '''
    code = '     character(4) :: cheese = "a & !\n     & b'
    log.reset()
    unit_under_test = FortranStringReader(code)
    mode = FortranFormat(False, False)
    unit_under_test.set_format(mode)  # Force sloppy fixed format
    unit_under_test.get_source_item()
    assert log.messages['debug'] == []
    assert log.messages['info'] == []
    assert log.messages['error'] == []
    assert log.messages['critical'] == []
    expected = 'following character continuation: \'"\', expected None.'
    result = log.messages['warning'][0].split('<==')[1].lstrip()
    assert result == expected

    code = '     x=1 &\n     +1 &\n     -2'
    log.reset()
    unit_under_test = FortranStringReader(code)
    mode = FortranFormat(False, False)
    unit_under_test.set_format(mode)  # Force sloppy fixed format
    unit_under_test.get_source_item()
    assert log.messages['debug'] == []
    assert log.messages['info'] == []
    assert log.messages['error'] == []
    assert log.messages['critical'] == []
    expected = 'free format line continuation character `&\' detected ' \
               + 'in fix format code\n    2:     +1 &\n    3:     -2'
    result = log.messages['warning'][0].split('<==')[1].lstrip()
    assert result == expected
Beispiel #3
0
def test_base_handle_multilines(log):
    '''
    Tests that FortranReaderBase.get_source_item() logs the correct messages
    when there are quote discrepancies.
    '''
    code = 'character(8) :: test = \'foo"""bar'
    log.reset()
    unit_under_test = FortranStringReader(code)
    mode = FortranFormat(True, True)
    unit_under_test.set_format(mode)  # Force strict free format
    unit_under_test.get_source_item()
    assert log.messages['debug'] == []
    assert log.messages['info'] == []
    assert log.messages['error'] == []
    assert log.messages['critical'] == []
    expected = 'multiline prefix contains odd number of "\'" characters'
    result = log.messages['warning'][0].split('<==')[1].lstrip()
    assert result == expected

    code = 'goo """boo\n doo""" soo \'foo'
    log.reset()
    unit_under_test = FortranStringReader(code)
    mode = FortranFormat(True, True)
    unit_under_test.set_format(mode)  # Force strict free format
    unit_under_test.get_source_item()
    assert log.messages['debug'] == []
    assert log.messages['info'] == []
    assert log.messages['error'] == []
    assert log.messages['critical'] == []
    expected = 'following character continuation: "\'", expected None.'
    result = log.messages['warning'][0].split('<==')[1].lstrip()
    assert result == expected
Beispiel #4
0
def test_comments_within_continuation():
    '''Test that comments and multi-line statements are processed
    correctly.

    '''
    input_text = ("  ! Comment1\n"
                  "  real :: a &\n"
                  "  ! Comment2\n"
                  "          ,b\n"
                  "  ! Comment3\n")

    reader = FortranStringReader(input_text, ignore_comments=False)
    lines = list(reader)
    assert len(lines) == 4

    assert isinstance(lines[0], Comment)
    assert lines[0].span == (1, 1)
    assert lines[0].line == "! Comment1"

    assert lines[1].span == (2, 4)
    assert lines[1].line == "real :: a           ,b"

    assert isinstance(lines[2], Comment)
    assert lines[2].span == (3, 3)
    assert lines[2].line == "! Comment2"

    assert isinstance(lines[3], Comment)
    assert lines[3].span == (5, 5)
    assert lines[3].line == "! Comment3"

    reader = FortranStringReader(input_text, ignore_comments=True)
    lines = list(reader)
    assert len(lines) == 1
    assert lines[0].span == (2, 4)
    assert lines[0].line == "real :: a           ,b"
Beispiel #5
0
def test_derived_type_codeblocks(f2008_parser):
    ''' Check that we create a CodeBlock if we encounter unsupported
    entries in a parse tree describing a derived-type access. We have
    to test with invalid content in two locations. '''
    code = ("subroutine my_sub()\n"
            "  use some_mod, only: my_type\n"
            "  type(my_type), dimension(3) :: var\n"
            "  var(1)%region%subgrid(3)%stop = 1\n"
            "end subroutine my_sub\n")
    processor = Fparser2Reader()
    # First create a valid parse tree.
    reader = FortranStringReader(code)
    fparser2spec = f2008_parser(reader)
    dref = Fortran2003.walk(fparser2spec, Fortran2003.Data_Ref)[0]
    # Now break the Data_Ref instance by modifying its first child. Requesting
    # a subset of items from a tuple appears to generate a new tuple so
    # explicitly create a list and then create a tuple from that.
    item_list = ["hello"] + list(dref.items[1:])
    dref.items = tuple(item_list)
    sched = processor.generate_schedule("my_sub", fparser2spec)
    cblocks = sched.walk(CodeBlock)
    assert len(cblocks) == 1
    assert isinstance(cblocks[0].parent, Assignment)
    # Repeat but this time break the Data_Ref by modifying its second child.
    reader = FortranStringReader(code)
    fparser2spec = f2008_parser(reader)
    dref = Fortran2003.walk(fparser2spec, Fortran2003.Data_Ref)[0]
    dref.items = (dref.items[0], "hello")
    sched = processor.generate_schedule("my_sub", fparser2spec)
    cblocks = sched.walk(CodeBlock)
    assert len(cblocks) == 1
    assert isinstance(cblocks[0].parent, Assignment)
def test_redundant_empty_only_list():
    ''' Check that we drop 'use's with an empty only list if they become
    redundant. #TODO #11 Check for appropriate logging messages here once
    logging is implemented. '''
    fake_parent = KernelSchedule("dummy_schedule")
    processor = Fparser2Reader()
    # Empty only-list followed by wildcard import
    reader = FortranStringReader("use mod1, only:\n" "use mod1\n")
    fparser2spec = Fortran2003.Specification_Part(reader)
    processor.process_declarations(fake_parent, fparser2spec.content, [])
    csym = fake_parent.symbol_table.lookup("mod1")
    assert csym.wildcard_import
    # Wildcard import followed by empty only-list
    reader = FortranStringReader("use mod2\n" "use mod2, only:\n")
    fparser2spec = Fortran2003.Specification_Part(reader)
    processor.process_declarations(fake_parent, fparser2spec.content, [])
    csym = fake_parent.symbol_table.lookup("mod2")
    assert csym.wildcard_import
    # Empty only-list followed by named import
    reader = FortranStringReader("use mod3, only:\n" "use mod3, only: fred\n")
    fparser2spec = Fortran2003.Specification_Part(reader)
    processor.process_declarations(fake_parent, fparser2spec.content, [])
    sym_table = fake_parent.symbol_table
    csym = sym_table.lookup("mod3")
    assert not csym.wildcard_import
    assert sym_table.imported_symbols(csym)[0].name == "fred"
    # Named import followed by empty only-list
    reader = FortranStringReader("use mod4, only: bob\n" "use mod4, only:\n")
    fparser2spec = Fortran2003.Specification_Part(reader)
    processor.process_declarations(fake_parent, fparser2spec.content, [])
    csym = sym_table.lookup("mod4")
    assert not csym.wildcard_import
    assert sym_table.imported_symbols(csym)[0].name == "bob"
Beispiel #7
0
def test_array_notation_rank():
    ''' Check that the _array_notation_rank() utility handles various examples
    of array notation.

    TODO #754 fix test so that 'disable_declaration_check' fixture is not
    required.
    '''
    fake_parent = Schedule()
    processor = Fparser2Reader()
    reader = FortranStringReader("  z1_st(:, 2, :) = ptsu(:, :, 3)")
    fparser2spec = Fortran2003.Assignment_Stmt(reader)
    processor.process_nodes(fake_parent, [fparser2spec])
    assert processor._array_notation_rank(fake_parent[0].lhs) == 2
    reader = FortranStringReader("  z1_st(:, :, 2, :) = ptsu(:, :, :, 3)")
    fparser2spec = Fortran2003.Assignment_Stmt(reader)
    processor.process_nodes(fake_parent, [fparser2spec])
    assert processor._array_notation_rank(fake_parent[1].lhs) == 3
    # We don't support bounds on slices
    reader = FortranStringReader("  z1_st(:, 1:n, 2, :) = ptsu(:, :, :, 3)")
    fparser2spec = Fortran2003.Assignment_Stmt(reader)
    processor.process_nodes(fake_parent, [fparser2spec])
    with pytest.raises(NotImplementedError) as err:
        processor._array_notation_rank(fake_parent[2].lhs)
    assert ("Only array notation of the form my_array(:, :, ...) is "
            "supported." in str(err.value))
Beispiel #8
0
def test_base_fixed_nonlabel(log):
    '''
    Tests that FortranReaderBase.get_source_item() logs the correct messages
    when there is an unexpected character in the initial 6 columns.
    '''
    # Checks that a bad character in the first column causes an event to be
    # logged.
    code = 'w    integer :: i'
    log.reset()
    unit_under_test = FortranStringReader(code)
    mode = FortranFormat(False, True)
    unit_under_test.set_format(mode)  # Force fixed format
    unit_under_test.get_source_item()
    assert log.messages['debug'] == []
    assert log.messages['info'] == []
    assert log.messages['error'] == []
    assert log.messages['critical'] == []
    result = log.messages['warning'][0].split('<==')[1].lstrip()
    expected = "non-space/digit char 'w' found in column 1 of fixed " \
               + "Fortran code, interpreting line as comment line"
    assert result == expected

    # Checks a bad character in columns 2-6
    for i in range(1, 5):
        code = ' ' * i + 'w' + ' ' * (5 - i) + 'integer :: i'
        log.reset()
        unit_under_test = FortranStringReader(code)
        mode = FortranFormat(False, True)
        unit_under_test.set_format(mode)  # Force strict fixed format
        unit_under_test.get_source_item()
        assert log.messages['debug'] == []
        assert log.messages['info'] == []
        assert log.messages['error'] == []
        assert log.messages['critical'] == []
        result = log.messages['warning'][0].split('<==')[1].lstrip()
        expected = "non-space/digit char 'w' found in column {col} " \
                   + "of fixed Fortran code"
        assert result == expected.format(col=i + 1)

    # Checks for a bad character, not in the first column, with "sloppy" mode
    # engaged.
    code = ' w   integer :: i'
    log.reset()
    unit_under_test = FortranStringReader(code)
    mode = FortranFormat(False, False)
    unit_under_test.set_format(mode)  # Force sloppy fixed format
    unit_under_test.get_source_item()
    assert log.messages['debug'] == []
    assert log.messages['info'] == []
    assert log.messages['error'] == []
    assert log.messages['critical'] == []
    expected = "non-space/digit char 'w' found in column 2 " \
               + "of fixed Fortran code, switching to free format mode"
    result = log.messages['warning'][0].split('<==')[1].lstrip()
    assert result == expected
Beispiel #9
0
    def __init__(self, parent, datatype="", entity_decls=None, intent="",
                 pointer=False, kind="", dimension="", allocatable=False):
        '''
        :param parent: node to which to add this declaration as a child
        :type parent: :py:class:`psyclone.f2pygen.BaseGen`
        :param str datatype: the (intrinsic) type for this declaration
        :param list entity_decls: list of variable names to declare
        :param str intent: the INTENT attribute of this declaration
        :param bool pointer: whether or not this is a pointer declaration
        :param str kind: the KIND attribute to use for this declaration
        :param str dimension: the DIMENSION specifier (i.e. the xx in
                              DIMENSION(xx))
        :param bool allocatable: whether this declaration is for an
                                 ALLOCATABLE quantity

        :raises RuntimeError: if no variable names are specified
        :raises RuntimeError: if datatype is not one of "integer" or "real"
        '''
        if entity_decls is None:
            raise RuntimeError(
                "Cannot create a variable declaration without specifying the "
                "name(s) of the variable(s)")
        fort_fmt = FortranFormat(True, False)  # free form, strict
        if datatype.lower() == "integer":
            reader = FortranStringReader("integer :: vanilla")
            reader.set_format(fort_fmt)
            myline = reader.next()
            self._decl = fparser1.typedecl_statements.Integer(parent.root,
                                                              myline)
        elif datatype.lower() == "real":
            reader = FortranStringReader("real :: vanilla")
            reader.set_format(fort_fmt)
            myline = reader.next()
            self._decl = fparser1.typedecl_statements.Real(parent.root, myline)
        else:
            raise RuntimeError(
                "f2pygen:DeclGen:init: Only integer and real are currently"
                " supported and you specified '{0}'".format(datatype))
        # make a copy of entity_decls as we may modify it
        local_entity_decls = entity_decls[:]
        self._decl.entity_decls = local_entity_decls
        my_attrspec = []
        if intent != "":
            my_attrspec.append("intent({0})".format(intent))
        if pointer is not False:
            my_attrspec.append("pointer")
        if allocatable is not False:
            my_attrspec.append("allocatable")
        self._decl.attrspec = my_attrspec
        if dimension != "":
            my_attrspec.append("dimension({0})".format(dimension))
        if kind is not "":
            self._decl.selector = ('', kind)
        BaseGen.__init__(self, parent, self._decl)
Beispiel #10
0
def test_single_comment():
    '''Test that a free format single line comment is output as expected'''
    input_text = "! a comment\n"

    reader = FortranStringReader(input_text, ignore_comments=False)
    lines = list(reader)
    assert len(lines) == 1
    assert isinstance(lines[0], Comment)
    assert lines[0].span == (1, 1)
    assert lines[0].line + "\n" == input_text

    reader = FortranStringReader(input_text, ignore_comments=True)
    lines = list(reader)
    assert len(lines) == 0
Beispiel #11
0
def test_single_blank_line(input_text):
    '''Test that a single blank line with or without white space is output
    as an empty Comment object.

    '''
    reader = FortranStringReader(input_text, ignore_comments=False)
    lines = list(reader)
    assert len(lines) == 1
    assert isinstance(lines[0], Comment)
    assert lines[0].span == (1, 1)
    assert lines[0].line == ""

    reader = FortranStringReader(input_text, ignore_comments=True)
    lines = list(reader)
    assert len(lines) == 0
def test_brackets_array_constructor(left, right):
    ''' Test parsing of array constructor specified with both valid types of
    bracket. '''
    fcode = "array = {0} 1, 2, 3{1}".format(left, right)
    reader = FortranStringReader(fcode)
    ast = Fortran2003.Assignment_Stmt(reader)
    assert isinstance(ast, Fortran2003.Assignment_Stmt)
    assert isinstance(ast.children[2], Fortran2003.Array_Constructor)
    assert isinstance(ast.children[2].children[1], Fortran2003.Ac_Value_List)
    assert "array = {0}1, 2, 3{1}".format(left, right) in str(ast)
    # Invalid content between valid brackets
    fcode = "array = {0}call hello(){1}".format(left, right)
    reader = FortranStringReader(fcode)
    ast = Fortran2003.Assignment_Stmt(reader)
    assert ast is None
Beispiel #13
0
def test_parallel_if_block(parser):
    ''' Check that we can enclose an IF-block within a parallel region. '''
    reader = FortranStringReader("program do_loop\n"
                                 "integer :: ji\n"
                                 "integer, parameter :: jpi=64\n"
                                 "logical :: init\n"
                                 "real :: sto_tmp(jpi), sto_tmp2(jpi)\n"
                                 "if(init)then\n"
                                 "  do ji = 1,jpi\n"
                                 "    sto_tmp(ji) = 1.0d0\n"
                                 "  end do\n"
                                 "else\n"
                                 "  do ji = 1,jpi\n"
                                 "    sto_tmp2(ji) = 1.0d0\n"
                                 "  end do\n"
                                 "end if\n"
                                 "end program do_loop\n")
    code = parser(reader)
    psy = PSyFactory(API, distributed_memory=False).create(code)
    schedule = psy.invokes.invoke_list[0].schedule
    acc_trans = TransInfo().get_trans_name('ACCParallelTrans')
    schedule, _ = acc_trans.apply(schedule.children[0:1])
    code = str(psy.gen)
    assert ("  !$ACC PARALLEL\n"
            "  IF (init) THEN\n"
            "    DO ji = 1, jpi\n" in code)
    assert ("    END DO\n" "  END IF\n" "  !$ACC END PARALLEL\n" in code)
def test_call_not_implicit_loop():
    ''' Check we do not incorrectly identify an implicit loop when array
    notation is used in the arguments to a function call. '''
    code = "z3d(1,:,:) =  ptr_sjk( pvtr(:,:,:), btmsk(:,:,jn)*btm30(:,:) )"
    reader = FortranStringReader(code)
    assign = Fortran2003.Assignment_Stmt(reader)
    assert not nemo.NemoImplicitLoop.match(assign)
def test_1d_array_not_implicit_loop():
    ''' Check that we do not identify the use of array-notation in 1D loops
    as being implicit loops (since we don't know what the loop is over). '''
    code = "z1d(:) =  1.0d0"
    reader = FortranStringReader(code)
    assign = Fortran2003.Assignment_Stmt(reader)
    assert not nemo.NemoImplicitLoop.match(assign)
Beispiel #16
0
def test_kernels_in_data_region(parser):
    ''' Check that directives end up in the correct locations when enclosing
    a kernels region inside a data region. '''
    reader = FortranStringReader("program one_loop\n"
                                 "integer :: ji, jpj\n"
                                 "real(kind=wp) :: sto_tmp(5)\n"
                                 "do ji = 1,jpj\n"
                                 "  sto_tmp(ji) = 0.0\n"
                                 "end do\n"
                                 "end program one_loop\n")
    code = parser(reader)
    psy = PSyFactory(API, distributed_memory=False).create(code)
    schedule = psy.invokes.invoke_list[0].schedule
    acc_dtrans = TransInfo().get_trans_name('ACCDataTrans')
    acc_ktrans = TransInfo().get_trans_name('ACCKernelsTrans')
    schedule, _ = acc_ktrans.apply(schedule.children[:],
                                   {"default_present": True})
    schedule, _ = acc_dtrans.apply(schedule.children[:])
    new_code = str(psy.gen)
    assert ("  !$ACC DATA COPYOUT(sto_tmp)\n"
            "  !$ACC KERNELS DEFAULT(PRESENT)\n"
            "  DO ji = 1, jpj\n" in new_code)
    assert ("  END DO\n"
            "  !$ACC END KERNELS\n"
            "  !$ACC END DATA\n"
            "END PROGRAM one_loop" in new_code)
Beispiel #17
0
def test_missed_array_case(parser):
    ''' Check that we raise the expected InternalError if our internal
    sanity check spots that we've missed an array access.
    TODO #309 - remove this test. '''
    code = ("program do_bound\n"
            "  integer :: ice_mask(8,8)\n"
            "  real(kind=wp) :: trim_width(8), zdta(8,8)\n"
            "  integer :: ji, jj, dom\n"
            "  do jj = 1, trim_width(dom)\n"
            "    do ji = 1, 8\n"
            "      select case(ice_mask(ji,jj))\n"
            "      case(0)\n"
            "        zdta(ji,jj) = 1.0\n"
            "      case(1)\n"
            "        zdta(ji,jj) = 0.0\n"
            "      end select\n"
            "    end do\n"
            "  end do\n"
            "end program do_bound\n")
    reader = FortranStringReader(code)
    ptree = parser(reader)
    psy = PSyFactory(API, distributed_memory=False).create(ptree)
    schedule = psy.invokes.get('do_bound').schedule
    acc_trans = TransInfo().get_trans_name('ACCDataTrans')
    # Put the second loop nest inside a data region
    acc_trans.apply(schedule.children)
    with pytest.raises(InternalError) as err:
        _ = str(psy.gen)
    assert ("ArrayReference 'ice_mask' present in source code ("
            "'ice_mask(ji, jj)') but not identified" in str(err.value))
Beispiel #18
0
def test_replicated_loop(parser, tmpdir):
    '''Check code generation with two loops that have the same
    structure.

    '''
    reader = FortranStringReader("subroutine replicate()\n"
                                 "   INTEGER :: dummy\n"
                                 "   REAL :: zwx(10,10)\n"
                                 "   zwx(:,:) = 0.e0\n"
                                 "   zwx(:,:) = 0.e0\n"
                                 "END subroutine replicate\n")
    code = parser(reader)
    psy = PSyFactory(API, distributed_memory=False).create(code)
    schedule = psy.invokes.get('replicate').schedule
    acc_trans = TransInfo().get_trans_name('ACCDataTrans')
    schedule, _ = acc_trans.apply(schedule.children[0:1])
    schedule, _ = acc_trans.apply(schedule.children[1:2])
    gen_code = str(psy.gen)

    assert ("  !$ACC DATA COPYOUT(zwx)\n"
            "  zwx(:, :) = 0.E0\n"
            "  !$ACC END DATA\n"
            "  !$ACC DATA COPYOUT(zwx)\n"
            "  zwx(:, :) = 0.E0\n"
            "  !$ACC END DATA" in gen_code)
    assert Compile(tmpdir).string_compiles(gen_code)
Beispiel #19
0
def test_no_code_blocks(parser):
    ''' Check that we refuse to include CodeBlocks (i.e. code that we
    don't recognise) within a data region. '''
    reader = FortranStringReader("program write_out\n"
                                 " integer :: ji, jpj\n"
                                 "real(kind=wp) :: sto_tmp(5)\n"
                                 "do ji = 1,jpj\n"
                                 "read(*,*) sto_tmp(ji)\n"
                                 "end do\n"
                                 "do ji = 1,jpj\n"
                                 "write(*,*) sto_tmp(ji)\n"
                                 "end do\n"
                                 "end program write_out\n")
    code = parser(reader)
    psy = PSyFactory(API, distributed_memory=False).create(code)
    schedule = psy.invokes.invoke_list[0].schedule
    acc_trans = TransInfo().get_trans_name('ACCDataTrans')
    with pytest.raises(TransformationError) as err:
        _, _ = acc_trans.apply(schedule.children[0:1])
    assert ("'CodeBlock' cannot be enclosed by a ACCDataTrans"
            in str(err.value))
    with pytest.raises(TransformationError) as err:
        _, _ = acc_trans.apply(schedule.children[1:2])
    assert ("'CodeBlock' cannot be enclosed by a ACCDataTrans"
            in str(err.value))
Beispiel #20
0
def test_multikern_if(parser):
    ''' Check that we can include an if-block containing multiple
    loops within a kernels region. '''
    reader = FortranStringReader("program implicit_loop\n"
                                 "real(kind=wp) :: sto_tmp(5)\n"
                                 "if(do_this)then\n"
                                 "do jk = 1, 3\n"
                                 "  sto_tmp(jk) = jk\n"
                                 "end do\n"
                                 "else\n"
                                 "do jk = 1, 5\n"
                                 "  sto_tmp(jk) = jk\n"
                                 "end do\n"
                                 "end if\n"
                                 "end program implicit_loop\n")
    code = parser(reader)
    psy = PSyFactory(API, distributed_memory=False).create(code)
    schedule = psy.invokes.invoke_list[0].schedule
    acc_trans = TransInfo().get_trans_name('ACCKernelsTrans')
    schedule, _ = acc_trans.apply(schedule.children[0:1], default_present=True)
    gen_code = str(psy.gen).lower()
    assert ("!$acc kernels default(present)\n"
            "  if (do_this) then\n"
            "    do jk = 1, 3\n" in gen_code)
    assert ("    end do\n"
            "  end if\n"
            "  !$acc end kernels\n"
            "end program implicit_loop" in gen_code)
Beispiel #21
0
def test_kernels_within_if(parser):
    ''' Check that we can put a kernels region within an if block. '''
    reader = FortranStringReader("program if_then\n"
                                 "if(do_this)then\n"
                                 "  do ji=1,jpi\n"
                                 "    fld(ji) = 1.0\n"
                                 "  end do\n"
                                 "else\n"
                                 "  fld2d(:,:) = 0.0\n"
                                 "end if\n"
                                 "end program if_then\n")
    code = parser(reader)
    psy = PSyFactory(API, distributed_memory=False).create(code)
    schedule = psy.invokes.invoke_list[0].schedule
    acc_trans = TransInfo().get_trans_name('ACCKernelsTrans')

    schedule, _ = acc_trans.apply(schedule.children[0].if_body,
                                  default_present=True)
    schedule, _ = acc_trans.apply(schedule.children[0].else_body,
                                  default_present=True)
    new_code = str(psy.gen)
    assert ("  IF (do_this) THEN\n"
            "    !$ACC KERNELS DEFAULT(PRESENT)\n"
            "    DO ji = 1, jpi\n" in new_code)
    assert ("    END DO\n"
            "    !$ACC END KERNELS\n"
            "  ELSE\n"
            "    !$ACC KERNELS DEFAULT(PRESENT)\n"
            "    fld2d(:, :) = 0.0\n"
            "    !$ACC END KERNELS\n"
            "  END IF\n" in new_code)
Beispiel #22
0
def test_if_statement(parser):
    ''' Tests handling an if statement
    '''
    reader = FortranStringReader('''program test_prog
                                 integer :: a, b, i
                                 real, dimension(5) :: p, q, r
                                 if (a .eq. b) then
                                    p(i) = q(i)
                                 else
                                   q(i) = r(i)
                                 endif
                                 end program test_prog''')
    ast = parser(reader)
    psy = PSyFactory(API).create(ast)
    schedule = psy.invokes.get("test_prog").schedule

    if_stmt = schedule.children[0]
    assert isinstance(if_stmt, IfBlock)
    var_accesses = VariablesAccessInfo(if_stmt)
    assert str(var_accesses) == "a: READ, b: READ, i: READ, p: WRITE, "\
                                "q: READ+WRITE, r: READ"
    # Test that the two accesses to 'q' indeed show up as
    q_accesses = var_accesses["q"].all_accesses
    assert len(q_accesses) == 2
    assert q_accesses[0].access_type == AccessType.READ
    assert q_accesses[1].access_type == AccessType.WRITE
    assert q_accesses[0].location < q_accesses[1].location
Beispiel #23
0
def create_schedule(code, routine_name, ast_processor=Fparser2Reader):
    '''Utility function that returns a PSyIR tree from Fortran
    code using fparser2 and (by default) Fparser2Reader.

    :param str code: Fortran code.
    :param str routine_name: the name of the Fortran routine for which to \
                             create the PSyIR tree.
    :param ast_processor: the particular front-end to use. Defaults \
                          to Fparser2Reader.
    :type ast_processor: :py:class:`psyclone.psyGen.Fparser2Reader`


    :returns: PSyIR tree representing the Fortran code.
    :rtype: Subclass of :py:class:`psyclone.psyGen.Node`

    '''
    reader = FortranStringReader(code)
    f2003_parser = ParserFactory().create(std="f2003")
    parse_tree = f2003_parser(reader)

    # Generate PSyIR schedule from fparser2 parse tree
    processor = ast_processor()
    schedule = processor.generate_schedule(routine_name, parse_tree)

    return schedule
Beispiel #24
0
def test_multi_put_item(ignore_comments):
    '''Check that multiple lines can be pushed back and will be returned
    correctly in the specified order (actually the reverse of the
    original). Test with and without ignoring comments.

    '''
    reader = FortranStringReader(FORTRAN_CODE, ignore_comments=ignore_comments)
    orig_lines = []
    while True:
        orig_line = reader.get_item()
        if not orig_line:
            break
        # Make sure our original lines are kept in reverse order.
        orig_lines.insert(0, orig_line)

    # Put back original lines in reverse order as that is what we
    # would expect when processing and rolling back.
    for line in orig_lines:
        reader.put_item(line)

    # Lines should now be returned in the correct order (so compare in
    # reverse order with the original line list)
    while True:
        filo_line = reader.get_item()
        if not filo_line:
            break
        assert filo_line == orig_lines.pop(-1)
    assert not orig_lines
Beispiel #25
0
def test_get_type_by_name(monkeypatch):
    ''' Tests for HasImplicitStmt.get_type_by_name(). '''
    from fparser.common.utils import AnalyzeError
    from fparser.common.readfortran import FortranStringReader
    from fparser.common.sourceinfo import FortranFormat
    from fparser.one.typedecl_statements import Real, Integer
    from fparser.one.parsefortran import FortranParser
    # We can't just create a HasImplicitStmt object so we get the parser
    # to create a module object as that sub-classes HasImplicitStmt (amongst
    # other things).
    string = '''\
module some_block
end module some_block
'''
    reader = FortranStringReader(string)
    reader.set_format(FortranFormat(True, False))
    parser = FortranParser(reader)
    parser.parse()
    mod = parser.block.content[0]
    # Now we have a Module object, we can call get_type_by_name()...
    rtype = mod.get_type_by_name("a_real")
    assert isinstance(rtype, Real)
    itype = mod.get_type_by_name("i_int")
    assert isinstance(itype, Integer)
    # Check that we raise the correct error if we don't have any implicit
    # rules set
    monkeypatch.setattr(mod.a, "implicit_rules", None)
    with pytest.raises(AnalyzeError) as err:
        _ = mod.get_type_by_name("i_int")
    assert "Implicit rules mapping is null" in str(err)
Beispiel #26
0
def test_parallel_two_loops(parser):
    ''' Check that we can enclose two loops within a parallel region. '''
    reader = FortranStringReader("program do_loop\n"
                                 "integer :: ji\n"
                                 "integer, parameter :: jpi=11\n"
                                 "real :: sto_tmp(jpi), sto_tmp2(jpi)\n"
                                 "do ji = 1,jpi\n"
                                 "  sto_tmp(ji) = 1.0d0\n"
                                 "end do\n"
                                 "do ji = 1,jpi\n"
                                 "  sto_tmp2(ji) = 1.0d0\n"
                                 "end do\n"
                                 "end program do_loop\n")
    code = parser(reader)
    psy = PSyFactory(API, distributed_memory=False).create(code)
    schedule = psy.invokes.invoke_list[0].schedule
    acc_trans = TransInfo().get_trans_name('ACCParallelTrans')
    schedule, _ = acc_trans.apply(schedule[0:2])
    code = str(psy.gen)
    assert ("PROGRAM do_loop\n"
            "  INTEGER :: ji\n"
            "  INTEGER, PARAMETER :: jpi = 11\n"
            "  REAL :: sto_tmp(jpi), sto_tmp2(jpi)\n"
            "  !$ACC PARALLEL\n"
            "  DO ji = 1, jpi\n"
            "    sto_tmp(ji) = 1.0D0\n"
            "  END DO\n"
            "  DO ji = 1, jpi\n"
            "    sto_tmp2(ji) = 1.0D0\n"
            "  END DO\n"
            "  !$ACC END PARALLEL\n"
            "END PROGRAM do_loop" in code)
Beispiel #27
0
def test_explicit_loop(parser):
    ''' Check that we can apply the transformation to an explicit loop. '''
    reader = FortranStringReader("program do_loop\n"
                                 "real :: sto_tmp(jpj), sto_tmp2(jpj)\n"
                                 "do ji = 1,jpj\n"
                                 "  sto_tmp(ji) = 1.0d0\n"
                                 "end do\n"
                                 "do ji = 1,jpj\n"
                                 "  sto_tmp2(ji) = 1.0d0\n"
                                 "end do\n"
                                 "end program do_loop\n")
    code = parser(reader)
    psy = PSyFactory(API, distributed_memory=False).create(code)
    schedule = psy.invokes.invoke_list[0].schedule
    acc_trans = TransInfo().get_trans_name('ACCLoopTrans')
    schedule, _ = acc_trans.apply(schedule.children[0])
    schedule, _ = acc_trans.apply(schedule.children[1], independent=False)
    code = str(psy.gen)
    assert ("PROGRAM do_loop\n"
            "  REAL :: sto_tmp(jpj), sto_tmp2(jpj)\n"
            "  !$ACC LOOP INDEPENDENT\n"
            "  DO ji = 1, jpj\n"
            "    sto_tmp(ji) = 1.0D0\n"
            "  END DO\n"
            "  !$ACC LOOP\n"
            "  DO ji = 1, jpj\n"
            "    sto_tmp2(ji) = 1.0D0\n"
            "  END DO\n"
            "END PROGRAM do_loop" in code)
Beispiel #28
0
def test_get_type_by_name_implicit():
    ''' Tests for HasImplicitStmt.get_type_by_name() when the source code
    contains IMPLICIT statements. '''
    from fparser.common.readfortran import FortranStringReader
    from fparser.common.sourceinfo import FortranFormat
    from fparser.one.typedecl_statements import Real, Integer
    from fparser.one.parsefortran import FortranParser
    # We can't just create a HasImplicitStmt object so we get the parser
    # to create a module object as that sub-classes HasImplicitStmt (amongst
    # other things).
    string = '''\
module some_block
  implicit real (a-e)
  implicit integer (f-z)
end module some_block
'''
    reader = FortranStringReader(string)
    reader.set_format(FortranFormat(True, False))
    parser = FortranParser(reader)
    parser.parse()
    # Get the module object
    mod = parser.block.content[0]
    # We have to run the analyze method on the Implicit objects
    # produced by the parser in order to populate the implicit_rules
    # of the module.
    mod.content[0].analyze()
    mod.content[1].analyze()
    # Now we can call get_type_by_name()...
    rtype = mod.get_type_by_name("a_real")
    assert isinstance(rtype, Real)
    itype = mod.get_type_by_name("f_int")
    assert isinstance(itype, Integer)
Beispiel #29
0
def test_kern_sched_parents(parser):
    ''' Check that the children of a Kernel schedule have that schedule
    as their parent. '''
    reader = FortranStringReader("program fake_kern\n"
                                 "integer :: ji, jj, jpi, jpj\n"
                                 "real(kind=wp) :: sto_tmp(5,5)\n"
                                 "do ji = 1,jpi\n"
                                 "  do jj = 1,jpj\n"
                                 "    sto_tmp(ji,jj) = 1.0\n"
                                 "    sto_tmp(ji,jj) = 2.0*sto_tmp(ji,jj)\n"
                                 "    if(jj == 1)then\n"
                                 "      sto_tmp(ji,jj) = sto_tmp(ji,jj)-1.0\n"
                                 "    end if\n"
                                 "  end do\n"
                                 "end do\n"
                                 "end program fake_kern\n")
    code = parser(reader)
    psy = PSyFactory(API, distributed_memory=False).create(code)
    schedule = psy.invokes.invoke_list[0].schedule
    # Find the (one and only) kernel
    kernels = schedule.walk(nemo.NemoKern)
    assert len(kernels) == 1
    # Get its schedule
    sched = kernels[0].get_kernel_schedule()
    # Check that the children of the schedule have it as their parent
    for child in sched.children:
        assert child.parent is sched
Beispiel #30
0
def test_where_ordering(parser):
    ''' Check that the generated schedule has the correct ordering when
    a WHERE construct is processed.

    '''
    reader = FortranStringReader(
        "    subroutine test(zdiv, pbef, paft, zmsk, tmask)\n"
        "      integer, parameter :: wp=1\n"
        "      real :: zsml\n"
        "      integer :: ji, jj, jpjm1, jpim1\n"
        "      real :: zdiv(:,:), pbef(:,:), paft(:,:), zmsk(:,:), "
        "tmask(:,:)\n"
        "      zsml = 1.e-15_wp\n"
        "      DO jj = 2, jpjm1\n"
        "         DO ji = 2, jpim1\n"
        "            zdiv(ji,jj) =  1.0_wp\n"
        "         END DO\n"
        "      END DO\n"
        "      CALL lbc_lnk( zdiv, 'T', 1. )\n"
        "      WHERE( pbef(:,:) == 0._wp .AND. paft(:,:) == 0._wp .AND. "
        "zdiv(:,:) == 0._wp )   ;   zmsk(:,:) = 0._wp\n"
        "      ELSEWHERE;   zmsk(:,:) = 1._wp * tmask(:,:,1)\n"
        "      END WHERE\n"
        "    end subroutine test\n")
    fparser2_tree = parser(reader)
    processor = Fparser2Reader()
    result = processor.generate_schedule("test", fparser2_tree)
    assert isinstance(result[0], Assignment)
    assert isinstance(result[1], Loop)
    assert isinstance(result[2], CodeBlock)
    assert isinstance(result[3], Loop)