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_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))
def test_am_create(): ''' Test the create method of ArrayMember. ''' amem = nodes.ArrayMember.create("subdomains", [ nodes.Literal("1", symbols.INTEGER_TYPE), nodes.Literal("2", symbols.INTEGER_TYPE) ]) assert isinstance(amem, nodes.ArrayMember) assert len(amem.children) == 2 assert isinstance(amem.indices[1], nodes.Literal) assert amem.indices[1].parent is amem with pytest.raises(GenerationError) as err: nodes.ArrayMember.create("subdomains", nodes.Literal("1", symbols.INTEGER_TYPE)) assert ("indices argument in create method of ArrayMember class should be " "a list but found 'Literal'" in str(err.value))
def test_asmr_create(): ''' Test the create method of ArrayOfStructuresMember. ''' asmr = nodes.ArrayOfStructuresMember.create( "regions", [nodes.Literal("3", symbols.INTEGER_TYPE)], nodes.Member("sub_mesh")) assert len(asmr.children) == 2 assert isinstance(asmr.children[0], nodes.Member) assert asmr.children[1].value == "3"
def test_am_validate_child(): ''' Test the _validate_child method of ArrayMember. ''' idx = nodes.Literal("3", symbols.INTEGER_TYPE) amr = nodes.ArrayMember("sub_mesh") with pytest.raises(GenerationError) as err: amr.addchild("wrong") assert "'str' can't be child 0 of 'ArrayMember'" in str(err.value) amr.addchild(idx) assert amr.children[0] is idx
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>]")
def test_asmr_indices(): ''' Test the indices property of ArrayOfStructuresMember. ''' asmr = nodes.ArrayOfStructuresMember.create( "regions", [nodes.Literal("3", symbols.INTEGER_TYPE)], nodes.Member("sub_mesh")) indices = asmr.indices assert len(indices) == 1 assert isinstance(indices[0], nodes.Literal) assert indices[0].value == "3" # Break the children of the node to check that we get the expected # error. asmr._children = [asmr._children[0]] with pytest.raises(InternalError) as err: asmr.indices assert ("must have one or more children representing array-index " "expressions but found none" in str(err.value)) asmr._children = [asmr._children[0], "hello"] with pytest.raises(InternalError) as err: asmr.indices assert ("malformed or incomplete: child 1 must represent an array-index " "expression but found 'str' instead of psyir.nodes.DataNode or " "Range" in str(err.value))
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)
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
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)