示例#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"
示例#2
0
def test_implicit_topyf(monkeypatch):
    ''' Tests for the topyf() method of HasImplicitStmt. '''
    from fparser.common.readfortran import FortranStringReader
    from fparser.common.sourceinfo import FortranFormat
    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]
    code = mod.topyf()
    assert "! default IMPLICIT rules apply" in code
    mod.content[0].analyze()
    mod.content[1].analyze()
    code = mod.topyf()
    assert "REAL (a, b, c, d, e)" in code
    assert "INTEGER (f, g, h" in code
    monkeypatch.setattr(mod.a, "implicit_rules", None)
    code = mod.topyf()
    assert "IMPLICIT NONE" in code
示例#3
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"
示例#4
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)
示例#5
0
def adduse(name, parent, only=False, funcnames=None):
    '''
    Adds a use statement with the specified name to the supplied object.
    This routine is required when modifying an existing AST (e.g. when
    modifying a kernel). The classes are used when creating an AST from
    scratch (for the PSy layer).

    :param str name: name of module to USE
    :param parent: node in fparser1 AST to which to add this USE as a child
    :type parent: :py:class:`fparser.one.block_statements.*`
    :param bool only: whether this USE has an "ONLY" clause
    :param list funcnames: list of quantities to follow the "ONLY" clause

    :returns: an fparser1 Use object
    :rtype: :py:class:`fparser.one.block_statements.Use`
    '''
    reader = FortranStringReader("use kern,only : func1_kern=>func1")
    reader.set_format(FortranFormat(True, True))  # free form, strict
    myline = reader.next()

    # find an appropriate place to add in our use statement
    while not (isinstance(parent, fparser1.block_statements.Program) or
               isinstance(parent, fparser1.block_statements.Module) or
               isinstance(parent, fparser1.block_statements.Subroutine)):
        parent = parent.parent
    use = fparser1.block_statements.Use(parent, myline)
    use.name = name
    use.isonly = only
    if funcnames is None:
        funcnames = []
        use.isonly = False
    use.items = funcnames

    parent.content.insert(0, use)
    return use
示例#6
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)
示例#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))
示例#8
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"
示例#10
0
def parse(cls, line, label='', isfree=True, isstrict=False):
    '''Tries to parse a Fortran line using the given class cls.
    If successful, it then converts the parsed statement back to
    a string. If isstrict is false, it will then try to parse
    this string again (recursively calling itself, with isstrict
    set to true) and make sure that the re-parsed string is
    identical to the input.
    It returns the string representation of the parsed input line.
    '''

    if label:
        line = label + ' : ' + line
    reader = FortranStringReader(line)
    reader.set_format(fparser.common.sourceinfo.FortranFormat(
        isfree, isstrict))
    item = next(reader)
    if not cls.match(item.get_line()):
        raise ValueError('%r does not match %s pattern' % (line, cls.__name__))
    stmt = cls(item, item)
    if stmt.isvalid:
        # Check that we can successfully parse the string representation
        # of the parsed object
        stmt_string = str(stmt)
        if not isstrict:
            reparsed_stmt_string = parse(cls, stmt_string, isstrict=True)
            if stmt_string != reparsed_stmt_string:
                raise ValueError(
                    'Failed to parse %r with %s pattern in Pyf '
                    'mode, got %r' %
                    (stmt_string, cls.__name__, reparsed_stmt_string))
        return stmt_string
    raise ValueError('parsing %r with %s pattern failed' %
                     (line, cls.__name__))
示例#11
0
def test_string_reader():
    '''
    Tests that Fortran source can be read from a string.
    '''
    unit_under_test = FortranStringReader(FULL_FREE_SOURCE)
    expected = fparser.common.sourceinfo.FortranFormat(True, False)
    assert unit_under_test.format == expected
    for expected in FULL_FREE_EXPECTED:
        assert unit_under_test.get_single_line(ignore_empty=True) == expected
示例#12
0
def test_include_not_found():
    '''Tests that FortranReaderBase.next() provides the include line when
    the included file is not found.

    '''
    code = "include 'nonexistant.f90'"
    unit_under_test = FortranStringReader(code)
    line = unit_under_test.next()
    assert str(line.line) == code
示例#13
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)
def test_nonblock_do_construct_tofortran_non_ascii():
    ''' Check that the tofortran() method works when the non-block
    do-construct contains a character string with non-ascii characters. '''
    from fparser.common.readfortran import FortranStringReader
    from fparser.common.sourceinfo import FortranFormat
    code = (u"      DO 50\n" u" 50   WRITE(*,*) ' for e1=1\xb0'\n")
    reader = FortranStringReader(code)
    # Ensure reader in in 'fixed-format' mode
    reader.set_format(FortranFormat(False, True))
    obj = Nonblock_Do_Construct(reader)
    out_str = str(obj)
    assert "for e1=1" in out_str
示例#15
0
    def __init__(self, parent, content):
        '''
        :param parent: node in AST to which to add the Comment as a child
        :type parent: :py:class:`psyclone.f2pygen.BaseGen`
        :param str content: the content of the comment
        '''
        reader = FortranStringReader("! content\n")
        reader.set_format(FortranFormat(True, True))  # free form, strict
        subline = reader.next()

        my_comment = Comment(parent.root, subline)
        my_comment.content = content

        BaseGen.__init__(self, parent, my_comment)
示例#16
0
    def __init__(self, parent, expr="UNSET", typeselect=False):
        '''
        Construct a SelectionGen for creating a SELECT block

        :param parent: node to which to add this select block as a child
        :type parent: :py:class:`psyclone.f2pygen.BaseGen`
        :param str expr: the CASE expression
        :param bool typeselect: whether or not this is a SELECT TYPE rather
                                than a SELECT CASE
        '''
        self._typeselect = typeselect
        reader = FortranStringReader(
            "SELECT CASE (x)\nCASE (1)\nCASE DEFAULT\nEND SELECT")
        reader.set_format(FortranFormat(True, True))  # free form, strict
        select_line = reader.next()
        self._case_line = reader.next()
        self._case_default_line = reader.next()
        end_select_line = reader.next()
        if self._typeselect:
            select = SelectType(parent.root, select_line)
        else:
            select = SelectCase(parent.root, select_line)
        endselect = EndSelect(select, end_select_line)
        select.expr = expr
        select.content.append(endselect)
        BaseGen.__init__(self, parent, select)
示例#17
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
示例#18
0
def test_fortranreaderbase_info(log):
    '''
    Tests that FortranReaderBase.info() causes a message to be logged.
    '''
    unit_under_test = FortranStringReader('x=3')
    thing = unit_under_test.get_source_item()
    unit_under_test.info('Mighty Whirlitzer', thing)
    assert log.messages['debug'] == []
    assert log.messages['error'] == []
    assert log.messages['warning'] == []
    assert log.messages['critical'] == []
    expected = '    1:x=3 <== Mighty Whirlitzer'
    result = log.messages['info'][0].split('\n')[1]
    assert result == expected
示例#19
0
def test_fortranreaderbase_warning(log):
    '''
    Tests that FortranReaderBase.warning() causes a message to be logged.
    '''
    unit_under_test = FortranStringReader('x=1')
    thing = unit_under_test.get_source_item()
    unit_under_test.warning('Flatulent Hermit', thing)
    assert log.messages['debug'] == []
    assert log.messages['info'] == []
    assert log.messages['error'] == []
    assert log.messages['critical'] == []
    expected = '    1:x=1 <== Flatulent Hermit'
    result = log.messages['warning'][0].split('\n')[1]
    assert result == expected
示例#20
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
示例#21
0
def test_fortranreaderbase_error(log):
    '''
    Tests that FortranReaderBase.error() causes a message to be logged.
    '''
    unit_under_test = FortranStringReader('x=2')
    thing = unit_under_test.get_source_item()
    with pytest.raises(SystemExit):
        unit_under_test.error('Thundering Chalmer', thing)
    assert log.messages['debug'] == []
    assert log.messages['info'] == []
    assert log.messages['warning'] == []
    assert log.messages['critical'] == []
    expected = '    1:x=2 <== Thundering Chalmer'
    result = log.messages['error'][0].split('\n')[1]
    assert result == expected
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
示例#23
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
示例#24
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)
示例#25
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)
示例#26
0
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)
示例#27
0
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)
示例#28
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))
示例#29
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)
示例#30
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))