def METHOD_NAME(expressions, **kwargs):
    """
    Lowering an expression consists of the following passes:
        * Indexify functions;
        * Align Indexeds with the computational domain;
        * Apply user-provided substitution;
    Examples
    --------
    f(x - 2*h_x, y) -> f[xi + 2, yi + 4]  (assuming halo_size=4)
    """
    # Normalize subs
    subs = {k: sympify(v) for k, v in kwargs.get('subs', {}).items()}
    processed = []
    for expr in as_tuple(expressions):
        try:
            dimension_map = expr.subdomain.dimension_map
        except AttributeError:
            # Some Relationals may be pure SymPy objects, thus lacking the subdomain
            dimension_map = {}
        # Handle Functions (typical case)
        mapper = {f: METHOD_NAME(f.indexify(subs=dimension_map), **kwargs)
                  for f in expr.find(AbstractFunction)}
        # Handle Indexeds (from index notation)
        for i in retrieve_indexed(expr):
            f = i.function
            # Introduce shifting to align with the computational domain
            indices = [(METHOD_NAME(a) + o) for a, o in
                       zip(i.indices, f._size_nodomain.left)]
            # Substitute spacing (spacing only used in own dimension)
            indices = [i.xreplace({d.spacing: 1, -d.spacing: -1})
                       for i, d in zip(indices, f.dimensions)]
            # Apply substitutions, if necessary
            if dimension_map:
                indices = [j.xreplace(dimension_map) for j in indices]
            mapper[i] = f.indexed[indices]
        # Add dimensions map to the mapper in case dimensions are used
        # as an expression, i.e. Eq(u, x, subdomain=xleft)
        mapper.update(dimension_map)
        # Add the user-supplied substitutions
        mapper.update(subs)
        # Apply mapper to expression
        processed.append(uxreplace(expr, mapper))
    if isinstance(expressions, Iterable):
        return processed
    else:
        assert len(processed) == 1
        return processed.pop()