def _get_idx_expr_recurse(exprnode, indexedcols, idxexprs, strexpr):
    """Here lives the actual implementation of the get_idx_expr() wrapper.

    'idxexprs' is a list of expressions in the form ``(var, (ops),
    (limits))``. 'strexpr' is the indexable expression in string format.
    These parameters will be received empty (i.e. [], ['']) for the
    first time and populated during the different recursive calls.
    Finally, they are returned in the last level to the original
    wrapper.  If 'exprnode' is not indexable, it will return the tuple
    ([], ['']) so as to signal this.

    """

    not_indexable = ([], [''])
    op_conv = {
        'and': '&',
        'or': '|',
        'not': '~',
    }
    negcmp = {
        'lt': 'ge',
        'le': 'gt',
        'ge': 'lt',
        'gt': 'le',
    }

    def fix_invert(idxcmp, exprnode, indexedcols):
        invert = False
        # Loop until all leading negations have been dealt with
        while idxcmp[1] == "invert":
            invert ^= True
            # The information about the negated node is in first position
            exprnode = idxcmp[0]
            idxcmp = _get_indexable_cmp(exprnode, indexedcols)
        return idxcmp, exprnode, invert

    # Indexable variable-constant comparison.
    idxcmp = _get_indexable_cmp(exprnode, indexedcols)
    idxcmp, exprnode, invert = fix_invert(idxcmp, exprnode, indexedcols)
    if idxcmp[0]:
        if invert:
            var, op, value = idxcmp
            if op == 'eq' and value in [True, False]:
                # ``var`` must be a boolean index.  Flip its value.
                value ^= True
            else:
                op = negcmp[op]
            expr = (var, (op,), (value,))
            invert = False
        else:
            expr = (idxcmp[0], (idxcmp[1],), (idxcmp[2],))
        return [expr]

    # For now negations of complex expressions will be not supported as
    # forming part of an indexable condition.  This might be supported in
    # the future.
    if invert:
        return not_indexable

    # Only conjunctions and disjunctions of comparisons are considered
    # for the moment.
    if exprnode.astType != 'op' or exprnode.value not in ['and', 'or']:
        return not_indexable

    left, right = exprnode.children
    # Get the expression at left
    lcolvar, lop, llim = _get_indexable_cmp(left, indexedcols)
    # Get the expression at right
    rcolvar, rop, rlim = _get_indexable_cmp(right, indexedcols)

    # Use conjunction of indexable VC comparisons like
    # ``(a <[=] x) & (x <[=] b)`` or ``(a >[=] x) & (x >[=] b)``
    # as ``a <[=] x <[=] b``, for the moment.
    op = exprnode.value
    if (lcolvar is not None and rcolvar is not None
            and _equiv_expr_node(lcolvar, rcolvar) and op == 'and'):
        if lop in ['gt', 'ge'] and rop in ['lt', 'le']:  # l <= x <= r
            expr = (lcolvar, (lop, rop), (llim, rlim))
            return [expr]
        if lop in ['lt', 'le'] and rop in ['gt', 'ge']:  # l >= x >= r
            expr = (rcolvar, (rop, lop), (rlim, llim))
            return [expr]

    # Recursively get the expressions at the left and the right
    lexpr = _get_idx_expr_recurse(left, indexedcols, idxexprs, strexpr)
    rexpr = _get_idx_expr_recurse(right, indexedcols, idxexprs, strexpr)

    def add_expr(expr, idxexprs, strexpr):
        """Add a single expression to the list."""

        if isinstance(expr, list):
            # expr is a single expression
            idxexprs.append(expr[0])
            lenexprs = len(idxexprs)
            # Mutate the strexpr string
            if lenexprs == 1:
                strexpr[:] = ["e0"]
            else:
                strexpr[:] = [
                    "(%s %s e%d)" % (strexpr[0], op_conv[op], lenexprs - 1)]

    # Add expressions to the indexable list when they are and'ed, or
    # they are both indexable.
    if lexpr != not_indexable and (op == "and" or rexpr != not_indexable):
        add_expr(lexpr, idxexprs, strexpr)
        if rexpr != not_indexable:
            add_expr(rexpr, idxexprs, strexpr)
        return (idxexprs, strexpr)
    if rexpr != not_indexable and op == "and":
        add_expr(rexpr, idxexprs, strexpr)
        return (idxexprs, strexpr)

    # Can not use indexed column.
    return not_indexable
dataset/ETHPy150Open PyTables/PyTables/tables/conditions.py/_get_idx_expr_recurse/original