class Visitor extends FunctionCopyVisitor<Context> {

        @Override
        public Symbol visitFunction(Function func, Context context) {<FILL_FUNCTION_BODY>}

        @Override
        public Symbol visitLiteral(Literal<?> symbol, Context context) {
            if (context.insideLogicalOperator && symbol.value() == null) {
                return Literal.of(context.nullReplacement);
            }
            return symbol;
        }
    }

            String functionName = func.name();

            // only operate inside logical operators
            if (Operators.LOGICAL_OPERATORS.contains(functionName)) {
                final boolean currentNullReplacement = context.nullReplacement;
                final boolean currentInsideLogicalOperator = context.insideLogicalOperator;
                context.insideLogicalOperator = true;

                if (NotPredicate.NAME.equals(functionName)) {
                    // not(null) -> not(false) would evaluate to true, so replacement boolean must be flipped
                    context.nullReplacement = !currentNullReplacement;
                }
                Symbol newFunc = super.visitFunction(func, context);

                if (newFunc != func) {
                    newFunc = context.postProcessor.apply(newFunc);
                }

                // reset context
                context.insideLogicalOperator = currentInsideLogicalOperator;
                context.nullReplacement = currentNullReplacement;

                return newFunc;
            }

            return func;
        
<no_super_class>