def make_component_symbol():
    '''
    Creates a Symbol of type "grid_type" equivalent to the Fortran:

      type :: grid_type
        integer :: nx
        type(region_type) :: region
      end type

    and

      type :: region_type
        integer :: startx
      end type

    :returns: symbol named "grid" of type "grid_type".
    :rtype: :py:class:`psyclone.psyir.symbols.DataSymbol`

    '''
    region_type = symbols.StructureType.create([
        ("startx", symbols.INTEGER_TYPE, symbols.Symbol.Visibility.PUBLIC)])
    region_type_symbol = symbols.DataTypeSymbol("region_type", region_type)
    grid_type = symbols.StructureType.create([
        ("nx", symbols.INTEGER_TYPE, symbols.Symbol.Visibility.PUBLIC),
        ("region", region_type_symbol, symbols.Symbol.Visibility.PUBLIC)])
    grid_type_symbol = symbols.DataTypeSymbol("grid_type", grid_type)
    grid_array_type = symbols.ArrayType(grid_type_symbol, [5])
    ssym = symbols.DataSymbol("grid", grid_array_type)
    return ssym
def test_asr_create_errors(component_symbol):
    ''' Test the validation checks within the create method. Most validation
    is done within the StructureReference class so there's not much to check
    here. '''
    with pytest.raises(TypeError) as err:
        _ = nodes.ArrayOfStructuresReference.create(1, [], [])
    assert ("'symbol' argument to ArrayOfStructuresReference.create() should "
            "be a DataSymbol but found 'int'" in str(err.value))
    scalar_symbol = symbols.DataSymbol("scalar", symbols.INTEGER_TYPE)
    with pytest.raises(TypeError) as err:
        _ = nodes.ArrayOfStructuresReference.create(scalar_symbol, [], [])
    assert ("ArrayType, DeferredType or UnknownType but symbol 'scalar' has "
            "type 'Scalar" in str(err.value))
    # Missing children (for array-index expressions)
    with pytest.raises(TypeError) as err:
        _ = nodes.ArrayOfStructuresReference.create(component_symbol,
                                                    False, ["hello"])
    assert ("must be a list containing at least one array-index expression "
            "but this is missing for symbol 'grid'" in str(err.value))
    # Missing member(s)
    with pytest.raises(ValueError) as err:
        _ = nodes.ArrayOfStructuresReference.create(
            component_symbol, [nodes.Literal("1", symbols.INTEGER_TYPE)], [])
    assert ("'members' that are being accessed but got an empty list for "
            "symbol 'grid'" in str(err.value))
示例#3
0
def create_structure_symbol(table):
    '''
    Utility to create a symbol of derived type and add it to the supplied
    symbol table.

    :param table: the symbol table to which to add the new symbol.
    :type table: :py:class:`psyclone.psyir.symbols.SymbolTable`

    :returns: the new DataSymbol representing a derived type.
    :rtype: :py:class:`psyclone.psyir.symbols.DataSymbol`

    '''
    region_type = symbols.StructureType.create([
        ("nx", symbols.INTEGER_TYPE, symbols.Symbol.Visibility.PUBLIC),
        ("ny", symbols.INTEGER_TYPE, symbols.Symbol.Visibility.PUBLIC),
        ("domain", symbols.TypeSymbol("dom_type", symbols.DeferredType()),
         symbols.Symbol.Visibility.PUBLIC)
    ])
    region_type_sym = symbols.TypeSymbol("grid_type", region_type)
    region_array_type = symbols.ArrayType(region_type_sym, [2, 2])
    grid_type = symbols.StructureType.create([
        ("dx", symbols.INTEGER_TYPE, symbols.Symbol.Visibility.PUBLIC),
        ("area", region_type_sym, symbols.Symbol.Visibility.PUBLIC),
        ("levels", region_array_type, symbols.Symbol.Visibility.PUBLIC)
    ])
    grid_type_sym = symbols.TypeSymbol("grid_type", grid_type)
    grid_var = symbols.DataSymbol("grid", grid_type_sym)
    table.add(grid_type_sym)
    table.add(grid_var)
    return grid_var
示例#4
0
def test_struc_ref_str():
    ''' Test the __str__ method of StructureReference. '''
    grid_type = symbols.StructureType.create([
        ("nx", symbols.INTEGER_TYPE, symbols.Symbol.Visibility.PUBLIC)])
    grid_type_symbol = symbols.TypeSymbol("grid_type", grid_type)
    ssym = symbols.DataSymbol("grid", grid_type_symbol)
    # Reference to scalar member of structure
    sref = nodes.StructureReference.create(ssym, ["nx"])
    assert (str(sref) == "StructureReference[name:'grid']\n"
            "Member[name:'nx']")
示例#5
0
def test_reference_accesses():
    ''' Test that the reference_accesses method does nothing. This will
    be addressed by #1028. '''
    var_access_info = VariablesAccessInfo()
    dref = nodes.StructureReference.create(
        symbols.DataSymbol(
            "grid", symbols.TypeSymbol("grid_type", symbols.DeferredType())),
        ["data"])
    dref.reference_accesses(var_access_info)
    assert var_access_info.all_signatures == []
示例#6
0
def test_struc_ref_create():
    ''' Tests for the create method. '''
    region_type = symbols.StructureType.create([
        ("startx", symbols.INTEGER_TYPE, symbols.Symbol.Visibility.PUBLIC)
    ])
    region_type_symbol = symbols.DataTypeSymbol("region_type", region_type)
    grid_type = symbols.StructureType.create([
        ("nx", symbols.INTEGER_TYPE, symbols.Symbol.Visibility.PUBLIC),
        ("region", region_type_symbol, symbols.Symbol.Visibility.PRIVATE),
        ("sub_grids", symbols.ArrayType(region_type_symbol, [3]),
         symbols.Symbol.Visibility.PUBLIC),
        ("data", symbols.ArrayType(symbols.REAL_TYPE,
                                   [10, 10]), symbols.Symbol.Visibility.PUBLIC)
    ])
    grid_type_symbol = symbols.DataTypeSymbol("grid_type", grid_type)
    ssym = symbols.DataSymbol("grid", grid_type_symbol)
    # Reference to scalar member of structure
    sref = nodes.StructureReference.create(ssym, ["nx"])
    assert sref.symbol is ssym
    assert len(sref.children) == 1
    assert sref.children[0].name == "nx"
    check_links(sref, sref.children)
    # Reference to scalar member of structure member of structure
    rref = nodes.StructureReference.create(ssym, ["region", "startx"])
    assert rref.children[0].name == "region"
    assert rref.children[0].children[0].name == "startx"
    check_links(rref.children[0], rref.children[0].children)
    # Reference to an element of an array member of the structure
    aref = nodes.StructureReference.create(ssym, [("data", [
        nodes.Literal("1", symbols.INTEGER_TYPE),
        nodes.Literal("5", symbols.INTEGER_TYPE)
    ])])
    assert isinstance(aref.children[0], nodes.ArrayMember)
    assert aref.children[0].name == "data"
    assert isinstance(aref.children[0].children[1], nodes.Literal)
    assert aref.children[0].children[1].value == "5"
    check_links(aref, aref.children)
    check_links(aref.children[0], aref.children[0].children)
    # Reference to an array of structures within a structure
    structarray_ref = nodes.StructureReference.create(
        ssym, [("sub_grids", [nodes.Literal("1", symbols.INTEGER_TYPE)])])
    assert isinstance(structarray_ref.children[0], nodes.ArrayMember)
    # Reference to a scalar member of an element of an array of structures
    # contained in a structure
    dref = nodes.StructureReference.create(
        ssym,
        [("sub_grids", [nodes.Literal("2", symbols.INTEGER_TYPE)]), "startx"])
    assert isinstance(dref.children[0], nodes.ArrayOfStructuresMember)
    assert isinstance(dref.children[0].children[0], nodes.Member)
    assert isinstance(dref.children[0].children[1], nodes.Literal)
    check_links(dref, dref.children)
    check_links(dref.children[0], dref.children[0].children)
def test_ast_str():
    ''' Test that the __str__ method of the StructureReference class works OK
    when we have an ArrayOfStructuresReference. '''
    grid_type = symbols.StructureType.create([
        ("nx", symbols.INTEGER_TYPE, symbols.Symbol.Visibility.PUBLIC)])
    grid_type_symbol = symbols.DataTypeSymbol("grid_type", grid_type)
    grid_array_type = symbols.ArrayType(grid_type_symbol, [5])
    ssym = symbols.DataSymbol("grid", grid_array_type)
    asref = nodes.ArrayOfStructuresReference.create(
        ssym, [nodes.Literal("2", symbols.INTEGER_TYPE)], ["nx"])
    assert (str(asref) == "ArrayOfStructuresReference[name:'grid']\n"
            "Member[name:'nx']\n"
            "Literal[value:'2', Scalar<INTEGER, UNDEFINED>]")
示例#8
0
def test_reference_accesses():
    ''' Test the reference_accesses method.
    '''
    dref = nodes.StructureReference.create(
        symbols.DataSymbol(
            "grid", symbols.DataTypeSymbol("grid_type",
                                           symbols.DeferredType())), ["data"])
    var_access_info = VariablesAccessInfo()
    dref.reference_accesses(var_access_info)

    assert var_access_info.all_signatures == [Signature(("grid", "data"))]
    # By default all accesses are marked as read
    assert str(var_access_info) == "grid%data: READ"
示例#9
0
def test_struc_ref_create_errors():
    ''' Tests for the validation checks in the create method. '''
    with pytest.raises(TypeError) as err:
        _ = nodes.StructureReference.create(None, [])
    assert ("'symbol' argument to StructureReference.create() should be a "
            "DataSymbol but found 'NoneType'" in str(err.value))
    with pytest.raises(TypeError) as err:
        _ = nodes.StructureReference.create(
            symbols.DataSymbol("fake", symbols.INTEGER_TYPE), [])
    assert ("symbol that is (or could be) a structure, however symbol "
            "'fake' has type 'Scalar" in str(err.value))
    with pytest.raises(TypeError) as err:
        _ = nodes.StructureReference.create(
            symbols.DataSymbol("grid", symbols.DeferredType()), 1)
    assert ("'members' argument to StructureReference._create() must be a "
            "list but found 'int'" in str(err.value))
    with pytest.raises(ValueError) as err:
        _ = nodes.StructureReference.create(
            symbols.DataSymbol("grid", symbols.DeferredType()), [])
    assert ("one or more structure 'members' that are being accessed but "
            "got an empty list for symbol 'grid'" in str(err.value))
    grid_type = symbols.StructureType.create([
        ("nx", symbols.INTEGER_TYPE, symbols.Symbol.Visibility.PUBLIC)
    ])
    tsymbol_known = symbols.DataTypeSymbol("grid_type", grid_type)
    with pytest.raises(TypeError) as err:
        _ = nodes.StructureReference.create(
            symbols.DataSymbol("grid", tsymbol_known), [1])
    assert ("'members' passed to StructureType._create() must consist of "
            "either 'str' or 2-tuple entries but found 'int' in the last "
            "entry while attempting to create reference to symbol 'grid'"
            in str(err.value))
    with pytest.raises(TypeError) as err:
        _ = nodes.StructureReference.create(
            symbols.DataSymbol("grid", tsymbol_known), [1, "hello"])
    assert ("'members' passed to StructureType._create() must consist of "
            "either 'str' or 2-tuple entries but found 'int' while "
            "attempting to create reference to symbol 'grid'"
            in str(err.value))
示例#10
0
def test_struc_ref_semantic_nav():
    ''' Test the 'member' property of the StructureReference. '''
    grid_type = symbols.StructureType.create([
        ("nx", symbols.INTEGER_TYPE, symbols.Symbol.Visibility.PUBLIC)])
    grid_type_symbol = symbols.TypeSymbol("grid_type", grid_type)
    ssym = symbols.DataSymbol("grid", grid_type_symbol)
    # Reference to scalar member of structure
    sref = nodes.StructureReference.create(ssym, ["nx"])
    assert sref.member is sref.children[0]
    # Break the first child to check that we get the expected error
    sref._children = ["broken"]
    with pytest.raises(InternalError) as err:
        _ = sref.member
    assert ("StructureReference malformed or incomplete. It must have a "
            "single child that must be a (sub-class of) Member, but "
            "found: ['broken']" in str(err.value))
示例#11
0
def test_asmr_validate_child():
    ''' Test the _validate_child method of ArrayOfStructuresMember. '''
    asmr = nodes.ArrayOfStructuresMember("regions")
    with pytest.raises(GenerationError) as err:
        asmr.addchild("wrong")
    assert ("'str' can't be child 0 of 'ArrayOfStructuresMember'"
            in str(err.value))
    asmr.addchild(nodes.Member("sub_mesh"))
    assert isinstance(asmr.children[0], nodes.Member)
    with pytest.raises(GenerationError) as err:
        asmr.addchild("2")
    assert ("'str' can't be child 1 of 'ArrayOfStructuresMember'"
            in str(err.value))
    idx = nodes.Reference(symbols.DataSymbol("idx", symbols.INTEGER_TYPE))
    asmr.addchild(idx)
    assert asmr.children[1] is idx
示例#12
0
def test_struc_ref_validate_child():
    ''' Tests for the _validate_child method. '''
    grid_type = symbols.StructureType.create([
        ("nx", symbols.INTEGER_TYPE, symbols.Symbol.Visibility.PUBLIC)])
    grid_type_symbol = symbols.TypeSymbol("grid_type", grid_type)
    ssym = symbols.DataSymbol("grid", grid_type_symbol)
    # Reference to scalar member of structure
    sref = nodes.StructureReference.create(ssym, ["nx"])
    # a StructureReference is only allowed (at most) one child.
    with pytest.raises(GenerationError) as err:
        sref.addchild("wrong")
    assert ("Item 'str' can't be child 1 of 'StructureReference'" in
            str(err.value))
    # If present, the first child has to be a MemberReference
    with pytest.raises(GenerationError) as err:
        sref.children[0] = "wrong"
    assert ("Item 'str' can't be child 0 of 'StructureReference'" in
            str(err.value))
示例#13
0
def test_asr_create(component_symbol):
    ''' Check the create method. '''
    int_one = nodes.Literal("1", symbols.INTEGER_TYPE)
    # Reference to scalar member of structure in array of structures
    asref = nodes.ArrayOfStructuresReference.create(component_symbol,
                                                    [int_one], ["nx"])
    assert isinstance(asref.children[0], nodes.Member)
    assert isinstance(asref.children[1], nodes.Literal)
    check_links(asref, asref.children)
    # Reference to member of structure member of structure in array of
    # structures
    asref = nodes.ArrayOfStructuresReference.create(component_symbol,
                                                    [int_one],
                                                    ["region", "startx"])
    assert isinstance(asref.children[0], nodes.StructureMember)
    assert isinstance(asref.children[0].children[0], nodes.Member)
    # Reference to range of structures
    lbound = nodes.BinaryOperation.create(
        nodes.BinaryOperation.Operator.LBOUND,
        nodes.Reference(component_symbol), int_one)
    ubound = nodes.BinaryOperation.create(
        nodes.BinaryOperation.Operator.UBOUND,
        nodes.Reference(component_symbol), int_one)
    my_range = nodes.Range.create(lbound, ubound)
    asref = nodes.ArrayOfStructuresReference.create(component_symbol,
                                                    [my_range], ["nx"])
    assert isinstance(asref.children[0], nodes.Member)
    assert isinstance(asref.children[1], nodes.Range)
    check_links(asref, asref.children)
    check_links(asref.children[1], asref.children[1].children)
    # Reference to a symbol of DeferredType
    ssym = symbols.DataSymbol("grid", symbols.DeferredType())
    asref = nodes.ArrayOfStructuresReference.create(ssym, [int_one],
                                                    ["region", "startx"])
    assert isinstance(asref.symbol.datatype, symbols.DeferredType)
    assert isinstance(asref.children[0], nodes.StructureMember)
    assert isinstance(asref.children[0].children[0], nodes.Member)
示例#14
0
def test_am_is_lower_upper_bound():
    ''' Test the is_lower/upper_bound methods of ArrayMember. '''
    one = nodes.Literal("1", symbols.INTEGER_TYPE)
    two = nodes.Literal("2", symbols.INTEGER_TYPE)
    amem1 = nodes.ArrayMember.create(
        "subdomains",
        [one.copy(), nodes.Literal("2", symbols.INTEGER_TYPE)])
    assert amem1.is_lower_bound(0) is False
    assert amem1.is_upper_bound(0) is False
    grid_type = symbols.DataTypeSymbol("grid_type", symbols.DeferredType())
    sym = symbols.DataSymbol("grid_var", grid_type)
    ref = nodes.StructureReference.create(sym, ["data"])
    # Start and stop for the range are binary operators but not the right ones
    start = nodes.operation.BinaryOperation.create(
        nodes.operation.BinaryOperation.Operator.UBOUND, ref.copy(),
        one.copy())
    stop = nodes.operation.BinaryOperation.create(
        nodes.operation.BinaryOperation.Operator.LBOUND, ref.copy(),
        one.copy())
    my_range = nodes.Range.create(start, stop)
    sref = nodes.StructureReference.create(sym, [("data", [my_range])])
    amem2 = sref.walk(nodes.ArrayMember)[0]
    assert amem2.is_lower_bound(0) is False
    assert amem2.is_upper_bound(0) is False
    # Correct binary operators but wrong types of operand
    start = nodes.operation.BinaryOperation.create(
        nodes.operation.BinaryOperation.Operator.LBOUND, one.copy(),
        one.copy())
    stop = nodes.operation.BinaryOperation.create(
        nodes.operation.BinaryOperation.Operator.UBOUND, one.copy(),
        one.copy())
    my_range = nodes.Range.create(start, stop)
    sref = nodes.StructureReference.create(sym, [("data", [my_range])])
    amem2 = sref.walk(nodes.ArrayMember)[0]
    assert amem2.is_lower_bound(0) is False
    assert amem2.is_upper_bound(0) is False
    # Correct start and stop arguments to Range
    start = nodes.operation.BinaryOperation.create(
        nodes.operation.BinaryOperation.Operator.LBOUND, ref.copy(),
        one.copy())
    stop = nodes.operation.BinaryOperation.create(
        nodes.operation.BinaryOperation.Operator.UBOUND, ref.copy(),
        one.copy())
    my_range = nodes.Range.create(start, stop)
    sref = nodes.StructureReference.create(sym, [("data", [my_range])])
    amem2 = sref.walk(nodes.ArrayMember)[0]
    assert amem2.is_lower_bound(0) is True
    assert amem2.is_upper_bound(0) is True
    # Range in a dimension other than the first
    start = nodes.operation.BinaryOperation.create(
        nodes.operation.BinaryOperation.Operator.LBOUND, ref.copy(),
        two.copy())
    stop = nodes.operation.BinaryOperation.create(
        nodes.operation.BinaryOperation.Operator.UBOUND, ref.copy(),
        two.copy())
    my_range = nodes.Range.create(start, stop)
    sref = nodes.StructureReference.create(sym,
                                           [("data", [one.copy(), my_range])])
    amem2 = sref.walk(nodes.ArrayMember)[0]
    assert amem2.is_lower_bound(0) is False
    assert amem2.is_upper_bound(0) is False
    assert amem2.is_lower_bound(1) is True
    assert amem2.is_upper_bound(1) is True
示例#15
0
def test_am_matching_access():
    ''' Test the _matching_access method of ArrayMember. '''
    one = nodes.Literal("1", symbols.INTEGER_TYPE)
    two = nodes.Literal("2", symbols.INTEGER_TYPE)
    amem1 = nodes.ArrayMember.create(
        "subdomains",
        [one.copy(), nodes.Literal("2", symbols.INTEGER_TYPE)])
    # Check when the ArrayMember has no parent Reference
    result = amem1._matching_access(
        nodes.Reference(symbols.DataSymbol("fake", symbols.INTEGER_TYPE)))
    assert result is False
    grid_type = symbols.DataTypeSymbol("grid_type", symbols.DeferredType())
    sym1 = symbols.DataSymbol("grid_var", grid_type)
    sym2 = symbols.DataSymbol("grid_var2", grid_type)
    ref1 = nodes.StructureReference.create(sym1, ["data"])
    # Reference is to a different symbol
    ref2 = nodes.StructureReference.create(sym2, [("data", [one.copy()])])
    assert ref2.member._matching_access(ref1) is False
    # Reference is to a different member of the same symbol
    ref2 = nodes.StructureReference.create(sym1, [("xvals", [one.copy()])])
    assert ref2.member._matching_access(ref1) is False
    ref1 = nodes.StructureReference.create(sym1, [("data", [one.copy()]),
                                                  ("xobs", [one.copy()])])
    ref2 = nodes.StructureReference.create(sym1, [("data", [one.copy()])])
    assert ref2.member._matching_access(ref1) is True
    ref2 = nodes.StructureReference.create(sym1, [("data", [one.copy()]),
                                                  ("yobs", [one.copy()])])
    amem = ref2.member.member  # "yobs"
    assert amem._matching_access(ref1) is False
    # The same 'signature' (a%b%c) but where b is an array access in one
    # case. This may not be possible in Fortran but we need to exercise
    # all conditions.
    ref1 = nodes.StructureReference.create(sym1,
                                           [("a", [one.copy()]), "b", "c"])
    ref2 = nodes.StructureReference.create(sym1, [("a", [one.copy()]),
                                                  ("b", [one.copy()]),
                                                  ("c", [one.copy()])])
    amem = ref2.walk(nodes.ArrayMember)[0]
    assert amem._matching_access(ref1) is False
    # Same 'signature' but with one array access having more dimensions.
    ref1 = nodes.StructureReference.create(sym1, [("a", [one.copy()]),
                                                  ("b", [one.copy()]),
                                                  ("c", [one.copy()])])
    ref2 = nodes.StructureReference.create(
        sym1, [("a", [one.copy()]), ("b", [one.copy(), one.copy()]),
               ("c", [one.copy()])])
    amem = ref2.walk(nodes.ArrayMember)[0]
    assert amem._matching_access(ref1) is False
    # Same 'signature' but with one array access having a different index.
    ref1 = nodes.StructureReference.create(
        sym1, [("a", [one.copy()]), ("b", [one.copy(), one.copy()]),
               ("c", [one.copy()])])
    ref2 = nodes.StructureReference.create(
        sym1, [("a", [one.copy()]), ("b", [one.copy(), two.copy()]),
               ("c", [one.copy()])])
    amem = ref2.walk(nodes.ArrayMember)[0]
    assert amem._matching_access(ref1) is False
    # Reference to an element of the same array
    ref1 = nodes.StructureReference.create(sym1, ["data"])
    ref2 = nodes.StructureReference.create(sym1, [("data", [one.copy()])])
    assert ref2.member._matching_access(ref1) is True
    # Reference to an ArrayOfStructures
    array_sym = symbols.DataSymbol("grids",
                                   symbols.ArrayType(grid_type, [two.copy()]))
    ref1 = nodes.ArrayOfStructuresReference.create(array_sym, [one.copy()],
                                                   ["data"])
    assert ref1._matching_access(nodes.Reference(array_sym))
    # member being compared is not at the bottom of a derived-type access
    ref1 = nodes.StructureReference.create(sym1, [("a", [one.copy()]),
                                                  ("b", [one.copy()]),
                                                  ("d", [one.copy()])])
    ref2 = nodes.StructureReference.create(sym1, [("a", [one.copy()]),
                                                  ("b", [one.copy()]),
                                                  ("c", [one.copy()])])
    amem = ref2.member.member
    assert amem.name == "b"
    assert amem._matching_access(ref1)