def test_program_handler(parser): '''Test that program handler works with multiple program units of different types. ''' code = ("module a\n" "end module\n" "program b\n" "end program b\n" "subroutine c\n" "end subroutine") expected = ("module a\n" " implicit none\n\n" " contains\n\n" "end module a\n" "program b\n\n\n" "end program b\n" "subroutine c()\n\n\n" "end subroutine c\n") processor = Fparser2Reader() reader = FortranStringReader(code) parse_tree = parser(reader) psyir = processor._program_handler(parse_tree, None) # Check PSyIR nodes are being created assert isinstance(psyir, FileContainer) assert psyir.parent is None writer = FortranWriter() result = writer(psyir) assert result == expected
def test_parse_derived_type(use_stmt, type_name): ''' Check that the fronted correctly creates a DataTypeSymbol of type StructureType from the declaration of a derived type. ''' fake_parent = KernelSchedule("dummy_schedule") symtab = fake_parent.symbol_table processor = Fparser2Reader() reader = FortranStringReader("{0}\n" "type :: my_type\n" " integer :: flag\n" " type({1}), private :: grid\n" " real, dimension(3) :: posn\n" "end type my_type\n" "type(my_type) :: var\n".format( use_stmt, type_name)) fparser2spec = Fortran2003.Specification_Part(reader) processor.process_declarations(fake_parent, fparser2spec.content, []) sym = symtab.lookup("my_type") assert isinstance(sym, DataTypeSymbol) assert isinstance(sym.datatype, StructureType) flag = sym.datatype.lookup("flag") assert isinstance(flag.datatype, ScalarType) assert flag.visibility == Symbol.Visibility.PUBLIC grid = sym.datatype.lookup("grid") assert isinstance(grid.datatype, DataTypeSymbol) assert isinstance(grid.datatype.datatype, DeferredType) assert grid.visibility == Symbol.Visibility.PRIVATE posn = sym.datatype.lookup("posn") assert isinstance(posn.datatype, ArrayType) var = symtab.lookup("var") assert var.datatype is sym
def test_call_noargs(): '''Test that fparser2reader transforms a Fortran subroutine call with no arguments into the equivalent PSyIR Call node. Also test that a new RoutineSymbol is added to the symbol table (with an unresolved interface) when one does not already exist. Also test that the Call node ast property is set to reference the original fparser2 call node. ''' reader = FortranStringReader(" call kernel()") ast = Fortran2003.Call_Stmt(reader) fake_parent = Schedule() processor = Fparser2Reader() processor.process_nodes(fake_parent, [ast]) call_node = fake_parent.children[0] assert isinstance(call_node, Call) assert not call_node.children routine_symbol = call_node.routine assert isinstance(routine_symbol, RoutineSymbol) assert isinstance(routine_symbol.interface, UnresolvedInterface) assert routine_symbol.name == "kernel" assert routine_symbol in call_node.scope.symbol_table.symbols assert (str(call_node)) == "Call[name='kernel']" assert call_node.ast == ast
def test_array_of_derived_type_ref(f2008_parser): ''' Test that the frontend handles a reference to a member of an element of an array of derived types. ''' processor = Fparser2Reader() reader = FortranStringReader("subroutine my_sub()\n" " use some_mod, only: my_type\n" " type(my_type), dimension(3) :: var\n" " integer :: idx = 2\n" " integer :: start = 2, stop = 3\n" " var(1)%flag = 0\n" " var(idx)%flag = 0\n" " var(start:stop)%flag = 1\n" " var(1)%region%start = 1\n" " var(1)%region%subgrid(3)%stop = 1\n" " var(1)%region%subgrid(3)%data(:) = 1.0\n" "end subroutine my_sub\n") fparser2spec = f2008_parser(reader) sched = processor.generate_schedule("my_sub", fparser2spec) assert not sched.walk(CodeBlock) assignments = sched.walk(Assignment) # var(1)%flag assign = assignments[0] assert isinstance(assign.lhs, ArrayOfStructuresReference) assert isinstance(assign.lhs.children[0], Member) assert assign.lhs.children[0].name == "flag" assert isinstance(assign.lhs.children[1], Literal) # var(idx)%flag assign = assignments[1] assert isinstance(assign.lhs, ArrayOfStructuresReference) assert isinstance(assign.lhs.children[0], Member) assert isinstance(assign.lhs.children[1], Reference) assert assign.lhs.children[1].symbol.name == "idx" # var(start:stop)%flag assign = assignments[2] assert isinstance(assign.lhs, ArrayOfStructuresReference) assert isinstance(assign.lhs.member, Member) assert isinstance(assign.lhs.indices[0], Range) assert isinstance(assign.lhs.indices[0].children[0], Reference) assert assign.lhs.indices[0].children[0].symbol.name == "start" # var(1)%region%start assign = assignments[3] assert isinstance(assign.lhs, ArrayOfStructuresReference) assert isinstance(assign.lhs.member, StructureMember) assert isinstance(assign.lhs.indices[0], Literal) assert assign.lhs.member.name == "region" assert isinstance(assign.lhs.member.member, Member) # var(1)%region%subgrid(3)%stop assign = assignments[4] assert isinstance(assign.lhs, ArrayOfStructuresReference) assert isinstance(assign.lhs.member.member, ArrayOfStructuresMember) assert isinstance(assign.lhs.member.member.member, Member) assert isinstance(assign.lhs.member.member.indices[0], Literal) # var(1)%region%subgrid(3)%data(:) assign = assignments[5] assert isinstance(assign.lhs, ArrayOfStructuresReference) amem = assign.lhs.member.member assert isinstance(amem, ArrayOfStructuresMember) assert isinstance(amem.member, ArrayMember) assert isinstance(amem.indices[0], Literal) assert isinstance(amem.member.indices[0], Range)
def test_generate_container(parser): ''' Test that generate_container creates a PSyIR container with the contents of the given fparser2 fortran module.''' dummy_module = ''' module dummy_mod use mod1 use mod2, only: var1 real :: modvar1 contains subroutine dummy_code(f1, f2, f3) real(wp), dimension(:,:), intent(in) :: f1 real(wp), dimension(:,:), intent(out) :: f2 real(wp), dimension(:,:) :: f3 f2 = f1 + 1 end subroutine dummy_code end module dummy_mod ''' reader = FortranStringReader(dummy_module) ast = parser(reader) processor = Fparser2Reader() container = processor.generate_container(ast) assert isinstance(container, Container) assert not container.children assert container.symbol_table assert container.symbol_table.lookup("modvar1") assert container.symbol_table.lookup("var1") assert container.symbol_table.lookup("mod1") assert container.symbol_table.lookup("mod2") assert container.symbol_table.lookup("dummy_code")
def test_handling_literal_precision_1(value, dprecision, intrinsic): '''Check that the fparser2 frontend can handle literals with a specified precision kind symbol. ''' if intrinsic == ScalarType.Intrinsic.CHARACTER: code = "x={0}_{1}".format(dprecision, value) else: code = "x={0}_{1}".format(value, dprecision) reader = FortranStringReader(code) astmt = Fortran2003.Assignment_Stmt(reader) fake_parent = Schedule() # Ensure the symbol table has an entry for "x" fake_parent.symbol_table.add( DataSymbol("x", ScalarType(ScalarType.Intrinsic.INTEGER, 4))) processor = Fparser2Reader() processor.process_nodes(fake_parent, [astmt]) assert not fake_parent.walk(CodeBlock) literal = fake_parent.children[0].children[1] assert isinstance(literal, Literal) assert literal.datatype.intrinsic == intrinsic if intrinsic == ScalarType.Intrinsic.BOOLEAN: assert ".{0}.".format(literal.value) == value.lower() else: assert literal.value == value assert isinstance(literal.datatype.precision, DataSymbol) assert literal.datatype.precision.name == dprecision assert isinstance(literal.datatype.precision.datatype, ScalarType) assert (literal.datatype.precision.datatype.intrinsic == ScalarType.Intrinsic.INTEGER)
def test_multi_use_stmt(): ''' Check that we handle the case where different symbols are imported from a module in separate USE statements. ''' fake_parent = KernelSchedule("dummy_schedule") processor = Fparser2Reader() reader = FortranStringReader("use my_mod, only: some_var\n" "use this_mod\n" "use my_mod, only: var1, var2\n" "use this_mod, only: var3\n") fparser2spec = Fortran2003.Specification_Part(reader) processor.process_declarations(fake_parent, fparser2spec.content, []) symtab = fake_parent.symbol_table csymbols = symtab.containersymbols # Although there are 4 use statements, there are only 2 modules assert len(csymbols) == 2 my_mod = symtab.lookup("my_mod") assert not my_mod.wildcard_import # Check that we have accumulated all imports import_list = symtab.imported_symbols(my_mod) assert len(import_list) == 3 names = [sym.name for sym in import_list] assert sorted(names) == ["some_var", "var1", "var2"] this_mod = symtab.lookup("this_mod") assert this_mod.wildcard_import names = [sym.name for sym in symtab.imported_symbols(this_mod)] assert names == ["var3"]
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 test_use_stmt(): ''' Check that SymbolTable entries are correctly created from module use statements. ''' fake_parent = KernelSchedule("dummy_schedule") processor = Fparser2Reader() reader = FortranStringReader("use my_mod, only: some_var\n" "use this_mod\n" "use other_mod, only: var1, var2\n") fparser2spec = Fortran2003.Specification_Part(reader) processor.process_declarations(fake_parent, fparser2spec.content, []) symtab = fake_parent.symbol_table for module_name in ["my_mod", "this_mod", "other_mod"]: container = symtab.lookup(module_name) assert isinstance(container, ContainerSymbol) assert container.name == module_name # Container reference is not updated until explicitly requested assert not container._reference for var in ["some_var", "var1", "var2"]: assert symtab.lookup(var).name == var assert symtab.lookup("some_var").interface.container_symbol \ == symtab.lookup("my_mod") assert symtab.lookup("var2").interface.container_symbol \ == symtab.lookup("other_mod")
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)
def process_where(code, fparser_cls, symbols=None): ''' Utility routine to process the supplied Fortran code and return the PSyIR and fparser2 parse trees. :param str code: Fortran code to process. :param type fparser_cls: the fparser2 class to instantiate to \ represent the supplied Fortran. :param symbols: list of symbol names that must be added to the symbol \ table before constructing the PSyIR. :type symbols: list of str :returns: 2-tuple of a parent PSyIR Schedule and the created instance of \ the requested fparser2 class. :rtype: (:py:class:`psyclone.psyir.nodes.Schedule`, \ :py:class:`fparser.two.utils.Base`) ''' sched = Schedule() if symbols: for sym_name in symbols: sched.symbol_table.new_symbol(sym_name) processor = Fparser2Reader() reader = FortranStringReader(code) fparser2spec = fparser_cls(reader) if fparser_cls is Fortran2003.Execution_Part: processor.process_nodes(sched, fparser2spec.content) else: processor.process_nodes(sched, [fparser2spec]) return sched, fparser2spec
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_handling_literal_precision_2(value, dprecision, intrinsic): '''Check that the fparser2 frontend can handle literals with a specified precision value. TODO #754 fix test so that 'disable_declaration_check' fixture is not required. ''' if intrinsic == ScalarType.Intrinsic.CHARACTER: code = "x={0}_{1}".format(dprecision, value) else: code = "x={0}_{1}".format(value, dprecision) reader = FortranStringReader(code) astmt = Fortran2003.Assignment_Stmt(reader) fake_parent = Schedule() processor = Fparser2Reader() processor.process_nodes(fake_parent, [astmt]) assert not fake_parent.walk(CodeBlock) literal = fake_parent.children[0].children[1] assert isinstance(literal, Literal) assert literal.datatype.intrinsic == intrinsic if intrinsic == ScalarType.Intrinsic.BOOLEAN: assert ".{0}.".format(literal.value) == value.lower() else: assert literal.value == value assert isinstance(literal.datatype.precision, int) assert literal.datatype.precision == dprecision
def test_call_args(f2008_parser): '''Test that fparser2reader transforms a Fortran subroutine call with arguments into the equivalent PSyIR Call node. ''' test_code = ("subroutine test()\n" "use my_mod, only : kernel\n" "real :: a,b\n" " call kernel(1.0, a, (a+b)*2.0, name=\"roo\")\n" "end subroutine") reader = FortranStringReader(test_code) ptree = f2008_parser(reader) processor = Fparser2Reader() sched = processor.generate_schedule("test", ptree) call_node = sched.children[0] assert isinstance(call_node, Call) assert len(call_node.children) == 4 assert isinstance(call_node.children[0], Literal) assert call_node.children[0].value == "1.0" assert isinstance(call_node.children[1], Reference) assert call_node.children[1].name == "a" assert isinstance(call_node.children[2], BinaryOperation) assert isinstance(call_node.children[3], CodeBlock) routine_symbol = call_node.routine assert isinstance(routine_symbol, RoutineSymbol) assert call_node.routine.name == "kernel" assert isinstance(routine_symbol.interface, GlobalInterface) assert routine_symbol is call_node.scope.symbol_table.lookup("kernel") assert (str(call_node)) == "Call[name='kernel']"
def test_number_handler(): ''' Check that the number_handler raises a NotImplementedError for an unrecognised fparser2 node. ''' processor = Fparser2Reader() fake_parent = Schedule() reader = FortranStringReader("(1.0, 1.0)") with pytest.raises(NotImplementedError): processor._number_handler(Fortran2003.Complex_Literal_Constant(reader), fake_parent)
def test_transformation(parser, test_case): ''' Check that the transformation works as expected. ''' input_code, expected = test_cases[test_case] trans = FoldConditionalReturnExpressionsTrans() processor = Fparser2Reader() reader = FortranStringReader(input_code) parse_tree = parser(reader) subroutine = processor.generate_psyir(parse_tree) trans.apply(subroutine) writer = FortranWriter() assert writer(subroutine) == expected
def test_generate_psyir_error(parser): '''Test that generate_psyir raises the expected exception if the supplied fparser2 parse tree does not have a Program node as its root.''' processor = Fparser2Reader() reader = FortranStringReader(MODULE_IN) parse_tree = parser(reader) with pytest.raises(GenerationError) as info: _ = processor.generate_psyir(parse_tree.children[0]) assert ("The Fparser2Reader generate_psyir method expects the root of " "the supplied fparser2 tree to be a Program, but found 'Module'" in str(info.value))
def test_name_clash_use_stmt(): ''' Check that we raise the expected error if we encounter a module with a name that's already taken in the Symbol Table. This is invalid Fortran but we need to test the error-handling in PSyclone. ''' fake_parent = KernelSchedule("dummy_schedule") processor = Fparser2Reader() reader = FortranStringReader("use my_mod, only: some_var\n" "use some_var, only: var1, var2\n") fparser2spec = Fortran2003.Specification_Part(reader) with pytest.raises(SymbolError) as err: processor.process_declarations(fake_parent, fparser2spec.content, []) assert "Found a USE of module 'some_var' but the symbol" in str(err.value)
def test_subscript_triplet_handler_error(): ''' Check that the subscript-triplet handler raises the expected error if the parent PSyIR node is not of the correct type. ''' processor = Fparser2Reader() fake_parent = Schedule() reader = FortranStringReader("x(:) = a") fp2node = Execution_Part.match(reader) triplet = fp2node[0][0].children[0].children[1].children[0] with pytest.raises(InternalError) as err: processor._subscript_triplet_handler(triplet, fake_parent) assert ("Expected parent PSyIR node to be either a Reference or a Member " "but got 'Schedule' when processing ':'" in str(err.value))
def test_use_no_only_list(): ''' Check that we create the correct Symbol Table entry for a use statement that has an 'only' clause but no list of imported symbols. ''' fake_parent = KernelSchedule("dummy_schedule") processor = Fparser2Reader() reader = FortranStringReader("use my_mod, only: some_var\n" "use some_mod, only:\n") fparser2spec = Fortran2003.Specification_Part(reader) processor.process_declarations(fake_parent, fparser2spec.content, []) some_mod = fake_parent.symbol_table.lookup("some_mod") assert not some_mod.wildcard_import assert fake_parent.symbol_table.imported_symbols(some_mod) == []
def test_missing_derived_type(): ''' Check that the fronted raises an error if it encounters a variable of a derived type that cannot be resolved. ''' fake_parent = KernelSchedule("dummy_schedule") processor = Fparser2Reader() reader = FortranStringReader("type(my_type) :: var") fparser2spec = Fortran2003.Specification_Part(reader) # This should raise an error because there's no Container from which # the definition of 'my_type' can be brought into scope. with pytest.raises(SymbolError) as err: processor.process_declarations(fake_parent, fparser2spec.content, []) assert "No Symbol found for name 'my_type'" in str(err.value)
def test_subroutine_handler(parser, fortran_writer, code, expected): '''Test that subroutine_handler handles valid Fortran subroutines.''' processor = Fparser2Reader() reader = FortranStringReader(code) parse_tree = parser(reader) subroutine = parse_tree.children[0] psyir = processor._subroutine_handler(subroutine, None) # Check the expected PSyIR nodes are being created assert isinstance(psyir, Routine) assert psyir.parent is None result = fortran_writer(psyir) assert expected == result
def test_derived_type_ref(f2008_parser): ''' Check that the frontend handles a references to a member of a derived type. ''' processor = Fparser2Reader() reader = FortranStringReader( "subroutine my_sub()\n" " use some_mod, only: my_type\n" " type(my_type) :: var\n" " var%flag = 0\n" " var%region%start = 1\n" " var%region%subgrid(3)%stop = 1\n" " var%region%subgrid(3)%data(:) = 1.0\n" " var%region%subgrid(3)%data(var%start:var%stop) = 1.0\n" "end subroutine my_sub\n") fparser2spec = f2008_parser(reader) sched = processor.generate_schedule("my_sub", fparser2spec) assert not sched.walk(CodeBlock) assignments = sched.walk(Assignment) # var%flag assign = assignments[0] assert isinstance(assign.lhs, StructureReference) assert isinstance(assign.lhs.children[0], Member) assert assign.lhs.children[0].name == "flag" # var%region%start assign = assignments[1] assert isinstance(assign.lhs, StructureReference) assert isinstance(assign.lhs.children[0], StructureMember) assert assign.lhs.children[0].name == "region" assert isinstance(assign.lhs.children[0].children[0], Member) assert assign.lhs.children[0].children[0].name == "start" # var%region%subgrid(3)%stop assign = assignments[2] amem = assign.lhs.children[0].children[0] assert isinstance(amem, ArrayOfStructuresMember) assert isinstance(amem.children[0], Member) assert isinstance(amem.children[1], Literal) assert amem.children[0].name == "stop" # var%region%subgrid(3)%data(:) assign = assignments[3] amem = assign.lhs.member.member assert isinstance(amem, ArrayOfStructuresMember) assert isinstance(amem.member, ArrayMember) assert isinstance(amem.member.indices[0], Range) assign = assignments[4] # var%region%subgrid(3)%data(var%start:var%stop) amem = assign.lhs.member.member.member assert isinstance(amem, ArrayMember) assert isinstance(amem.indices[0], Range) assert isinstance(amem.indices[0].children[0], StructureReference) assert isinstance(amem.indices[0].children[0].member, Member) assert amem.indices[0].children[0].member.name == "start"
def test_broken_use(monkeypatch): ''' Check that we raise the expected error if we encounter an unrecognised parse tree for a USE statement. ''' fake_parent = KernelSchedule("dummy_schedule") processor = Fparser2Reader() reader = FortranStringReader("use some_mod, only:\n") fparser2spec = Fortran2003.Specification_Part(reader) # Break the parse tree so that instead of ", ONLY:" it has "hello" monkeypatch.setattr( fparser2spec.content[0], "items", [None, None, Fortran2003.Name('my_mod'), 'hello', None]) with pytest.raises(NotImplementedError) as err: processor.process_declarations(fake_parent, fparser2spec.content, []) assert "unsupported USE statement: 'USE my_modhello'" in str(err.value)
def test_module_handler(parser, code, expected): '''Test that module_handler handles valid Fortran modules. ''' processor = Fparser2Reader() reader = FortranStringReader(code) parse_tree = parser(reader) module = parse_tree.children[0] psyir = processor._module_handler(module, None) # Check the expected PSyIR nodes are being created assert isinstance(psyir, Container) assert psyir.parent is None writer = FortranWriter() result = writer(psyir) assert expected == result
def test_generate_psyir(parser, code, expected, node_class): '''Test that generate_psyir generates PSyIR from an fparser2 parse tree. ''' processor = Fparser2Reader() reader = FortranStringReader(code) parse_tree = parser(reader) psyir = processor.generate_psyir(parse_tree) # Check the expected PSyIR nodes are being created assert isinstance(psyir, node_class) writer = FortranWriter() result = writer(psyir) assert result == expected
def test_public_private_symbol_error(parser): ''' Check that we raise the expected error when a symbol is listed as being both PUBLIC and PRIVATE. (fparser2 doesn't check for this.) ''' processor = Fparser2Reader() reader = FortranStringReader("module modulename\n" "private\n" "public var3\n" "private var4, var3\n" "end module modulename") fparser2spec = parser(reader) with pytest.raises(GenerationError) as err: processor.generate_container(fparser2spec) assert ("Symbols ['var3'] appear in access statements with both PUBLIC " "and PRIVATE" in str(err.value))
def test_multiple_access_stmt_error(parser): ''' Check that we raise the expected error when we encounter multiple access statements. (fparser2 doesn't check for this.) ''' processor = Fparser2Reader() reader = FortranStringReader("module modulename\n" "private\n" "public var3\n" "private\n" "end module modulename") fparser2spec = parser(reader) with pytest.raises(GenerationError) as err: processor.generate_container(fparser2spec) assert ("Module 'modulename' contains more than one access statement with" in str(err.value))
def test_size(expression, parser): ''' Basic test that the SIZE intrinsic is recognised and represented in the PSyIR. ''' from fparser.two.Fortran2003 import Execution_Part from psyclone.psyGen import Schedule, Assignment, BinaryOperation, \ Reference, Literal fake_parent = Schedule() processor = Fparser2Reader() reader = FortranStringReader(expression) fp2intrinsic = Execution_Part(reader).content[0] processor.process_nodes(fake_parent, [fp2intrinsic], None) assert isinstance(fake_parent[0], Assignment) assert isinstance(fake_parent[0].rhs, BinaryOperation) assert isinstance(fake_parent[0].rhs.children[0], Reference) assert isinstance(fake_parent[0].rhs.children[1], Literal)