summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--searchlib/abi-spec.json5
-rwxr-xr-xsearchlib/src/main/java/com/yahoo/searchlib/rankingexpression/ExpressionFunction.java5
-rw-r--r--searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/FunctionReferenceContext.java5
-rwxr-xr-xsearchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/ReferenceNode.java23
-rw-r--r--searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SerializationContext.java6
-rw-r--r--searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/TensorFunctionNode.java10
-rw-r--r--searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/transform/ConstantDereferencer.java20
7 files changed, 61 insertions, 13 deletions
diff --git a/searchlib/abi-spec.json b/searchlib/abi-spec.json
index d058104bf1b..6bce791914c 100644
--- a/searchlib/abi-spec.json
+++ b/searchlib/abi-spec.json
@@ -1416,7 +1416,8 @@
"public com.yahoo.searchlib.rankingexpression.ExpressionFunction getFunction(java.lang.String)",
"protected com.google.common.collect.ImmutableMap functions()",
"public java.lang.String getBinding(java.lang.String)",
- "public com.yahoo.searchlib.rankingexpression.rule.FunctionReferenceContext withBindings(java.util.Map)"
+ "public com.yahoo.searchlib.rankingexpression.rule.FunctionReferenceContext withBindings(java.util.Map)",
+ "public com.yahoo.searchlib.rankingexpression.rule.FunctionReferenceContext withoutBindings()"
],
"fields": []
},
@@ -1573,7 +1574,9 @@
"public void addArgumentTypeSerialization(java.lang.String, java.lang.String, com.yahoo.tensor.TensorType)",
"public void addFunctionTypeSerialization(java.lang.String, com.yahoo.tensor.TensorType)",
"public com.yahoo.searchlib.rankingexpression.rule.SerializationContext withBindings(java.util.Map)",
+ "public com.yahoo.searchlib.rankingexpression.rule.SerializationContext withoutBindings()",
"public java.util.Map serializedFunctions()",
+ "public bridge synthetic com.yahoo.searchlib.rankingexpression.rule.FunctionReferenceContext withoutBindings()",
"public bridge synthetic com.yahoo.searchlib.rankingexpression.rule.FunctionReferenceContext withBindings(java.util.Map)"
],
"fields": []
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/ExpressionFunction.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/ExpressionFunction.java
index 674571ff73e..559f690a32d 100755
--- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/ExpressionFunction.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/ExpressionFunction.java
@@ -134,7 +134,10 @@ public class ExpressionFunction {
for (int i = 0; i < arguments.size() && i < argumentValues.size(); ++i) {
argumentBindings.put(arguments.get(i), argumentValues.get(i).toString(new StringBuilder(), context, path, null).toString());
}
- return new Instance(toSymbol(argumentBindings), body.getRoot().toString(new StringBuilder(), context.withBindings(argumentBindings), path, null).toString());
+ context = argumentBindings.isEmpty() ? context.withoutBindings() : context.withBindings(argumentBindings);
+ String symbol = toSymbol(argumentBindings);
+ String expressionString = body.getRoot().toString(new StringBuilder(), context, path, null).toString();
+ return new Instance(symbol, expressionString);
}
/**
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/FunctionReferenceContext.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/FunctionReferenceContext.java
index 83aabada8f0..6717bec0258 100644
--- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/FunctionReferenceContext.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/FunctionReferenceContext.java
@@ -68,4 +68,9 @@ public class FunctionReferenceContext {
return new FunctionReferenceContext(this.functions, bindings);
}
+ /** Returns a fresh context without bindings */
+ public FunctionReferenceContext withoutBindings() {
+ return new FunctionReferenceContext(this.functions);
+ }
+
}
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/ReferenceNode.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/ReferenceNode.java
index 8fec3603f3e..335d3861d9d 100755
--- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/ReferenceNode.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/ReferenceNode.java
@@ -5,7 +5,6 @@ import com.yahoo.searchlib.rankingexpression.ExpressionFunction;
import com.yahoo.searchlib.rankingexpression.RankingExpression;
import com.yahoo.searchlib.rankingexpression.Reference;
import com.yahoo.searchlib.rankingexpression.evaluation.Context;
-import com.yahoo.searchlib.rankingexpression.evaluation.StringValue;
import com.yahoo.searchlib.rankingexpression.evaluation.Value;
import com.yahoo.tensor.TensorType;
import com.yahoo.tensor.evaluation.TypeContext;
@@ -13,7 +12,7 @@ import com.yahoo.tensor.evaluation.TypeContext;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List;
-import java.util.Optional;
+import java.util.Map;
/**
* A node referring either to a value in the context or to a named ranking expression function.
@@ -84,13 +83,25 @@ public final class ReferenceNode extends CompositeNode {
if (path.contains(myPath))
throw new IllegalStateException("Cycle in ranking expression function: " + path);
path.addLast(myPath);
- ExpressionFunction.Instance instance = function.expand(context, getArguments().expressions(), path);
+
+ String functionName = getName();
+ String functionPropertyName = RankingExpression.propertyName(functionName);
+ boolean alreadySerialized = context.serializedFunctions().containsKey(functionPropertyName);
+
+ if ( ! alreadySerialized || getArguments().size() > 0) {
+ ExpressionFunction.Instance instance = function.expand(context, getArguments().expressions(), path);
+ functionName = instance.getName();
+
+ context.addFunctionSerialization(RankingExpression.propertyName(functionName), instance.getExpressionString());
+ for (Map.Entry<String, TensorType> argumentType : function.argumentTypes().entrySet())
+ context.addArgumentTypeSerialization(functionName, argumentType.getKey(), argumentType.getValue());
+ if (function.returnType().isPresent())
+ context.addFunctionTypeSerialization(functionName, function.returnType().get());
+ }
path.removeLast();
- context.addFunctionSerialization(RankingExpression.propertyName(instance.getName()), instance.getExpressionString());
- return string.append("rankingExpression(").append(instance.getName()).append(')');
+ return string.append("rankingExpression(").append(functionName).append(')');
}
-
// Not resolved in this context: output as-is
return reference.toString(string, context, path, parent);
}
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SerializationContext.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SerializationContext.java
index d7807caa2b6..92889d6607b 100644
--- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SerializationContext.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/SerializationContext.java
@@ -95,6 +95,12 @@ public class SerializationContext extends FunctionReferenceContext {
return new SerializationContext(functions(), bindings, this.serializedFunctions);
}
+ /** Returns a fresh context without bindings */
+ @Override
+ public SerializationContext withoutBindings() {
+ return new SerializationContext(functions(), null, this.serializedFunctions);
+ }
+
public Map<String, String> serializedFunctions() { return serializedFunctions; }
}
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/TensorFunctionNode.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/TensorFunctionNode.java
index 6e1cdf52158..befe2179dc1 100644
--- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/TensorFunctionNode.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/TensorFunctionNode.java
@@ -333,10 +333,16 @@ public class TensorFunctionNode extends CompositeNode {
/** Returns a new context with the bindings replaced by the given bindings */
@Override
public ExpressionToStringContext withBindings(Map<String, String> bindings) {
- return new ExpressionToStringContext(new SerializationContext(wrappedSerializationContext.functions().values(), bindings),
- wrappedToStringContext, path, parent);
+ SerializationContext serializationContext = new SerializationContext(functions(), bindings, serializedFunctions());
+ return new ExpressionToStringContext(serializationContext, wrappedToStringContext, path, parent);
}
+ /** Returns a fresh context without bindings */
+ @Override
+ public SerializationContext withoutBindings() {
+ SerializationContext serializationContext = new SerializationContext(functions(), null, serializedFunctions());
+ return new ExpressionToStringContext(serializationContext, null, path, parent);
+ }
}
/** Turns an EvaluationContext into a Context */
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/transform/ConstantDereferencer.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/transform/ConstantDereferencer.java
index a541eac2421..fed4f60e983 100644
--- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/transform/ConstantDereferencer.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/transform/ConstantDereferencer.java
@@ -1,7 +1,7 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.searchlib.rankingexpression.transform;
-import com.yahoo.searchlib.rankingexpression.evaluation.TensorValue;
+import com.yahoo.searchlib.rankingexpression.Reference;
import com.yahoo.searchlib.rankingexpression.evaluation.Value;
import com.yahoo.searchlib.rankingexpression.rule.CompositeNode;
import com.yahoo.searchlib.rankingexpression.rule.ConstantNode;
@@ -28,8 +28,15 @@ public class ConstantDereferencer extends ExpressionTransformer<TransformContext
return node;
}
+ /** Returns true if the given reference is an attribute, constant or query feature */
+ private static boolean isSimpleFeature(Reference reference) {
+ if ( ! reference.isSimple()) return false;
+ String name = reference.name();
+ return name.equals("attribute") || name.equals("constant") || name.equals("query");
+ }
+
private ExpressionNode transformFeature(ReferenceNode node, TransformContext context) {
- if (!node.getArguments().isEmpty())
+ if ( ! node.getArguments().isEmpty() && ! isSimpleFeature(node.reference()))
return transformArguments(node, context);
else
return transformConstantReference(node, context);
@@ -44,7 +51,14 @@ public class ConstantDereferencer extends ExpressionTransformer<TransformContext
}
private ExpressionNode transformConstantReference(ReferenceNode node, TransformContext context) {
- Value value = context.constants().get(node.getName());
+ String name = node.getName();
+ if (node.reference().name().equals("constant")) {
+ ExpressionNode arg = node.getArguments().expressions().get(0);
+ if (arg instanceof ReferenceNode) {
+ name = ((ReferenceNode)arg).getName();
+ }
+ }
+ Value value = context.constants().get(name); // works if "constant(...)" is added
if (value == null || value.type().rank() > 0) {
return node; // not a number constant reference
}