Пример #1
0
def test_constructor():
    '''Test the optional constructor parameter (single node and list
    of nodes).'''
    from psyclone.tests.utilities import create_schedule
    code = '''module test
        contains
        subroutine tmp()
          integer :: a,b,c
          a = b/c
          c = a*b
        end subroutine tmp
        end module test'''
    schedule = create_schedule(code, "tmp")
    node1 = schedule[0]
    node2 = schedule[1]
    vai1 = VariablesAccessInfo(node1)
    assert str(vai1) == "a: WRITE, b: READ, c: READ"
    vai2 = VariablesAccessInfo([node1, node2])
    assert str(vai2) == "a: READ+WRITE, b: READ, c: READ+WRITE"

    with pytest.raises(InternalError) as err:
        VariablesAccessInfo([node1, node2, 3])
    assert "One element in the node list is not a Node, but of type " in \
        str(err.value)
    # The error message is slightly different between python 2 and 3
    # so only test for the part that is the same in both:
    assert "'int'>" in str(err.value)

    with pytest.raises(InternalError) as err:
        VariablesAccessInfo(1)
    assert "Error in VariablesAccessInfo" in str(err.value)
    # The error message is slightly different between python 2 and 3
    # so only test for the part that is the same in both:
    assert "'int'>" in str(err.value)
Пример #2
0
def test_fw_exception(fort_writer):
    '''Check the FortranWriter class instance raises an exception if an
    unsupported PSyIR node is found.

    '''
    # Generate fparser2 parse tree from Fortran code.
    code = ("module test\n"
            "contains\n"
            "subroutine tmp()\n"
            "  integer :: a,b,c\n"
            "  a = b/c\n"
            "end subroutine tmp\n"
            "end module test")
    schedule = create_schedule(code, "tmp")

    # pylint: disable=abstract-method
    # modify the reference to b to be something unsupported
    class Unsupported(Node):
        '''A PSyIR node that will not be supported by the Fortran visitor.'''

    # pylint: enable=abstract-method

    unsupported = Unsupported()
    assignment = schedule[0]
    binary_operation = assignment.rhs
    # The assignment.rhs method has no setter so access the reference
    # directly instead via children.
    assignment.children[1] = unsupported
    unsupported.children = binary_operation.children

    # Generate Fortran from the PSyIR schedule
    with pytest.raises(VisitorError) as excinfo:
        _ = fort_writer(schedule)
    assert "Unsupported node 'Unsupported' found" in str(excinfo)
Пример #3
0
def test_cw_loop():
    '''Tests writing out a Loop node in C. It parses Fortran code
    and outputs it as C. Note that this is atm a literal translation,
    the loops are not functionally identical to Fortran, see TODO #523.

    '''
    from psyclone.tests.utilities import create_schedule

    # Generate PSyIR from Fortran code.
    code = '''
        module test
        contains
        subroutine tmp()
          integer :: i, a
          integer, dimension(:) :: b
          do i = 1, 20, 2
            a = 2 * i
          enddo
        end subroutine tmp
        end module test'''
    schedule = create_schedule(code, "tmp")

    cvisitor = CWriter()
    result = cvisitor(schedule[0])
    correct = '''for(i=1; i<=20; i+=2)
{
  a = (2 * i);
}'''
    result = cvisitor(schedule[0])
    assert correct in result
Пример #4
0
def test_fw_ifblock(fort_writer):
    '''Check the FortranWriter class ifblock method
    correctly prints out the Fortran representation.

    '''
    # Generate fparser2 parse tree from Fortran code.
    code = ("module test\n"
            "contains\n"
            "subroutine tmp(a,n)\n"
            "  integer, intent(inout) :: n\n"
            "  real, intent(out) :: a(n)\n"
            "    if (n.gt.2) then\n"
            "      n=n+1\n"
            "    end if\n"
            "    if (n.gt.4) then\n"
            "      a = -1\n"
            "    else\n"
            "      a = 1\n"
            "    end if\n"
            "end subroutine tmp\n"
            "end module test")
    schedule = create_schedule(code, "tmp")

    # Generate Fortran from the PSyIR schedule
    result = fort_writer(schedule)
    assert ("  if (n > 2) then\n"
            "    n=n + 1\n"
            "  end if\n"
            "  if (n > 4) then\n"
            "    a=-1\n"
            "  else\n"
            "    a=1\n"
            "  end if\n") in result
Пример #5
0
def test_nemo_omp_parallel():
    '''Tests if an OpenMP parallel directive in NEMO is handled correctly.
    '''
    # Generate fparser2 parse tree from Fortran code.
    code = '''
        module test
        contains
        subroutine tmp()
          integer :: i, a
          integer, dimension(:) :: b
          do i = 1, 20, 2
            a = 2 * i
            b(i) = b(i) + a
          enddo
        end subroutine tmp
        end module test'''
    schedule = create_schedule(code, "tmp")
    from psyclone.transformations import OMPParallelTrans

    # Now apply a parallel transform
    omp_par = OMPParallelTrans()
    # Note that the loop is not handled as nemo kernel, so the
    # omp node-type-check will find the assignment statement and
    # prevent application of omp parallel to the loop. So
    # disable the node type check so that omp parallel is applied.
    omp_par.apply(schedule[0], {"node-type-check": False})

    fvisitor = FortranWriter()
    result = fvisitor(schedule)
    correct = '''!$omp parallel private(a,i)
    do i = 1, 20, 2
      a=2 * i
      b(i)=b(i) + a
    enddo
!$omp end parallel'''
    assert correct in result

    cvisitor = CWriter()
    result = cvisitor(schedule[0])
    correct = '''#pragma omp parallel private(a,i)
{
  for(i=1; i<=20; i+=2)
  {
    a = (2 * i);
    b[i] = (b[i] + a);
  }
}'''
    result = cvisitor(schedule[0])
    assert correct in result
Пример #6
0
def test_fw_size(fort_writer):
    ''' Check that the FortranWriter outputs a SIZE intrinsic call. '''
    code = ("module test_mod\n"
            "contains\n"
            "subroutine test_kern(a)\n"
            "  real, intent(in) :: a(:,:)\n"
            "  integer :: mysize\n"
            "  mysize = size(a, 2)\n"
            "end subroutine test_kern\n"
            "end module test_mod\n")
    schedule = create_schedule(code, "test_kern")

    # Generate Fortran from the PSyIR schedule
    result = fort_writer(schedule)
    assert "mysize=size(a, 2)" in result.lower()
Пример #7
0
def test_fw_return(fort_writer):
    '''Check the FortranWriter class return method
    correctly prints out the Fortran representation.

    '''
    # Generate fparser2 parse tree from Fortran code.
    code = ("module test\n"
            "contains\n"
            "subroutine tmp()\n"
            "  return\n"
            "end subroutine tmp\n"
            "end module test")
    schedule = create_schedule(code, "tmp")

    # Generate Fortran from the PSyIR schedule
    result = fort_writer(schedule)
    assert "  return\n" in result
Пример #8
0
def test_nemo_omp_parallel():
    '''Tests if an OpenMP parallel directive in NEMO is handled correctly.
    '''
    # Generate fparser2 parse tree from Fortran code.
    code = '''
        module test
        contains
        subroutine tmp()
          integer :: i, a
          integer, dimension(:) :: b
          do i = 1, 20, 2
            a = 2 * i
            b(i) = b(i) + a
          enddo
        end subroutine tmp
        end module test'''
    schedule = create_schedule(code, "tmp")
    from psyclone.transformations import OMPParallelTrans

    # Now apply a parallel transform
    omp_par = OMPParallelTrans()
    omp_par.apply(schedule[0])

    fvisitor = FortranWriter()
    result = fvisitor(schedule)
    correct = '''!$omp parallel private(a,i)
    do i = 1, 20, 2
      a=2 * i
      b(i)=b(i) + a
    enddo
!$omp end parallel'''
    assert correct in result

    cvisitor = CWriter()
    result = cvisitor(schedule[0])
    correct = '''#pragma omp parallel private(a,i)
{
  for(i=1; i<=20; i+=2)
  {
    a = (2 * i);
    b[i] = (b[i] + a);
  }
}'''
    result = cvisitor(schedule[0])
    assert correct in result
Пример #9
0
def test_fw_array(fort_writer):
    '''Check the FortranWriter class array method correctly prints
    out the Fortran representation of an array

    '''
    # Generate fparser2 parse tree from Fortran code.
    code = ("module test\n"
            "contains\n"
            "subroutine tmp(a,n)\n"
            "  integer, intent(in) :: n\n"
            "  real, intent(out) :: a(n,n,n)\n"
            "    a(2,n,3) = 0.0\n"
            "end subroutine tmp\n"
            "end module test")
    schedule = create_schedule(code, "tmp")

    # Generate Fortran from the PSyIR schedule
    result = fort_writer(schedule)
    assert "a(2,n,3)=0.0" in result
Пример #10
0
def test_fw_reference(fort_writer):
    '''Check the FortranWriter class reference method prints the
    appropriate information (the name of the reference it points to).
    Also check the method raises an exception if it has children as
    this is not expected.

    '''
    # Generate fparser2 parse tree from Fortran code. The line of
    # interest is a(n) = 0.0. The additional a=1 line is added to get
    # round a bug in the parser.
    code = ("module test\n"
            "contains\n"
            "subroutine tmp(a,n)\n"
            "  integer, intent(in) :: n\n"
            "  real, intent(out) :: a(n)\n"
            "    a = 1\n"
            "    a(n) = 0.0\n"
            "end subroutine tmp\n"
            "end module test")
    schedule = create_schedule(code, "tmp")

    # Generate Fortran from the PSyIR schedule
    result = fort_writer(schedule)

    # The asserts need to be split as the declaration order can change
    # between different versions of Python.
    assert ("subroutine tmp(a,n)\n"
            "  integer, intent(in) :: n\n"
            "  real, dimension(n), intent(out) :: a\n"
            "\n"
            "  a=1\n"
            "  a(n)=0.0\n"
            "\n"
            "end subroutine tmp\n") in result

    # Now add a child to the reference node
    reference = schedule[1].lhs.children[0]
    reference.children = ["hello"]

    # Generate Fortran from the PSyIR schedule
    with pytest.raises(VisitorError) as excinfo:
        result = fort_writer(schedule)
    assert "Expecting a Reference with no children but found" in str(excinfo)
Пример #11
0
def test_fw_naryopeator(fort_writer):
    ''' Check that the FortranWriter class nary_operation method correctly
    prints out the Fortran representation of an intrinsic.

    '''
    # Generate fparser2 parse tree from Fortran code.
    code = ("module test\n"
            "contains\n"
            "subroutine tmp(a,n)\n"
            "  integer, intent(in) :: n\n"
            "  real, intent(out) :: a\n"
            "    a = max(1.0,1.0,2.0)\n"
            "end subroutine tmp\n"
            "end module test")
    schedule = create_schedule(code, "tmp")

    # Generate Fortran from the PSyIR schedule
    result = fort_writer(schedule)
    assert "a=MAX(1.0, 1.0, 2.0)" in result
Пример #12
0
def test_fw_unaryoperator(fort_writer):
    '''Check the FortranWriter class unary_operation method
    correctly prints out the Fortran representation. Uses -1 as the
    example.

    '''
    # Generate fparser2 parse tree from Fortran code.
    code = ("module test\n"
            "contains\n"
            "subroutine tmp(a,n)\n"
            "  integer, intent(in) :: n\n"
            "  real, intent(out) :: a(n)\n"
            "    a = -1\n"
            "end subroutine tmp\n"
            "end module test")
    schedule = create_schedule(code, "tmp")

    # Generate Fortran from the PSyIR schedule
    result = fort_writer(schedule)
    assert "a=-1" in result
Пример #13
0
def test_fw_loop(fort_writer):
    '''Check the FortranWriter class loop method
    correctly prints out the Fortran representation.

    '''
    # Generate fparser2 parse tree from Fortran code.
    code = ("module test\n"
            "contains\n"
            "subroutine tmp()\n"
            "  integer :: i, sum\n"
            "  sum = 0\n"
            "  do i = 1, 20, 2\n"
            "    sum = sum + i\n"
            "  end do\n"
            "end subroutine tmp\n"
            "end module test")
    schedule = create_schedule(code, "tmp")

    # Generate Fortran from the PSyIR schedule
    result = fort_writer(schedule)
    assert "do i = 1, 20, 2\n" in result
Пример #14
0
def test_fw_naryopeator_unknown(fort_writer, monkeypatch):
    ''' Check that the FortranWriter class nary_operation method raises
    the expected error if it encounters an unknown operator.

    '''
    # Generate fparser2 parse tree from Fortran code.
    code = ("module test\n"
            "contains\n"
            "subroutine tmp(a,n)\n"
            "  integer, intent(in) :: n\n"
            "  real, intent(out) :: a\n"
            "    a = max(1.0,1.0,2.0)\n"
            "end subroutine tmp\n"
            "end module test")
    schedule = create_schedule(code, "tmp")
    # Remove max() from the list of supported nary operators
    monkeypatch.delitem(Fparser2Reader.nary_operators, "max")
    # Generate Fortran from the PSyIR schedule
    with pytest.raises(VisitorError) as err:
        _ = fort_writer(schedule)
    assert "Unexpected N-ary op" in str(err)
Пример #15
0
def test_fw_unaryoperator_unknown(fort_writer, monkeypatch):
    '''Check the FortranWriter class unary_operation method raises an
    exception if an unknown unary operator is found.

    '''
    # Generate fparser2 parse tree from Fortran code.
    code = ("module test\n"
            "contains\n"
            "subroutine tmp(a,n)\n"
            "  integer, intent(in) :: n\n"
            "  real, intent(out) :: a(n)\n"
            "    a = sin(1.0)\n"
            "end subroutine tmp\n"
            "end module test")
    schedule = create_schedule(code, "tmp")
    # Remove sin() from the dict of unary operators
    monkeypatch.delitem(Fparser2Reader.unary_operators, "sin")
    # Generate Fortran from the PSyIR schedule
    with pytest.raises(VisitorError) as excinfo:
        _ = fort_writer(schedule)
    assert "Unexpected unary op" in str(excinfo)
Пример #16
0
def test_fw_container_3(fort_writer, monkeypatch):
    '''Check the FortranWriter class raises an exception when a Container
    node contains a symbol table with an argument declaration (as this
    does not make sense).

    '''
    # Generate fparser2 parse tree from Fortran code.
    code = ("module test\n"
            "real :: a\n"
            "contains\n"
            "subroutine tmp()\n"
            "end subroutine tmp\n"
            "end module test")
    schedule = create_schedule(code, "tmp")
    container = schedule.root
    symbol = container.symbol_table.symbols[0]
    assert symbol.name == "a"
    monkeypatch.setattr(symbol, "_interface", Symbol.Argument())

    with pytest.raises(VisitorError) as excinfo:
        _ = fort_writer(container)
    assert ("Arguments are not allowed in this context but this symbol table "
            "contains argument(s): '['a']'." in str(excinfo))
Пример #17
0
def test_fw_codeblock_1(fort_writer):
    '''Check the FortranWriter class codeblock method correctly
    prints out the Fortran code contained within it.

    '''
    # Generate fparser2 parse tree from Fortran code.
    code = ("module test\n"
            "contains\n"
            "subroutine tmp()\n"
            "  integer :: a\n"
            "  a=1\n"
            "  print *,\"I am a code block\"\n"
            "  print *,\"with more than one line\"\n"
            "end subroutine tmp\n"
            "end module test")
    schedule = create_schedule(code, "tmp")
    # Check a code block exists in the schedule
    assert schedule.walk(CodeBlock)
    # Generate Fortran from the PSyIR schedule
    result = fort_writer(schedule)
    assert ("  a=1\n"
            "  PRINT *, \"I am a code block\"\n"
            "  PRINT *, \"with more than one line\"\n" in result)
Пример #18
0
def test_fw_container_2(fort_writer):
    '''Check the FortranWriter class outputs correct code when a Container
    node is found with a subroutine, use statements and
    declarations. Also raise an exception if the Container contains a
    Container.

    '''
    # Generate fparser2 parse tree from Fortran code.
    code = ("module test\n"
            "use test2_mod, only : a,b\n"
            "real :: c,d\n"
            "contains\n"
            "subroutine tmp()\n"
            "end subroutine tmp\n"
            "end module test")
    schedule = create_schedule(code, "tmp")
    container = schedule.root

    # Generate Fortran from the PSyIR schedule
    result = fort_writer(container)

    assert ("module test\n"
            "  use test2_mod, only : a\n"
            "  use test2_mod, only : b\n"
            "  real :: c\n"
            "  real :: d\n\n"
            "  contains\n"
            "  subroutine tmp()\n\n\n"
            "  end subroutine tmp\n\n"
            "end module test\n" in result)

    container.children.append(Container("child", parent=container))
    with pytest.raises(VisitorError) as excinfo:
        _ = fort_writer(container)
    assert ("The Fortran back-end requires all children of a Container "
            "to be KernelSchedules." in str(excinfo))
Пример #19
0
def test_fw_kernelschedule(fort_writer, monkeypatch):
    '''Check the FortranWriter class outputs correct code when a
    KernelSchedule node is found. Also tests that an exception is
    raised if KernelSchedule.name does not have a value.

    '''
    # Generate fparser2 parse tree from Fortran code.
    code = ("module test\n"
            "contains\n"
            "subroutine tmp(a,b,c)\n"
            "  use my_mod, only : d\n"
            "  real, intent(out) :: a(:)\n"
            "  real, intent(in) :: b(:)\n"
            "  integer, intent(in) :: c\n"
            "  a = b/c\n"
            "end subroutine tmp\n"
            "end module test")
    schedule = create_schedule(code, "tmp")

    # Generate Fortran from the PSyIR schedule
    result = fort_writer(schedule)

    assert ("subroutine tmp(a,b,c)\n"
            "  use my_mod, only : d\n"
            "  real, dimension(:), intent(out) :: a\n"
            "  real, dimension(:), intent(in) :: b\n"
            "  integer, intent(in) :: c\n"
            "\n"
            "  a=b / c\n"
            "\n"
            "end subroutine tmp\n") in result

    monkeypatch.setattr(schedule, "_name", None)
    with pytest.raises(VisitorError) as excinfo:
        _ = fort_writer(schedule)
    assert "Expected node name to have a value." in str(excinfo)
Пример #20
0
def test_fw_codeblock_2(fort_writer):
    '''Check the FortranWriter class codeblock method correctly prints out
    the Fortran representation when there is a code block that is part
    of a line (not a whole line). In this case the ":" in the array
    access is a code block.

    '''
    # Generate fparser2 parse tree from Fortran code.
    code = ("module test\n"
            "contains\n"
            "subroutine tmp(a,n)\n"
            "  integer, intent(in) :: n\n"
            "  real, intent(out) :: a(n,n,n)\n"
            "    a(2,n,:) = 0.0\n"
            "end subroutine tmp\n"
            "end module test")
    schedule = create_schedule(code, "tmp")

    # Check a code block exists in the schedule
    assert schedule.walk(CodeBlock)

    # Generate Fortran from the PSyIR schedule
    result = fort_writer(schedule)
    assert "a(2,n,:)=0.0" in result