def test_variables_access_info(): '''Test the implementation of VariablesAccessInfo, a class that manages a list of variables, each with a list of accesses. ''' var_accesses = VariablesAccessInfo() node1 = Node() var_accesses.add_access(Signature("read"), AccessType.READ, node1) node2 = Node() var_accesses.add_access(Signature("written"), AccessType.WRITE, node2) assert str(var_accesses) == "read: READ, written: WRITE" var_accesses.next_location() node = Node() var_accesses.add_access(Signature("written"), AccessType.WRITE, node) var_accesses.next_location() var_accesses.add_access(Signature("read_written"), AccessType.WRITE, node) var_accesses.add_access(Signature("read_written"), AccessType.READ, node) assert str(var_accesses) == "read: READ, read_written: READ+WRITE, "\ "written: WRITE" assert set(var_accesses.all_signatures) == set( [Signature("read"), Signature("written"), Signature("read_written")]) all_accesses = var_accesses[Signature("read")].all_accesses assert all_accesses[0].node == node1 written_accesses = var_accesses[Signature("written")].all_accesses assert written_accesses[0].location == 0 assert written_accesses[1].location == 1 # Check that the location pointer is pointing to the next statement: assert var_accesses.location == 2 # Create a new instance var_accesses2 = VariablesAccessInfo() var_accesses2.add_access(Signature("new_var"), AccessType.READ, node) var_accesses2.add_access(Signature("written"), AccessType.READ, node) # Now merge the new instance with the previous instance: var_accesses.merge(var_accesses2) assert str(var_accesses) == "new_var: READ, read: READ, " \ "read_written: READ+WRITE, written: READ+WRITE" with pytest.raises(KeyError): _ = var_accesses[Signature("does_not_exist")] with pytest.raises(KeyError): var_accesses.is_read(Signature("does_not_exist")) with pytest.raises(KeyError): var_accesses.is_written(Signature("does_not_exist")) assert "READWRITE" not in str(var_accesses) var_accesses.add_access(Signature("readwrite"), AccessType.READWRITE, node) assert "READWRITE" in str(var_accesses) with pytest.raises(InternalError) as err: var_accesses.add_access("no-signature", AccessType.READWRITE, node) assert "Got 'no-signature' of type 'str' but expected it to be of type " \ "psyclone.core.Signature." in str(err.value)
def test_assignment(parser): ''' Check that assignments set the right read/write accesses. ''' reader = FortranStringReader('''program test_prog use some_mod, only: f integer :: i, j real :: a, b, e, x, y real, dimension(5,5) :: c, d a = b c(i,j) = d(i,j+1)+e+f(x,y) c(i) = c(i) + 1 d(i,j) = sqrt(e(i,j)) end program test_prog''') ast = parser(reader) psy = PSyFactory(API).create(ast) schedule = psy.invokes.get("test_prog").schedule # Simple scalar assignment: a = b scalar_assignment = schedule.children[0] assert isinstance(scalar_assignment, Assignment) var_accesses = VariablesAccessInfo(scalar_assignment) # Test some test functions explicitly: assert var_accesses.is_written(Signature("a")) assert not var_accesses.is_read(Signature("a")) assert not var_accesses.is_written(Signature("b")) assert var_accesses.is_read(Signature("b")) # Array element assignment: c(i,j) = d(i,j+1)+e+f(x,y) array_assignment = schedule.children[1] assert isinstance(array_assignment, Assignment) var_accesses = VariablesAccessInfo(array_assignment) assert str(var_accesses) == "c: WRITE, d: READ, e: READ, f: READ, "\ "i: READ, j: READ, x: READ, y: READ" # Increment operation: c(i) = c(i)+1 increment_access = schedule.children[2] assert isinstance(increment_access, Assignment) var_accesses = VariablesAccessInfo(increment_access) assert str(var_accesses) == "c: READ+WRITE, i: READ" # Using an intrinsic: sqrt_access = schedule.children[3] assert isinstance(sqrt_access, Assignment) var_accesses = VariablesAccessInfo(sqrt_access) assert str(var_accesses) == "d: WRITE, e: READ, i: READ, j: READ"
def get_output_parameters(self, node_list, variables_info=None): # pylint: disable=no-self-use '''Return all variables that are output parameters, i.e. are written. :param node_list: list of PSyIR nodes to be analysed. :type node_list: list of :py:class:`psyclone.psyir.nodes.Node` :param variables_info: optional variable usage information, \ can be used to avoid repeatedly collecting this information. :type variables_info: \ :py:class:`psyclone.core.variables_info.VariablesAccessInfo` :returns: a list of all variable names that are written. :rtype: list of str ''' # Collect the information about all variables used: if not variables_info: variables_info = VariablesAccessInfo(node_list) return [str(signature) for signature in variables_info.all_signatures if variables_info.is_written(signature)]