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"
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
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"
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)
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
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)
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))
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"
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__))
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
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
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
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)
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)
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
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
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
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_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
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
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_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)
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)
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_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))
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)
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))