private void replaceFunctionFeatures(Set<ReferenceNode> features, SerializationContext context) {
            if (features == null) return;
            Set<ReferenceNode> functionFeatures = new LinkedHashSet<>();
            for (Iterator<ReferenceNode> i = features.iterator(); i.hasNext(); ) {
                ReferenceNode referenceNode = i.next();
                // Is the feature a function?
                ExpressionFunction function = context.getFunction(referenceNode.getName());
                if (function != null) {
                    if (referenceNode.getOutput() != null) {
                        throw new IllegalArgumentException("function " + referenceNode.getName() +
                                                           " cannot provide output " + referenceNode.getOutput() +
                                                           " demanded by feature " + referenceNode);
                    }
                    int needArgs = function.arguments().size();
                    var useArgs = referenceNode.getArguments();
                    if (needArgs != useArgs.size()) {
                        throw new IllegalArgumentException("function " + referenceNode.getName() +
                                                           " needs " + needArgs +
                                                           " arguments but gets " + useArgs.size() +
                                                           " from feature " + referenceNode);
                    }
                    var instance = function.expand(context, useArgs.expressions(), new java.util.ArrayDeque<>());
                    String propertyName = RankingExpression.propertyName(instance.getName());
                    String expressionString = instance.getExpressionString();
                    context.addFunctionSerialization(propertyName, expressionString);
                    function.returnType().ifPresent(t -> context.addFunctionTypeSerialization(instance.getName(), t));
                    String backendReference = wrapInRankingExpression(instance.getName());
                    var backendReferenceNode = new ReferenceNode(backendReference, List.of(), null);
                    // tell backend to map back to the name the user expects:
                    featureRenames.put(backendReference, referenceNode.toString());
                    functionFeatures.add(backendReferenceNode);
                    i.remove(); // Will add the expanded one in next block
                }
            }
            // Then, replace the features that were functions
            for (ReferenceNode mappedFun : functionFeatures) {
                features.add(mappedFun);
            }
        }
Creates a raw rank profile from the given rank profile
config-model/src/main/java/com/yahoo/schema/derived/RawRankProfile.java