Exemple #1
0
def test_use_mixed_case(f2003_create):
    '''Check that a use statement with mixed case keywords ('use' and
    'only') works as expected.

    '''
    line = "UsE my_model, OnLy: name"
    ast = Use_Stmt(line)
    assert "USE my_model, ONLY: name" in str(ast)
    assert repr(ast) == ("Use_Stmt(None, None, Name('my_model'), ', ONLY:', "
                         "Name('name'))")
Exemple #2
0
def test_use_spaces_2(f2003_create):
    '''Check that a use statement with spaces works correctly with an only
    clause.

    '''
    line = "  use  ,  intrinsic  ::  my_model  ,  only  :  name  "
    ast = Use_Stmt(line)
    assert "USE, INTRINSIC :: my_model, ONLY: name" in str(ast)
    assert repr(ast) == ("Use_Stmt(Module_Nature('INTRINSIC'), '::', "
                         "Name('my_model'), ', ONLY:', Name('name'))")
Exemple #3
0
def test_use_only_empty(f2003_create):
    '''Check that a use statement is parsed correctly when there is an
    only clause without any content.

    '''
    line = "use my_model, only:"
    ast = Use_Stmt(line)
    assert "USE my_model, ONLY:" in str(ast)
    assert repr(ast) == (
        "Use_Stmt(None, None, Name('my_model'), ', ONLY:', None)")
Exemple #4
0
def test_use_spaces_1(f2003_create):
    '''Check that a use statement with spaces works correctly with
    renaming.

    '''
    line = "  Use  ,  intrinsic  ::  my_model  ,  name=>new_name  "
    ast = Use_Stmt(line)
    assert "USE, INTRINSIC :: my_model, name => new_name" in str(ast)
    assert repr(ast) == (
        "Use_Stmt(Module_Nature('INTRINSIC'), '::', Name('my_model'), ',', "
        "Rename(None, Name('name'), Name('new_name')))")
Exemple #5
0
def test_use_only(f2003_create):
    '''Check that a use statement is parsed correctly when there is an
    only clause.

    '''
    line = "use my_model, only: name"
    ast = Use_Stmt(line)
    assert "USE my_model, ONLY: name" in str(ast)
    assert repr(ast) == (
        "Use_Stmt(None, None, Name('my_model'), ', ONLY:', Only_List(',', "
        "(Name('name'),)))")
Exemple #6
0
def test_syntaxerror(f2003_create):
    '''Test that NoMatchError is raised for various syntax errors.'''
    for line in [
            "us", "ust", "use", "usemy_model", "use, ", "use, ::",
            "use, intrinsic", "use, intrinsic::", "use, intrinsic my_module",
            "use,", "use my_model,", "use my_model, only",
            "use my_model, only ;", "use my_model, only name"
    ]:
        with pytest.raises(NoMatchError) as excinfo:
            _ = Use_Stmt(line)
        assert "Use_Stmt: '{0}'".format(line) in str(excinfo.value)
Exemple #7
0
def test_parser_caseinsensitive1():
    '''Check that the test for the existance of a builtin call in a use
    statement is case insensitive.

    '''
    parser = Parser()
    use = Use_Stmt("use my_mod, only : SETVAL_X")
    parser.update_arg_to_module_map(use)
    with pytest.raises(ParseError) as excinfo:
        parser.create_builtin_kernel_call("SetVal_X", None)
    assert "A built-in cannot be named in a use statement" \
        in str(excinfo.value)
Exemple #8
0
def adduse(parse_tree, location, name, only=None, funcnames=None):
    '''Add a Fortran 'use' statement to an existing fparser2 parse
    tree. This will be added at the first valid location before the
    current location.

    This function should be part of the fparser2 replacement for
    f2pygen (which uses fparser1) but is kept here until this is
    developed, see issue #240.

    The 'parse_tree' argument is only required as fparser2 currently
    does not connect a child to a parent. This will be addressed in
    issue fparser:#102.

    :param parse_tree: The full parse tree of the associated code
    :type parse_tree: :py:class:`fparser.two.utils.Base`
    :param location: The current location (node) in the parse tree \
    provided in the parse_tree argument
    :type location: :py:class:`fparser.two.utils.Base`
    :param str name: The name of the use statement
    :param bool only: Whether to include the 'only' clause in the use \
    statement or not. Defaults to None which will result in only being \
    added if funcnames has content and not being added otherwise.
    :param funcnames: A list of names to include in the use statement's \
    only list. If the list is empty or None then nothing is \
    added. Defaults to None.
    :type funcnames: list of str

    :raises GenerationError: if the location is not part of the parse \
    tree.
    :raises GenerationError: if the location is not a valid location \
    to add a use statement.
    :raises NotImplementedError: if the type of parent node is not \
    supported.
    :raises InternalError: if the type of parent node does not have \
    the expected structure.

    '''
    # pylint: disable=too-many-locals
    # pylint: disable=too-many-branches
    from fparser.two.utils import walk_ast
    from fparser.two.Fortran2003 import Main_Program, Module, \
        Subroutine_Subprogram, Function_Subprogram, Use_Stmt, \
        Specification_Part
    from psyclone.psyGen import GenerationError, InternalError

    if location is None:
        raise GenerationError("alg_gen.py:adduse: Location argument must "
                              "not be None.")
    if funcnames:
        # funcnames have been provided for the only clause.
        if only is False:
            # However, the only clause has been explicitly set to False.
            raise GenerationError(
                "alg_gen.py:adduse: If the 'funcnames' argument is provided "
                "and has content, then the 'only' argument must not be set "
                "to 'False'.")
        if only is None:
            # only has not been specified so set it to True as it is
            # required when funcnames has content.
            only = True

    if only is None:
        # only has not been specified and we can therefore infer that
        # funcnames is empty or is not provided (as earlier code would
        # have set only to True otherwise) so only is not required.
        only = False

    # Create the specified use statement
    only_str = ""
    if only:
        only_str = ", only :"
    my_funcnames = funcnames
    if funcnames is None:
        my_funcnames = []
    use = Use_Stmt("use {0}{1} {2}".format(name, only_str,
                                           ", ".join(my_funcnames)))

    # find the parent program statement containing the specified location
    parent_prog_statement = None
    found = False
    for child in walk_ast(parse_tree.content):
        if child == location:
            found = True
            break
        if isinstance(child, (Main_Program, Module, Subroutine_Subprogram,
                              Function_Subprogram)):
            parent_prog_statement = child

    if not found:
        raise GenerationError("alg_gen.py:adduse: The specified location is "
                              "not in the parse tree.")
    if not parent_prog_statement:
        raise GenerationError(
            "alg_gen.py:adduse: The specified location is invalid as it has "
            "no parent in the parse tree that is a program, module, "
            "subroutine or function.")
    if not isinstance(
            parent_prog_statement,
        (Main_Program, Subroutine_Subprogram, Function_Subprogram)):
        # We currently only support program, subroutine and function
        # as ancestors
        raise NotImplementedError(
            "alg_gen.py:adduse: Unsupported parent code found '{0}'. "
            "Currently support is limited to program, subroutine and "
            "function.".format(str(type(parent_prog_statement))))
    if not isinstance(parent_prog_statement.content[1], Specification_Part):
        raise InternalError(
            "alg_gen.py:adduse: The second child of the parent code "
            "(content[1]) is expected to be a specification part but "
            "found '{0}'.".format(repr(parent_prog_statement.content[1])))

    # add the use statement as the first child of the specification
    # part of the program
    spec_part = parent_prog_statement.content[1]
    spec_part.content.insert(0, use)

    return parse_tree
Exemple #9
0
def test_use_colons(f2003_create):
    '''Check that a basic use with '::' is parsed correctly.'''
    line = "use :: my_model"
    ast = Use_Stmt(line)
    assert "USE :: my_model" in str(ast)
    assert repr(ast) == "Use_Stmt(None, '::', Name('my_model'), '', None)"
Exemple #10
0
 def check_use(reader):
     '''Internal helper function to avoid code replication.'''
     ast = Use_Stmt(reader)
     assert "USE my_model" in str(ast)
     assert repr(ast) == "Use_Stmt(None, None, Name('my_model'), '', None)"