Example #1
0
def test_assignment_children_validation():
    '''Test that children added to assignment are validated. Assignment
    accepts just 2 children and both are DataNodes.

    '''
    # Create method with lhs not a Node.
    with pytest.raises(GenerationError) as excinfo:
        _ = Assignment.create("invalid", Literal("0.0", REAL_SINGLE_TYPE))
    assert ("Item 'str' can't be child 0 of 'Assignment'. The valid format "
            "is: 'DataNode, DataNode'.") in str(excinfo.value)

    # Create method with rhs not a Node.
    with pytest.raises(GenerationError) as excinfo:
        _ = Assignment.create(Reference(DataSymbol("tmp", REAL_SINGLE_TYPE)),
                              "invalid")
    assert ("Item 'str' can't be child 1 of 'Assignment'. The valid format "
            "is: 'DataNode, DataNode'.") in str(excinfo.value)

    # Direct assignment of a 3rd children
    assignment = Assignment.create(
        Reference(DataSymbol("tmp", REAL_SINGLE_TYPE)),
        Literal("0.0", REAL_SINGLE_TYPE))
    with pytest.raises(GenerationError) as excinfo:
        assignment.children.append(Literal("0.0", REAL_SINGLE_TYPE))
    assert ("Item 'Literal' can't be child 2 of 'Assignment'. The valid format"
            " is: 'DataNode, DataNode'.") in str(excinfo.value)
Example #2
0
def test_apply2(tmpdir):
    '''Test that the matmul2code apply method produces the expected
    PSyIR. We use the Fortran backend to help provide the test for
    correctness. This example includes extra indices for the vector
    and matrix arrays with additional indices being literals.

    '''
    trans = Matmul2CodeTrans()
    matmul = create_matmul()
    matmul.children[0].children[2] = Literal("1", INTEGER_TYPE)
    matmul.children[1].children[1] = Literal("2", INTEGER_TYPE)
    trans.apply(matmul)
    writer = FortranWriter()
    result = writer(matmul.root)
    assert (
        "subroutine my_kern()\n"
        "  integer, parameter :: idx = 3\n"
        "  real, dimension(5,10,15) :: x\n"
        "  real, dimension(10,20) :: y\n"
        "  real, dimension(10) :: result\n"
        "  integer :: i\n"
        "  integer :: j\n"
        "\n"
        "  do i = 1, 5, 1\n"
        "    result(i) = 0.0\n"
        "    do j = 1, 10, 1\n"
        "      result(i) = result(i) + x(i,j,1) * y(j,2)\n"
        "    enddo\n"
        "  enddo\n"
        "\n"
        "end subroutine my_kern" in result)
    assert Compile(tmpdir).string_compiles(result)
Example #3
0
def test_lower_to_lang_level_single_node():
    ''' Test the lower_to_language_level() method when a Schedule contains
    a single ProfileNode.

    '''
    Profiler.set_options([Profiler.INVOKES])
    symbol_table = SymbolTable()
    arg1 = symbol_table.new_symbol(symbol_type=DataSymbol, datatype=REAL_TYPE)
    zero = Literal("0.0", REAL_TYPE)
    one = Literal("1.0", REAL_TYPE)
    assign1 = Assignment.create(Reference(arg1), zero)
    assign2 = Assignment.create(Reference(arg1), one)

    kschedule = KernelSchedule.create(
        "work1", symbol_table, [assign1, assign2, Return()])
    Profiler.add_profile_nodes(kschedule, Loop)
    assert isinstance(kschedule.children[0], ProfileNode)
    assert isinstance(kschedule.children[-1], Return)
    kschedule.lower_to_language_level()
    # The ProfileNode should have been replaced by two CodeBlocks with its
    # children inserted between them.
    assert isinstance(kschedule[0], CodeBlock)
    # The first CodeBlock should have the "profile-start" annotation.
    assert kschedule[0].annotations == ["profile-start"]
    ptree = kschedule[0].get_ast_nodes
    assert len(ptree) == 1
    assert isinstance(ptree[0], Fortran2003.Call_Stmt)
    assert kschedule[1] is assign1
    assert kschedule[2] is assign2
    assert isinstance(kschedule[-2], CodeBlock)
    assert kschedule[-2].annotations == []
    ptree = kschedule[-2].get_ast_nodes
    assert len(ptree) == 1
    assert isinstance(ptree[0], Fortran2003.Call_Stmt)
    assert isinstance(kschedule[-1], Return)
Example #4
0
def test_range_view(capsys):
    ''' Check that calling view() on an array with a child Range works
    as expected. '''
    from psyclone.psyir.nodes import Array
    from psyclone.psyir.nodes.node import colored, SCHEDULE_COLOUR_MAP
    # Create the PSyIR for 'my_array(1, 1:10)'
    erange = Range.create(Literal("1", INTEGER_SINGLE_TYPE),
                          Literal("10", INTEGER_SINGLE_TYPE))
    array_type = ArrayType(REAL_SINGLE_TYPE, [10, 10])
    array = Array.create(DataSymbol("my_array", array_type),
                         [Literal("1", INTEGER_SINGLE_TYPE), erange])
    array.view()
    stdout, _ = capsys.readouterr()
    arrayref = colored("ArrayReference",
                       SCHEDULE_COLOUR_MAP[array._colour_key])
    literal = colored("Literal",
                      SCHEDULE_COLOUR_MAP[array.children[0]._colour_key])
    rangestr = colored("Range", SCHEDULE_COLOUR_MAP[erange._colour_key])
    indent = "    "
    assert (arrayref + "[name:'my_array']\n" + indent + literal +
            "[value:'1', Scalar<INTEGER, SINGLE>]\n" + indent + rangestr +
            "[]\n" + 2 * indent + literal +
            "[value:'1', Scalar<INTEGER, SINGLE>]\n" + 2 * indent + literal +
            "[value:'10', Scalar<INTEGER, SINGLE>]\n" + 2 * indent + literal +
            "[value:'1', Scalar<INTEGER, UNDEFINED>]\n" in stdout)
Example #5
0
def test_create():
    '''Test that the static create() method creates a NemoLoop instance
    and its children corectly.

    '''
    variable = DataSymbol("ji", INTEGER_TYPE)
    start = Literal("2", INTEGER_TYPE)
    stop = Literal("10", INTEGER_TYPE)
    step = Literal("1", INTEGER_TYPE)
    x_var = DataSymbol("X", REAL_TYPE)
    children = [Assignment.create(Reference(x_var), Literal("3.0", REAL_TYPE))]
    nemo_loop = NemoLoop.create(variable, start, stop, step, children)
    assert isinstance(nemo_loop, NemoLoop)
    assert nemo_loop.loop_type == "lon"
    assert isinstance(nemo_loop.loop_body, Schedule)
    assert len(nemo_loop.loop_body.children) == 1
    assert nemo_loop.loop_body.children[0] is children[0]
    assert children[0].parent is nemo_loop.loop_body
    assert nemo_loop.loop_body.parent is nemo_loop
    assert nemo_loop.variable is variable
    assert nemo_loop.start_expr is start
    assert nemo_loop.stop_expr is stop
    assert nemo_loop.step_expr is step
    writer = FortranWriter()
    result = writer(nemo_loop)
    assert ("do ji = 2, 10, 1\n" "  X = 3.0\n" "enddo" in result)
Example #6
0
def test_scope():
    '''Test that the scope method in a Node instance returns the closest
    ancestor Schedule or Container Node (including itself) or raises
    an exception if one does not exist.

    '''
    kernel_symbol_table = SymbolTable()
    symbol = DataSymbol("tmp", REAL_TYPE)
    kernel_symbol_table.add(symbol)
    ref = Reference(symbol)
    assign = Assignment.create(ref, Literal("0.0", REAL_TYPE))
    kernel_schedule = KernelSchedule.create("my_kernel", kernel_symbol_table,
                                            [assign])
    container = Container.create("my_container", SymbolTable(),
                                 [kernel_schedule])
    assert ref.scope is kernel_schedule
    assert assign.scope is kernel_schedule
    assert kernel_schedule.scope is kernel_schedule
    assert container.scope is container

    anode = Literal("x", INTEGER_TYPE)
    with pytest.raises(SymbolError) as excinfo:
        _ = anode.scope
    assert ("Unable to find the scope of node "
            "'Literal[value:'x', Scalar<INTEGER, UNDEFINED>]' as "
            "none of its ancestors are Container or Schedule nodes."
            in str(excinfo.value))
Example #7
0
def test_cw_array():
    '''Check the CWriter class array method correctly prints
    out the C representation of an array.

    '''
    cwriter = CWriter()

    symbol = DataSymbol('a', REAL_TYPE)
    arr = Array(symbol)
    lit = Literal('0.0', REAL_TYPE)
    assignment = Assignment.create(arr, lit)

    # An array without any children (dimensions) should produce an error.
    with pytest.raises(VisitorError) as excinfo:
        result = cwriter(assignment)
    assert "Arrays must have at least 1 dimension but found node: '" \
        in str(excinfo.value)

    # Dimensions can be references, literals or operations
    arr.addchild(Reference(DataSymbol('b', INTEGER_TYPE), parent=arr))
    arr.addchild(Literal('1', INTEGER_TYPE, parent=arr))
    uop = UnaryOperation.create(UnaryOperation.Operator.MINUS,
                                Literal('2', INTEGER_TYPE))
    uop.parent = arr
    arr.addchild(uop)

    result = cwriter(assignment)
    # Results is reversed and flatten (row-major 1D)
    # dimensions are called <name>LEN<dimension> by convention
    assert result == "a[(-2) * aLEN2 * aLEN1 + 1 * aLEN1 + b] = 0.0;\n"
Example #8
0
    def __init__(self, parent=None, loop_type=""):
        Loop.__init__(self,
                      parent=parent,
                      valid_loop_types=["", "colours", "colour"])
        self.loop_type = loop_type

        # Work out the variable name from  the loop type
        if self._loop_type == "colours":
            tag = "colours_loop_idx"
            suggested_name = "colour"
        elif self._loop_type == "colour":
            tag = "colour_loop_idx"
            suggested_name = "cell"
        else:
            tag = "cell_loop_idx"
            suggested_name = "cell"

        symtab = self.scope.symbol_table
        try:
            data_symbol = symtab.lookup_with_tag(tag)
        except KeyError:
            name = symtab.new_symbol_name(suggested_name)
            data_symbol = DataSymbol(name, INTEGER_TYPE)
            symtab.add(data_symbol, tag=tag)
        self.variable = data_symbol

        # Pre-initialise the Loop children  # TODO: See issue #440
        self.addchild(Literal("NOT_INITIALISED", INTEGER_TYPE,
                              parent=self))  # start
        self.addchild(Literal("NOT_INITIALISED", INTEGER_TYPE,
                              parent=self))  # stop
        self.addchild(Literal("1", INTEGER_TYPE, parent=self))  # step
        self.addchild(Schedule(parent=self))  # loop body
Example #9
0
def test_create_errors():
    '''Test that the expected exceptions are raised when the arguments to
    the create method are invalid.

    '''
    variable = DataSymbol("ji", INTEGER_TYPE)
    start = Literal("2", INTEGER_TYPE)
    stop = Literal("10", INTEGER_TYPE)
    step = Literal("1", INTEGER_TYPE)
    x_var = DataSymbol("X", REAL_TYPE)
    children = [Assignment.create(Reference(x_var), Literal("3.0", REAL_TYPE))]
    with pytest.raises(GenerationError) as info:
        _ = NemoLoop.create(None, start, stop, step, children)
    assert ("Generation Error: variable property in Loop class should be a "
            "DataSymbol but found 'NoneType'" in str(info.value))
    with pytest.raises(GenerationError) as info:
        _ = NemoLoop.create(variable, None, stop, step, children)
    assert ("Generation Error: Item 'NoneType' can't be child 0 of 'Loop'. "
            "The valid format is: 'DataNode, DataNode, DataNode, Schedule'."
            in str(info.value))
    with pytest.raises(GenerationError) as info:
        _ = NemoLoop.create(variable, start, None, step, children)
    assert ("Generation Error: Item 'NoneType' can't be child 1 of 'Loop'. "
            "The valid format is: 'DataNode, DataNode, DataNode, Schedule'."
            in str(info.value))
    with pytest.raises(GenerationError) as info:
        _ = NemoLoop.create(variable, start, stop, None, children)
    assert ("Generation Error: Item 'NoneType' can't be child 2 of 'Loop'. "
            "The valid format is: 'DataNode, DataNode, DataNode, Schedule'."
            in str(info.value))
    with pytest.raises(GenerationError) as info:
        _ = NemoLoop.create(variable, start, stop, step, None)
    assert ("Generation Error: children argument in create method of NemoLoop "
            "class should be a list but found 'NoneType'." in str(info.value))
Example #10
0
def create_expr(symbol_table):
    '''Utility routine that creates and returns an expression containing a
    number of array references containing range nodes. The expression
    looks like the following (using Fortran array notation):

    x(2:n:2)*z(1,2:n:2)+a(1)

    :param symbol_table: the symbol table to which we add the array \
        symbols.
    :type symbol_table: :py:class:`psyclone.psyir.symbol.SymbolTable`

    :returns: an expression containing 3 array references, 2 of which \
        contain ranges.
    :rtype: :py:class:`psyclone.psyir.nodes.BinaryOperation`

    '''
    array_symbol = DataSymbol("x", ArrayType(REAL_TYPE, [10]))
    symbol_table.add(array_symbol)
    symbol_n = symbol_table.lookup("n")
    array_x = Array.create(array_symbol, [create_stepped_range(symbol_n)])
    array_symbol = DataSymbol("z", ArrayType(REAL_TYPE, [10, 10]))
    symbol_table.add(array_symbol)
    array_z = Array.create(
        array_symbol,
        [Literal("1", INTEGER_TYPE),
         create_stepped_range(symbol_n)])
    array_symbol = DataSymbol("a", ArrayType(REAL_TYPE, [10]))
    array_a = Array.create(array_symbol, [Literal("1", INTEGER_TYPE)])
    symbol_table.add(array_symbol)
    mult = BinaryOperation.create(BinaryOperation.Operator.MUL, array_x,
                                  array_z)
    add = BinaryOperation.create(BinaryOperation.Operator.ADD, mult, array_a)
    return add
Example #11
0
def test_range_references_props():
    ''' Test that the properties of a Range return what we expect
    when the start, stop and step are references or expressions. '''
    from psyclone.psyir.nodes import BinaryOperation, KernelSchedule
    sched = KernelSchedule("test_sched")
    sym_table = sched.symbol_table
    start_symbol = DataSymbol("istart", INTEGER_SINGLE_TYPE)
    stop_symbol = DataSymbol("istop", INTEGER_SINGLE_TYPE)
    step_symbol = DataSymbol("istep", INTEGER_SINGLE_TYPE)
    sym_table.add(start_symbol)
    sym_table.add(stop_symbol)
    sym_table.add(step_symbol)
    startvar = Reference(start_symbol)
    stopvar = Reference(stop_symbol)
    start = BinaryOperation.create(BinaryOperation.Operator.SUB, startvar,
                                   Literal("1", INTEGER_SINGLE_TYPE))
    stop = BinaryOperation.create(BinaryOperation.Operator.ADD, stopvar,
                                  Literal("1", INTEGER_SINGLE_TYPE))
    step = Reference(step_symbol)
    erange = Range.create(start, stop, step)
    assert erange.start is start
    assert erange.stop is stop
    assert erange.step is step
    assert erange.children[0] is start
    assert erange.children[1] is stop
    assert erange.children[2] is step
Example #12
0
    def __init__(self, parent=None, topology_name="", loop_type=""):
        Loop.__init__(self, parent=parent, valid_loop_types=["inner", "outer"])
        self.loop_type = loop_type

        if self._loop_type == "inner":
            tag = "inner_loop_idx"
            suggested_name = "i"
        elif self.loop_type == "outer":
            tag = "outer_loop_idx"
            suggested_name = "j"

        symtab = self.scope.symbol_table
        try:
            self.variable = symtab.lookup_with_tag(tag)
        except KeyError:
            self.variable = symtab.new_symbol(suggested_name,
                                              tag,
                                              symbol_type=DataSymbol,
                                              datatype=INTEGER_TYPE)

        # Pre-initialise the Loop children  # TODO: See issue #440
        self.addchild(Literal("NOT_INITIALISED", INTEGER_TYPE,
                              parent=self))  # start
        self.addchild(Literal("NOT_INITIALISED", INTEGER_TYPE,
                              parent=self))  # stop
        self.addchild(Literal("1", INTEGER_TYPE, parent=self))  # step
        self.addchild(Schedule(parent=self))  # loop body
def test_type_convert_binaryop_create(operation, op_str):
    '''Test that the create method in the BinaryOperation class correctly
    creates a BinaryOperation instance for the REAL and INT type-conversion
    operations..

    '''
    sym = DataSymbol("tmp1", REAL_SINGLE_TYPE)
    lhs = Reference(sym)
    wp_sym = DataSymbol("wp", INTEGER_SINGLE_TYPE)
    # Reference to a kind parameter
    rhs = Reference(wp_sym)
    binaryoperation = BinaryOperation.create(operation, lhs, rhs)
    assert binaryoperation._operator is operation
    check_links(binaryoperation, [lhs, rhs])
    result = FortranWriter().binaryoperation_node(binaryoperation)
    assert op_str + "(tmp1, wp)" in result.lower()
    # Kind specified with an integer literal
    rhs = Literal("4", INTEGER_SINGLE_TYPE)
    binaryoperation = BinaryOperation.create(operation, lhs.detach(), rhs)
    check_links(binaryoperation, [lhs, rhs])
    result = FortranWriter().binaryoperation_node(binaryoperation)
    assert op_str + "(tmp1, 4)" in result.lower()
    # Kind specified as an arithmetic expression
    rhs = BinaryOperation.create(BinaryOperation.Operator.ADD,
                                 Reference(wp_sym),
                                 Literal("2", INTEGER_SINGLE_TYPE))
    binaryoperation = BinaryOperation.create(operation, lhs.detach(), rhs)
    check_links(binaryoperation, [lhs, rhs])
    result = FortranWriter().binaryoperation_node(binaryoperation)
    assert op_str + "(tmp1, wp + 2)" in result.lower()
Example #14
0
def test_reference_accesses_bounds(operator_type):
    '''Test that the reference_accesses method behaves as expected when
    the reference is the first argument to either the lbound or ubound
    intrinsic as that is simply looking up the array bounds (therefore
    var_access_info should be empty) and when the reference is the
    second argument of either the lbound or ubound intrinsic (in which
    case the access should be a read).

    '''
    # Note, one would usually expect UBOUND to provide the upper bound
    # of a range but to simplify the test both LBOUND and UBOUND are
    # used for the lower bound. This does not affect the test.
    one = Literal("1", INTEGER_TYPE)
    array_symbol = DataSymbol("test", ArrayType(REAL_TYPE, [10]))
    array_ref1 = Reference(array_symbol)
    array_ref2 = Reference(array_symbol)
    array_access = ArrayReference.create(array_symbol, [one])

    # test when first or second argument to LBOUND or UBOUND is an
    # array reference
    operator = BinaryOperation.create(operator_type, array_ref1, array_ref2)
    array_access.children[0] = Range.create(operator, one.copy(), one.copy())
    var_access_info = VariablesAccessInfo()
    array_ref1.reference_accesses(var_access_info)
    assert str(var_access_info) == ""
    var_access_info = VariablesAccessInfo()
    array_ref2.reference_accesses(var_access_info)
    assert str(var_access_info) == "test: READ"
Example #15
0
def test_arraytype():
    '''Test that the ArrayType class __init__ works as expected. Test the
    different dimension datatypes that are supported.'''
    scalar_type = ScalarType(ScalarType.Intrinsic.INTEGER, 4)
    data_symbol = DataSymbol("var", scalar_type, constant_value=30)
    one = Literal("1", scalar_type)
    var_plus_1 = BinaryOperation.create(BinaryOperation.Operator.ADD,
                                        Reference(data_symbol), one)
    literal = Literal("20", scalar_type)
    array_type = ArrayType(scalar_type, [
        10, literal, var_plus_1,
        Reference(data_symbol), ArrayType.Extent.DEFERRED,
        ArrayType.Extent.ATTRIBUTE
    ])
    assert isinstance(array_type, ArrayType)
    assert len(array_type.shape) == 6
    # Provided as an int but stored as a Literal
    shape0 = array_type.shape[0]
    assert isinstance(shape0, Literal)
    assert shape0.value == "10"
    assert shape0.datatype.intrinsic == ScalarType.Intrinsic.INTEGER
    assert shape0.datatype.precision == ScalarType.Precision.UNDEFINED
    # Provided and stored as a Literal (DataNode)
    assert array_type.shape[1] is literal
    # Provided and stored as an Operator (DataNode)
    assert array_type.shape[2] is var_plus_1
    # Provided and stored as a Reference to a DataSymbol
    assert isinstance(array_type.shape[3], Reference)
    assert array_type.shape[3].symbol is data_symbol
    # Provided and stored as a deferred extent
    assert array_type.shape[4] == ArrayType.Extent.DEFERRED
    # Provided as an attribute extent
    assert array_type.shape[5] == ArrayType.Extent.ATTRIBUTE
Example #16
0
def test_binaryoperation_node_str():
    ''' Check the node_str method of the Binary Operation class.'''
    binary_operation = BinaryOperation(BinaryOperation.Operator.ADD)
    op1 = Literal("1", INTEGER_SINGLE_TYPE)
    op2 = Literal("1", INTEGER_SINGLE_TYPE)
    binary_operation.addchild(op1)
    binary_operation.addchild(op2)
    coloredtext = colored("BinaryOperation", BinaryOperation._colour)
    assert coloredtext+"[operator:'ADD']" in binary_operation.node_str()
Example #17
0
def test_naryoperation_node_str():
    ''' Check the node_str method of the Nary Operation class.'''
    nary_operation = NaryOperation(NaryOperation.Operator.MAX)
    nary_operation.addchild(Literal("1", INTEGER_SINGLE_TYPE))
    nary_operation.addchild(Literal("1", INTEGER_SINGLE_TYPE))
    nary_operation.addchild(Literal("1", INTEGER_SINGLE_TYPE))

    coloredtext = colored("NaryOperation", NaryOperation._colour)
    assert coloredtext+"[operator:'MAX']" in nary_operation.node_str()
Example #18
0
def test_literal_init_empty_value():
    '''Test the initialisation of a Literal object with an empty value
    argument raises the expected exception unless it is of CHARACTER_TYPE.

    '''
    with pytest.raises(ValueError) as err:
        Literal("", REAL_DOUBLE_TYPE)
    assert "A non-character literal value cannot be empty." in str(err.value)
    lit = Literal("", CHARACTER_TYPE)
    assert lit.value == ""
Example #19
0
def test_binaryoperation_node_str():
    ''' Check the node_str method of the Binary Operation class.'''
    from psyclone.psyir.nodes.node import colored, SCHEDULE_COLOUR_MAP
    binary_operation = BinaryOperation(BinaryOperation.Operator.ADD)
    op1 = Literal("1", INTEGER_SINGLE_TYPE, parent=binary_operation)
    op2 = Literal("1", INTEGER_SINGLE_TYPE, parent=binary_operation)
    binary_operation.addchild(op1)
    binary_operation.addchild(op2)
    coloredtext = colored("BinaryOperation", SCHEDULE_COLOUR_MAP["Operation"])
    assert coloredtext + "[operator:'ADD']" in binary_operation.node_str()
Example #20
0
def test_literal_children_validation():
    '''Test that children added to Literals are validated. A Literal node does
    not accept any children.

    '''
    literal = Literal("1", INTEGER_SINGLE_TYPE)
    with pytest.raises(GenerationError) as excinfo:
        literal.addchild(Literal("2", INTEGER_SINGLE_TYPE))
    assert ("Item 'Literal' can't be child 0 of 'Literal'. Literal is a"
            " LeafNode and doesn't accept children.") in str(excinfo.value)
Example #21
0
def test_correct_2abs(tmpdir):
    '''Check that a valid example produces the expected output when there
    is more than one ABS() in an expression.

    '''
    Config.get().api = "nemo"
    operation = example_psyir(
        lambda arg: BinaryOperation.create(
            BinaryOperation.Operator.MUL, arg,
            Literal("3.14", REAL_TYPE)))
    root = operation.root
    assignment = operation.parent
    abs_op = UnaryOperation.create(UnaryOperation.Operator.ABS,
                                   Literal("1.0", REAL_TYPE))
    operation.detach()
    op1 = BinaryOperation.create(BinaryOperation.Operator.ADD,
                                 operation, abs_op)
    assignment.addchild(op1)
    writer = FortranWriter()
    result = writer(root)
    assert (
        "subroutine abs_example(arg)\n"
        "  real, intent(inout) :: arg\n"
        "  real :: psyir_tmp\n\n"
        "  psyir_tmp = ABS(arg * 3.14) + ABS(1.0)\n\n"
        "end subroutine abs_example\n") in result
    trans = Abs2CodeTrans()
    trans.apply(operation, root.symbol_table)
    trans.apply(abs_op, root.symbol_table)
    result = writer(root)
    assert (
        "subroutine abs_example(arg)\n"
        "  real, intent(inout) :: arg\n"
        "  real :: psyir_tmp\n"
        "  real :: res_abs\n"
        "  real :: tmp_abs\n"
        "  real :: res_abs_1\n"
        "  real :: tmp_abs_1\n\n"
        "  tmp_abs = arg * 3.14\n"
        "  if (tmp_abs > 0.0) then\n"
        "    res_abs = tmp_abs\n"
        "  else\n"
        "    res_abs = tmp_abs * -1.0\n"
        "  end if\n"
        "  tmp_abs_1 = 1.0\n"
        "  if (tmp_abs_1 > 0.0) then\n"
        "    res_abs_1 = tmp_abs_1\n"
        "  else\n"
        "    res_abs_1 = tmp_abs_1 * -1.0\n"
        "  end if\n"
        "  psyir_tmp = res_abs + res_abs_1\n\n"
        "end subroutine abs_example\n") in result
    assert Compile(tmpdir).string_compiles(result)
    # Remove the created config instance
    Config._instance = None
Example #22
0
def test_loop_navigation_properties():
    # pylint: disable=too-many-statements
    ''' Tests the start_expr, stop_expr, step_expr and loop_body
    setter and getter properties.

    '''
    loop = Loop()

    # Properties return an error if the node is incomplete
    error_str = ("Loop is incomplete. It should have exactly 4 "
                 "children, but found")
    with pytest.raises(InternalError) as err:
        _ = loop.start_expr
    assert error_str in str(err.value)

    loop.addchild(Literal("start", INTEGER_SINGLE_TYPE))
    loop.addchild(Literal("stop", INTEGER_SINGLE_TYPE))
    loop.addchild(Literal("step", INTEGER_SINGLE_TYPE))

    # If it's not fully complete, it still returns an error
    with pytest.raises(InternalError) as err:
        _ = loop.start_expr
    assert error_str in str(err.value)
    with pytest.raises(InternalError) as err:
        _ = loop.stop_expr
    assert error_str in str(err.value)
    with pytest.raises(InternalError) as err:
        _ = loop.step_expr
    assert error_str in str(err.value)
    with pytest.raises(InternalError) as err:
        _ = loop.loop_body
    assert error_str in str(err.value)
    with pytest.raises(InternalError) as err:
        loop.start_expr = Literal("invalid", INTEGER_SINGLE_TYPE)
    assert error_str in str(err.value)
    with pytest.raises(InternalError) as err:
        loop.stop_expr = Literal("invalid", INTEGER_SINGLE_TYPE)
    assert error_str in str(err.value)
    with pytest.raises(InternalError) as err:
        loop.step_expr = Literal("invalid", INTEGER_SINGLE_TYPE)
    assert error_str in str(err.value)

    # Check that Getters properties work
    loop.addchild(Schedule(parent=loop))
    loop.loop_body.addchild(Return(parent=loop.loop_body))

    assert loop.start_expr.value == "start"
    assert loop.stop_expr.value == "stop"
    assert loop.step_expr.value == "step"
    assert isinstance(loop.loop_body[0], Return)

    # Test Setters
    loop.start_expr = Literal("newstart", INTEGER_SINGLE_TYPE)
    loop.stop_expr = Literal("newstop", INTEGER_SINGLE_TYPE)
    loop.step_expr = Literal("newstep", INTEGER_SINGLE_TYPE)

    assert loop.start_expr.value == "newstart"
    assert loop.stop_expr.value == "newstop"
    assert loop.step_expr.value == "newstep"
Example #23
0
def test_correct_2min(tmpdir):
    '''Check that a valid example produces the expected output when there
    is more than one MIN() in an expression.

    '''
    Config.get().api = "nemo"
    operation = example_psyir_binary(lambda arg: arg)
    root = operation.root
    assignment = operation.parent
    operation.detach()
    min_op = BinaryOperation.create(BinaryOperation.Operator.MIN,
                                    Literal("1.0", REAL_TYPE),
                                    Literal("2.0", REAL_TYPE))
    op1 = BinaryOperation.create(BinaryOperation.Operator.ADD, min_op,
                                 operation)
    assignment.addchild(op1)

    writer = FortranWriter()
    result = writer(root)
    assert ("subroutine min_example(arg, arg_1)\n"
            "  real, intent(inout) :: arg\n"
            "  real, intent(inout) :: arg_1\n"
            "  real :: psyir_tmp\n\n"
            "  psyir_tmp = MIN(1.0, 2.0) + MIN(arg, arg_1)\n\n"
            "end subroutine min_example\n") in result
    trans = Min2CodeTrans()
    trans.apply(operation, root.symbol_table)
    trans.apply(min_op, root.symbol_table)
    result = writer(root)
    assert ("subroutine min_example(arg, arg_1)\n"
            "  real, intent(inout) :: arg\n"
            "  real, intent(inout) :: arg_1\n"
            "  real :: psyir_tmp\n"
            "  real :: res_min\n"
            "  real :: tmp_min\n"
            "  real :: res_min_1\n"
            "  real :: tmp_min_1\n\n"
            "  res_min = arg\n"
            "  tmp_min = arg_1\n"
            "  if (tmp_min < res_min) then\n"
            "    res_min = tmp_min\n"
            "  end if\n"
            "  res_min_1 = 1.0\n"
            "  tmp_min_1 = 2.0\n"
            "  if (tmp_min_1 < res_min_1) then\n"
            "    res_min_1 = tmp_min_1\n"
            "  end if\n"
            "  psyir_tmp = res_min_1 + res_min\n\n"
            "end subroutine min_example\n") in result
    assert Compile(tmpdir).string_compiles(result)
    # Remove the created config instance
    Config._instance = None
Example #24
0
def test_naryoperation_node_str():
    ''' Check the node_str method of the Nary Operation class.'''
    from psyclone.psyir.nodes.node import colored, SCHEDULE_COLOUR_MAP
    nary_operation = NaryOperation(NaryOperation.Operator.MAX)
    nary_operation.addchild(
        Literal("1", INTEGER_SINGLE_TYPE, parent=nary_operation))
    nary_operation.addchild(
        Literal("1", INTEGER_SINGLE_TYPE, parent=nary_operation))
    nary_operation.addchild(
        Literal("1", INTEGER_SINGLE_TYPE, parent=nary_operation))

    coloredtext = colored("NaryOperation", SCHEDULE_COLOUR_MAP["Operation"])
    assert coloredtext + "[operator:'MAX']" in nary_operation.node_str()
Example #25
0
def test_create_unknown():
    '''Test that the static create() method creates a NemoLoop instance
    with an unknown loop type if the loop type is not recognised.

    '''
    variable = DataSymbol("idx", INTEGER_TYPE)
    start = Literal("2", INTEGER_TYPE)
    stop = Literal("10", INTEGER_TYPE)
    step = Literal("1", INTEGER_TYPE)
    x_var = DataSymbol("X", REAL_TYPE)
    children = [Assignment.create(Reference(x_var), Literal("3.0", REAL_TYPE))]
    nemo_loop = NemoLoop.create(variable, start, stop, step, children)
    assert nemo_loop.loop_type == "unknown"
Example #26
0
def test_correct_expr(tmpdir):
    '''Check that a valid example produces the expected output when SIGN
    is part of an expression.

    '''
    Config.get().api = "nemo"
    operation = example_psyir(lambda arg: BinaryOperation.create(
        BinaryOperation.Operator.MUL, arg, Literal("3.14", REAL_TYPE)))
    root = operation.root
    assignment = operation.parent
    operation.detach()
    op1 = BinaryOperation.create(BinaryOperation.Operator.ADD,
                                 Literal("1.0", REAL_TYPE), operation)
    op2 = BinaryOperation.create(BinaryOperation.Operator.ADD, op1,
                                 Literal("2.0", REAL_TYPE))
    assignment.addchild(op2)
    writer = FortranWriter()
    result = writer(root)
    assert ("subroutine sign_example(arg, arg_1)\n"
            "  real, intent(inout) :: arg\n"
            "  real, intent(inout) :: arg_1\n"
            "  real :: psyir_tmp\n\n"
            "  psyir_tmp = 1.0 + SIGN(arg * 3.14, arg_1) + 2.0\n\n"
            "end subroutine sign_example\n") in result
    trans = Sign2CodeTrans()
    trans.apply(operation, root.symbol_table)
    result = writer(root)
    assert ("subroutine sign_example(arg, arg_1)\n"
            "  real, intent(inout) :: arg\n"
            "  real, intent(inout) :: arg_1\n"
            "  real :: psyir_tmp\n"
            "  real :: res_sign\n"
            "  real :: tmp_sign\n"
            "  real :: res_abs\n"
            "  real :: tmp_abs\n\n"
            "  tmp_abs = arg * 3.14\n"
            "  if (tmp_abs > 0.0) then\n"
            "    res_abs = tmp_abs\n"
            "  else\n"
            "    res_abs = tmp_abs * -1.0\n"
            "  end if\n"
            "  res_sign = res_abs\n"
            "  tmp_sign = arg_1\n"
            "  if (tmp_sign < 0.0) then\n"
            "    res_sign = res_sign * -1.0\n"
            "  end if\n"
            "  psyir_tmp = 1.0 + res_sign + 2.0\n\n"
            "end subroutine sign_example\n") in result
    assert Compile(tmpdir).string_compiles(result)
    # Remove the created config instance
    Config._instance = None
Example #27
0
def test_binaryoperation_can_be_printed():
    '''Test that a Binary Operation instance can always be printed (i.e. is
    initialised fully)'''
    binary_operation = BinaryOperation(BinaryOperation.Operator.ADD)
    assert "BinaryOperation[operator:'ADD']" in str(binary_operation)
    op1 = Literal("1", INTEGER_SINGLE_TYPE)
    op2 = Literal("2", INTEGER_SINGLE_TYPE)
    binary_operation.addchild(op1)
    binary_operation.addchild(op2)
    # Check the node children are also printed
    assert ("Literal[value:'1', Scalar<INTEGER, SINGLE>]\n"
            in str(binary_operation))
    assert ("Literal[value:'2', Scalar<INTEGER, SINGLE>]"
            in str(binary_operation))
Example #28
0
def test_loop_create_invalid():
    '''Test that the create method in a Loop class raises the expected
    exception if the provided input is invalid.

    '''
    zero = Literal("0", INTEGER_SINGLE_TYPE)
    one = Literal("1", INTEGER_SINGLE_TYPE)
    children = [
        Assignment.create(Reference(DataSymbol("x", INTEGER_SINGLE_TYPE)), one)
    ]

    # invalid variable (test_check_variable tests check all ways a
    # variable could be invalid. Here we just check that the
    # _check_variable() method is called correctly)
    with pytest.raises(GenerationError) as excinfo:
        _ = Loop.create(1, zero, one, one, children)
    assert ("variable property in Loop class should be a DataSymbol but "
            "found 'int'.") in str(excinfo.value)

    variable = DataSymbol("i", INTEGER_TYPE)

    # start not a Node.
    with pytest.raises(GenerationError) as excinfo:
        _ = Loop.create(variable, "invalid", one, one, children)
    assert ("Item 'str' can't be child 0 of 'Loop'. The valid format is: "
            "'DataNode, DataNode, DataNode, Schedule'.") in str(excinfo.value)

    # stop not a Node.
    with pytest.raises(GenerationError) as excinfo:
        _ = Loop.create(variable, zero, "invalid", one, children)
    assert ("Item 'str' can't be child 1 of 'Loop'. The valid format is: "
            "'DataNode, DataNode, DataNode, Schedule'.") in str(excinfo.value)

    # step not a Node.
    with pytest.raises(GenerationError) as excinfo:
        _ = Loop.create(variable, zero, one, "invalid", children)
    assert ("Item 'str' can't be child 2 of 'Loop'. The valid format is: "
            "'DataNode, DataNode, DataNode, Schedule'.") in str(excinfo.value)

    # children not a list
    with pytest.raises(GenerationError) as excinfo:
        _ = Loop.create(variable, zero, one, one, "invalid")
    assert ("children argument in create method of Loop class should "
            "be a list but found 'str'." in str(excinfo.value))

    # contents of children list are not Node.
    with pytest.raises(GenerationError) as excinfo:
        _ = Loop.create(variable, zero, one, one, ["invalid"])
    assert ("Item 'str' can't be child 0 of 'Schedule'. The valid format is: "
            "'[Statement]*'." in str(excinfo.value))
Example #29
0
def test_cw_literal():
    '''Check the CWriter class literal method correctly prints
    out the C representation of a Literal.

    '''

    cwriter = CWriter()

    lit = Literal('1', INTEGER_TYPE)
    assert cwriter(lit) == '1'

    # Test that scientific notation is output correctly
    lit = Literal("3e5", REAL_TYPE, None)
    assert cwriter(lit) == '3e5'
Example #30
0
def test_ifblock_create_invalid():
    '''Test that the create method in an IfBlock class raises the expected
    exception if the provided input is invalid.

    '''
    if_condition = Literal('true', BOOLEAN_TYPE)
    if_body = [
        Assignment.create(Reference(DataSymbol("tmp", REAL_SINGLE_TYPE)),
                          Literal("0.0", REAL_SINGLE_TYPE)),
        Assignment.create(Reference(DataSymbol("tmp2", REAL_SINGLE_TYPE)),
                          Literal("1.0", REAL_SINGLE_TYPE))
    ]

    # if_condition not a Node.
    with pytest.raises(GenerationError) as excinfo:
        _ = IfBlock.create("True", if_body)
    assert ("Item 'str' can't be child 0 of 'If'. The valid format is: "
            "'DataNode, Schedule [, Schedule]'.") in str(excinfo.value)

    # One or more if body not a Node.
    if_body_err = [
        Assignment.create(Reference(DataSymbol("tmp", REAL_SINGLE_TYPE)),
                          Literal("0.0", REAL_SINGLE_TYPE)), "invalid"
    ]
    with pytest.raises(GenerationError) as excinfo:
        _ = IfBlock.create(if_condition, if_body_err)
    assert ("Item 'str' can't be child 1 of 'Schedule'. The valid format is: "
            "'[Statement]*'.") in str(excinfo.value)

    # If body not a list.
    with pytest.raises(GenerationError) as excinfo:
        _ = IfBlock.create(if_condition, "invalid")
    assert ("if_body argument in create method of IfBlock class should be a "
            "list.") in str(excinfo.value)

    # One of more of else_body not a Node.
    else_body_err = [
        Assignment.create(Reference(DataSymbol("tmp", REAL_SINGLE_TYPE)),
                          Literal("1.0", REAL_SINGLE_TYPE)), "invalid"
    ]
    with pytest.raises(GenerationError) as excinfo:
        _ = IfBlock.create(if_condition, if_body, else_body_err)
    assert ("Item 'str' can't be child 1 of 'Schedule'. The valid format is: "
            "'[Statement]*'.") in str(excinfo.value)

    # Else body not a list.
    with pytest.raises(GenerationError) as excinfo:
        _ = IfBlock.create(if_condition, if_body, "invalid")
    assert ("else_body argument in create method of IfBlock class should be a "
            "list.") in str(excinfo.value)