def test_find_or_create_imported_symbol_2():
    ''' Check that the _find_or_create_imported_symbol() method creates new
    symbols when appropriate. '''
    # Create some suitable PSyIR from scratch
    symbol_table = SymbolTable()
    symbol_table.add(DataSymbol("tmp", REAL_TYPE))
    kernel1 = KernelSchedule.create("mod_1", SymbolTable(), [])
    container = Container.create("container_name", symbol_table, [kernel1])
    xvar = DataSymbol("x", REAL_TYPE)
    xref = Reference(xvar)
    assign = Assignment.create(xref, Literal("1.0", REAL_TYPE))
    kernel1.addchild(assign)
    # We have no wildcard imports so there can be no symbol named 'undefined'
    with pytest.raises(SymbolError) as err:
        _ = _find_or_create_imported_symbol(assign, "undefined")
    assert "No Symbol found for name 'undefined'" in str(err.value)
    # We should be able to find the 'tmp' symbol in the parent Container
    sym = _find_or_create_imported_symbol(assign, "tmp")
    assert sym.datatype.intrinsic == ScalarType.Intrinsic.REAL
    # Add a wildcard import to the SymbolTable of the KernelSchedule
    new_container = ContainerSymbol("some_mod")
    new_container.wildcard_import = True
    kernel1.symbol_table.add(new_container)
    # Symbol not in any container but we do have wildcard imports so we
    # get a new symbol back
    new_symbol = _find_or_create_imported_symbol(assign, "undefined")
    assert new_symbol.name == "undefined"
    assert isinstance(new_symbol.interface, UnresolvedInterface)
    # pylint: disable=unidiomatic-typecheck
    assert type(new_symbol) == Symbol
    assert "undefined" not in container.symbol_table
    assert kernel1.symbol_table.lookup("undefined") is new_symbol
Ejemplo n.º 2
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
Ejemplo n.º 3
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
Ejemplo n.º 4
0
def test_oclw_gen_declaration():
    '''Check the OpenCLWriter class gen_declaration method produces
    the expected declarations.

    '''
    oclwriter = OpenCLWriter()

    # Basic entry - Scalar are passed by value and don't have additional
    # qualifiers.
    symbol = DataSymbol("dummy1", INTEGER_TYPE)
    result = oclwriter.gen_declaration(symbol)
    assert result == "int dummy1"

    # Array argument has a memory qualifier (only __global for now)
    array_type = ArrayType(INTEGER_TYPE, [2, ArrayType.Extent.ATTRIBUTE, 2])
    symbol = DataSymbol("dummy2", array_type)
    result = oclwriter.gen_declaration(symbol)
    assert result == "__global int * restrict dummy2"

    # Array with unknown intent
    array_type = ArrayType(INTEGER_TYPE, [2, ArrayType.Extent.ATTRIBUTE, 2])
    symbol = DataSymbol("dummy2",
                        array_type,
                        interface=ArgumentInterface(
                            ArgumentInterface.Access.UNKNOWN))
    result = oclwriter.gen_declaration(symbol)
    assert result == "__global int * restrict dummy2"
Ejemplo n.º 5
0
def test_is_array_range():
    '''test that the is_array_range method behaves as expected, returning
    true if the LHS of the assignment is an array range access and
    false otherwise.

    '''
    one = Literal("1.0", REAL_TYPE)
    int_one = Literal("1", INTEGER_TYPE)
    var = DataSymbol("x", REAL_TYPE)
    reference = Reference(var)

    # lhs is not an array
    assignment = Assignment.create(reference, one)
    assert not assignment.is_array_range

    # lhs is an array reference but has no range
    array_type = ArrayType(REAL_TYPE, [10, 10])
    symbol = DataSymbol("x", array_type)
    array_ref = ArrayReference(symbol, [1, 3])
    assignment = Assignment.create(array_ref, one)
    assert not assignment.is_array_range

    # lhs is an array reference with a range
    my_range = Range.create(int_one, int_one, int_one)
    array_ref = ArrayReference.create(symbol, [my_range, int_one])
    assignment = Assignment.create(array_ref, one)
    assert assignment.is_array_range
Ejemplo n.º 6
0
def test_check_variable():
    '''Test the _check_variable utility method behaves as expected'''

    with pytest.raises(GenerationError) as info:
        Loop._check_variable(None)
    assert ("variable property in Loop class should be a DataSymbol but "
            "found 'NoneType'." in str(info.value))

    with pytest.raises(GenerationError) as info:
        Loop._check_variable("hello")
    assert ("variable property in Loop class should be a DataSymbol but "
            "found 'str'." in str(info.value))

    array_type = ArrayType(INTEGER_TYPE, shape=[10, 20])
    array_symbol = DataSymbol("my_array", array_type)
    with pytest.raises(GenerationError) as info:
        Loop._check_variable(array_symbol)
    assert ("variable property in Loop class should be a ScalarType but "
            "found 'ArrayType'." in str(info.value))

    scalar_symbol = DataSymbol("my_array", REAL_TYPE)
    with pytest.raises(GenerationError) as info:
        Loop._check_variable(scalar_symbol)
    assert ("variable property in Loop class should be a scalar integer but "
            "found 'REAL'." in str(info.value))

    scalar_symbol = DataSymbol("my_array", INTEGER_TYPE)
    assert Loop._check_variable(scalar_symbol) is None
Ejemplo n.º 7
0
def example_psyir(create_expression):
    '''Utility function that creates a PSyIR tree containing an ABS
    intrinsic operator and returns the operator.

    :param function create_expresssion: function used to create the \
        content of the ABS operator.

    :returns: PSyIR ABS operator instance.
    :rtype: :py:class:`psyclone.psyGen.UnaryOperation`

    '''
    symbol_table = SymbolTable()
    name1 = symbol_table.new_symbol_name("arg")
    arg1 = DataSymbol(name1,
                      REAL_TYPE,
                      interface=ArgumentInterface(
                          ArgumentInterface.Access.READWRITE))
    symbol_table.add(arg1)
    name2 = symbol_table.new_symbol_name()
    local = DataSymbol(name2, REAL_TYPE)
    symbol_table.add(local)
    symbol_table.specify_argument_list([arg1])
    var1 = Reference(arg1)
    var2 = Reference(local)
    oper = UnaryOperation.Operator.ABS
    operation = UnaryOperation.create(oper, create_expression(var1))
    assign = Assignment.create(var2, operation)
    _ = KernelSchedule.create("abs_example", symbol_table, [assign])
    return operation
Ejemplo n.º 8
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)
Ejemplo n.º 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.copy()])
    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.copy()])
    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.copy()])
    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.copy()])
    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))
Ejemplo n.º 10
0
def test_datasymbol_copy_properties():
    '''Test that the DataSymbol copy_properties method works as expected.'''
    array_type = ArrayType(REAL_SINGLE_TYPE, [1, 2])
    symbol = DataSymbol("myname",
                        array_type,
                        constant_value=None,
                        interface=ArgumentInterface(
                            ArgumentInterface.Access.READWRITE))

    # Check an exception is raised if an incorrect argument is passed in
    with pytest.raises(TypeError) as excinfo:
        symbol.copy_properties(None)
    assert ("Argument should be of type 'DataSymbol' but found 'NoneType'."
            "") in str(excinfo.value)

    new_symbol = DataSymbol("other_name",
                            INTEGER_SINGLE_TYPE,
                            constant_value=7)

    symbol.copy_properties(new_symbol)

    assert symbol.name == "myname"
    assert symbol.datatype.intrinsic == ScalarType.Intrinsic.INTEGER
    assert symbol.datatype.precision == ScalarType.Precision.SINGLE
    assert symbol.is_local
    assert isinstance(symbol.constant_value, Literal)
    assert symbol.constant_value.value == "7"
    assert (
        symbol.constant_value.datatype.intrinsic == symbol.datatype.intrinsic)
    assert (
        symbol.constant_value.datatype.precision == symbol.datatype.precision)
Ejemplo n.º 11
0
def test_apply_existing_names():
    '''Check that the apply method uses existing iterators appropriately
    when their symbols are already defined.

    '''
    _, invoke_info = get_invoke("implicit_do.f90", api=API, idx=0)
    schedule = invoke_info.schedule
    assignment = schedule[0]
    array_ref = assignment.lhs
    trans = NemoArrayRange2LoopTrans()
    symbol_table = schedule.symbol_table
    symbol_table.add(DataSymbol("ji", INTEGER_TYPE))
    symbol_table.add(DataSymbol("jj", INTEGER_TYPE))
    symbol_table.add(DataSymbol("jk", INTEGER_TYPE))

    trans.apply(array_ref.children[2])
    trans.apply(array_ref.children[1])
    trans.apply(array_ref.children[0])

    writer = FortranWriter()
    result = writer(schedule)
    assert ("do jk = 1, jpk, 1\n"
            "  do jj = 1, jpj, 1\n"
            "    do ji = 1, jpi, 1\n"
            "      umask(ji,jj,jk) = 0.0e0\n"
            "    enddo\n"
            "  enddo\n"
            "enddo" in result)
Ejemplo n.º 12
0
def test_array_range_with_reduction():
    ''' Test that we correctly identify an array range when it is the result
        of a reduction from an array, e.g x(1, INT(SUM(map(:, :), 1))) = 1.0

    '''
    one = Literal("1.0", REAL_TYPE)
    int_one = Literal("1", INTEGER_TYPE)
    int_two = Literal("2", INTEGER_TYPE)
    int_array_type = ArrayType(INTEGER_SINGLE_TYPE, [10, 10])
    map_sym = DataSymbol("map", int_array_type)
    array_type = ArrayType(REAL_TYPE, [10, 10])
    symbol = DataSymbol("x", array_type)
    lbound1 = BinaryOperation.create(BinaryOperation.Operator.LBOUND,
                                     Reference(map_sym), int_one.copy())
    ubound1 = BinaryOperation.create(BinaryOperation.Operator.UBOUND,
                                     Reference(map_sym), int_one.copy())
    my_range1 = Range.create(lbound1, ubound1)
    lbound2 = BinaryOperation.create(BinaryOperation.Operator.LBOUND,
                                     Reference(map_sym), int_two.copy())
    ubound2 = BinaryOperation.create(BinaryOperation.Operator.UBOUND,
                                     Reference(map_sym), int_two.copy())
    my_range2 = Range.create(lbound2, ubound2)
    bsum_op = BinaryOperation.create(
        BinaryOperation.Operator.SUM,
        ArrayReference.create(map_sym, [my_range1, my_range2]), int_one.copy())
    int_op2 = UnaryOperation.create(UnaryOperation.Operator.INT, bsum_op)
    assignment = Assignment.create(
        ArrayReference.create(symbol, [int_one.copy(), int_op2]), one.copy())
    assert assignment.is_array_range is True
Ejemplo n.º 13
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)
Ejemplo n.º 14
0
def test_fusetrans_error_not_same_parent():
    ''' Check that we reject attempts to fuse loops which don't share the
    same parent '''
    from psyclone.transformations import LoopFuseTrans

    sch1 = Schedule()
    sch2 = Schedule()
    loop1 = Loop(variable=DataSymbol("i", INTEGER_TYPE), parent=sch1)
    loop2 = Loop(variable=DataSymbol("j", INTEGER_TYPE), parent=sch2)
    sch1.addchild(loop1)
    sch2.addchild(loop2)

    loop1.addchild(Literal("1", INTEGER_TYPE, parent=loop1))  # start
    loop1.addchild(Literal("10", INTEGER_TYPE, parent=loop1))  # stop
    loop1.addchild(Literal("1", INTEGER_TYPE, parent=loop1))  # step
    loop1.addchild(Schedule(parent=loop1))  # loop body

    loop2.addchild(Literal("1", INTEGER_TYPE, parent=loop2))  # start
    loop2.addchild(Literal("10", INTEGER_TYPE, parent=loop2))  # stop
    loop2.addchild(Literal("1", INTEGER_TYPE, parent=loop2))  # step
    loop2.addchild(Schedule(parent=loop2))  # loop body

    fuse = LoopFuseTrans()

    # Try to fuse loops with different parents
    with pytest.raises(TransformationError) as err:
        fuse.validate(loop1, loop2)
    assert ("Error in LoopFuseTrans transformation. Loops do not have the "
            "same parent" in str(err.value))
Ejemplo n.º 15
0
def test_fusetrans_error_not_same_parent():
    ''' Check that we reject attempts to fuse loops which don't share the
    same parent '''

    loop1 = Loop.create(DataSymbol("i", INTEGER_TYPE),
                        Literal("1",
                                INTEGER_TYPE), Literal("10", INTEGER_TYPE),
                        Literal("1", INTEGER_TYPE), [Return()])
    sch1 = Schedule()
    sch1.addchild(loop1)

    sch2 = Schedule()
    loop2 = Loop.create(DataSymbol("j", INTEGER_TYPE),
                        Literal("1",
                                INTEGER_TYPE), Literal("10", INTEGER_TYPE),
                        Literal("1", INTEGER_TYPE), [Return()])

    sch2.addchild(loop2)

    fuse = LoopFuseTrans()

    # Try to fuse loops with different parents
    with pytest.raises(TransformationError) as err:
        fuse.validate(loop1, loop2)
    assert ("Error in LoopFuseTrans transformation. Loops do not have the "
            "same parent" in str(err.value))
Ejemplo n.º 16
0
def test_operations_can_be_copied():
    ''' Test that an operation can be copied. '''

    operands = [Reference(DataSymbol("tmp1", REAL_SINGLE_TYPE)),
                Reference(DataSymbol("tmp2", REAL_SINGLE_TYPE)),
                Reference(DataSymbol("tmp3", REAL_SINGLE_TYPE))]
    operation = NaryOperation.create(NaryOperation.Operator.MAX, operands)

    operation1 = operation.copy()
    assert isinstance(operation1, NaryOperation)
    assert operation1 is not operation
    assert operation1.operator is NaryOperation.Operator.MAX
    assert operation1.children[0].symbol.name == "tmp1"
    assert operation1.children[0] is not operands[0]
    assert operation1.children[0].parent is operation1
    assert operation1.children[1].symbol.name == "tmp2"
    assert operation1.children[1] is not operands[1]
    assert operation1.children[1].parent is operation1
    assert operation1.children[2].symbol.name == "tmp3"
    assert operation1.children[2] is not operands[2]
    assert operation1.children[2].parent is operation1
    assert len(operation1.children) == 3
    assert len(operation.children) == 3

    # Modifying the new operation does not affect the original
    operation1._operator = NaryOperation.Operator.MIN
    operation1.children.pop()
    assert len(operation1.children) == 2
    assert len(operation.children) == 3
    assert operation1.operator is NaryOperation.Operator.MIN
    assert operation.operator is NaryOperation.Operator.MAX
Ejemplo n.º 17
0
def test_binaryoperation_create_invalid():
    '''Test that the create method in a BinaryOperation class raises the
    expected exception if the provided input is invalid.

    '''
    ref1 = Reference(DataSymbol("tmp1", REAL_SINGLE_TYPE))
    ref2 = Reference(DataSymbol("tmp2", REAL_SINGLE_TYPE))
    add = BinaryOperation.Operator.ADD

    # oper not a BinaryOperation.Operator.
    with pytest.raises(GenerationError) as excinfo:
        _ = BinaryOperation.create("invalid", ref1, ref2)
    assert ("oper argument in create method of BinaryOperation class should "
            "be a PSyIR BinaryOperation Operator but found 'str'."
            in str(excinfo.value))

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

    # rhs not a Node.
    with pytest.raises(GenerationError) as excinfo:
        _ = BinaryOperation.create(add, ref1, "invalid")
    assert ("Item 'str' can't be child 1 of 'BinaryOperation'. The valid "
            "format is: 'DataNode, DataNode'.") in str(excinfo.value)
Ejemplo n.º 18
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 = ArrayReference(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"
Ejemplo n.º 19
0
def test_datasymbol_constant_value_setter():
    '''Test that a DataSymbol constant value can be set if given a new valid
    constant value.'''

    # Test with valid constant values
    sym = DataSymbol('a', INTEGER_SINGLE_TYPE, constant_value=7)
    assert sym.constant_value.value == "7"
    sym.constant_value = 9
    assert sym.constant_value.value == "9"

    sym = DataSymbol('a', REAL_SINGLE_TYPE, constant_value=3.1415)
    assert sym.constant_value.value == "3.1415"
    sym.constant_value = 1.0
    assert sym.constant_value.value == "1.0"

    sym = DataSymbol('a', BOOLEAN_TYPE, constant_value=True)
    assert sym.constant_value.value == "true"
    sym.constant_value = False
    assert sym.constant_value.value == "false"

    # Test with valid constant expressions
    lhs = Literal('2', INTEGER_SINGLE_TYPE)
    rhs = Reference(DataSymbol('constval', INTEGER_SINGLE_TYPE))
    ct_expr = BinaryOperation.create(BinaryOperation.Operator.ADD, lhs, rhs)
    sym = DataSymbol('a', INTEGER_SINGLE_TYPE, constant_value=ct_expr)
    assert isinstance(sym.constant_value, BinaryOperation)
    assert sym.constant_value is ct_expr
Ejemplo n.º 20
0
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()
Ejemplo n.º 21
0
def test_is_not_array_range():
    ''' Test that is_array_range correctly rejects things that aren't
    an assignment to an array range.

    '''
    int_one = Literal("1", INTEGER_SINGLE_TYPE)
    one = Literal("1.0", REAL_TYPE)
    var = DataSymbol("x", REAL_TYPE)
    reference = Reference(var)

    # lhs is not an array
    assignment = Assignment.create(reference, one)
    assert assignment.is_array_range is False

    # lhs is an array reference but has no range
    array_type = ArrayType(REAL_TYPE, [10, 10])
    symbol = DataSymbol("y", array_type)
    array_ref = Reference(symbol)
    assignment = Assignment.create(array_ref, one.copy())
    assert assignment.is_array_range is False

    # lhs is an array reference but the single index value is obtained
    # using an array range, y(1, SUM(map(:), 1)) = 1.0
    int_array_type = ArrayType(INTEGER_SINGLE_TYPE, [10])
    map_sym = DataSymbol("map", int_array_type)
    start = BinaryOperation.create(BinaryOperation.Operator.LBOUND,
                                   Reference(map_sym), int_one.copy())
    stop = BinaryOperation.create(BinaryOperation.Operator.UBOUND,
                                  Reference(map_sym), int_one.copy())
    my_range = Range.create(start, stop)
    sum_op = BinaryOperation.create(BinaryOperation.Operator.SUM,
                                    ArrayReference.create(map_sym, [my_range]),
                                    int_one.copy())
    assignment = Assignment.create(
        ArrayReference.create(symbol, [int_one.copy(), sum_op]), one.copy())
    assert assignment.is_array_range is False

    # When the slice has two operator ancestors, one of which is a reduction
    # e.g y(1, SUM(ABS(map(:)), 1)) = 1.0
    abs_op = UnaryOperation.create(
        UnaryOperation.Operator.ABS,
        ArrayReference.create(map_sym, [my_range.copy()]))
    sum_op2 = BinaryOperation.create(BinaryOperation.Operator.SUM, abs_op,
                                     int_one.copy())
    assignment = Assignment.create(
        ArrayReference.create(symbol, [int_one.copy(), sum_op2]), one.copy())
    assert assignment.is_array_range is False

    # lhs is a scalar member of a structure
    grid_type = StructureType.create([
        ("dx", REAL_SINGLE_TYPE, Symbol.Visibility.PUBLIC),
        ("dy", REAL_SINGLE_TYPE, Symbol.Visibility.PUBLIC)
    ])
    grid_type_symbol = DataTypeSymbol("grid_type", grid_type)
    grid_sym = DataSymbol("grid", grid_type_symbol)
    assignment = Assignment.create(StructureReference.create(grid_sym, ["dx"]),
                                   one.copy())
    assert assignment.is_array_range is False
Ejemplo n.º 22
0
def test_cw_assignment():
    '''Check the CWriter class assignment method generate the appropriate
    output.

    '''
    assignment = Assignment.create(Reference(DataSymbol('a', REAL_TYPE)),
                                   Reference(DataSymbol('b', REAL_TYPE)))
    # Generate C from the PSyIR schedule
    cwriter = CWriter()
    result = cwriter(assignment)
    assert result == "a = b;\n"
Ejemplo n.º 23
0
def test_cw_binaryoperator():
    '''Check the CWriter class binary_operation method correctly
    prints out the C representation of any given BinaryOperation.

    '''
    cwriter = CWriter()

    # Test UnaryOperation without children.
    binary_operation = BinaryOperation(BinaryOperation.Operator.ADD)
    with pytest.raises(VisitorError) as err:
        _ = cwriter(binary_operation)
    assert ("BinaryOperation malformed or incomplete. It should have "
            "exactly 2 children, but found 0." in str(err.value))

    # Test with children
    ref1 = Reference(DataSymbol("a", REAL_TYPE))
    ref2 = Reference(DataSymbol("b", REAL_TYPE))
    binary_operation = BinaryOperation.create(BinaryOperation.Operator.ADD,
                                              ref1, ref2)
    assert cwriter(binary_operation) == '(a + b)'

    # Test all supported Operators
    test_list = ((BinaryOperation.Operator.ADD,
                  '(a + b)'), (BinaryOperation.Operator.SUB, '(a - b)'),
                 (BinaryOperation.Operator.MUL,
                  '(a * b)'), (BinaryOperation.Operator.DIV, '(a / b)'),
                 (BinaryOperation.Operator.REM,
                  '(a % b)'), (BinaryOperation.Operator.POW, 'pow(a, b)'),
                 (BinaryOperation.Operator.EQ,
                  '(a == b)'), (BinaryOperation.Operator.NE, '(a != b)'),
                 (BinaryOperation.Operator.GT,
                  '(a > b)'), (BinaryOperation.Operator.GE, '(a >= b)'),
                 (BinaryOperation.Operator.LT,
                  '(a < b)'), (BinaryOperation.Operator.LE, '(a <= b)'),
                 (BinaryOperation.Operator.AND,
                  '(a && b)'), (BinaryOperation.Operator.OR,
                                '(a || b)'), (BinaryOperation.Operator.SIGN,
                                              'copysign(a, b)'))

    for operator, expected in test_list:
        binary_operation._operator = operator
        assert cwriter(binary_operation) == expected

    # Test that an unsupported operator raises a error
    class Unsupported(object):
        '''Dummy class'''
        def __init__(self):
            pass

    binary_operation._operator = Unsupported
    with pytest.raises(VisitorError) as err:
        _ = cwriter(binary_operation)
    assert "The C backend does not support the '" in str(err.value)
    assert "' operator." in str(err.value)
Ejemplo n.º 24
0
def test_binaryoperation_create():
    '''Test that the create method in the BinaryOperation class correctly
    creates a BinaryOperation instance.

    '''
    lhs = Reference(DataSymbol("tmp1", REAL_SINGLE_TYPE))
    rhs = Reference(DataSymbol("tmp2", REAL_SINGLE_TYPE))
    oper = BinaryOperation.Operator.ADD
    binaryoperation = BinaryOperation.create(oper, lhs, rhs)
    check_links(binaryoperation, [lhs, rhs])
    result = FortranWriter().binaryoperation_node(binaryoperation)
    assert result == "tmp1 + tmp2"
Ejemplo n.º 25
0
def test_naryoperation_create():
    '''Test that the create method in the NaryOperation class correctly
    creates an NaryOperation instance.

    '''
    children = [Reference(DataSymbol("tmp1", REAL_SINGLE_TYPE)),
                Reference(DataSymbol("tmp2", REAL_SINGLE_TYPE)),
                Reference(DataSymbol("tmp3", REAL_SINGLE_TYPE))]
    oper = NaryOperation.Operator.MAX
    naryoperation = NaryOperation.create(oper, children)
    check_links(naryoperation, children)
    result = FortranWriter().naryoperation_node(naryoperation)
    assert result == "MAX(tmp1, tmp2, tmp3)"
Ejemplo n.º 26
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"
Ejemplo n.º 27
0
def test_call_create():
    '''Test that the create method creates a valid call with arguments'''

    routine = RoutineSymbol("ellie")
    array_type = ArrayType(INTEGER_TYPE, shape=[10, 20])
    arguments = [
        Reference(DataSymbol("arg1", INTEGER_TYPE)),
        Array(DataSymbol("arg2", array_type))
    ]
    call = Call.create(routine, arguments)
    assert call.routine is routine
    for idx, child, in enumerate(call.children):
        assert child is arguments[idx]
        assert child.parent is call
Ejemplo n.º 28
0
def test_cw_size():
    ''' Check the CWriter class SIZE method raises the expected error since
    there is no C equivalent. '''
    cwriter = CWriter()
    arr = ArrayReference(DataSymbol('a', INTEGER_TYPE))
    lit = Literal('1', INTEGER_TYPE)
    size = BinaryOperation.create(BinaryOperation.Operator.SIZE, arr, lit)
    lhs = Reference(DataSymbol('length', INTEGER_TYPE))
    assignment = Assignment.create(lhs, size)

    with pytest.raises(VisitorError) as excinfo:
        cwriter(assignment)
    assert ("C backend does not support the 'Operator.SIZE' operator"
            in str(excinfo.value))
Ejemplo n.º 29
0
def test_datasymbol_scalar_array():
    '''Test that the DataSymbol property is_scalar returns True if the
    DataSymbol is a scalar and False if not and that the DataSymbol property
    is_array returns True if the DataSymbol is an array and False if not.

    '''
    sym1 = DataSymbol("s1", INTEGER_SINGLE_TYPE)
    array_type = ArrayType(REAL_SINGLE_TYPE,
                           [ArrayType.Extent.ATTRIBUTE, 2, sym1])
    sym2 = DataSymbol("s2", array_type)
    assert sym1.is_scalar
    assert not sym1.is_array
    assert not sym2.is_scalar
    assert sym2.is_array
Ejemplo n.º 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)