Example #1
0
def test_routine_properties():
    ''' Check the various properties of the Routine class. '''
    node1 = Routine("hello")
    assert node1.dag_name == "routine_hello_0"
    assert node1.return_type is None
    assert node1.is_program is False
    assert node1.name == "hello"
    # Give the Routine a child to get full coverage of __str__ method
    node1.addchild(Assignment())
    assert "Routine[name:'hello']:\nAssignment" in str(node1)

    node2 = Routine("bonjour", return_type=INTEGER_TYPE)
    assert node2.return_type == INTEGER_TYPE
    assert node2.is_program is False

    node3 = Routine("gutentag", is_program=True)
    assert node3.return_type is None
    assert node3.is_program

    node4 = Routine("welcome", is_program=True, return_type=INTEGER_TYPE)
    assert node4.return_type == INTEGER_TYPE
    assert node4.is_program

    with pytest.raises(TypeError) as err:
        node4.name = node3
    assert "must be a str but got" in str(err.value)
    node4.name = "goodbye"
    assert node4.name == "goodbye"
Example #2
0
def test_routine_create_invalid():
    '''Test that the create method in the Routine class raises the
    expected exceptions if the provided input is invalid.

    '''
    symbol_table = SymbolTable()
    symbol = DataSymbol("x", REAL_TYPE)
    symbol_table.add(symbol)
    children = [Assignment.create(Reference(symbol),
                                  Literal("1", REAL_TYPE))]

    # name is not a string.
    with pytest.raises(TypeError) as excinfo:
        _ = Routine.create(1, symbol_table, children)
    assert ("name argument in create method of Routine class "
            "should be a string but found 'int'.") in str(excinfo.value)

    # symbol_table not a SymbolTable.
    with pytest.raises(TypeError) as excinfo:
        _ = Routine.create("mod_name", "invalid", children)
    assert ("symbol_table argument in create method of Routine class "
            "should be a SymbolTable but found 'str'.") in str(excinfo.value)

    # children not a list.
    with pytest.raises(TypeError) as excinfo:
        _ = Routine.create("mod_name", symbol_table, "invalid")
    assert ("children argument in create method of Routine class "
            "should be a list but found 'str'." in str(excinfo.value))

    # contents of children list are not Node.
    with pytest.raises(TypeError) as excinfo:
        _ = Routine.create("mod_name", symbol_table, ["invalid"])
    assert (
        "child of children argument in create method of Routine class "
        "should be a PSyIR Node but found 'str'." in str(excinfo.value))
Example #3
0
def test_routine_constructor():
    ''' Check the constructor and associated type checking. '''
    with pytest.raises(TypeError) as err:
        Routine(1)
    assert "must be a str but got" in str(err.value)
    with pytest.raises(TypeError) as err:
        Routine("hello", is_program=1)
    assert "'is_program' must be a bool" in str(err.value)
    node = Routine("hello")
    assert node._name == "hello"
Example #4
0
def test_routine_return_symbol_setter():
    ''' Check that the return_symbol setter works correctly and rejects invalid
    values.

    '''
    node = Routine("hello")
    assert node.return_symbol is None
    with pytest.raises(TypeError) as err:
        node.return_symbol = "wrong"
    assert ("Routine return-symbol should be a DataSymbol but found 'str'" in
            str(err.value))
    sym = DataSymbol("result", REAL_TYPE)
    with pytest.raises(KeyError) as err:
        node.return_symbol = sym
    assert ("For a symbol to be a return-symbol, it must be present in the "
            "symbol table of the Routine but 'result' is not." in
            str(err.value))
    node.symbol_table.add(sym)
    node.return_symbol = sym
    assert node.return_symbol is sym
Example #5
0
def test_routine_name_setter():
    ''' Check the name setter property of the Routine class updates its
    name and its associated Routine symbol. '''

    node = Routine("hello")  # The constructor has an implicit name setter
    # Check the associated RoutineSymbol has been created
    assert "hello" in node.symbol_table
    assert isinstance(node.symbol_table.lookup("hello"), RoutineSymbol)
    # Check with an incorrect value type
    with pytest.raises(TypeError) as err:
        node.name = 3
    assert "must be a str but got" in str(err.value)

    # Perform a successful name change
    node.name = "goodbye"
    assert node.name == "goodbye"
    # Check that the previous symbol has been deleted and the new one created
    assert "welcome" not in node.symbol_table
    assert "goodbye" in node.symbol_table
    # Check that the 'own_routine_symbol' tag has been updated
    assert node.symbol_table.lookup_with_tag('own_routine_symbol').name == \
        "goodbye"
Example #6
0
def test_routine_create():
    '''Test that the create method correctly creates a Routine instance. '''
    symbol_table = SymbolTable()
    symbol = DataSymbol("tmp", REAL_TYPE)
    symbol_table.add(symbol)
    assignment = Assignment.create(Reference(symbol),
                                   Literal("0.0", REAL_TYPE))
    kschedule = Routine.create("mod_name", symbol_table, [assignment],
                               is_program=True, return_type=INTEGER_TYPE)
    assert isinstance(kschedule, Routine)
    check_links(kschedule, [assignment])
    assert kschedule.symbol_table is symbol_table
    assert kschedule.is_program
    assert kschedule.return_type == INTEGER_TYPE
Example #7
0
def test_file_container_create():
    '''Test that the create method in the Container class correctly
    creates a FileContainer instance.

    '''
    symbol_table = SymbolTable()
    symbol_table.add(DataSymbol("tmp", REAL_SINGLE_TYPE))
    module = Container.create("mod_1", symbol_table, [])
    program = Routine.create("prog_1", SymbolTable(), [], is_program=True)
    file_container = FileContainer.create("container_name", SymbolTable(),
                                          [module, program])
    assert isinstance(file_container, FileContainer)
    result = FortranWriter().filecontainer_node(file_container)
    assert result == ("module mod_1\n"
                      "  implicit none\n"
                      "  real :: tmp\n\n"
                      "  contains\n\n"
                      "end module mod_1\n"
                      "program prog_1\n\n\n"
                      "end program prog_1\n")
Example #8
0
def test_routine_properties():
    ''' Check the various properties of the Routine class. '''
    node1 = Routine("hello")
    assert node1.dag_name == "routine_hello_0"
    assert node1.return_symbol is None
    assert node1.is_program is False
    assert node1.name == "hello"
    # Give the Routine a child to get full coverage of __str__ method
    node1.addchild(Assignment())
    assert "Routine[name:'hello']:\nAssignment" in str(node1)

    node2 = Routine("bonjour")
    assert node2.is_program is False

    node3 = Routine("gutentag", is_program=True)
    assert node3.is_program
Example #9
0
def test_scoping_node_copy_hierarchy():
    ''' Test that the ScopingNode copy() method creates a new symbol table
    with copied symbols and updates the children references.

    This test has 2 ScopingNodes, and the copy will only be applied to the
    inner one. This means that the References to the symbols on the outer
    scope should not be duplicated. Also it contains argument symbols and
    a reference inside another reference to make sure all these are copied
    appropriately.
    '''
    parent_node = Container("module")
    symbol_b = parent_node.symbol_table.new_symbol("b",
                                                   symbol_type=DataSymbol,
                                                   datatype=ArrayType(
                                                       INTEGER_TYPE, [5]))
    schedule = Routine("routine")
    parent_node.addchild(schedule)
    symbol_a = schedule.symbol_table.new_symbol(
        "a",
        symbol_type=DataSymbol,
        datatype=INTEGER_TYPE,
        interface=ArgumentInterface(ArgumentInterface.Access.READWRITE))
    schedule.symbol_table.specify_argument_list([symbol_a])
    symbol_i = schedule.symbol_table.new_symbol("i",
                                                symbol_type=DataSymbol,
                                                datatype=INTEGER_TYPE)

    schedule.addchild(
        Assignment.create(
            Reference(symbol_a),
            ArrayReference.create(symbol_b, [Reference(symbol_i)])))

    new_schedule = schedule.copy()

    # Check that the symbol_table has been deep copied
    assert new_schedule.symbol_table is not schedule.symbol_table
    assert new_schedule.symbol_table.lookup("i") is not \
        schedule.symbol_table.lookup("i")
    assert new_schedule.symbol_table.lookup("a") is not \
        schedule.symbol_table.lookup("a")

    # Check that 'a' and 'i' have been copied to the new symbol table.
    assert new_schedule[0].lhs.symbol not in schedule.symbol_table.symbols
    assert new_schedule[0].lhs.symbol in new_schedule.symbol_table.symbols
    assert new_schedule[0].rhs.children[0].symbol not in \
        schedule.symbol_table.symbols
    assert new_schedule[0].rhs.children[0].symbol in \
        new_schedule.symbol_table.symbols

    # Add the "_new" suffix to all symbol in the copied schedule
    for symbol in new_schedule.symbol_table.symbols:
        new_schedule.symbol_table.rename_symbol(symbol, symbol.name + "_new")

    # An update to a symbol in the outer scope must affect both copies of the
    # inner schedule.
    parent_node.symbol_table.rename_symbol(symbol_b, symbol_b.name + "_global")

    # Insert the schedule back to the original container
    parent_node.addchild(new_schedule)

    # Check that the expected code is generated
    # TODO #1200: the new 'routine' RoutineSymbol also needs to change.
    expected = '''\
module module
  implicit none
  integer, dimension(5) :: b_global

  contains
  subroutine routine(a)
    integer, intent(inout) :: a
    integer :: i

    a = b_global(i)

  end subroutine routine
  subroutine routine(a_new)
    integer, intent(inout) :: a_new
    integer :: i_new

    a_new = b_global(i_new)

  end subroutine routine

end module module
'''
    writer = FortranWriter()
    output = writer(parent_node)
    assert expected == output
Example #10
0
def create_psyir_tree():
    ''' Create an example PSyIR Tree.

    :returns: an example PSyIR tree.
    :rtype: :py:class:`psyclone.psyir.nodes.Container`

    '''
    # Symbol table, symbols and scalar datatypes
    symbol_table = SymbolTable()
    arg1 = symbol_table.new_symbol(symbol_type=DataSymbol,
                                   datatype=REAL_TYPE,
                                   interface=ArgumentInterface(
                                       ArgumentInterface.Access.READWRITE))
    symbol_table.specify_argument_list([arg1])
    tmp_symbol = symbol_table.new_symbol(symbol_type=DataSymbol,
                                         datatype=REAL_DOUBLE_TYPE)
    index_symbol = symbol_table.new_symbol(root_name="i",
                                           symbol_type=DataSymbol,
                                           datatype=INTEGER4_TYPE)
    real_kind = symbol_table.new_symbol(root_name="RKIND",
                                        symbol_type=DataSymbol,
                                        datatype=INTEGER_TYPE,
                                        constant_value=8)
    routine_symbol = RoutineSymbol("my_sub")

    # Array using precision defined by another symbol
    scalar_type = ScalarType(ScalarType.Intrinsic.REAL, real_kind)
    array = symbol_table.new_symbol(root_name="a",
                                    symbol_type=DataSymbol,
                                    datatype=ArrayType(scalar_type, [10]))

    # Make generators for nodes which do not have other Nodes as children,
    # with some predefined scalar datatypes
    def zero():
        return Literal("0.0", REAL_TYPE)

    def one():
        return Literal("1.0", REAL4_TYPE)

    def two():
        return Literal("2.0", scalar_type)

    def int_zero():
        return Literal("0", INTEGER_SINGLE_TYPE)

    def int_one():
        return Literal("1", INTEGER8_TYPE)

    def tmp1():
        return Reference(arg1)

    def tmp2():
        return Reference(tmp_symbol)

    # Unary Operation
    oper = UnaryOperation.Operator.SIN
    unaryoperation = UnaryOperation.create(oper, tmp2())

    # Binary Operation
    oper = BinaryOperation.Operator.ADD
    binaryoperation = BinaryOperation.create(oper, one(), unaryoperation)

    # Nary Operation
    oper = NaryOperation.Operator.MAX
    naryoperation = NaryOperation.create(oper, [tmp1(), tmp2(), one()])

    # Array reference using a range
    lbound = BinaryOperation.create(BinaryOperation.Operator.LBOUND,
                                    Reference(array), int_one())
    ubound = BinaryOperation.create(BinaryOperation.Operator.UBOUND,
                                    Reference(array), int_one())
    my_range = Range.create(lbound, ubound)
    tmparray = ArrayReference.create(array, [my_range])

    # Assignments
    assign1 = Assignment.create(tmp1(), zero())
    assign2 = Assignment.create(tmp2(), zero())
    assign3 = Assignment.create(tmp2(), binaryoperation)
    assign4 = Assignment.create(tmp1(), tmp2())
    assign5 = Assignment.create(tmp1(), naryoperation)
    assign6 = Assignment.create(tmparray, two())

    # Call
    call = Call.create(routine_symbol, [tmp1(), binaryoperation.copy()])

    # If statement
    if_condition = BinaryOperation.create(BinaryOperation.Operator.GT, tmp1(),
                                          zero())
    ifblock = IfBlock.create(if_condition, [assign3, assign4])

    # Loop
    loop = Loop.create(index_symbol, int_zero(), int_one(), int_one(),
                       [ifblock])

    # Routine
    routine = Routine.create("work", symbol_table,
                             [assign1, call, assign2, loop, assign5, assign6])

    # Container
    container_symbol_table = SymbolTable()
    container = Container.create("CONTAINER", container_symbol_table,
                                 [routine])

    # Import data from another container
    external_container = ContainerSymbol("some_mod")
    container_symbol_table.add(external_container)
    external_var = DataSymbol("some_var",
                              INTEGER_TYPE,
                              interface=GlobalInterface(external_container))
    container_symbol_table.add(external_var)
    routine_symbol.interface = GlobalInterface(external_container)
    container_symbol_table.add(routine_symbol)

    # Routine (specified as being a program)
    program_symbol_table = SymbolTable()
    work_symbol = RoutineSymbol("work")
    container_symbol = ContainerSymbol("CONTAINER")
    work_symbol.interface = GlobalInterface(container_symbol)
    arg_symbol = program_symbol_table.new_symbol(root_name="arg",
                                                 symbol_type=DataSymbol,
                                                 datatype=REAL_TYPE)
    program_symbol_table.add(container_symbol)
    program_symbol_table.add(work_symbol)
    call = Call.create(work_symbol, [Reference(arg_symbol)])
    program = Routine.create("some_program",
                             program_symbol_table, [call],
                             is_program=True)

    # File container
    file_container = FileContainer.create("dummy", SymbolTable(),
                                          [container, program])

    return file_container