async function evaluateBinary(expr, input, environment) {
        var result;
        var lhs = await evaluate(expr.lhs, input, environment);
        var op = expr.value;

        //defer evaluation of RHS to allow short-circuiting
        var evalrhs = async () => await evaluate(expr.rhs, input, environment);
        if (op === "and" || op === "or") {
            try {
                return await evaluateBooleanExpression(lhs, evalrhs, op);
            } catch(err) {
                err.position = expr.position;
                err.token = op;
                throw err;
            }
        }

        var rhs = await evalrhs();
        try {
            switch (op) {
                case '+':
                case '-':
                case '*':
                case '/':
                case '%':
                    result = evaluateNumericExpression(lhs, rhs, op);
                    break;
                case '=':
                case '!=':
                    result = evaluateEqualityExpression(lhs, rhs, op);
                    break;
                case '<':
                case '<=':
                case '>':
                case '>=':
                    result = evaluateComparisonExpression(lhs, rhs, op);
                    break;
                case '&':
                    result = evaluateStringConcat(lhs, rhs);
                    break;
                case '..':
                    result = evaluateRangeExpression(lhs, rhs);
                    break;
                case 'in':
                    result = evaluateIncludesExpression(lhs, rhs);
                    break;
            }
        } catch(err) {
            err.position = expr.position;
            err.token = op;
            throw err;
        }
        return result;
    }
Evaluate binary expression against input data
@param {Object} expr - JSONata expression
@param {Object} input - Input data to evaluate against
@param {Object} environment - Environment
@returns {*} Evaluated input data