def evaluateBinaryOperation(node, sphinxContext):
    leftValue = evaluate(node.leftExpr, sphinxContext, value=True, fallback=UNBOUND)
    rightValue = evaluate(node.rightExpr, sphinxContext, value=True, fallback=UNBOUND)
    op = node.op
    if sphinxContext.formulaOptions.traceVariableExpressionEvaluation:
        sphinxContext.modelXbrl.info("sphinx:trace",
             _("Binary op %(op)s v1: %(leftValue)s, v2: %(rightValue)s"), 
             sourceFileLine=node.sourceFileLine, op=op, leftValue=leftValue, rightValue=rightValue)
    if op == ":=":
        if sphinxContext.ruleNode.bind  == "left":
            if rightValue is UNBOUND: raise StopIteration
        elif sphinxContext.ruleNode.bind  == "right":
            if leftValue is UNBOUND: raise StopIteration
        elif sphinxContext.ruleNode.bind  == "either":
            if leftValue is UNBOUND and rightValue is UNBOUND: raise StopIteration
        else: # both or default
            if leftValue is UNBOUND or rightValue is UNBOUND: raise StopIteration
        return (leftValue, rightValue)
    elif op in {"|+|", "|+", "+|", "+", "|-|", "|-", "-|", "-"}:
        if leftValue is UNBOUND: 
            if op[0] == '|':
                raise StopIteration
            else:
                leftValue = 0
        if rightValue is UNBOUND:
            if op[-1] == '|':
                raise StopIteration
            else:
                rightValue = 0
    else:
        if leftValue is UNBOUND:
            return UNBOUND
        if rightValue is UNBOUND:
            if op == "or" and leftValue:
                return True
            return UNBOUND
        if op == "/" and rightValue == 0:  # prevent divide by zero
            return UNBOUND
    try:
        result = {'+': operator.add, '-': operator.sub, '*': operator.mul, '/': operator.truediv,
                  '<': operator.lt, '>': operator.gt, '<=': operator.le, '>=': operator.ge,
                  '==': operator.eq, '!=': operator.ne,
                  'and': operator.and_, 'or': operator.or_,
                  }[op](leftValue, rightValue)
        return result
    except __HOLE__:
        sphinxContext.modelXbrl.error("sphinx:error",
             _("Operation \"%(op)s\" not implemented for %(node)s"), 
             sourceFileLine=node.sourceFileLine, op=op, node=str(node))
    except (TypeError, ZeroDivisionError) as err:
        sphinxContext.modelXbrl.error("sphinx:error",
             _("Operation \"%(op)s\" raises exception %(error)s for %(node)s"), 
             sourceFileLine=node.sourceFileLine, op=op, node=str(node), error=str(err))
    return None
dataset/ETHPy150Open Arelle/Arelle/arelle/plugin/sphinx/SphinxEvaluator.py/evaluateBinaryOperation