class BitwiseFunctions {

    private static final TriConsumer<String, BitString, BitString> LENGTH_VALIDATOR = (op, bs1, bs2) -> {
        if (bs1.length() != bs2.length()) {
            throw new IllegalArgumentException(String.format(Locale.ENGLISH, "Cannot %s bit strings of different sizes", op));
        }
    };

    private static <T> void register(Functions.Builder module,
                                     String name,
                                     DataType<T> type,
                                     BinaryOperator<T> operator) {<FILL_FUNCTION_BODY>}

    public static void register(Functions.Builder module) {
        register(module, "AND", LONG, (a, b) -> a & b);
        register(module, "AND", INTEGER, (a, b) -> a & b);
        register(module, "AND", SHORT, (a, b) -> (short) (a & b)); // Bitwise operations on short and byte types are auto-casted to int, need to cast back.
        register(module, "AND", BYTE, (a, b) -> (byte) (a & b));
        register(module, "AND", BitStringType.INSTANCE_ONE, (a, b) -> {
            LENGTH_VALIDATOR.accept("AND", a, b);
            a.bitSet().and(b.bitSet());
            return a;
        });

        register(module, "OR", LONG, (a, b) -> a | b);
        register(module, "OR", INTEGER, (a, b) -> a | b);
        register(module, "OR", SHORT, (a, b) -> (short) (a | b));
        register(module, "OR", BYTE, (a, b) -> (byte) (a | b));
        register(module, "OR", BitStringType.INSTANCE_ONE, (a, b) -> {
            LENGTH_VALIDATOR.accept("OR", a, b);
            a.bitSet().or(b.bitSet());
            return a;
        });

        register(module, "XOR", LONG, (a, b) -> a ^ b);
        register(module, "XOR", INTEGER, (a, b) -> a ^ b);
        register(module, "XOR", SHORT, (a, b) -> (short) (a ^ b));
        register(module, "XOR", BYTE, (a, b) -> (byte) (a ^ b));
        register(module, "XOR", BitStringType.INSTANCE_ONE, (a, b) -> {
            LENGTH_VALIDATOR.accept("XOR", a, b);
            a.bitSet().xor(b.bitSet());
            return a;
        });
    }
}

        TypeSignature typeSignature = type.getTypeSignature();
        Signature scalar = Signature.scalar(
                name.toLowerCase(Locale.ENGLISH),
                typeSignature,
                typeSignature,
                typeSignature
            )
            .withFeatures(Scalar.DETERMINISTIC_ONLY)
            .withFeature(Scalar.Feature.NULLABLE);
        module.add(scalar, (signature, boundSignature) -> new BinaryScalar<>(operator, signature, boundSignature, type));
    
<no_super_class>