Exemple #1
0
def test_imp_none_in_subroutine():
    ''' test that implicit none can be added to a subroutine '''
    module = ModuleGen(name="testmodule")
    subroutine = SubroutineGen(module, name="testsubroutine")
    module.add(subroutine)
    subroutine.add(ImplicitNoneGen(subroutine))
    assert 'IMPLICIT NONE' in str(subroutine.root)
Exemple #2
0
def test_progunitgen_multiple_generic_use():
    '''Check that we correctly handle the case where duplicate use statements
    are added'''
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsubroutine")
    module.add(sub)
    sub.add(UseGen(sub, name="fred"))
    sub.add(UseGen(sub, name="fred"))
    assert count_lines(sub.root, "USE fred") == 1
Exemple #3
0
def test_imp_none_in_subroutine_already_exists():
    ''' test that implicit none is not added to a subroutine when
    one already exists'''
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsubroutine", implicitnone=True)
    module.add(sub)
    sub.add(ImplicitNoneGen(sub))
    count = count_lines(sub.root, "IMPLICIT NONE")
    assert count == 1, \
        "There should only be one instance of IMPLICIT NONE"
Exemple #4
0
def test_imp_none_exception_if_wrong_parent():
    ''' test that an exception is thrown if implicit none is added
    and the parent is not a module or a subroutine '''
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsubroutine")
    module.add(sub)
    dogen = DoGen(sub, "i", "1", "10")
    sub.add(dogen)
    with pytest.raises(Exception):
        dogen.add(ImplicitNoneGen(dogen))
Exemple #5
0
def test_typedeclgen_names():
    ''' Check that the names method of TypeDeclGen works as expected '''
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsubroutine")
    module.add(sub)
    dgen = TypeDeclGen(sub, datatype="my_type", entity_decls=["type1"])
    sub.add(dgen)
    names = dgen.names
    assert len(names) == 1
    assert names[0] == "type1"
Exemple #6
0
def test_do_loop_with_increment():
    ''' Test that we correctly generate code for a do loop with
    non-unit increment '''
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsub")
    module.add(sub)
    dogen = DoGen(sub, "it", "1", "10", step="2")
    sub.add(dogen)
    count = count_lines(sub.root, "DO it=1,10,2")
    assert count == 1
Exemple #7
0
def test_basegen_previous_loop_no_loop():
    '''Check that we raise an error when requesting the position of the
    previous loop if we don't have a loop '''
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsubroutine")
    module.add(sub)
    # Request the position of the last loop
    # even though we haven't got one
    with pytest.raises(RuntimeError) as err:
        sub.previous_loop()
    assert "no loop found - there is no previous loop" in str(err)
Exemple #8
0
def test_basegen_last_declaration_no_vars():
    '''Check that we raise an error when requesting the position of the
    last variable declaration if we don't have any variables'''
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsubroutine")
    module.add(sub)
    # Request the position of the last variable declaration
    # even though we haven't got any
    with pytest.raises(RuntimeError) as err:
        sub.last_declaration()
    assert "no variable declarations found" in str(err)
Exemple #9
0
def test_adduse_default_funcnames():
    ''' Test that the adduse module method works correctly when we do
    not specify a list of funcnames '''
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsubroutine")
    module.add(sub)
    call = CallGen(sub, name="testcall", args=["a", "b"])
    sub.add(call)
    from psyclone.f2pygen import adduse
    adduse("fred", call.root)
    gen = str(sub.root)
    expected = ("    SUBROUTINE testsubroutine()\n" "      USE fred\n")
    assert expected in gen
Exemple #10
0
def test_imp_none_in_subroutine_with_use_and_decs():
    ''' test that implicit none is added after any use statements
    and before any declarations in a subroutine when auto (the
    default) is used for insertion'''
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsubroutine")
    module.add(sub)
    sub.add(DeclGen(sub, datatype="integer", entity_decls=["var1"]))
    sub.add(TypeDeclGen(sub, datatype="my_type", entity_decls=["type1"]))
    sub.add(UseGen(sub, "fred"))
    sub.add(ImplicitNoneGen(sub))
    in_idx = line_number(sub.root, "IMPLICIT NONE")
    assert in_idx == 2
Exemple #11
0
def test_adduse():
    ''' Test that the adduse module method works correctly when we use a
    call object as our starting point '''
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsubroutine")
    module.add(sub)
    call = CallGen(sub, name="testcall", args=["a", "b"])
    sub.add(call)
    from psyclone.f2pygen import adduse
    adduse("fred", call.root, only=True, funcnames=["astaire"])
    gen = str(sub.root)
    expected = ("    SUBROUTINE testsubroutine()\n"
                "      USE fred, ONLY: astaire\n")
    assert expected in gen
Exemple #12
0
def test_typeselectiongen():
    ''' Check that SelectionGen works as expected for a type '''
    from psyclone.f2pygen import SelectionGen
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsubroutine")
    module.add(sub)
    sgen = SelectionGen(sub, expr="my_var=>another_var", typeselect=True)
    sub.add(sgen)
    agen = AssignGen(sgen, lhs="happy", rhs=".TRUE.")
    sgen.addcase("fspace", [agen])
    sgen.adddefault()
    gen = str(sub.root)
    print gen
    assert "SELECT TYPE ( my_var=>another_var )" in gen
    assert "TYPE IS ( fspace )" in gen
Exemple #13
0
def test_subroutine_var_with_implicit_none():
    ''' test that a variable is added after an implicit none
    statement in a subroutine'''
    module = ModuleGen(name="testmodule")
    subroutine = SubroutineGen(module,
                               name="testsubroutine",
                               implicitnone=True)
    module.add(subroutine)
    subroutine.add(
        DeclGen(subroutine, datatype="integer", entity_decls=["var1"]))
    idx_var = line_number(subroutine.root, "INTEGER var1")
    idx_imp_none = line_number(subroutine.root, "IMPLICIT NONE")
    print str(module.root)
    assert idx_var - idx_imp_none == 1, \
        "variable declation must be after implicit none"
Exemple #14
0
def test_do_loop_add_after():
    ''' Test that we correctly generate code for a do loop when adding a
    child to it with position *after* '''
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsub")
    module.add(sub)
    dogen = DoGen(sub, "it", "1", "10", step="2")
    sub.add(dogen)
    assign1 = AssignGen(dogen, lhs="happy", rhs=".TRUE.")
    dogen.add(assign1)
    assign2 = AssignGen(dogen, lhs="sad", rhs=".FALSE.")
    dogen.add(assign2, position=["before", assign1.root])
    a1_line = line_number(sub.root, "happy = ")
    a2_line = line_number(sub.root, "sad = ")
    assert a1_line > a2_line
Exemple #15
0
def test_lfricfields_stub_err():
    ''' Check that the LFRicFields constructor raises the expected internal
    error if it encounters an unrecognised intrinsic type of a field
    argument when generating a kernel stub.

    '''
    fparser.logging.disable(fparser.logging.CRITICAL)
    ast = fpapi.parse(FIELD_CODE, ignore_comments=False)
    metadata = DynKernMetadata(ast)
    kernel = DynKern()
    kernel.load_meta(metadata)
    # Create an empty Kernel stub module and subroutine objects
    psy_module = ModuleGen("testkern_2qr_int_field_mod")
    sub_stub = SubroutineGen(psy_module,
                             name="testkern_2qr_int_field_code",
                             implicitnone=True)
    # Sabotage the field argument to make it have an invalid intrinsic type
    fld_arg = kernel.arguments.args[1]
    fld_arg.descriptor._data_type = "gh_invalid_type"
    print(fld_arg.descriptor._data_type)
    with pytest.raises(InternalError) as err:
        LFRicFields(kernel)._stub_declarations(sub_stub)
    assert ("Found an unsupported data type 'gh_invalid_type' in "
            "kernel stub declarations for the field argument 'field_2'. "
            "Supported types are {0}.".format(
                LFRicArgDescriptor.VALID_FIELD_DATA_TYPES) in str(err.value))
Exemple #16
0
def test_selectiongen_addcase():
    ''' Check that SelectionGen.addcase() works as expected when no
    content is supplied'''
    from psyclone.f2pygen import SelectionGen
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsubroutine")
    module.add(sub)
    sgen = SelectionGen(sub, expr="my_var")
    sub.add(sgen)
    sgen.addcase("1")
    gen = str(sub.root)
    print gen
    expected = ("      SELECT CASE ( my_var )\n"
                "        CASE ( 1 )\n"
                "      END SELECT")
    assert expected in gen
Exemple #17
0
def test_subgen_implicit_none_default():
    ''' test that implicit none is not added to the subroutine by
    default '''
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsubroutine")
    module.add(sub)
    count = count_lines(sub.root, "IMPLICIT NONE")
    assert count == 0, "IMPLICIT NONE SHOULD NOT EXIST BY DEFAULT"
Exemple #18
0
def test_subgen_implicit_none_false():
    ''' test that implicit none is not added to the subroutine if
    not requested '''
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsubroutine", implicitnone=False)
    module.add(sub)
    count = count_lines(sub.root, "IMPLICIT NONE")
    assert count == 0, "IMPLICIT NONE SHOULD NOT EXIST"
Exemple #19
0
def test_subgen_implicit_none_true():
    ''' test that implicit none is added to the subroutine if
    requested '''
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsubroutine", implicitnone=True)
    module.add(sub)
    count = count_lines(sub.root, "IMPLICIT NONE")
    assert count == 1, "IMPLICIT NONE SHOULD EXIST"
Exemple #20
0
def test_declgen_wrong_type():
    ''' Check that we raise an appropriate error if we attempt to create
    a DeclGen for an unsupported type '''
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsubroutine")
    module.add(sub)
    with pytest.raises(RuntimeError) as err:
        _ = DeclGen(sub, datatype="complex", entity_decls=["rvar1"])
    assert "Only integer and real are currently supported" in str(err)
Exemple #21
0
 def gen_code(self, parent):
     ''' Generates Dynamo specific invocation code (the subroutine called
         by the associated invoke call in the algorithm layer). This
         consists of the PSy invocation subroutine and the declaration of
         its arguments.'''
     from psyclone.f2pygen import SubroutineGen, TypeDeclGen
     # create the subroutine
     invoke_sub = SubroutineGen(parent,
                                name=self.name,
                                args=self.psy_unique_var_names)
     self.schedule.gen_code(invoke_sub)
     parent.add(invoke_sub)
     # add the subroutine argument declarations
     my_typedecl = TypeDeclGen(invoke_sub,
                               datatype="field_type",
                               entity_decls=self.psy_unique_var_names,
                               intent="inout")
     invoke_sub.add(my_typedecl)
Exemple #22
0
def test_typedeclgen_missing_names():
    ''' Check that we raise an error if we attempt to create TypeDeclGen
    without naming the variables '''
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsubroutine")
    module.add(sub)
    with pytest.raises(RuntimeError) as err:
        _ = TypeDeclGen(sub, datatype="my_type")
    assert ("Cannot create a declaration of a derived-type variable "
            "without specifying" in str(err))
Exemple #23
0
def test_declgen_missing_names():
    ''' Check that we raise an error if we attempt to create a DeclGen
    without naming the variable(s) '''
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsubroutine")
    module.add(sub)
    with pytest.raises(RuntimeError) as err:
        _ = DeclGen(sub, datatype="integer")
    assert ("Cannot create a variable declaration without specifying "
            "the name" in str(err))
Exemple #24
0
def test_modulegen_add_wrong_parent():
    ''' Check that attempting to add an object to a ModuleGen fails
    if the object's parent is not that ModuleGen '''
    module = ModuleGen(name="testmodule")
    module_wrong = ModuleGen(name="another_module")
    sub = SubroutineGen(module_wrong, name="testsubroutine")
    with pytest.raises(RuntimeError) as err:
        module.add(sub)
    print str(err)
    assert "because it is not a descendant of it or of any of" in str(err)
Exemple #25
0
def test_basegen_start_parent_loop_dbg(capsys):
    '''Check the debug option to the start_parent_loop method'''
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsubroutine")
    module.add(sub)
    loop = DoGen(sub, "it", "1", "10")
    sub.add(loop)
    call = CallGen(loop, "testcall")
    loop.add(call)
    call.start_parent_loop(debug=True)
    out, _ = capsys.readouterr()
    print out
    expected = ("Parent is a do loop so moving to the parent\n"
                "The type of the current node is now <class "
                "'fparser.one.block_statements.Do'>\n"
                "The type of parent is <class "
                "'fparser.one.block_statements.Subroutine'>\n"
                "Finding the loops position in its parent ...\n"
                "The loop's index is  0\n")
    assert expected in out
Exemple #26
0
def test_basegen_append_default():
    ''' Check if no position argument is supplied to BaseGen.add() then it
    defaults to appending '''
    from psyclone.f2pygen import BaseGen
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsubroutine")
    module.add(sub)
    BaseGen.add(sub, DeclGen(sub, datatype="integer", entity_decls=["var1"]))
    BaseGen.add(sub, CommentGen(sub, " hello"))
    cindex = line_number(sub.root, "hello")
    assert cindex == 3
Exemple #27
0
def test_selectiongen():
    ''' Check that SelectionGen works as expected '''
    from psyclone.f2pygen import SelectionGen
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsubroutine")
    module.add(sub)
    sgen = SelectionGen(sub, expr="my_var")
    sub.add(sgen)
    agen = AssignGen(sgen, lhs="happy", rhs=".TRUE.")
    sgen.addcase("1", [agen])
    # TODO how do we specify what happens in the default case?
    sgen.adddefault()
    gen = str(sub.root)
    print gen
    expected = ("SELECT CASE ( my_var )\n"
                "CASE ( 1 )\n"
                "        happy = .TRUE.\n"
                "CASE DEFAULT\n"
                "      END SELECT")
    assert expected in gen
    assert False
Exemple #28
0
def test_adduse_empty_only():
    ''' Test that the adduse module method works correctly when we specify
    that we want it to be specific but then don't provide a list of
    entities for the only qualifier '''
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsubroutine")
    module.add(sub)
    from psyclone.f2pygen import adduse
    # Add a use statement with only=True but an empty list of entities
    adduse("fred", sub.root, only=True, funcnames=[])
    assert count_lines(sub.root, "USE fred") == 1
    assert count_lines(sub.root, "USE fred, only") == 0
Exemple #29
0
 def gen_code(self, parent):
     ''' Generates GOcean specific invocation code (the subroutine called
         by the associated invoke call in the algorithm layer). This
         consists of the PSy invocation subroutine and the declaration of
         its arguments.'''
     from psyclone.f2pygen import SubroutineGen, DeclGen, TypeDeclGen
     # create the subroutine
     invoke_sub = SubroutineGen(parent, name=self.name,
                                args=self.psy_unique_var_names)
     parent.add(invoke_sub)
     self.schedule.gen_code(invoke_sub)
     # add the subroutine argument declarations for arrays
     if len(self.unique_args_arrays) > 0:
         my_decl_arrays = DeclGen(invoke_sub, datatype="REAL",
                                  intent="inout", kind="go_wp",
                                  entity_decls=self.unique_args_arrays,
                                  dimension=":,:")
         invoke_sub.add(my_decl_arrays)
     # add the subroutine argument declarations for scalars
     if len(self.unique_args_scalars) > 0:
         my_decl_scalars = \
             TypeDeclGen(invoke_sub,
                         datatype="scalar_field_type",
                         entity_decls=self.unique_args_scalars,
                         intent="inout")
         invoke_sub.add(my_decl_scalars)
Exemple #30
0
def test_basegen_start_parent_loop_omp_end_dbg(capsys):
    '''Check the debug option to the start_parent_loop method when we have
    an OpenMP end directive'''
    module = ModuleGen(name="testmodule")
    sub = SubroutineGen(module, name="testsubroutine")
    module.add(sub)
    dgen = DirectiveGen(sub, "omp", "end", "do", "")
    sub.add(dgen)
    loop = DoGen(sub, "it", "1", "10")
    sub.add(loop)
    call = CallGen(loop, "testcall")
    loop.add(call)
    call.start_parent_loop(debug=True)
    out, _ = capsys.readouterr()
    print out
    expected = ("Parent is a do loop so moving to the parent\n"
                "The type of the current node is now <class "
                "'fparser.one.block_statements.Do'>\n"
                "The type of parent is <class "
                "'fparser.one.block_statements.Subroutine'>\n"
                "Finding the loops position in its parent ...\n"
                "The loop's index is  1\n"
                "The type of the object at the index is <class "
                "'fparser.one.block_statements.Do'>\n"
                "If preceding node is a directive then move back one\n"
                "preceding node is a directive so find out what type ...\n")

    assert expected in out