예제 #1
0
def test_create_structuretype():
    ''' Test the create() method of StructureType. '''
    # One member will have its type defined by a DataTypeSymbol
    tsymbol = DataTypeSymbol("my_type", DeferredType())
    stype = StructureType.create([
        ("fred", INTEGER_TYPE, Symbol.Visibility.PUBLIC),
        ("george", REAL_TYPE, Symbol.Visibility.PRIVATE),
        ("barry", tsymbol, Symbol.Visibility.PUBLIC)])
    assert len(stype.components) == 3
    george = stype.lookup("george")
    assert isinstance(george, StructureType.ComponentType)
    assert george.name == "george"
    assert george.datatype == REAL_TYPE
    assert george.visibility == Symbol.Visibility.PRIVATE
    barry = stype.lookup("barry")
    assert isinstance(barry, StructureType.ComponentType)
    assert barry.datatype is tsymbol
    assert barry.visibility == Symbol.Visibility.PUBLIC
    with pytest.raises(TypeError) as err:
        StructureType.create([
            ("fred", INTEGER_TYPE, Symbol.Visibility.PUBLIC),
            ("george", Symbol.Visibility.PRIVATE)])
    assert ("Each component must be specified using a 3-tuple of (name, "
            "type, visibility) but found a tuple with 2 members: ("
            "'george', " in str(err.value))
예제 #2
0
def test_create_datatypesymbol():
    ''' Check that a basic DataTypeSymbol can be created with the expected
    properties. '''
    sym = DataTypeSymbol("my_type", DeferredType())
    assert sym.name == "my_type"
    assert isinstance(sym.datatype, DeferredType)
    assert str(sym) == "my_type : DataTypeSymbol"
예제 #3
0
def test_create_datatypesymbol_wrong_datatype():
    ''' Check that attempting to specify the type of a DataTypeSymbol with an
    invalid type results in the expected error. '''
    sym = DataTypeSymbol("my_type", DeferredType())
    with pytest.raises(TypeError) as err:
        sym.datatype = "integer"
    assert ("datatype of a DataTypeSymbol must be specified using a "
            "DataType but got: 'str'" in str(err.value))
예제 #4
0
def test_create_struct_reference():
    ''' Tests for the _create_struct_reference() utility. '''
    one = Literal("1", INTEGER_TYPE)
    with pytest.raises(InternalError) as err:
        _create_struct_reference(None, StructureReference, Symbol("fake"),
                                 ["hello", 1], [])
    assert ("List of members must contain only strings or tuples but found "
            "entry of type 'int'" in str(err.value))
    with pytest.raises(NotImplementedError) as err:
        _create_struct_reference(None, StructureType, Symbol("fake"),
                                 ["hello"], [])
    assert "Cannot create structure reference for type '" in str(err.value)
    with pytest.raises(InternalError) as err:
        _create_struct_reference(None, StructureReference,
                                 DataSymbol("fake", DeferredType()), ["hello"],
                                 [one.copy()])
    assert ("Creating a StructureReference but array indices have been "
            "supplied" in str(err.value))
    with pytest.raises(InternalError) as err:
        _create_struct_reference(None, ArrayOfStructuresReference,
                                 DataSymbol("fake", DeferredType()), ["hello"],
                                 [])
    assert ("Cannot create an ArrayOfStructuresReference without one or more "
            "index expressions" in str(err.value))
    ref = _create_struct_reference(None, StructureReference,
                                   DataSymbol("fake", DeferredType()),
                                   ["hello"], [])
    assert isinstance(ref, StructureReference)
    assert isinstance(ref.member, Member)
    assert ref.member.name == "hello"
    # Check that we can create an ArrayOfStructuresReference and that any
    # PSyIR nodes are copied.
    idx_var = one.copy()
    idx_var2 = one.copy()
    aref = _create_struct_reference(None, ArrayOfStructuresReference,
                                    DataSymbol("fake", DeferredType()),
                                    ["a", ("b", [idx_var2])], [idx_var])
    assert isinstance(aref, ArrayOfStructuresReference)
    assert isinstance(aref.member, StructureMember)
    assert aref.member.name == "a"
    assert aref.member.member.name == "b"
    assert len(aref.member.member.indices) == 1
    assert aref.member.member.indices[0] is not idx_var2
    assert len(aref.indices) == 1
    assert aref.indices[0] is not idx_var
예제 #5
0
def test_arraytype_datatypesymbol():
    ''' Test that we can correctly create an ArrayType when the type of the
    elements is specified as a DataTypeSymbol. '''
    tsym = DataTypeSymbol("my_type", DeferredType())
    atype = ArrayType(tsym, [5])
    assert isinstance(atype, ArrayType)
    assert len(atype.shape) == 1
    assert atype.intrinsic is tsym
    assert atype.precision is None
예제 #6
0
def test_datatypesymbol_copy():
    ''' Check that a DataTypeSymbol can be copied. '''
    symbol = DataTypeSymbol("my_type", DeferredType(),
                            visibility=Symbol.Visibility.PRIVATE,
                            interface=UnresolvedInterface())
    new_symbol = symbol.copy()
    assert new_symbol is not symbol
    assert new_symbol.name == "my_type"
    assert isinstance(new_symbol.datatype, DeferredType)
    assert new_symbol.visibility == Symbol.Visibility.PRIVATE
    assert isinstance(new_symbol.interface, UnresolvedInterface)
예제 #7
0
def test_datasymbol_constant_value_setter_invalid():
    '''Test that a DataSymbol constant value setter raises the appropriate
    error if an invalid value and/or datatype are given.'''

    # Test with invalid constant values
    sym = DataSymbol('a', DeferredType())
    with pytest.raises(ValueError) as error:
        sym.constant_value = 1.0
    assert ("Error setting constant value for symbol 'a'. A DataSymbol with "
            "a constant value must be a scalar or an array but found "
            "'DeferredType'." in str(error.value))

    # Test with invalid constant expressions
    ct_expr = Return()
    with pytest.raises(ValueError) as error:
        _ = DataSymbol('a', INTEGER_SINGLE_TYPE, constant_value=ct_expr)
    assert "Error setting constant value for symbol 'a'. PSyIR static " \
        "expressions can only contain PSyIR literal, operation or reference" \
        " nodes but found:" in str(error.value)

    with pytest.raises(ValueError) as error:
        DataSymbol('a',
                   INTEGER_SINGLE_TYPE,
                   interface=ArgumentInterface(),
                   constant_value=9)
    assert ("Error setting constant value for symbol 'a'. A DataSymbol with "
            "an ArgumentInterface can not have a constant value."
            in str(error.value))

    with pytest.raises(ValueError) as error:
        DataSymbol('a', INTEGER_SINGLE_TYPE, constant_value=9.81)
    assert ("Error setting constant value for symbol 'a'. This DataSymbol "
            "instance datatype is 'Scalar<INTEGER, SINGLE>' which "
            "means the constant value is expected to be") in str(error.value)
    assert "'int'>' but found " in str(error.value)
    assert "'float'>'." in str(error.value)

    with pytest.raises(ValueError) as error:
        DataSymbol('a', CHARACTER_TYPE, constant_value=42)
    assert ("Error setting constant value for symbol 'a'. This DataSymbol "
            "instance datatype is 'Scalar<CHARACTER, UNDEFINED>' which "
            "means the constant value is expected to be") in str(error.value)
    assert "'str'>' but found " in str(error.value)
    assert "'int'>'." in str(error.value)

    with pytest.raises(ValueError) as error:
        DataSymbol('a', BOOLEAN_TYPE, constant_value="hello")
    assert ("Error setting constant value for symbol 'a'. This DataSymbol "
            "instance datatype is 'Scalar<BOOLEAN, UNDEFINED>' which "
            "means the constant value is expected to be") in str(error.value)
    assert "'bool'>' but found " in str(error.value)
    assert "'str'>'." in str(error.value)
예제 #8
0
def test_datasymbol_initialisation():
    '''Test that a DataSymbol instance can be created when valid arguments are
    given, otherwise raise relevant exceptions.'''

    # Test with valid arguments
    assert isinstance(DataSymbol('a', REAL_SINGLE_TYPE), DataSymbol)
    assert isinstance(DataSymbol('a', REAL_DOUBLE_TYPE), DataSymbol)
    assert isinstance(DataSymbol('a', REAL4_TYPE), DataSymbol)
    kind = DataSymbol('r_def', INTEGER_SINGLE_TYPE)
    real_kind_type = ScalarType(ScalarType.Intrinsic.REAL, kind)
    assert isinstance(DataSymbol('a', real_kind_type),
                      DataSymbol)
    # real constants are not currently supported
    assert isinstance(DataSymbol('a', INTEGER_SINGLE_TYPE), DataSymbol)
    assert isinstance(DataSymbol('a', INTEGER_DOUBLE_TYPE, constant_value=0),
                      DataSymbol)
    assert isinstance(DataSymbol('a', INTEGER4_TYPE),
                      DataSymbol)

    assert isinstance(DataSymbol('a', CHARACTER_TYPE), DataSymbol)
    assert isinstance(DataSymbol('a', CHARACTER_TYPE,
                                 constant_value="hello"), DataSymbol)
    assert isinstance(DataSymbol('a', BOOLEAN_TYPE), DataSymbol)
    assert isinstance(DataSymbol('a', BOOLEAN_TYPE,
                                 constant_value=False),
                      DataSymbol)
    array_type = ArrayType(REAL_SINGLE_TYPE, [ArrayType.Extent.ATTRIBUTE])
    assert isinstance(DataSymbol('a', array_type), DataSymbol)

    array_type = ArrayType(REAL_SINGLE_TYPE, [3])
    assert isinstance(DataSymbol('a', array_type), DataSymbol)
    array_type = ArrayType(REAL_SINGLE_TYPE, [3, ArrayType.Extent.ATTRIBUTE])
    assert isinstance(DataSymbol('a', array_type), DataSymbol)
    assert isinstance(DataSymbol('a', REAL_SINGLE_TYPE), DataSymbol)
    assert isinstance(DataSymbol('a', REAL8_TYPE), DataSymbol)
    dim = DataSymbol('dim', INTEGER_SINGLE_TYPE,
                     interface=UnresolvedInterface())
    array_type = ArrayType(REAL_SINGLE_TYPE, [Reference(dim)])
    assert isinstance(DataSymbol('a', array_type), DataSymbol)
    array_type = ArrayType(REAL_SINGLE_TYPE,
                           [3, Reference(dim), ArrayType.Extent.ATTRIBUTE])
    assert isinstance(DataSymbol('a', array_type), DataSymbol)
    assert isinstance(
        DataSymbol('a', REAL_SINGLE_TYPE,
                   interface=ArgumentInterface(
                       ArgumentInterface.Access.READWRITE)), DataSymbol)
    assert isinstance(
        DataSymbol('a', REAL_SINGLE_TYPE,
                   visibility=Symbol.Visibility.PRIVATE), DataSymbol)
    assert isinstance(DataSymbol('field', DataTypeSymbol("field_type",
                                                         DeferredType())),
                      DataSymbol)
예제 #9
0
def test_datasymbol_resolve_deferred(monkeypatch):
    ''' Test the datasymbol resolve_deferred method '''
    symbola = DataSymbol('a', INTEGER_SINGLE_TYPE)
    new_sym = symbola.resolve_deferred()
    # For a DataSymbol (unlike a Symbol), resolve_deferred should always
    # return the object on which it was called.
    assert new_sym is symbola
    module = ContainerSymbol("dummy_module")
    symbolb = DataSymbol('b', visibility=Symbol.Visibility.PRIVATE,
                         datatype=DeferredType(),
                         interface=GlobalInterface(module))
    # Monkeypatch the get_external_symbol() method so that it just returns
    # a new DataSymbol
    monkeypatch.setattr(symbolb, "get_external_symbol",
                        lambda: DataSymbol("b", INTEGER_SINGLE_TYPE))
    new_sym = symbolb.resolve_deferred()
    assert new_sym is symbolb
    assert new_sym.datatype == INTEGER_SINGLE_TYPE
    assert new_sym.visibility == Symbol.Visibility.PRIVATE
    assert isinstance(new_sym.interface, GlobalInterface)
예제 #10
0
    '''
    _, invoke_info = get_invoke("explicit_do.f90", api=API, idx=0)
    schedule = invoke_info.schedule
    assignments = schedule.walk(Assignment)
    assert len(assignments) == 1
    assignment = assignments[0]
    array_ref = assignment.lhs
    with pytest.raises(IndexError):
        _ = get_outer_index(array_ref)


@pytest.mark.parametrize(
    "datatype",
    [REAL_TYPE, ArrayType(INTEGER_TYPE, [10]),
     DeferredType()])
def test_loop_variable_name_error(datatype):
    '''Check that the expected exception is raised when the config file
    specifies a loop iteration name but it is already declared in the
    code as something that is not a scalar.

    '''
    _, 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("jk", datatype))
    with pytest.raises(TransformationError) as info:
        trans.apply(array_ref.children[2])
예제 #11
0
SCALAR_TYPE = ScalarType(ScalarType.Intrinsic.REAL, REAL_KIND)

# Derived-type definition in container
GRID_TYPE = StructureType.create([
    ("dx", SCALAR_TYPE, Symbol.Visibility.PUBLIC),
    ("dy", SCALAR_TYPE, Symbol.Visibility.PUBLIC)])
GRID_TYPE_SYMBOL = TypeSymbol("grid_type", GRID_TYPE)
CONTAINER_SYMBOL_TABLE.add(GRID_TYPE_SYMBOL)

# Kernel symbol table, symbols and scalar datatypes
SYMBOL_TABLE = SymbolTable()

CONT = ContainerSymbol("kernel_mod")
SYMBOL_TABLE.add(CONT)

DTYPE_SYMBOL = TypeSymbol("other_type", DeferredType(),
                          interface=GlobalInterface(CONT))
SYMBOL_TABLE.add(DTYPE_SYMBOL)

# Create the definition of the 'field_type'
FIELD_TYPE_DEF = StructureType.create(
    [("data", ArrayType(SCALAR_TYPE, [10]), Symbol.Visibility.PUBLIC),
     ("grid", GRID_TYPE_SYMBOL, Symbol.Visibility.PUBLIC),
     ("sub_meshes", ArrayType(GRID_TYPE_SYMBOL, [3]),
      Symbol.Visibility.PUBLIC),
     ("flag", INTEGER4_TYPE, Symbol.Visibility.PUBLIC)])
FIELD_TYPE_SYMBOL = TypeSymbol("field_type", FIELD_TYPE_DEF)
CONTAINER_SYMBOL_TABLE.add(FIELD_TYPE_SYMBOL)

# Create an argument of this derived type. At this point we know only that
# DTYPE_SYMBOL refers to a type defined in the CONT container.
예제 #12
0
def test_deferredtype_str():
    '''Test that the DeferredType class str method works as expected.'''
    data_type = DeferredType()
    assert str(data_type) == "DeferredType"
예제 #13
0
def test_deferredtype():
    '''Test that the DeferredType class can be created successfully.'''
    assert isinstance(DeferredType(), DeferredType)
예제 #14
0
    def create(cls, children, symbol_table, ast=None, options=None):
        '''
        Creates a new (sub-class of a) PSyData node with the supplied
        'children' nodes as its children. The symbols used by the PSyData API
        are added to the supplied symbol table. This is a class method so that
        it acts as a factory for the various sub-classes of PSyDataNode.

        :param children: the PSyIR nodes that will become children of the \
            new PSyData node.
        :type children: list of :py:class:`psyclone.psyir.nodes.Node`
        :param symbol_table: the associated SymbolTable to which symbols \
            must be added.
        :type symbol_table: :py:class:`psyclone.psyir.symbols.SymbolTable`
        :parent ast: reference to fparser2 parse tree for the routine being \
            instrumented with PSyData calls.
        :type ast: :py:class:`fparser.two.Fortran2003.Base`
        :param options: a dictionary with options for transformations.
        :type options: dictionary of string:values or None
        :param str options[prefix"]: a prefix to use for the PSyData module \
            name (``prefix_psy_data_mod``) and the PSyDataType \
            (``prefix_PSyDataType``) - a "_" will be added automatically. \
            It defaults to "", which means the module name used will just be \
            ``psy_data_mod``, and the data type ``PSyDataType``.
        :param (str,str) options["region_name"]: an optional name to use for \
            this PSyDataNode, provided as a 2-tuple containing a module name \
            followed by a local name. The pair of strings should uniquely \
             identify a region unless aggregate information is required \
            (and is supported by the runtime library).

        :raises TypeError: if the supplied children or symbol table are not \
            of the correct type.

        '''
        if not isinstance(children, list):
            raise TypeError("Error in PSyDataNode.create(). The 'children' "
                            "argument must be a list (of PSyIR nodes) but got "
                            "'{0}'".format(type(children).__name__))
        if children and not all(isinstance(child, Node) for child in children):
            raise TypeError(
                "Error in PSyDataNode.create(). The 'children' argument must "
                "be a list of PSyIR nodes but it contains: {0}".format(
                    [type(child).__name__ for child in children]))
        if not isinstance(symbol_table, SymbolTable):
            raise TypeError(
                "Error in PSyDataNode.create(). The 'symbol_table' argument "
                "must be an instance of psyir.symbols.SymbolTable but got "
                "'{0}'.".format(type(symbol_table).__name__))

        data_node = cls(ast=ast, options=options)

        # Ensure that we have a container symbol for the API access
        try:
            csym = symbol_table.lookup_with_tag(data_node.fortran_module)
        except KeyError:
            # The tag doesn't exist which means that we haven't already added
            # this Container as part of a PSyData transformation.
            csym = ContainerSymbol(data_node.fortran_module)
            symbol_table.add(csym, tag=data_node.fortran_module)

        # A PSyData node always contains a Schedule
        # TODO 435 we can probably get rid of _insert_schedule() once we
        # do away with the ast argument?
        # pylint: disable=protected-access
        sched = data_node._insert_schedule(children=children, ast=ast)
        data_node.addchild(sched)

        # The use statement that will be inserted by the update() method. Any
        # use of a module of the same name that doesn't match this will result
        # in a NotImplementedError at code-generation time.
        # TODO #435 remove this when removing the update() method
        data_node.use_stmt = "use {0}, only: ".format(
            data_node.fortran_module) + ", ".join(symbol.name for symbol in
                                                  data_node.imported_symbols)
        # Add the symbols that will be imported from the module. Use the
        # PSyData names as tags to ensure we don't attempt to add them more
        # than once if multiple transformations are applied.
        for sym in data_node.imported_symbols:
            symbol_table.symbol_from_tag(sym.name, symbol_type=sym.symbol_type,
                                         interface=GlobalInterface(csym),
                                         datatype=DeferredType())

        # Store the name of the PSyData variable that is used for this
        # PSyDataNode. This allows the variable name to be shown in str
        # (and also, calling create_name in gen() would result in the name
        # being changed every time gen() is called).
        data_node._var_name = symbol_table.next_available_name(
            data_node._psy_data_symbol_with_prefix)
        psydata_type = UnknownFortranType(
            "type({0}), save, target :: {1}".format(data_node.type_name,
                                                    data_node._var_name))
        symbol_table.new_symbol(data_node._var_name, symbol_type=DataSymbol,
                                datatype=psydata_type)
        return data_node