コード例 #1
0
def test_redundant_empty_only_list():
    ''' Check that we drop 'use's with an empty only list if they become
    redundant. #TODO #11 Check for appropriate logging messages here once
    logging is implemented. '''
    fake_parent = KernelSchedule("dummy_schedule")
    processor = Fparser2Reader()
    # Empty only-list followed by wildcard import
    reader = FortranStringReader("use mod1, only:\n" "use mod1\n")
    fparser2spec = Fortran2003.Specification_Part(reader)
    processor.process_declarations(fake_parent, fparser2spec.content, [])
    csym = fake_parent.symbol_table.lookup("mod1")
    assert csym.wildcard_import
    # Wildcard import followed by empty only-list
    reader = FortranStringReader("use mod2\n" "use mod2, only:\n")
    fparser2spec = Fortran2003.Specification_Part(reader)
    processor.process_declarations(fake_parent, fparser2spec.content, [])
    csym = fake_parent.symbol_table.lookup("mod2")
    assert csym.wildcard_import
    # Empty only-list followed by named import
    reader = FortranStringReader("use mod3, only:\n" "use mod3, only: fred\n")
    fparser2spec = Fortran2003.Specification_Part(reader)
    processor.process_declarations(fake_parent, fparser2spec.content, [])
    sym_table = fake_parent.symbol_table
    csym = sym_table.lookup("mod3")
    assert not csym.wildcard_import
    assert sym_table.imported_symbols(csym)[0].name == "fred"
    # Named import followed by empty only-list
    reader = FortranStringReader("use mod4, only: bob\n" "use mod4, only:\n")
    fparser2spec = Fortran2003.Specification_Part(reader)
    processor.process_declarations(fake_parent, fparser2spec.content, [])
    csym = sym_table.lookup("mod4")
    assert not csym.wildcard_import
    assert sym_table.imported_symbols(csym)[0].name == "bob"
コード例 #2
0
def test_parse_derived_type(use_stmt, type_name):
    ''' Check that the fronted correctly creates a DataTypeSymbol of type
    StructureType from the declaration of a derived type. '''
    fake_parent = KernelSchedule("dummy_schedule")
    symtab = fake_parent.symbol_table
    processor = Fparser2Reader()
    reader = FortranStringReader("{0}\n"
                                 "type :: my_type\n"
                                 "  integer :: flag\n"
                                 "  type({1}), private :: grid\n"
                                 "  real, dimension(3) :: posn\n"
                                 "end type my_type\n"
                                 "type(my_type) :: var\n".format(
                                     use_stmt, type_name))
    fparser2spec = Fortran2003.Specification_Part(reader)
    processor.process_declarations(fake_parent, fparser2spec.content, [])
    sym = symtab.lookup("my_type")
    assert isinstance(sym, DataTypeSymbol)
    assert isinstance(sym.datatype, StructureType)
    flag = sym.datatype.lookup("flag")
    assert isinstance(flag.datatype, ScalarType)
    assert flag.visibility == Symbol.Visibility.PUBLIC
    grid = sym.datatype.lookup("grid")
    assert isinstance(grid.datatype, DataTypeSymbol)
    assert isinstance(grid.datatype.datatype, DeferredType)
    assert grid.visibility == Symbol.Visibility.PRIVATE
    posn = sym.datatype.lookup("posn")
    assert isinstance(posn.datatype, ArrayType)
    var = symtab.lookup("var")
    assert var.datatype is sym
コード例 #3
0
def test_multi_use_stmt():
    ''' Check that we handle the case where different symbols are imported
    from a module in separate USE statements. '''
    fake_parent = KernelSchedule("dummy_schedule")
    processor = Fparser2Reader()
    reader = FortranStringReader("use my_mod, only: some_var\n"
                                 "use this_mod\n"
                                 "use my_mod, only: var1, var2\n"
                                 "use this_mod, only: var3\n")
    fparser2spec = Fortran2003.Specification_Part(reader)
    processor.process_declarations(fake_parent, fparser2spec.content, [])
    symtab = fake_parent.symbol_table
    csymbols = symtab.containersymbols
    # Although there are 4 use statements, there are only 2 modules
    assert len(csymbols) == 2
    my_mod = symtab.lookup("my_mod")
    assert not my_mod.wildcard_import
    # Check that we have accumulated all imports
    import_list = symtab.imported_symbols(my_mod)
    assert len(import_list) == 3
    names = [sym.name for sym in import_list]
    assert sorted(names) == ["some_var", "var1", "var2"]
    this_mod = symtab.lookup("this_mod")
    assert this_mod.wildcard_import
    names = [sym.name for sym in symtab.imported_symbols(this_mod)]
    assert names == ["var3"]
コード例 #4
0
def test_use_stmt():
    ''' Check that SymbolTable entries are correctly created from
    module use statements. '''
    fake_parent = KernelSchedule("dummy_schedule")
    processor = Fparser2Reader()
    reader = FortranStringReader("use my_mod, only: some_var\n"
                                 "use this_mod\n"
                                 "use other_mod, only: var1, var2\n")
    fparser2spec = Fortran2003.Specification_Part(reader)
    processor.process_declarations(fake_parent, fparser2spec.content, [])

    symtab = fake_parent.symbol_table

    for module_name in ["my_mod", "this_mod", "other_mod"]:
        container = symtab.lookup(module_name)
        assert isinstance(container, ContainerSymbol)
        assert container.name == module_name
        # Container reference is not updated until explicitly requested
        assert not container._reference

    for var in ["some_var", "var1", "var2"]:
        assert symtab.lookup(var).name == var

    assert symtab.lookup("some_var").interface.container_symbol \
        == symtab.lookup("my_mod")
    assert symtab.lookup("var2").interface.container_symbol \
        == symtab.lookup("other_mod")
コード例 #5
0
def test_missing_derived_type():
    ''' Check that the fronted raises an error if it encounters a variable
    of a derived type that cannot be resolved. '''
    fake_parent = KernelSchedule("dummy_schedule")
    processor = Fparser2Reader()
    reader = FortranStringReader("type(my_type) :: var")
    fparser2spec = Fortran2003.Specification_Part(reader)
    # This should raise an error because there's no Container from which
    # the definition of 'my_type' can be brought into scope.
    with pytest.raises(SymbolError) as err:
        processor.process_declarations(fake_parent, fparser2spec.content, [])
    assert "No Symbol found for name 'my_type'" in str(err.value)
コード例 #6
0
def test_use_no_only_list():
    ''' Check that we create the correct Symbol Table entry for a use
    statement that has an 'only' clause but no list of imported symbols. '''
    fake_parent = KernelSchedule("dummy_schedule")
    processor = Fparser2Reader()
    reader = FortranStringReader("use my_mod, only: some_var\n"
                                 "use some_mod, only:\n")
    fparser2spec = Fortran2003.Specification_Part(reader)
    processor.process_declarations(fake_parent, fparser2spec.content, [])
    some_mod = fake_parent.symbol_table.lookup("some_mod")
    assert not some_mod.wildcard_import
    assert fake_parent.symbol_table.imported_symbols(some_mod) == []
コード例 #7
0
def test_name_clash_use_stmt():
    ''' Check that we raise the expected error if we encounter a module
    with a name that's already taken in the Symbol Table. This is invalid
    Fortran but we need to test the error-handling in PSyclone. '''
    fake_parent = KernelSchedule("dummy_schedule")
    processor = Fparser2Reader()
    reader = FortranStringReader("use my_mod, only: some_var\n"
                                 "use some_var, only: var1, var2\n")
    fparser2spec = Fortran2003.Specification_Part(reader)
    with pytest.raises(SymbolError) as err:
        processor.process_declarations(fake_parent, fparser2spec.content, [])
    assert "Found a USE of module 'some_var' but the symbol" in str(err.value)
コード例 #8
0
def test_broken_use(monkeypatch):
    ''' Check that we raise the expected error if we encounter an unrecognised
    parse tree for a USE statement. '''
    fake_parent = KernelSchedule("dummy_schedule")
    processor = Fparser2Reader()
    reader = FortranStringReader("use some_mod, only:\n")
    fparser2spec = Fortran2003.Specification_Part(reader)
    # Break the parse tree so that instead of ", ONLY:" it has "hello"
    monkeypatch.setattr(
        fparser2spec.content[0], "items",
        [None, None, Fortran2003.Name('my_mod'), 'hello', None])
    with pytest.raises(NotImplementedError) as err:
        processor.process_declarations(fake_parent, fparser2spec.content, [])
    assert "unsupported USE statement: 'USE my_modhello'" in str(err.value)
コード例 #9
0
def test_use_stmt_error(monkeypatch):
    ''' Check that we raise the expected error if the parse tree representing
    a USE statement doesn't have the expected structure. '''
    fake_parent = KernelSchedule("dummy_schedule")
    processor = Fparser2Reader()
    reader = FortranStringReader("use my_mod, only: some_var\n"
                                 "use this_mod\n"
                                 "use other_mod, only: var1, var2\n")
    fparser2spec = Fortran2003.Specification_Part(reader)
    monkeypatch.setattr(fparser2spec.content[0], "items",
                        [None, "hello", None])
    with pytest.raises(GenerationError) as err:
        processor.process_declarations(fake_parent, fparser2spec.content, [])
    assert ("Expected the parse tree for a USE statement to contain 5 items "
            "but found 3 for 'hello'" in str(err.value))
コード例 #10
0
def test_deferred_derived_type(type_name):
    ''' Check that we get a symbol with a type given by a DataTypeSymbol (which
    itself is of DeferredType) for a declaration using an unresolved derived
    type. '''
    fake_parent = KernelSchedule("dummy_schedule")
    symtab = fake_parent.symbol_table
    processor = Fparser2Reader()
    reader = FortranStringReader("use my_mod\n"
                                 "type({0}) :: var".format(type_name))
    fparser2spec = Fortran2003.Specification_Part(reader)
    processor.process_declarations(fake_parent, fparser2spec.content, [])
    vsym = symtab.lookup("var")
    assert isinstance(vsym.datatype, DataTypeSymbol)
    assert isinstance(vsym.datatype.datatype, DeferredType)
    tsym = symtab.lookup("my_type")
    assert isinstance(tsym, DataTypeSymbol)
コード例 #11
0
def test_use_local_symbol_error():
    ''' Check that we raise the expected error if we encounter an import of
    a symbol that is already declared to be local. '''
    from psyclone.psyir.symbols import DataSymbol, LocalInterface, \
        INTEGER_SINGLE_TYPE
    fake_parent = KernelSchedule("dummy_schedule")
    # In practise this situation is hard to trigger as USE statements must
    # come before local declarations. Therefore we manually add a symbol
    # to the table first.
    fake_parent.symbol_table.add(
        DataSymbol("fred", INTEGER_SINGLE_TYPE, interface=LocalInterface()))
    processor = Fparser2Reader()
    reader = FortranStringReader("use mod2, only: fred\n")
    fparser2spec = Fortran2003.Specification_Part(reader)
    with pytest.raises(SymbolError) as err:
        processor.process_declarations(fake_parent, fparser2spec.content, [])
    assert "'fred' is imported from module 'mod2' but is" in str(err.value)
コード例 #12
0
def test_derived_type_self_ref(type_name):
    ''' Test that we can parse a derived type that contains a pointer
    reference of that same type. The 'pointer' attribute is not supported
    so we get a DataTypeSymbol of UnknownFortranType. '''
    fake_parent = KernelSchedule("dummy_schedule")
    symtab = fake_parent.symbol_table
    processor = Fparser2Reader()
    reader = FortranStringReader("type :: my_type\n"
                                 "  type({0}), pointer :: next => null()\n"
                                 "  integer :: flag\n"
                                 "end type my_type\n"
                                 "type({0}) :: var\n".format(type_name))
    fparser2spec = Fortran2003.Specification_Part(reader)
    processor.process_declarations(fake_parent, fparser2spec.content, [])
    sym = symtab.lookup("my_type")
    assert isinstance(sym, DataTypeSymbol)
    assert isinstance(sym.datatype, UnknownFortranType)
    assert symtab.lookup("var").datatype is sym
コード例 #13
0
def test_use_same_symbol():
    ''' Check that we handle the case where the same symbol is imported from
    different modules.
    #TODO #11 Once logging is added, check that we log an appropriate
    warning for this case.
    '''
    fake_parent = KernelSchedule("dummy_schedule")
    processor = Fparser2Reader()
    reader = FortranStringReader("use mod2, only: fred\n"
                                 "use mod3, only: fred\n")
    fparser2spec = Fortran2003.Specification_Part(reader)
    processor.process_declarations(fake_parent, fparser2spec.content, [])
    csym = fake_parent.symbol_table.lookup("mod2")
    assert fake_parent.symbol_table.imported_symbols(csym)[0].name == "fred"
    csym = fake_parent.symbol_table.lookup("mod3")
    # mod3 will have an empty list of symbols as 'fred' is already imported
    # from mod2.
    assert not fake_parent.symbol_table.imported_symbols(csym)
コード例 #14
0
def test_derived_type_accessibility():
    '''
    Check that accessibility statements/attributes within a derived type
    are handled correctly.
    '''
    fake_parent = KernelSchedule("dummy_schedule")
    symtab = fake_parent.symbol_table
    processor = Fparser2Reader()
    reader = FortranStringReader("type :: my_type\n"
                                 "  private\n"
                                 "  integer :: flag\n"
                                 "  real, public :: scale\n"
                                 "end type my_type\n")
    fparser2spec = Fortran2003.Specification_Part(reader)
    processor.process_declarations(fake_parent, fparser2spec.content, [])
    sym = symtab.lookup("my_type")
    assert isinstance(sym, DataTypeSymbol)
    flag = sym.datatype.lookup("flag")
    assert flag.visibility == Symbol.Visibility.PRIVATE
    scale = sym.datatype.lookup("scale")
    assert scale.visibility == Symbol.Visibility.PUBLIC