private ExpressionNode transformFunctionNode(FunctionNode function, RankProfileTransformContext context) {
        String name = function.getFunction().toString();
        RankProfile.RankingExpressionFunction rankingExpressionFunction = context.rankProfile().findFunction(name);
        if (rankingExpressionFunction == null)
            return transformChildren(function, context);

        int functionArity = function.getFunction().arity();
        if (functionArity != rankingExpressionFunction.function().arguments().size())
            return transformChildren(function, context);

        ReferenceNode node = new ReferenceNode(name, function.children(), null);
        return transformChildren(node, context);
    }
Transforms function nodes to reference nodes if a rank profile function shadows a built-in function.
This has the effect of allowing rank profile functions to redefine built-in functions.
Another effect is that we can add built-in functions over time
without fear of breaking existing users' functions with the same name.

However, there is a (largish) caveat. If a user has a function with a certain number
of arguments, and we add in a built-in function with a different arity,
this will cause parse errors as the Java parser gives precedence to
built-in functions.

@author lesters
config-model/src/main/java/com/yahoo/schema/expressiontransforms/FunctionShadower.java