public object visitBinaryExpr(Expr.Binary expr) { object left = Evaluate(expr.left); object right = Evaluate(expr.right); if (expr.op.type == TokenType.AND) { return(GetTruthValue(left) && GetTruthValue(right)); } if (expr.op.type == TokenType.OR) { return(GetTruthValue(left) || GetTruthValue(right)); } // same for strings, numbers and bools switch (expr.op.type) { case TokenType.EQUAL_EQUAL: return(IsEqual(left, right)); case TokenType.BANG_EQUAL: return(!IsEqual(left, right)); } // string specific if (left is string || right is string) { if (expr.op.type != TokenType.PLUS) { throw new RuntimeError(expr.op, expr.op.type.ToString() + " not a valid operator on strings."); } return(Stringify(left) + Stringify(right)); } // number specific CheckNumberOperands(expr.op, left, right); switch (expr.op.type) { case TokenType.PLUS: return((double)left + (double)right); case TokenType.MINUS: return((double)left - (double)right); case TokenType.STAR: return((double)left * (double)right); case TokenType.SLASH: double r = (double)right; if (r == 0) { throw new RuntimeError(expr.op, "Divide by zero error."); } return((double)left / r); case TokenType.GREATER: return((double)left > (double)right); case TokenType.GREATER_EQUAL: return((double)left >= (double)right); case TokenType.LESS: return((double)left < (double)right); case TokenType.LESS_EQUAL: return((double)left <= (double)right); default: Lox.ReportError(expr.op, expr.op.type.ToString() + " not a valid operator on doubles."); return(right); } }