/**
   * Wrap the given expression with a logging method call. Some kinds of expressions don't like
   * being wrapped in a simple fashion and so we have to handle them specially. The
   * ExpressionTransformer doesn't have methods for each type so we check for each one here.
   *
   * <p>TODO: There are potentially other expressions which need special handling (like indexing and
   * variables). This code may be working because those types have their parent being wrapped and we
   * don't transform their children.
   *
   * @param lineNumber line number to report for this value
   * @param expression the expression whose value we want to report
   * @return an expression that computes the value and also reports it somewheres
   */
  private Expression loggingExpression(Integer lineNumber, Expression expression) {
    if (expression instanceof DeclarationExpression) {
      DeclarationExpression declarationExpression = (DeclarationExpression) expression;

      return new DeclarationExpression(
          declarationExpression.getLeftExpression(),
          declarationExpression.getOperation(),
          loggingExpression(lineNumber, declarationExpression.getRightExpression()));
    }

    if (expression instanceof BooleanExpression) {
      BooleanExpression booleanExpression = (BooleanExpression) expression;
      return new BooleanExpression(
          new MethodCallExpression(
              new VariableExpression("this"),
              "_log",
              new ArgumentListExpression(
                  new ConstantExpression(lineNumber), booleanExpression.getExpression())));
    }

    return new MethodCallExpression(
        new VariableExpression("this"),
        "_log",
        new ArgumentListExpression(new ConstantExpression(lineNumber), expression));
  }