def METHOD_NAME(expr, visual=True):
    """
    returns the number of access to memory in terms of WRITE and READ.
    expr: sympy.Expr
        any sympy expression or pyccel.ast.core object
    visual: bool
        If ``visual`` is ``True`` then the number of each type of operation is shown
        with the core class types (or their virtual equivalent) multiplied by the
        number of times they occur.
    local_vars: list
        list of variables that are supposed to be in the fast memory. We will
        ignore their corresponding memory accesses.
    """
    WRITE = Symbol('WRITE')
    READ  = Symbol('READ')
    symbol_map = {}
    used_names = set()
    if isinstance(expr, Assign):
        return METHOD_NAME(expr.rhs, visual) + WRITE
    elif isinstance(expr, PythonTuple):
        return sum(METHOD_NAME(i, visual) for i in expr)
    elif isinstance(expr, CodeBlock):
        return sum(METHOD_NAME(i, visual) for i in expr.body)
    elif isinstance(expr, Module):
        return METHOD_NAME(expr.program, visual)
    elif isinstance(expr, Program):
        return METHOD_NAME(expr.body, visual)
    elif isinstance(expr, For):
        s = pyccel_to_sympy(expr.iterable, symbol_map, used_names).size
        ops = sum(METHOD_NAME(i, visual) for i in expr.body.body)
        return ops*s
    elif isinstance(expr, (NumpyZeros, NumpyOnes)):
        import numpy as np
        return WRITE*np.prod(expr.shape)
    elif isinstance(expr, Basic):
        atoms = expr.get_attribute_nodes(PyccelSymbol, FunctionDef)
        return READ*len(atoms)
    else:
        raise NotImplementedError('TODO count_access for {}'.format(type(expr)))