aboutsummaryrefslogtreecommitdiffstats
path: root/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@oath.com>2018-02-14 09:42:46 +0100
committerJon Bratseth <bratseth@oath.com>2018-02-14 09:42:46 +0100
commitfa0bc59e2313aa6b6249ad88f7c1892a3a29553d (patch)
treef426c5657280a25c4599deecc5cca3be9378cab7 /searchlib/src/main/java/com/yahoo/searchlib/rankingexpression
parentc17b1582face7c7f31fea7e151a5855908fe04f5 (diff)
Handle argument bindings
Diffstat (limited to 'searchlib/src/main/java/com/yahoo/searchlib/rankingexpression')
-rwxr-xr-xsearchlib/src/main/java/com/yahoo/searchlib/rankingexpression/FeatureList.java5
-rw-r--r--searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/ArrayContext.java4
-rw-r--r--searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/DoubleOnlyArrayContext.java2
-rw-r--r--searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/MapContext.java2
-rw-r--r--searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/MapTypeContext.java8
-rw-r--r--searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/Arguments.java14
-rwxr-xr-xsearchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/ReferenceNode.java91
7 files changed, 108 insertions, 18 deletions
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/FeatureList.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/FeatureList.java
index 49466f1974d..f0532d9d433 100755
--- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/FeatureList.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/FeatureList.java
@@ -91,8 +91,8 @@ public class FeatureList implements Iterable<ReferenceNode> {
/**
* Returns the feature at the given index.
*
- * @param i The index of the feature to return.
- * @return The featuer at the given index.
+ * @param i the index of the feature to return.
+ * @return the feature at the given index.
*/
public ReferenceNode get(int i) {
return features.get(i);
@@ -137,4 +137,5 @@ public class FeatureList implements Iterable<ReferenceNode> {
public Iterator<ReferenceNode> iterator() {
return features.iterator();
}
+
}
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/ArrayContext.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/ArrayContext.java
index 5f8daa69ecf..486affe9371 100644
--- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/ArrayContext.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/ArrayContext.java
@@ -82,8 +82,8 @@ public class ArrayContext extends AbstractArrayContext implements Cloneable {
}
@Override
- public TensorType getType(String name) {
- Integer index = nameToIndex().get(name);
+ public TensorType getType(Name name) {
+ Integer index = nameToIndex().get(name.toString());
if (index == null) return null;
return values[index].type();
}
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/DoubleOnlyArrayContext.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/DoubleOnlyArrayContext.java
index 0625e8506cc..01b8bffe995 100644
--- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/DoubleOnlyArrayContext.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/DoubleOnlyArrayContext.java
@@ -68,7 +68,7 @@ public class DoubleOnlyArrayContext extends AbstractArrayContext {
}
@Override
- public TensorType getType(String name) { return TensorType.empty; }
+ public TensorType getType(Name name) { return TensorType.empty; }
/** Perform a slow lookup by name */
@Override
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/MapContext.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/MapContext.java
index a81d0c89f8f..c7679ea9e55 100644
--- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/MapContext.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/MapContext.java
@@ -42,7 +42,7 @@ public class MapContext extends Context {
/** Returns the type of the given value key, or null if it is not bound. */
@Override
- public TensorType getType(String key) {
+ public TensorType getType(Name key) {
Value value = bindings.get(key);
if (value == null) return null;
return value.type();
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/MapTypeContext.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/MapTypeContext.java
index d461ae52cbe..2ddc8213d94 100644
--- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/MapTypeContext.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/MapTypeContext.java
@@ -15,18 +15,18 @@ import java.util.Map;
*/
public class MapTypeContext implements TypeContext {
- private final Map<String, TensorType> featureTypes = new HashMap<>();
+ private final Map<Name, TensorType> featureTypes = new HashMap<>();
public void setType(String name, TensorType type) {
- featureTypes.put(name, type);
+ featureTypes.put(new Name(name), type);
}
@Override
- public TensorType getType(String name) {
+ public TensorType getType(Name name) {
return featureTypes.get(name);
}
/** Returns an unmodifiable map of the bindings in this */
- public Map<String, TensorType> bindings() { return Collections.unmodifiableMap(featureTypes); }
+ public Map<Name, TensorType> bindings() { return Collections.unmodifiableMap(featureTypes); }
}
diff --git a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/Arguments.java b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/Arguments.java
index fb9a7cb9ad7..d7163fe9166 100644
--- a/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/Arguments.java
+++ b/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/rule/Arguments.java
@@ -13,7 +13,8 @@ import java.util.List;
/**
* A set of argument expressions to a function or feature.
- * This is immutable.
+ * This is a value object.
+ *.
*
* @author bratseth
*/
@@ -22,7 +23,11 @@ public final class Arguments implements Serializable {
private final ImmutableList<ExpressionNode> expressions;
public Arguments() {
- this(null);
+ this(ImmutableList.of());
+ }
+
+ public Arguments(ExpressionNode singleArgument) {
+ this(ImmutableList.of(singleArgument));
}
public Arguments(List<? extends ExpressionNode> expressions) {
@@ -62,8 +67,9 @@ public final class Arguments implements Serializable {
}
@Override
- public boolean equals(Object rhs) {
- return rhs instanceof Arguments && expressions.equals(((Arguments)rhs).expressions);
+ public boolean equals(Object other) {
+ if (other == this) return true;
+ return other instanceof Arguments && expressions.equals(((Arguments)other).expressions);
}
@Override
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 ebfef21a815..e121fa12b5f 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
@@ -9,8 +9,13 @@ import com.yahoo.tensor.TensorType;
import com.yahoo.tensor.evaluation.TypeContext;
import java.util.ArrayDeque;
+import java.util.Arrays;
import java.util.Deque;
import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
/**
* A node referring either to a value in the context or to a named ranking expression (function aka macro).
@@ -31,6 +36,7 @@ public final class ReferenceNode extends CompositeNode {
}
public ReferenceNode(String name, List<? extends ExpressionNode> arguments, String output) {
+ Objects.requireNonNull(name, "name cannot be null");
this.name = name;
this.arguments = arguments != null ? new Arguments(arguments) : new Arguments();
this.output = output;
@@ -119,11 +125,10 @@ public final class ReferenceNode extends CompositeNode {
@Override
public TensorType type(TypeContext context) {
- String feature = toString(new SerializationContext(), null, false);
- TensorType type = context.getType(feature);
- // TensorType type = context.getType(name, arguments, output); TODO
+ TensorType type = context.getType(new Reference(name, arguments, output,
+ toString(new SerializationContext(), null, true)));
if (type == null)
- throw new IllegalArgumentException("Unknown feature '" + feature + "'");
+ throw new IllegalArgumentException("Unknown feature '" + toString() + "'");
return type;
}
@@ -139,4 +144,82 @@ public final class ReferenceNode extends CompositeNode {
return new ReferenceNode(name, newChildren, output);
}
+ /** Wraps the content of this in a form which can be passed to a type context */
+ // TODO: Extract to top level?
+ public static class Reference extends TypeContext.Name {
+
+ private static final Pattern identifierRegexp = Pattern.compile("[A-Za-z0-9_][A-Za-z0-9_-]*");
+
+ private final String name;
+ private final Arguments arguments;
+
+ /** The output, or null if none */
+ private final String output;
+
+ public Reference(String name, Arguments arguments, String output, String stringForm) {
+ super(stringForm);
+ Objects.requireNonNull(name, "name cannot be null");
+ Objects.requireNonNull(arguments, "arguments cannot be null");
+ Objects.requireNonNull(stringForm, "stringForm cannot be null");
+ this.name = name;
+ this.arguments = arguments;
+ this.output = output;
+ }
+
+ public String name() { return name; }
+ public Arguments arguments() { return arguments; }
+ public String output() { return output; }
+
+ /** Creates a reference to a simple feature consisting of a name and a single argument */
+ public static Reference simple(String name, String argumentValue) {
+ return new Reference(name,
+ new Arguments(new ReferenceNode(argumentValue)),
+ null,
+ name + "(" + quoteIfNecessary(argumentValue) + ")");
+ }
+
+ /**
+ * Returns the given simple feature as a reference, or empty if it is not a valid simple
+ * feature string on the form name(argument).
+ */
+ public static Optional<Reference> simple(String feature) {
+ int startParenthesis = feature.indexOf('(');
+ if (startParenthesis < 0)
+ return Optional.empty();
+ int endParenthesis = feature.lastIndexOf(')');
+ String featureName = feature.substring(0, startParenthesis);
+ if (startParenthesis < 1 || endParenthesis < startParenthesis) return Optional.empty();
+ String argument = feature.substring(startParenthesis + 1, endParenthesis);
+ if (argument.startsWith("'") || argument.startsWith("\""))
+ argument = argument.substring(1);
+ if (argument.endsWith("'") || argument.endsWith("\""))
+ argument = argument.substring(0, argument.length() - 1);
+ return Optional.of(simple(featureName, argument));
+ }
+
+ private static String quoteIfNecessary(String s) {
+ if (identifierRegexp.matcher(s).matches())
+ return s;
+ else
+ return "\"" + s + "\"";
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) return true;
+ if ( ! (o instanceof Reference)) return false;
+ Reference other = (Reference)o;
+ if ( ! Objects.equals(other.name, this.name)) return false;
+ if ( ! Objects.equals(other.arguments, this.arguments)) return false;
+ if ( ! Objects.equals(other.output, this.output)) return false;
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, arguments, output);
+ }
+
+ }
+
}