docs: public static Boolean compare(Object left, Object right, EvaluationContext ctx, BiPredicate<Comparable, Comparable> op) {
          if ( left == null || right == null ) {
              return null;
          } else if ((left instanceof ChronoPeriod && right instanceof ChronoPeriod)) {
              // periods have special compare semantics in FEEL as it ignores "days". Only months and years are compared
              Long l = ComparablePeriod.toTotalMonths((ChronoPeriod) left);
              Long r = ComparablePeriod.toTotalMonths((ChronoPeriod) right);
              return op.test( l, r );
          } else if (left instanceof TemporalAccessor && right instanceof TemporalAccessor) {
              // Handle specific cases when both date / datetime
              TemporalAccessor l = (TemporalAccessor) left;
              TemporalAccessor r = (TemporalAccessor) right;
              if (BuiltInType.determineTypeFromInstance(left) == BuiltInType.TIME && BuiltInType.determineTypeFromInstance(right) == BuiltInType.TIME) {
                  return op.test(valuet(l), valuet(r));
              } else if (BuiltInType.determineTypeFromInstance(left) == BuiltInType.DATE_TIME && BuiltInType.determineTypeFromInstance(right) == BuiltInType.DATE_TIME) {
                  return op.test(valuedt(l, r.query(TemporalQueries.zone())), valuedt(r, l.query(TemporalQueries.zone())));
              } // fallback; continue:
          }
          // last fallback:
          if ((left instanceof String && right instanceof String) ||
              (left instanceof Number && right instanceof Number) ||
              (left instanceof Boolean && right instanceof Boolean) ||
              (left instanceof Comparable && left.getClass().isAssignableFrom(right.getClass()))) {
              Comparable l = (Comparable) left;
              Comparable r = (Comparable) right;
              return op.test(l, r);
          }
          return null;
      }